]> Pileus Git - ~andy/gtk/blob - gtk/gtknotebook.c
Merges from gtk-1-2
[~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
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gtknotebook.h"
28 #include "gtksignal.h"
29 #include "gtkmain.h"
30 #include "gtkmenu.h"
31 #include "gtkmenuitem.h"
32 #include "gtklabel.h"
33 #include <gdk/gdkkeysyms.h>
34 #include <stdio.h>
35 #include "gtkintl.h"
36
37
38 #define TAB_OVERLAP    2
39 #define TAB_CURVATURE  1
40 #define ARROW_SIZE     12
41 #define ARROW_SPACING  0
42 #define FOCUS_WIDTH    1
43 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
44 #define NOTEBOOK_SCROLL_DELAY      (100)
45
46
47 enum {
48   SWITCH_PAGE,
49   LAST_SIGNAL
50 };
51
52 enum {
53   STEP_PREV,
54   STEP_NEXT
55 };
56
57 enum {
58   ARG_0,
59   ARG_TAB_POS,
60   ARG_SHOW_TABS,
61   ARG_SHOW_BORDER,
62   ARG_SCROLLABLE,
63   ARG_TAB_BORDER,
64   ARG_TAB_HBORDER,
65   ARG_TAB_VBORDER,
66   ARG_PAGE,
67   ARG_ENABLE_POPUP,
68   ARG_HOMOGENEOUS
69 };
70
71 enum {
72   CHILD_ARG_0,
73   CHILD_ARG_TAB_LABEL,
74   CHILD_ARG_MENU_LABEL,
75   CHILD_ARG_POSITION,
76   CHILD_ARG_TAB_EXPAND,
77   CHILD_ARG_TAB_FILL,
78   CHILD_ARG_TAB_PACK
79 };
80
81 /** GtkNotebook Methods **/
82 static void gtk_notebook_class_init          (GtkNotebookClass *klass);
83 static void gtk_notebook_init                (GtkNotebook      *notebook);
84
85 /** GtkObject Methods **/
86 static void gtk_notebook_destroy             (GtkObject        *object);
87 static void gtk_notebook_set_arg             (GtkObject        *object,
88                                               GtkArg           *arg,
89                                               guint             arg_id);
90 static void gtk_notebook_get_arg             (GtkObject        *object,
91                                               GtkArg           *arg,
92                                               guint             arg_id);
93
94 /** GtkWidget Methods **/
95 static void gtk_notebook_map                 (GtkWidget        *widget);
96 static void gtk_notebook_unmap               (GtkWidget        *widget);
97 static void gtk_notebook_realize             (GtkWidget        *widget);
98 static void gtk_notebook_unrealize           (GtkWidget        *widget);
99 static void gtk_notebook_size_request        (GtkWidget        *widget,
100                                               GtkRequisition   *requisition);
101 static void gtk_notebook_size_allocate       (GtkWidget        *widget,
102                                               GtkAllocation    *allocation);
103 static void gtk_notebook_draw                (GtkWidget        *widget,
104                                               GdkRectangle     *area);
105 static gint gtk_notebook_expose              (GtkWidget        *widget,
106                                               GdkEventExpose   *event);
107 static gint gtk_notebook_button_press        (GtkWidget        *widget,
108                                               GdkEventButton   *event);
109 static gint gtk_notebook_button_release      (GtkWidget        *widget,
110                                               GdkEventButton   *event);
111 static gint gtk_notebook_enter_notify        (GtkWidget        *widget,
112                                               GdkEventCrossing *event);
113 static gint gtk_notebook_leave_notify        (GtkWidget        *widget,
114                                               GdkEventCrossing *event);
115 static gint gtk_notebook_motion_notify       (GtkWidget        *widget,
116                                               GdkEventMotion   *event);
117 static gint gtk_notebook_key_press           (GtkWidget        *widget,
118                                               GdkEventKey      *event);
119 static gint gtk_notebook_focus_in            (GtkWidget        *widget,
120                                               GdkEventFocus    *event);
121 static gint gtk_notebook_focus_out           (GtkWidget        *widget,
122                                               GdkEventFocus    *event);
123 static void gtk_notebook_draw_focus          (GtkWidget        *widget);
124 static void gtk_notebook_style_set           (GtkWidget        *widget,
125                                               GtkStyle         *previous_style);
126
127 /** GtkContainer Methods **/
128 static void gtk_notebook_set_child_arg       (GtkContainer     *container,
129                                               GtkWidget        *child,
130                                               GtkArg           *arg,
131                                               guint             arg_id);
132 static void gtk_notebook_get_child_arg       (GtkContainer     *container,
133                                               GtkWidget        *child,
134                                               GtkArg           *arg,
135                                               guint             arg_id);
136 static void gtk_notebook_add                 (GtkContainer     *container,
137                                               GtkWidget        *widget);
138 static void gtk_notebook_remove              (GtkContainer     *container,
139                                               GtkWidget        *widget);
140 static gint gtk_notebook_focus               (GtkContainer     *container,
141                                               GtkDirectionType  direction);
142 static void gtk_notebook_set_focus_child     (GtkContainer     *container,
143                                               GtkWidget        *child);
144 static GtkType gtk_notebook_child_type       (GtkContainer     *container);
145 static void gtk_notebook_forall              (GtkContainer     *container,
146                                               gboolean          include_internals,
147                                               GtkCallback       callback,
148                                               gpointer          callback_data);
149
150 /** GtkNotebook Private Functions **/
151 static void gtk_notebook_panel_realize       (GtkNotebook      *notebook);
152 static void gtk_notebook_expose_tabs         (GtkNotebook      *notebook);
153 static void gtk_notebook_focus_changed       (GtkNotebook      *notebook,
154                                               GtkNotebookPage  *old_page);
155 static void gtk_notebook_real_remove         (GtkNotebook      *notebook,
156                                               GList            *list);
157 static void gtk_notebook_update_labels       (GtkNotebook      *notebook);
158 static gint gtk_notebook_timer               (GtkNotebook      *notebook);
159 static gint gtk_notebook_page_compare        (gconstpointer     a,
160                                               gconstpointer     b);
161 static gint  gtk_notebook_real_page_position (GtkNotebook      *notebook,
162                                               GList            *list);
163 static GList * gtk_notebook_search_page      (GtkNotebook      *notebook,
164                                               GList            *list,
165                                               gint              direction,
166                                               gboolean          find_visible);
167
168 /** GtkNotebook Drawing Functions **/
169 static void gtk_notebook_paint               (GtkWidget        *widget,
170                                               GdkRectangle     *area);
171 static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
172                                               GtkNotebookPage  *page,
173                                               GdkRectangle     *area);
174 static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
175                                               guint             arrow);
176 static void gtk_notebook_set_shape           (GtkNotebook      *notebook);
177
178 /** GtkNotebook Size Allocate Functions **/
179 static void gtk_notebook_pages_allocate      (GtkNotebook      *notebook,
180                                               GtkAllocation    *allocation);
181 static void gtk_notebook_page_allocate       (GtkNotebook      *notebook,
182                                               GtkNotebookPage  *page,
183                                               GtkAllocation    *allocation);
184 static void gtk_notebook_calc_tabs           (GtkNotebook      *notebook,
185                                               GList            *start,
186                                               GList           **end,
187                                               gint             *tab_space,
188                                               guint             direction);
189
190 /** GtkNotebook Page Switch Methods **/
191 static void gtk_notebook_real_switch_page    (GtkNotebook      *notebook,
192                                               GtkNotebookPage  *page,
193                                               guint             page_num);
194
195 /** GtkNotebook Page Switch Functions **/
196 static void gtk_notebook_switch_page         (GtkNotebook      *notebook,
197                                               GtkNotebookPage  *page,
198                                               gint              page_num);
199 static gint gtk_notebook_page_select         (GtkNotebook      *notebook);
200 static void gtk_notebook_switch_focus_tab    (GtkNotebook      *notebook,
201                                               GList            *new_child);
202 static void gtk_notebook_menu_switch_page    (GtkWidget        *widget,
203                                               GtkNotebookPage  *page);
204
205 /** GtkNotebook Menu Functions **/
206 static void gtk_notebook_menu_item_create    (GtkNotebook      *notebook,
207                                               GList            *list);
208 static void gtk_notebook_menu_label_unparent (GtkWidget        *widget,
209                                               gpointer          data);
210 static void gtk_notebook_menu_detacher       (GtkWidget        *widget,
211                                               GtkMenu          *menu);
212
213
214 static GtkContainerClass *parent_class = NULL;
215 static guint notebook_signals[LAST_SIGNAL] = { 0 };
216
217 GtkType
218 gtk_notebook_get_type (void)
219 {
220   static GtkType notebook_type = 0;
221
222   if (!notebook_type)
223     {
224       static const GtkTypeInfo notebook_info =
225       {
226         "GtkNotebook",
227         sizeof (GtkNotebook),
228         sizeof (GtkNotebookClass),
229         (GtkClassInitFunc) gtk_notebook_class_init,
230         (GtkObjectInitFunc) gtk_notebook_init,
231         /* reserved_1 */ NULL,
232         /* reserved_2 */ NULL,
233         (GtkClassInitFunc) NULL,
234       };
235
236       notebook_type = gtk_type_unique (gtk_container_get_type (), &notebook_info);
237     }
238
239   return notebook_type;
240 }
241
242 static void
243 gtk_notebook_class_init (GtkNotebookClass *class)
244 {
245   GtkObjectClass *object_class;
246   GtkWidgetClass *widget_class;
247   GtkContainerClass *container_class;
248
249   object_class = (GtkObjectClass*) class;
250   widget_class = (GtkWidgetClass*) class;
251   container_class = (GtkContainerClass*) class;
252   parent_class = gtk_type_class (gtk_container_get_type ());
253
254   gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
255   gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
256   gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_WRITABLE, ARG_TAB_BORDER);
257   gtk_object_add_arg_type ("GtkNotebook::tab_hborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_HBORDER);
258   gtk_object_add_arg_type ("GtkNotebook::tab_vborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_VBORDER);
259   gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
260   gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
261   gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
262   gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
263   gtk_object_add_arg_type ("GtkNotebook::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
264
265   gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
266   gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
267   gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
268   gtk_container_add_child_arg_type ("GtkNotebook::tab_fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_FILL);
269   gtk_container_add_child_arg_type ("GtkNotebook::tab_pack", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_PACK);
270
271   notebook_signals[SWITCH_PAGE] =
272     gtk_signal_new ("switch_page",
273                     GTK_RUN_LAST,
274                     object_class->type,
275                     GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
276                     gtk_marshal_NONE__POINTER_UINT,
277                     GTK_TYPE_NONE, 2,
278                     GTK_TYPE_POINTER,
279                     GTK_TYPE_UINT);
280
281   gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
282
283   object_class->set_arg = gtk_notebook_set_arg;
284   object_class->get_arg = gtk_notebook_get_arg;
285   object_class->destroy = gtk_notebook_destroy;
286
287   widget_class->map = gtk_notebook_map;
288   widget_class->unmap = gtk_notebook_unmap;
289   widget_class->realize = gtk_notebook_realize;
290   widget_class->unrealize = gtk_notebook_unrealize;
291   widget_class->size_request = gtk_notebook_size_request;
292   widget_class->size_allocate = gtk_notebook_size_allocate;
293   widget_class->draw = gtk_notebook_draw;
294   widget_class->expose_event = gtk_notebook_expose;
295   widget_class->button_press_event = gtk_notebook_button_press;
296   widget_class->button_release_event = gtk_notebook_button_release;
297   widget_class->enter_notify_event = gtk_notebook_enter_notify;
298   widget_class->leave_notify_event = gtk_notebook_leave_notify;
299   widget_class->motion_notify_event = gtk_notebook_motion_notify;
300   widget_class->key_press_event = gtk_notebook_key_press;
301   widget_class->focus_in_event = gtk_notebook_focus_in;
302   widget_class->focus_out_event = gtk_notebook_focus_out;
303   widget_class->draw_focus = gtk_notebook_draw_focus;
304   widget_class->style_set = gtk_notebook_style_set;
305    
306   container_class->add = gtk_notebook_add;
307   container_class->remove = gtk_notebook_remove;
308   container_class->forall = gtk_notebook_forall;
309   container_class->focus = gtk_notebook_focus;
310   container_class->set_focus_child = gtk_notebook_set_focus_child;
311   container_class->get_child_arg = gtk_notebook_get_child_arg;
312   container_class->set_child_arg = gtk_notebook_set_child_arg;
313   container_class->child_type = gtk_notebook_child_type;
314
315   class->switch_page = gtk_notebook_real_switch_page;
316 }
317
318 static void
319 gtk_notebook_init (GtkNotebook *notebook)
320 {
321   GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
322   GTK_WIDGET_UNSET_FLAGS (notebook, GTK_NO_WINDOW);
323
324   notebook->cur_page = NULL;
325   notebook->children = NULL;
326   notebook->first_tab = NULL;
327   notebook->focus_tab = NULL;
328   notebook->panel = NULL;
329   notebook->menu = NULL;
330
331   notebook->tab_hborder = 2;
332   notebook->tab_vborder = 2;
333
334   notebook->show_tabs = TRUE;
335   notebook->show_border = TRUE;
336   notebook->tab_pos = GTK_POS_TOP;
337   notebook->scrollable = FALSE;
338   notebook->in_child = 0;
339   notebook->click_child = 0;
340   notebook->button = 0;
341   notebook->need_timer = 0;
342   notebook->child_has_focus = FALSE;
343   notebook->have_visible_child = FALSE;
344 }
345
346 GtkWidget*
347 gtk_notebook_new (void)
348 {
349   return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
350 }
351
352 /* Private GtkObject Methods :
353  * 
354  * gtk_notebook_destroy
355  * gtk_notebook_set_arg
356  * gtk_notebook_get_arg
357  */
358 static void
359 gtk_notebook_destroy (GtkObject *object)
360 {
361   GtkNotebook *notebook;
362   
363   g_return_if_fail (object != NULL);
364   g_return_if_fail (GTK_IS_NOTEBOOK (object));
365
366   notebook = GTK_NOTEBOOK (object);
367
368   if (notebook->menu)
369     gtk_notebook_popup_disable (notebook);
370
371   GTK_OBJECT_CLASS (parent_class)->destroy (object);
372 }
373
374 static void
375 gtk_notebook_set_arg (GtkObject *object,
376                       GtkArg    *arg,
377                       guint      arg_id)
378 {
379   GtkNotebook *notebook;
380
381   notebook = GTK_NOTEBOOK (object);
382
383   switch (arg_id)
384     {
385     case ARG_SHOW_TABS:
386       gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
387       break;
388     case ARG_SHOW_BORDER:
389       gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
390       break;
391     case ARG_SCROLLABLE:
392       gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
393       break;
394     case ARG_ENABLE_POPUP:
395       if (GTK_VALUE_BOOL (*arg))
396         gtk_notebook_popup_enable (notebook);
397       else
398         gtk_notebook_popup_disable (notebook);
399       break;
400     case ARG_HOMOGENEOUS:
401       gtk_notebook_set_homogeneous_tabs (notebook, GTK_VALUE_BOOL (*arg));
402       break;  
403     case ARG_PAGE:
404       gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
405       break;
406     case ARG_TAB_POS:
407       gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
408       break;
409     case ARG_TAB_BORDER:
410       gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
411       break;
412     case ARG_TAB_HBORDER:
413       gtk_notebook_set_tab_hborder (notebook, GTK_VALUE_UINT (*arg));
414       break;
415     case ARG_TAB_VBORDER:
416       gtk_notebook_set_tab_vborder (notebook, GTK_VALUE_UINT (*arg));
417       break;
418     default:
419       break;
420     }
421 }
422
423 static void
424 gtk_notebook_get_arg (GtkObject *object,
425                       GtkArg    *arg,
426                       guint      arg_id)
427 {
428   GtkNotebook *notebook;
429
430   notebook = GTK_NOTEBOOK (object);
431
432   switch (arg_id)
433     {
434     case ARG_SHOW_TABS:
435       GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
436       break;
437     case ARG_SHOW_BORDER:
438       GTK_VALUE_BOOL (*arg) = notebook->show_border;
439       break;
440     case ARG_SCROLLABLE:
441       GTK_VALUE_BOOL (*arg) = notebook->scrollable;
442       break;
443     case ARG_ENABLE_POPUP:
444       GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
445       break;
446     case ARG_HOMOGENEOUS:
447       GTK_VALUE_BOOL (*arg) = notebook->homogeneous;
448       break;
449     case ARG_PAGE:
450       GTK_VALUE_INT (*arg) = gtk_notebook_get_current_page (notebook);
451       break;
452     case ARG_TAB_POS:
453       GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
454       break;
455     case ARG_TAB_HBORDER:
456       GTK_VALUE_UINT (*arg) = notebook->tab_hborder;
457       break;
458     case ARG_TAB_VBORDER:
459       GTK_VALUE_UINT (*arg) = notebook->tab_vborder;
460       break;
461     default:
462       arg->type = GTK_TYPE_INVALID;
463       break;
464     }
465 }
466
467 /* Private GtkWidget Methods :
468  * 
469  * gtk_notebook_map
470  * gtk_notebook_unmap
471  * gtk_notebook_realize
472  * gtk_notebook_size_request
473  * gtk_notebook_size_allocate
474  * gtk_notebook_draw
475  * gtk_notebook_expose
476  * gtk_notebook_button_press
477  * gtk_notebook_button_release
478  * gtk_notebook_enter_notify
479  * gtk_notebook_leave_notify
480  * gtk_notebook_motion_notify
481  * gtk_notebook_key_press
482  * gtk_notebook_focus_in
483  * gtk_notebook_focus_out
484  * gtk_notebook_draw_focus
485  * gtk_notebook_style_set
486  */
487 static void
488 gtk_notebook_map (GtkWidget *widget)
489 {
490   GtkNotebook *notebook;
491   GtkNotebookPage *page;
492   GList *children;
493
494   g_return_if_fail (widget != NULL);
495   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
496
497   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
498
499   notebook = GTK_NOTEBOOK (widget);
500
501   if (notebook->cur_page && 
502       GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
503       !GTK_WIDGET_MAPPED (notebook->cur_page->child))
504     gtk_widget_map (notebook->cur_page->child);
505
506   if (notebook->scrollable)
507       gtk_notebook_pages_allocate (notebook, &(widget->allocation));
508   else
509     {
510       children = notebook->children;
511
512       while (children)
513         {
514           page = children->data;
515           children = children->next;
516
517           if (page->tab_label &&
518               GTK_WIDGET_VISIBLE (page->tab_label) &&
519               !GTK_WIDGET_MAPPED (page->tab_label))
520             gtk_widget_map (page->tab_label);
521         }
522     }
523
524   gdk_window_show (widget->window);
525 }
526
527 static void
528 gtk_notebook_unmap (GtkWidget *widget)
529 {
530   g_return_if_fail (widget != NULL);
531   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
532
533   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
534   gdk_window_hide (widget->window);
535   if (GTK_NOTEBOOK (widget)->panel)
536     gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
537 }
538
539 static void
540 gtk_notebook_realize (GtkWidget *widget)
541 {
542   GtkNotebook *notebook;
543   GdkWindowAttr attributes;
544   gint attributes_mask;
545
546   g_return_if_fail (widget != NULL);
547   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
548
549   notebook = GTK_NOTEBOOK (widget);
550   GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
551
552   attributes.window_type = GDK_WINDOW_CHILD;
553   attributes.x = widget->allocation.x;
554   attributes.y = widget->allocation.y;
555   attributes.width = widget->allocation.width;
556   attributes.height = widget->allocation.height;
557   attributes.wclass = GDK_INPUT_OUTPUT;
558   attributes.visual = gtk_widget_get_visual (widget);
559   attributes.colormap = gtk_widget_get_colormap (widget);
560   attributes.event_mask = gtk_widget_get_events (widget);
561   attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
562                             GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
563
564   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
565
566   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
567   gdk_window_set_user_data (widget->window, notebook);
568
569   widget->style = gtk_style_attach (widget->style, widget->window);
570   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
571
572   gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
573   if (notebook->scrollable)
574     gtk_notebook_panel_realize (notebook);
575 }
576
577 static void
578 gtk_notebook_unrealize (GtkWidget *widget)
579 {
580   GtkNotebook *notebook;
581
582   g_return_if_fail (widget != NULL);
583   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
584
585   notebook = GTK_NOTEBOOK (widget);
586
587   if (notebook->panel)
588     {
589       gdk_window_set_user_data (notebook->panel, NULL);
590       gdk_window_destroy (notebook->panel);
591       notebook->panel = NULL;
592     }
593
594   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
595     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
596 }
597
598 static void
599 gtk_notebook_size_request (GtkWidget      *widget,
600                            GtkRequisition *requisition)
601 {
602   GtkNotebook *notebook;
603   GtkNotebookPage *page;
604   GList *children;
605   GtkRequisition child_requisition;
606   gboolean switch_page = FALSE;
607   gint vis_pages;
608
609   g_return_if_fail (widget != NULL);
610   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
611   g_return_if_fail (requisition != NULL);
612
613   notebook = GTK_NOTEBOOK (widget);
614   widget->requisition.width = 0;
615   widget->requisition.height = 0;
616
617   for (children = notebook->children, vis_pages = 0; children;
618        children = children->next)
619     {
620       page = children->data;
621
622       if (GTK_WIDGET_VISIBLE (page->child))
623         {
624           vis_pages++;
625           gtk_widget_size_request (page->child, &child_requisition);
626           
627           widget->requisition.width = MAX (widget->requisition.width,
628                                            child_requisition.width);
629           widget->requisition.height = MAX (widget->requisition.height,
630                                             child_requisition.height);
631
632           if (GTK_WIDGET_MAPPED (page->child) && page != notebook->cur_page)
633             gtk_widget_unmap (page->child);
634           if (notebook->menu && page->menu_label->parent &&
635               !GTK_WIDGET_VISIBLE (page->menu_label->parent))
636             gtk_widget_show (page->menu_label->parent);
637         }
638       else
639         {
640           if (page == notebook->cur_page)
641             switch_page = TRUE;
642           if (notebook->menu && page->menu_label->parent &&
643               GTK_WIDGET_VISIBLE (page->menu_label->parent))
644             gtk_widget_hide (page->menu_label->parent);
645         }
646     }
647
648   if (notebook->show_border || notebook->show_tabs)
649     {
650       widget->requisition.width += widget->style->klass->xthickness * 2;
651       widget->requisition.height += widget->style->klass->ythickness * 2;
652
653       if (notebook->show_tabs)
654         {
655           gint tab_width = 0;
656           gint tab_height = 0;
657           gint tab_max = 0;
658           gint padding;
659           
660           for (children = notebook->children; children;
661                children = children->next)
662             {
663               page = children->data;
664               
665               if (GTK_WIDGET_VISIBLE (page->child))
666                 {
667                   if (!GTK_WIDGET_VISIBLE (page->tab_label))
668                     gtk_widget_show (page->tab_label);
669
670                   gtk_widget_size_request (page->tab_label,
671                                            &child_requisition);
672
673                   page->requisition.width = 
674                     child_requisition.width +
675                     2 * widget->style->klass->xthickness;
676                   page->requisition.height = 
677                     child_requisition.height +
678                     2 * widget->style->klass->ythickness;
679                   
680                   switch (notebook->tab_pos)
681                     {
682                     case GTK_POS_TOP:
683                     case GTK_POS_BOTTOM:
684                       page->requisition.height += 2 * (notebook->tab_vborder +
685                                                        FOCUS_WIDTH);
686                       tab_height = MAX (tab_height, page->requisition.height);
687                       tab_max = MAX (tab_max, page->requisition.width);
688                       break;
689                     case GTK_POS_LEFT:
690                     case GTK_POS_RIGHT:
691                       page->requisition.width += 2 * (notebook->tab_hborder +
692                                                       FOCUS_WIDTH);
693                       tab_width = MAX (tab_width, page->requisition.width);
694                       tab_max = MAX (tab_max, page->requisition.height);
695                       break;
696                     }
697                 }
698               else if (GTK_WIDGET_VISIBLE (page->tab_label))
699                 gtk_widget_hide (page->tab_label);
700             }
701
702           children = notebook->children;
703
704           if (vis_pages)
705             {
706               switch (notebook->tab_pos)
707                 {
708                 case GTK_POS_TOP:
709                 case GTK_POS_BOTTOM:
710                   if (tab_height == 0)
711                     break;
712
713                   if (notebook->scrollable && vis_pages > 1 && 
714                       widget->requisition.width < tab_width)
715                     tab_height = MAX (tab_height, ARROW_SIZE);
716
717                   padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
718                                  notebook->tab_hborder) - TAB_OVERLAP;
719                   tab_max += padding;
720                   while (children)
721                     {
722                       page = children->data;
723                       children = children->next;
724                   
725                       if (!GTK_WIDGET_VISIBLE (page->child))
726                         continue;
727
728                       if (notebook->homogeneous)
729                         page->requisition.width = tab_max;
730                       else
731                         page->requisition.width += padding;
732
733                       tab_width += page->requisition.width;
734                       page->requisition.height = tab_height;
735                     }
736
737                   if (notebook->scrollable && vis_pages > 1 &&
738                       widget->requisition.width < tab_width)
739                     tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
740
741                   if (notebook->homogeneous && !notebook->scrollable)
742                     widget->requisition.width = MAX (widget->requisition.width,
743                                                      vis_pages * tab_max +
744                                                      TAB_OVERLAP);
745                   else
746                     widget->requisition.width = MAX (widget->requisition.width,
747                                                      tab_width + TAB_OVERLAP);
748
749                   widget->requisition.height += tab_height;
750                   break;
751                 case GTK_POS_LEFT:
752                 case GTK_POS_RIGHT:
753                   if (tab_width == 0)
754                     break;
755
756                   if (notebook->scrollable && vis_pages > 1 && 
757                       widget->requisition.height < tab_height)
758                     tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
759
760                   padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
761                                  notebook->tab_vborder) - TAB_OVERLAP;
762                   tab_max += padding;
763
764                   while (children)
765                     {
766                       page = children->data;
767                       children = children->next;
768
769                       if (!GTK_WIDGET_VISIBLE (page->child))
770                         continue;
771
772                       page->requisition.width   = tab_width;
773
774                       if (notebook->homogeneous)
775                         page->requisition.height = tab_max;
776                       else
777                         page->requisition.height += padding;
778
779                       tab_height += page->requisition.height;
780                     }
781
782                   if (notebook->scrollable && vis_pages > 1 && 
783                       widget->requisition.height < tab_height)
784                     tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
785
786                   widget->requisition.width += tab_width;
787
788                   if (notebook->homogeneous && !notebook->scrollable)
789                     widget->requisition.height =
790                       MAX (widget->requisition.height,
791                            vis_pages * tab_max + TAB_OVERLAP);
792                   else
793                     widget->requisition.height =
794                       MAX (widget->requisition.height,
795                            tab_height + TAB_OVERLAP);
796
797                   if (!notebook->homogeneous || notebook->scrollable)
798                     vis_pages = 1;
799                   widget->requisition.height = MAX (widget->requisition.height,
800                                                     vis_pages * tab_max +
801                                                     TAB_OVERLAP);
802                   break;
803                 }
804             }
805         }
806       else
807         {
808           for (children = notebook->children; children;
809                children = children->next)
810             {
811               page = children->data;
812               
813               if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
814                 gtk_widget_hide (page->tab_label);
815             }
816         }
817     }
818
819   widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
820   widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
821
822   if (switch_page)
823     {
824       if (vis_pages)
825         {
826           for (children = notebook->children; children;
827                children = children->next)
828             {
829               page = children->data;
830               if (GTK_WIDGET_VISIBLE (page->child))
831                 {
832                   gtk_notebook_switch_page (notebook, page, -1);
833                   break;
834                 }
835             }
836         }
837       else if (GTK_WIDGET_VISIBLE (widget))
838         {
839           widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
840           widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
841         }
842     }
843   if (vis_pages && !notebook->cur_page)
844     {
845       children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
846       if (children)
847         {
848           notebook->first_tab = children;
849           gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
850         }
851     }
852 }
853
854 static void
855 gtk_notebook_size_allocate (GtkWidget     *widget,
856                             GtkAllocation *allocation)
857 {
858   GtkNotebook *notebook;
859   GtkNotebookPage *page;
860   GtkAllocation child_allocation;
861   GList *children;
862
863   g_return_if_fail (widget != NULL);
864   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
865   g_return_if_fail (allocation != NULL);
866
867   widget->allocation = *allocation;
868   if (GTK_WIDGET_REALIZED (widget))
869     gdk_window_move_resize (widget->window,
870                             allocation->x, allocation->y,
871                             allocation->width, allocation->height);
872
873   notebook = GTK_NOTEBOOK (widget);
874   if (notebook->children)
875     {
876       child_allocation.x = GTK_CONTAINER (widget)->border_width;
877       child_allocation.y = GTK_CONTAINER (widget)->border_width;
878       child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
879       child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
880
881       if (notebook->show_tabs || notebook->show_border)
882         {
883           child_allocation.x += widget->style->klass->xthickness;
884           child_allocation.y += widget->style->klass->ythickness;
885           child_allocation.width = MAX (1, (gint)child_allocation.width -
886                                         (gint) widget->style->klass->xthickness * 2);
887           child_allocation.height = MAX (1, (gint)child_allocation.height -
888                                          (gint) widget->style->klass->ythickness * 2);
889
890           if (notebook->show_tabs && notebook->children && notebook->cur_page)
891             {
892               switch (notebook->tab_pos)
893                 {
894                 case GTK_POS_TOP:
895                   child_allocation.y += notebook->cur_page->requisition.height;
896                 case GTK_POS_BOTTOM:
897                   child_allocation.height =
898                     MAX (1, (gint)child_allocation.height -
899                          (gint)notebook->cur_page->requisition.height);
900                   break;
901                 case GTK_POS_LEFT:
902                   child_allocation.x += notebook->cur_page->requisition.width;
903                 case GTK_POS_RIGHT:
904                   child_allocation.width =
905                     MAX (1, (gint)child_allocation.width -
906                          (gint)notebook->cur_page->requisition.width);
907                   break;
908                 }
909             }
910         }
911
912       children = notebook->children;
913       while (children)
914         {
915           page = children->data;
916           children = children->next;
917           
918           if (GTK_WIDGET_VISIBLE (page->child))
919             gtk_widget_size_allocate (page->child, &child_allocation);
920         }
921
922       gtk_notebook_pages_allocate (notebook, allocation);
923     }
924    gtk_notebook_set_shape (notebook);
925 }
926
927 static void
928 gtk_notebook_draw (GtkWidget    *widget,
929                    GdkRectangle *area)
930 {
931   GtkNotebook *notebook;
932   GdkRectangle child_area;
933   GdkRectangle draw_area;
934
935   g_return_if_fail (widget != NULL);
936   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
937   g_return_if_fail (area != NULL);
938
939   notebook = GTK_NOTEBOOK (widget);
940
941   draw_area = *area;
942
943   if (GTK_WIDGET_DRAWABLE (widget))
944     {
945       gboolean have_visible_child;
946
947       have_visible_child = notebook->cur_page && GTK_WIDGET_VISIBLE (notebook->cur_page->child);
948
949       if (have_visible_child != notebook->have_visible_child)
950         {
951           notebook->have_visible_child = have_visible_child;
952           draw_area.x = 0;
953           draw_area.y = 0;
954           draw_area.width = widget->allocation.width;
955           draw_area.height = widget->allocation.height;
956         }
957
958       gtk_notebook_paint (widget, &draw_area);
959
960       gtk_widget_draw_focus (widget);
961
962       if (notebook->cur_page && GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
963           gtk_widget_intersect (notebook->cur_page->child, &draw_area, &child_area))
964         gtk_widget_draw (notebook->cur_page->child, &child_area);
965     }
966   else
967     notebook->have_visible_child = FALSE;
968 }
969
970 static gint
971 gtk_notebook_expose (GtkWidget      *widget,
972                      GdkEventExpose *event)
973 {
974   GtkNotebook *notebook;
975   GdkEventExpose child_event;
976   GdkRectangle child_area;
977    
978   g_return_val_if_fail (widget != NULL, FALSE);
979   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
980   g_return_val_if_fail (event != NULL, FALSE);
981
982   if (GTK_WIDGET_DRAWABLE (widget))
983     {
984       notebook = GTK_NOTEBOOK (widget);
985
986       gtk_notebook_paint (widget, &event->area);
987       if (notebook->show_tabs)
988         {
989           if (notebook->cur_page && 
990               gtk_widget_intersect (notebook->cur_page->tab_label, 
991                                     &event->area, &child_area))
992             gtk_widget_draw_focus (widget);
993         }
994
995       child_event = *event;
996       if (notebook->cur_page && 
997           GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
998           gtk_widget_intersect (notebook->cur_page->child, &event->area, 
999                                 &child_event.area))
1000         gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1001     }
1002
1003   return FALSE;
1004 }
1005
1006 static gint
1007 gtk_notebook_button_press (GtkWidget      *widget,
1008                            GdkEventButton *event)
1009 {
1010   GtkNotebook *notebook;
1011   GtkNotebookPage *page;
1012   GList *children;
1013   gint num;
1014
1015   g_return_val_if_fail (widget != NULL, FALSE);
1016   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1017   g_return_val_if_fail (event != NULL, FALSE);
1018
1019   notebook = GTK_NOTEBOOK (widget);
1020
1021   if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1022       notebook->button)
1023     return FALSE;
1024
1025   if (event->window == notebook->panel)
1026     {
1027       if (!GTK_WIDGET_HAS_FOCUS (widget))
1028         gtk_widget_grab_focus (widget);
1029
1030       gtk_grab_add (widget);
1031       notebook->button = event->button;
1032
1033       if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1034         {
1035           notebook->click_child = GTK_ARROW_LEFT;
1036           if (event->button == 1)
1037             {
1038               if (!notebook->focus_tab ||
1039                   gtk_notebook_search_page (notebook, notebook->focus_tab,
1040                                             STEP_PREV, TRUE))
1041                 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1042
1043               if (!notebook->timer)
1044                 {
1045                   notebook->timer = gtk_timeout_add 
1046                     (NOTEBOOK_INIT_SCROLL_DELAY, 
1047                      (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1048                   notebook->need_timer = TRUE;
1049                 }
1050             }
1051           else if (event->button == 2)
1052             gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1053           else if (event->button == 3)
1054             gtk_notebook_switch_focus_tab (notebook,
1055                                            gtk_notebook_search_page (notebook,
1056                                                                      NULL,
1057                                                                      STEP_NEXT,
1058                                                                      TRUE));
1059           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1060         }
1061       else
1062         {
1063           notebook->click_child = GTK_ARROW_RIGHT;
1064           if (event->button == 1)
1065             {
1066               if (!notebook->focus_tab ||
1067                   gtk_notebook_search_page (notebook, notebook->focus_tab,
1068                                             STEP_NEXT, TRUE))
1069                 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1070
1071               if (!notebook->timer)
1072                 {
1073                   notebook->timer = gtk_timeout_add 
1074                     (NOTEBOOK_INIT_SCROLL_DELAY, 
1075                      (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1076                   notebook->need_timer = TRUE;
1077                 }
1078             }      
1079           else if (event->button == 2)
1080             gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1081           else if (event->button == 3)
1082             gtk_notebook_switch_focus_tab
1083               (notebook, gtk_notebook_search_page (notebook, NULL,
1084                                                    STEP_PREV, TRUE));
1085           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1086         }
1087     }
1088   else if (event->window == widget->window)
1089     {
1090       if (event->button == 3 && notebook->menu)
1091         {
1092           gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL, 
1093                           NULL, NULL, 3, event->time);
1094           return FALSE;
1095         }
1096
1097       num = 0;
1098       children = notebook->children;
1099       while (children)
1100         {
1101           page = children->data;
1102           
1103           if (GTK_WIDGET_VISIBLE (page->child) &&
1104               page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1105               (event->x >= page->allocation.x) &&
1106               (event->y >= page->allocation.y) &&
1107               (event->x <= (page->allocation.x + page->allocation.width)) &&
1108               (event->y <= (page->allocation.y + page->allocation.height)))
1109             {
1110               if (page == notebook->cur_page && notebook->focus_tab &&
1111                   notebook->focus_tab != children &&
1112                   GTK_WIDGET_HAS_FOCUS (notebook))
1113                 {
1114                   GtkNotebookPage *old_page;
1115
1116                   notebook->child_has_focus = FALSE;
1117                   old_page = (GtkNotebookPage *)
1118                               (notebook->focus_tab->data);
1119                   gtk_notebook_switch_focus_tab (notebook, children);
1120                   gtk_notebook_focus_changed (notebook, old_page);
1121                 }
1122               else
1123                 {
1124                   gtk_notebook_switch_focus_tab (notebook, children);
1125                   gtk_widget_grab_focus (widget);
1126                   gtk_notebook_switch_page (notebook, page, num);
1127                 }
1128               break;
1129             }
1130           children = children->next;
1131           num++;
1132         }
1133       if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1134         gtk_widget_grab_focus (widget);
1135     }
1136    gtk_notebook_set_shape (notebook);
1137   return FALSE;
1138 }
1139
1140 static gint
1141 gtk_notebook_button_release (GtkWidget      *widget,
1142                              GdkEventButton *event)
1143 {
1144   GtkNotebook *notebook;
1145
1146   g_return_val_if_fail (widget != NULL, FALSE);
1147   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1148   g_return_val_if_fail (event != NULL, FALSE);
1149
1150   if (event->type != GDK_BUTTON_RELEASE)
1151     return FALSE;
1152
1153   notebook = GTK_NOTEBOOK (widget);
1154
1155   if (event->button == notebook->button)
1156     {
1157       guint click_child;
1158
1159       if (notebook->timer)
1160         {
1161           gtk_timeout_remove (notebook->timer);
1162           notebook->timer = 0;
1163           notebook->need_timer = FALSE;
1164         }
1165       gtk_grab_remove (widget);
1166       click_child = notebook->click_child;
1167       notebook->click_child = 0;
1168       notebook->button = 0;
1169       gtk_notebook_draw_arrow (notebook, click_child);
1170       
1171     }
1172   return FALSE;
1173 }
1174
1175 static gint
1176 gtk_notebook_enter_notify (GtkWidget        *widget,
1177                            GdkEventCrossing *event)
1178 {
1179   GtkNotebook *notebook;
1180
1181   g_return_val_if_fail (widget != NULL, FALSE);
1182   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1183   g_return_val_if_fail (event != NULL, FALSE);
1184
1185   notebook = GTK_NOTEBOOK (widget);
1186
1187   if (event->window == notebook->panel)
1188     {
1189       gint x;
1190       gint y;
1191
1192       gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1193
1194       if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1195         {
1196           notebook->in_child = GTK_ARROW_LEFT;
1197
1198           if (notebook->click_child == 0) 
1199             gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1200         }
1201       else 
1202         {
1203           notebook->in_child = GTK_ARROW_RIGHT;
1204
1205           if (notebook->click_child == 0) 
1206             gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1207         }
1208     }
1209
1210   return FALSE;
1211 }
1212
1213 static gint
1214 gtk_notebook_leave_notify (GtkWidget        *widget,
1215                            GdkEventCrossing *event)
1216 {
1217   GtkNotebook *notebook;
1218
1219   g_return_val_if_fail (widget != NULL, FALSE);
1220   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1221   g_return_val_if_fail (event != NULL, FALSE);
1222
1223   notebook = GTK_NOTEBOOK (widget);
1224
1225   if (event->window == notebook->panel && !notebook->click_child)
1226     {
1227       if (notebook->in_child == GTK_ARROW_LEFT)
1228         {
1229           notebook->in_child = 0;
1230           gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1231         }
1232       else
1233         {
1234           notebook->in_child = 0;
1235           gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1236         }
1237     }
1238   return FALSE;
1239 }
1240
1241 static gint
1242 gtk_notebook_motion_notify (GtkWidget      *widget,
1243                             GdkEventMotion *event)
1244 {
1245   GtkNotebook *notebook;
1246
1247   g_return_val_if_fail (widget != NULL, FALSE);
1248   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1249   g_return_val_if_fail (event != NULL, FALSE);
1250
1251   notebook = GTK_NOTEBOOK (widget);
1252   
1253   if (notebook->button)
1254     return FALSE;
1255
1256   if (event->window == notebook->panel)
1257     {
1258       gint x;
1259       
1260       x = event->x;
1261       if (event->is_hint)
1262         gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1263
1264       if (x <= ARROW_SIZE + ARROW_SPACING / 2 && 
1265           notebook->in_child == GTK_ARROW_RIGHT)
1266         {
1267           notebook->in_child = GTK_ARROW_LEFT;
1268           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1269           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1270         }
1271       else if (x > ARROW_SIZE + ARROW_SPACING / 2 && 
1272                notebook->in_child == GTK_ARROW_LEFT)
1273         {
1274           notebook->in_child = GTK_ARROW_RIGHT;
1275           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1276           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1277         }
1278       return FALSE;
1279     }
1280   return FALSE;
1281 }
1282
1283 static gint
1284 gtk_notebook_key_press (GtkWidget   *widget,
1285                         GdkEventKey *event)
1286 {
1287   GtkNotebook *notebook;
1288   GtkDirectionType direction = 0;
1289   GList *list;
1290
1291   g_return_val_if_fail (widget != NULL, FALSE);
1292   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1293   g_return_val_if_fail (event != NULL, FALSE);
1294
1295   notebook = GTK_NOTEBOOK (widget);
1296
1297   if (!notebook->children || !notebook->show_tabs)
1298     return FALSE;
1299
1300   switch (event->keyval)
1301     {
1302     case GDK_Up:
1303       switch (notebook->tab_pos)
1304         {
1305         case GTK_POS_BOTTOM:
1306           gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1307           return TRUE;
1308         case GTK_POS_TOP:
1309           return FALSE;
1310         default:
1311           direction = GTK_DIR_UP;
1312           break;
1313         }
1314       break;
1315     case GDK_Left:
1316       switch (notebook->tab_pos)
1317         {
1318         case GTK_POS_RIGHT:
1319           gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1320           return TRUE;
1321         case GTK_POS_LEFT:
1322           return FALSE;
1323         default:
1324           direction = GTK_DIR_LEFT;
1325           break;
1326         }
1327       break;
1328     case GDK_Down:
1329       switch (notebook->tab_pos)
1330         {
1331         case GTK_POS_TOP:
1332           gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1333           return TRUE;
1334         case GTK_POS_BOTTOM:
1335           return FALSE;
1336         default:
1337           direction = GTK_DIR_DOWN;
1338           break;
1339         }
1340       break;
1341     case GDK_Right:
1342       switch (notebook->tab_pos)
1343         {
1344         case GTK_POS_LEFT:
1345           gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1346           return TRUE;
1347         case GTK_POS_RIGHT:
1348           return FALSE;
1349         default:
1350           direction = GTK_DIR_RIGHT;
1351           break;
1352         }
1353       break;
1354     case GDK_Tab:
1355     case GDK_ISO_Left_Tab:
1356       if (event->state & GDK_SHIFT_MASK)
1357         direction = GTK_DIR_TAB_BACKWARD;
1358       else
1359         direction = GTK_DIR_TAB_FORWARD;
1360       break;
1361     case GDK_Home:
1362       list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1363       if (list)
1364         gtk_notebook_switch_focus_tab (notebook, list);
1365       return TRUE;
1366     case GDK_End:
1367       list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
1368       if (list)
1369         gtk_notebook_switch_focus_tab (notebook, list);
1370       return TRUE;
1371     case GDK_Return:
1372     case GDK_space:
1373       gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1374       return TRUE;
1375     default:
1376       return FALSE;
1377     }
1378   return gtk_container_focus (GTK_CONTAINER (widget), direction);
1379 }
1380
1381 static gint
1382 gtk_notebook_focus_in (GtkWidget     *widget,
1383                        GdkEventFocus *event)
1384 {
1385   g_return_val_if_fail (widget != NULL, FALSE);
1386   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1387   g_return_val_if_fail (event != NULL, FALSE);
1388
1389   GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1390   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1391   gtk_widget_draw_focus (widget);
1392
1393   return FALSE;
1394 }
1395
1396 static gint
1397 gtk_notebook_focus_out (GtkWidget     *widget,
1398                         GdkEventFocus *event)
1399 {
1400   g_return_val_if_fail (widget != NULL, FALSE);
1401   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1402   g_return_val_if_fail (event != NULL, FALSE);
1403
1404   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1405   gtk_widget_draw_focus (widget);
1406
1407   return FALSE;
1408 }
1409
1410 static void
1411 gtk_notebook_draw_focus (GtkWidget *widget)
1412 {
1413   GtkNotebook *notebook;
1414
1415   g_return_if_fail (widget != NULL);
1416   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1417
1418   notebook = GTK_NOTEBOOK (widget);
1419
1420   if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1421       notebook->focus_tab)
1422     {
1423       GtkNotebookPage *page;
1424       GdkRectangle area;
1425
1426       page = notebook->focus_tab->data;
1427
1428       area.x = page->tab_label->allocation.x - 1;
1429       area.y = page->tab_label->allocation.y - 1;
1430       area.width = page->tab_label->allocation.width + 2;
1431       area.height = page->tab_label->allocation.height + 2;
1432
1433       gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1434     }
1435 }
1436
1437 static void
1438 gtk_notebook_style_set (GtkWidget *widget,
1439                         GtkStyle  *previous_style)
1440 {
1441   if (GTK_WIDGET_REALIZED (widget) &&
1442       !GTK_WIDGET_NO_WINDOW (widget))
1443     {
1444       gtk_style_set_background (widget->style, widget->window, widget->state);
1445       if (GTK_WIDGET_DRAWABLE (widget))
1446         gdk_window_clear (widget->window);
1447     }
1448
1449   gtk_notebook_set_shape (GTK_NOTEBOOK(widget));
1450 }
1451
1452 /* Private GtkContainer Methods :
1453  * 
1454  * gtk_notebook_set_child_arg
1455  * gtk_notebook_get_child_arg
1456  * gtk_notebook_add
1457  * gtk_notebook_remove
1458  * gtk_notebook_focus
1459  * gtk_notebook_set_focus_child
1460  * gtk_notebook_child_type
1461  * gtk_notebook_forall
1462  */
1463 static void
1464 gtk_notebook_set_child_arg (GtkContainer     *container,
1465                             GtkWidget        *child,
1466                             GtkArg           *arg,
1467                             guint             arg_id)
1468 {
1469   gboolean expand;
1470   gboolean fill;
1471   GtkPackType pack_type;
1472
1473   switch (arg_id)
1474     {
1475     case CHILD_ARG_TAB_LABEL:
1476       /* a NULL pointer indicates a default_tab setting, otherwise
1477        * we need to set the associated label
1478        */
1479       gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1480                                        GTK_VALUE_STRING(*arg));
1481       break;
1482     case CHILD_ARG_MENU_LABEL:
1483       gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1484                                         GTK_VALUE_STRING (*arg));
1485       break;
1486     case CHILD_ARG_POSITION:
1487       gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1488                                   GTK_VALUE_INT (*arg));
1489       break;
1490     case CHILD_ARG_TAB_EXPAND:
1491       gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1492                                             &expand, &fill, &pack_type);
1493       gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1494                                           GTK_VALUE_BOOL (*arg),
1495                                           fill, pack_type);
1496       break;
1497     case CHILD_ARG_TAB_FILL:
1498       gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1499                                             &expand, &fill, &pack_type);
1500       gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1501                                           expand,
1502                                           GTK_VALUE_BOOL (*arg),
1503                                           pack_type);
1504       break;
1505     case CHILD_ARG_TAB_PACK:
1506       gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1507                                             &expand, &fill, &pack_type);
1508       gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1509                                           expand, fill,
1510                                           GTK_VALUE_BOOL (*arg));
1511       break;
1512     default:
1513       break;
1514     }
1515 }
1516
1517 static void
1518 gtk_notebook_get_child_arg (GtkContainer     *container,
1519                             GtkWidget        *child,
1520                             GtkArg           *arg,
1521                             guint             arg_id)
1522 {
1523   GList *list;
1524   GtkNotebook *notebook;
1525   GtkWidget *label;
1526   gboolean expand;
1527   gboolean fill;
1528   GtkPackType pack_type;
1529
1530   notebook = GTK_NOTEBOOK (container);
1531
1532   if (!(list = g_list_find_custom (notebook->children, child,
1533                                    gtk_notebook_page_compare)))
1534     {
1535       arg->type = GTK_TYPE_INVALID;
1536       return;
1537     }
1538
1539   switch (arg_id)
1540     {
1541     case CHILD_ARG_TAB_LABEL:
1542       label = gtk_notebook_get_tab_label (notebook, child);
1543
1544       if (label && GTK_IS_LABEL (label))
1545         GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
1546       else
1547         GTK_VALUE_STRING (*arg) = NULL;
1548       break;
1549     case CHILD_ARG_MENU_LABEL:
1550       label = gtk_notebook_get_menu_label (notebook, child);
1551
1552       if (label && GTK_IS_LABEL (label))
1553         GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
1554       else
1555         GTK_VALUE_STRING (*arg) = NULL;
1556       break;
1557     case CHILD_ARG_POSITION:
1558       GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
1559       break;
1560     case CHILD_ARG_TAB_EXPAND:
1561         gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1562                                               &expand, NULL, NULL);
1563         GTK_VALUE_BOOL (*arg) = expand;
1564       break;
1565     case CHILD_ARG_TAB_FILL:
1566         gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1567                                               NULL, &fill, NULL);
1568         GTK_VALUE_BOOL (*arg) = fill;
1569       break;
1570     case CHILD_ARG_TAB_PACK:
1571         gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1572                                               NULL, NULL, &pack_type);
1573         GTK_VALUE_BOOL (*arg) = pack_type;
1574       break;
1575     default:
1576       arg->type = GTK_TYPE_INVALID;
1577       break;
1578     }
1579 }
1580
1581 static void
1582 gtk_notebook_add (GtkContainer *container,
1583                   GtkWidget    *widget)
1584 {
1585   g_return_if_fail (container != NULL);
1586   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1587
1588   gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget, 
1589                                  NULL, NULL, -1);
1590 }
1591
1592 static void
1593 gtk_notebook_remove (GtkContainer *container,
1594                      GtkWidget    *widget)
1595 {
1596   GtkNotebook *notebook;
1597   GtkNotebookPage *page;
1598   GList *children;
1599   guint page_num;
1600
1601   g_return_if_fail (container != NULL);
1602   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1603   g_return_if_fail (widget != NULL);
1604
1605   notebook = GTK_NOTEBOOK (container);
1606
1607   children = notebook->children;
1608   page_num = 0;
1609   while (children)
1610     {
1611       page = children->data;
1612       if (page->child == widget)
1613         {
1614           gtk_notebook_real_remove (notebook, children);
1615           break;
1616         }
1617       page_num++;
1618       children = children->next;
1619     }
1620 }
1621
1622 static gint
1623 gtk_notebook_focus (GtkContainer     *container,
1624                     GtkDirectionType  direction)
1625 {
1626   GtkNotebook *notebook;
1627   GtkNotebookPage *page = NULL;
1628   GtkNotebookPage *old_page = NULL;
1629
1630   g_return_val_if_fail (container != NULL, FALSE);
1631   g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
1632
1633   notebook = GTK_NOTEBOOK (container);
1634
1635   if (!GTK_WIDGET_DRAWABLE (notebook) ||
1636       !GTK_WIDGET_IS_SENSITIVE (container) ||
1637       !notebook->children ||
1638       !notebook->cur_page)
1639     return FALSE;
1640
1641   if (!notebook->show_tabs)
1642     {
1643       if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) &&
1644           GTK_WIDGET_IS_SENSITIVE (notebook->cur_page->child))
1645         {
1646           if (GTK_IS_CONTAINER (notebook->cur_page->child))
1647             {
1648               if (gtk_container_focus
1649                   (GTK_CONTAINER (notebook->cur_page->child), direction))
1650                 return TRUE;
1651             }
1652           else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
1653             {
1654               if (!container->focus_child)
1655                 {
1656                   gtk_widget_grab_focus (notebook->cur_page->child);
1657                   return TRUE;
1658                 }
1659             }
1660         }
1661       return FALSE;
1662     }
1663
1664   if (notebook->focus_tab)
1665     old_page = notebook->focus_tab->data;
1666
1667   if (container->focus_child && old_page &&
1668       container->focus_child == old_page->child && notebook->child_has_focus)
1669     {
1670       if (GTK_WIDGET_DRAWABLE (container->focus_child))
1671         {
1672           if (GTK_IS_CONTAINER (container->focus_child) &&
1673               !GTK_WIDGET_HAS_FOCUS (container->focus_child))
1674             {
1675               if (gtk_container_focus (GTK_CONTAINER (container->focus_child),
1676                                        direction))
1677                 return TRUE;
1678             }
1679           gtk_widget_grab_focus (GTK_WIDGET(notebook));
1680           return TRUE;
1681         }
1682       notebook->focus_tab = NULL;
1683       return FALSE;
1684     }
1685
1686   if (!GTK_WIDGET_HAS_FOCUS (container))
1687     notebook->focus_tab = NULL;
1688
1689   switch (direction)
1690     {
1691     case GTK_DIR_TAB_FORWARD:
1692     case GTK_DIR_RIGHT:
1693     case GTK_DIR_DOWN:
1694       gtk_notebook_switch_focus_tab
1695         (notebook, gtk_notebook_search_page (notebook, notebook->focus_tab,
1696                                              STEP_NEXT, TRUE));
1697       break;
1698     case GTK_DIR_TAB_BACKWARD:
1699     case GTK_DIR_LEFT:
1700     case GTK_DIR_UP:
1701       gtk_notebook_switch_focus_tab
1702         (notebook, gtk_notebook_search_page (notebook, notebook->focus_tab,
1703                                              STEP_PREV, TRUE));
1704       break;
1705     }
1706
1707   if (notebook->focus_tab)
1708     {
1709       if (!GTK_WIDGET_HAS_FOCUS (container))
1710         gtk_widget_grab_focus (GTK_WIDGET (container));
1711
1712       page = notebook->focus_tab->data;
1713       if (GTK_WIDGET_MAPPED (page->tab_label))
1714         gtk_notebook_focus_changed (notebook, old_page);
1715       else
1716         {
1717           gtk_notebook_pages_allocate (notebook, 
1718                                        &(GTK_WIDGET (notebook)->allocation));
1719           gtk_notebook_expose_tabs (notebook);
1720         }
1721       return TRUE;
1722     }
1723
1724   gtk_notebook_focus_changed (notebook, old_page);
1725   return FALSE;
1726 }
1727
1728 static void
1729 gtk_notebook_set_focus_child (GtkContainer *container,
1730                               GtkWidget    *child)
1731 {
1732   GtkNotebook *notebook;
1733
1734   g_return_if_fail (container != NULL);
1735   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1736   
1737   if (child)
1738     {
1739       g_return_if_fail (GTK_IS_WIDGET (child));
1740
1741       notebook = GTK_NOTEBOOK (container);
1742
1743       notebook->child_has_focus = TRUE;
1744       if (!notebook->focus_tab)
1745         {
1746           GList *children;
1747           GtkNotebookPage *page;
1748
1749           children = notebook->children;
1750           while (children)
1751             {
1752               page = children->data;
1753               if (page->child == child || page->tab_label == child)
1754                 gtk_notebook_switch_focus_tab (notebook, children);
1755               children = children->next;
1756             }
1757         }
1758     }
1759   parent_class->set_focus_child (container, child);
1760 }
1761
1762 static void
1763 gtk_notebook_forall (GtkContainer *container,
1764                      gboolean      include_internals,
1765                      GtkCallback   callback,
1766                      gpointer      callback_data)
1767 {
1768   GtkNotebook *notebook;
1769   GList *children;
1770
1771   g_return_if_fail (container != NULL);
1772   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1773   g_return_if_fail (callback != NULL);
1774
1775   notebook = GTK_NOTEBOOK (container);
1776
1777   children = notebook->children;
1778   while (children)
1779     {
1780       GtkNotebookPage *page;
1781       
1782       page = children->data;
1783       children = children->next;
1784       (* callback) (page->child, callback_data);
1785       if (include_internals)
1786         {
1787           if (page->tab_label)
1788             (* callback) (page->tab_label, callback_data);
1789           if (page->menu_label)
1790             (* callback) (page->menu_label, callback_data);
1791         }
1792     }
1793 }
1794
1795 static GtkType
1796 gtk_notebook_child_type (GtkContainer     *container)
1797 {
1798   return GTK_TYPE_WIDGET;
1799 }
1800
1801 /* Private GtkNotebook Functions:
1802  *
1803  * gtk_notebook_panel_realize
1804  * gtk_notebook_expose_tabs
1805  * gtk_notebook_focus_changed
1806  * gtk_notebook_real_remove
1807  * gtk_notebook_update_labels
1808  * gtk_notebook_timer
1809  * gtk_notebook_page_compare
1810  * gtk_notebook_real_page_position
1811  * gtk_notebook_search_page
1812  */
1813 static void
1814 gtk_notebook_panel_realize (GtkNotebook *notebook)
1815 {
1816   GtkWidget *widget;
1817   GdkWindowAttr attributes;
1818   gint attributes_mask;
1819   
1820   g_return_if_fail (notebook != NULL);
1821   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1822   
1823   widget = GTK_WIDGET (notebook);
1824   
1825   attributes.window_type = GDK_WINDOW_CHILD;
1826   attributes.wclass = GDK_INPUT_OUTPUT;
1827   attributes.visual = gtk_widget_get_visual (widget);
1828   attributes.colormap = gtk_widget_get_colormap (widget);
1829   attributes.event_mask = gtk_widget_get_events (widget);
1830   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK 
1831     | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1832     | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1833   
1834   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1835
1836   attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1837   attributes.height = ARROW_SIZE;
1838
1839   attributes.x = (widget->allocation.width - attributes.width - 
1840                   GTK_CONTAINER (notebook)->border_width);
1841   attributes.y = (widget->allocation.height - ARROW_SIZE -
1842                   GTK_CONTAINER (notebook)->border_width);
1843   if (notebook->tab_pos == GTK_POS_TOP)
1844     attributes.y = GTK_CONTAINER (notebook)->border_width;
1845   else if (notebook->tab_pos == GTK_POS_LEFT)
1846     attributes.x = (widget->allocation.x +
1847                     GTK_CONTAINER (notebook)->border_width);
1848
1849   notebook->panel = gdk_window_new (widget->window, &attributes, 
1850                                     attributes_mask);
1851   gtk_style_set_background (widget->style, notebook->panel, 
1852                             GTK_STATE_NORMAL);
1853   gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
1854   gdk_window_set_user_data (notebook->panel, widget);
1855 }
1856
1857 static void
1858 gtk_notebook_expose_tabs (GtkNotebook *notebook)
1859 {
1860   GtkWidget *widget;
1861   GtkNotebookPage *page;
1862   GdkEventExpose event;
1863   gint border;
1864
1865   widget = GTK_WIDGET (notebook);
1866   border = GTK_CONTAINER (notebook)->border_width;
1867
1868   if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
1869     return;
1870
1871   page = notebook->first_tab->data;
1872
1873   event.type = GDK_EXPOSE;
1874   event.window = widget->window;
1875   event.count = 0;
1876   event.area.x = border;
1877   event.area.y = border;
1878
1879   switch (notebook->tab_pos)
1880     {
1881     case GTK_POS_BOTTOM:
1882       event.area.y = (widget->allocation.height - border -
1883                       page->allocation.height -
1884                       widget->style->klass->ythickness);
1885       if (page != notebook->cur_page)
1886         event.area.y -= widget->style->klass->ythickness;
1887     case GTK_POS_TOP:
1888       event.area.width = widget->allocation.width - 2 * border;
1889       event.area.height = (page->allocation.height +
1890                            widget->style->klass->ythickness);
1891       if (page != notebook->cur_page)
1892         event.area.height += widget->style->klass->ythickness;
1893       break;
1894     case GTK_POS_RIGHT:
1895       event.area.x = (widget->allocation.width - border -
1896                       page->allocation.width -
1897                       widget->style->klass->xthickness);
1898       if (page != notebook->cur_page)
1899         event.area.x -= widget->style->klass->xthickness;
1900     case GTK_POS_LEFT:
1901       event.area.width = (page->allocation.width +
1902                           widget->style->klass->xthickness);
1903       event.area.height = widget->allocation.height - 2 * border;
1904       if (page != notebook->cur_page)
1905         event.area.width += widget->style->klass->xthickness;
1906       break;
1907     }        
1908   gtk_widget_event (widget, (GdkEvent *) &event);
1909 }
1910
1911 static void
1912 gtk_notebook_focus_changed (GtkNotebook     *notebook,
1913                             GtkNotebookPage *old_page)
1914 {
1915   g_return_if_fail (notebook != NULL);
1916   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1917
1918   if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs) 
1919     {
1920       GdkRectangle area;
1921
1922       if (notebook->focus_tab)
1923         {
1924           GtkNotebookPage *page;
1925
1926           page = notebook->focus_tab->data;
1927
1928           area.x = page->tab_label->allocation.x - 1;
1929           area.y = page->tab_label->allocation.y - 1;
1930           area.width = page->tab_label->allocation.width + 2;
1931           area.height = page->tab_label->allocation.height + 2;
1932
1933           gtk_notebook_draw_tab (notebook, page, &area);
1934         }
1935
1936       if (old_page)
1937         {
1938           area.x = old_page->tab_label->allocation.x - 1;
1939           area.y = old_page->tab_label->allocation.y - 1;
1940           area.width = old_page->tab_label->allocation.width + 2;
1941           area.height = old_page->tab_label->allocation.height + 2;
1942
1943           gtk_notebook_draw_tab (notebook, old_page, &area);
1944         }
1945     }
1946 }
1947
1948 static gint
1949 gtk_notebook_timer (GtkNotebook *notebook)
1950 {
1951   gboolean retval = FALSE;
1952
1953   GDK_THREADS_ENTER ();
1954   
1955   if (notebook->timer)
1956     {
1957       if (notebook->click_child == GTK_ARROW_LEFT)
1958         {
1959           if (!notebook->focus_tab ||
1960               gtk_notebook_search_page (notebook, notebook->focus_tab,
1961                                         STEP_PREV, TRUE))
1962             gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1963         }
1964       else if (notebook->click_child == GTK_ARROW_RIGHT)
1965         {
1966           if (!notebook->focus_tab ||
1967               gtk_notebook_search_page (notebook, notebook->focus_tab,
1968                                         STEP_NEXT, TRUE))
1969             gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1970         }
1971       if (notebook->need_timer) 
1972         {
1973           notebook->need_timer = FALSE;
1974           notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
1975                                              (GtkFunction) gtk_notebook_timer, 
1976                                              (gpointer) notebook);
1977         }
1978       else
1979         retval = TRUE;
1980     }
1981
1982   GDK_THREADS_LEAVE ();
1983
1984   return retval;
1985 }
1986
1987 static gint
1988 gtk_notebook_page_compare (gconstpointer a,
1989                            gconstpointer b)
1990 {
1991   return (((GtkNotebookPage *) a)->child != b);
1992 }
1993
1994 static void
1995 gtk_notebook_real_remove (GtkNotebook *notebook,
1996                           GList       *list)
1997 {
1998   GtkNotebookPage *page;
1999   GList * next_list;
2000   gint need_resize = FALSE;
2001
2002   next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2003   if (!next_list)
2004     next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2005
2006   if (notebook->cur_page == list->data)
2007     { 
2008       notebook->cur_page = NULL;
2009       if (next_list)
2010         gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2011     }
2012
2013   if (list == notebook->first_tab)
2014     notebook->first_tab = next_list;
2015   if (list == notebook->focus_tab)
2016     gtk_notebook_switch_focus_tab (notebook, next_list);
2017
2018   page = list->data;
2019
2020   if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2021     need_resize = TRUE;
2022
2023   gtk_widget_unparent (page->child);
2024
2025   if (page->tab_label)
2026     gtk_widget_unparent (page->tab_label);
2027
2028   if (notebook->menu)
2029     {
2030       gtk_container_remove (GTK_CONTAINER (notebook->menu), 
2031                             page->menu_label->parent);
2032       gtk_widget_queue_resize (notebook->menu);
2033     }
2034   if (!page->default_menu)
2035     gtk_widget_unref (page->menu_label);
2036   
2037   notebook->children = g_list_remove_link (notebook->children, list);
2038   g_list_free (list);
2039   g_free (page);
2040
2041   gtk_notebook_update_labels (notebook);
2042   if (need_resize)
2043     gtk_widget_queue_resize (GTK_WIDGET (notebook));
2044 }
2045
2046 static void
2047 gtk_notebook_update_labels (GtkNotebook *notebook)
2048 {
2049   GtkNotebookPage *page;
2050   GList *list;
2051   gchar string[32];
2052   gint page_num = 1;
2053
2054   for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2055        list;
2056        list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2057     {
2058       page = list->data;
2059       g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2060       if (notebook->show_tabs)
2061         {
2062           if (page->default_tab)
2063             {
2064               if (!page->tab_label)
2065                 {
2066                   page->tab_label = gtk_label_new (string);
2067                   gtk_widget_set_parent (page->tab_label,
2068                                          GTK_WIDGET (notebook));
2069                 }
2070               else
2071                 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2072             }
2073
2074           if (GTK_WIDGET_VISIBLE (page->child) &&
2075               !GTK_WIDGET_VISIBLE (page->tab_label))
2076             gtk_widget_show (page->tab_label);
2077           else if (!GTK_WIDGET_VISIBLE (page->child) &&
2078                    GTK_WIDGET_VISIBLE (page->tab_label))
2079             gtk_widget_hide (page->tab_label);
2080         }
2081       if (notebook->menu && page->default_menu)
2082         {
2083           if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2084             gtk_label_set_text (GTK_LABEL (page->menu_label),
2085                            GTK_LABEL (page->tab_label)->label);
2086           else
2087             gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2088         }
2089     }  
2090 }
2091
2092 static gint
2093 gtk_notebook_real_page_position (GtkNotebook *notebook,
2094                                  GList       *list)
2095 {
2096   GList *work;
2097   gint count_start;
2098
2099   g_return_val_if_fail (notebook != NULL, -1);
2100   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2101   g_return_val_if_fail (list != NULL, -1);
2102
2103   for (work = notebook->children, count_start = 0;
2104        work && work != list; work = work->next)
2105     if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2106       count_start++;
2107
2108   if (!work)
2109     return -1;
2110
2111   if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2112     return count_start;
2113
2114   return (count_start + g_list_length (list) - 1);
2115 }
2116
2117 static GList *
2118 gtk_notebook_search_page (GtkNotebook *notebook,
2119                           GList       *list,
2120                           gint         direction,
2121                           gboolean     find_visible)
2122 {
2123   GtkNotebookPage *page = NULL;
2124   GList *old_list = NULL;
2125   gint flag = 0;
2126
2127   g_return_val_if_fail (notebook != NULL, NULL);
2128   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2129
2130   switch (direction)
2131     {
2132     case STEP_PREV:
2133       flag = GTK_PACK_END;
2134       break;
2135
2136     case STEP_NEXT:
2137       flag = GTK_PACK_START;
2138       break;
2139     }
2140
2141   if (list)
2142     page = list->data;
2143
2144   if (!page || page->pack == flag)
2145     {
2146       if (list)
2147         {
2148           old_list = list;
2149           list = list->next;
2150         }
2151       else
2152         list = notebook->children;
2153
2154       while (list)
2155         {
2156           page = list->data;
2157           if (page->pack == flag &&
2158               (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2159             return list;
2160           old_list = list;
2161           list = list->next;
2162         }
2163       list = old_list;
2164     }
2165   else
2166     {
2167       old_list = list;
2168       list = list->prev;
2169     }
2170   while (list)
2171     {
2172       page = list->data;
2173       if (page->pack != flag &&
2174           (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2175         return list;
2176       old_list = list;
2177       list = list->prev;
2178     }
2179   return NULL;
2180 }
2181
2182 /* Private GtkNotebook Drawing Functions:
2183  *
2184  * gtk_notebook_paint
2185  * gtk_notebook_draw_tab
2186  * gtk_notebook_draw_arrow
2187  * gtk_notebook_set_shape
2188  */
2189 static void
2190 gtk_notebook_paint (GtkWidget    *widget,
2191                     GdkRectangle *area)
2192 {
2193   GtkNotebook *notebook;
2194   GtkNotebookPage *page;
2195   GList *children;
2196   gboolean showarrow;
2197   gint width, height;
2198   gint x, y;
2199   gint gap_x = 0, gap_width = 0;
2200    
2201   g_return_if_fail (widget != NULL);
2202   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2203   g_return_if_fail (area != NULL);
2204
2205   if (!GTK_WIDGET_DRAWABLE (widget))
2206     return;
2207
2208   notebook = GTK_NOTEBOOK (widget);
2209
2210   if ((!notebook->show_tabs && !notebook->show_border) ||
2211       !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2212     {
2213       gdk_window_clear_area (widget->window,
2214                              area->x, area->y,
2215                              area->width, area->height);
2216       return;
2217     }
2218
2219   x = GTK_CONTAINER (widget)->border_width;
2220   y = GTK_CONTAINER (widget)->border_width;
2221   width = widget->allocation.width - x * 2;
2222   height = widget->allocation.height - y * 2;
2223
2224   if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2225     {
2226       gtk_paint_box (widget->style, widget->window,
2227                      GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2228                      area, widget, "notebook",
2229                      x, y, width, height);
2230       return;
2231     }
2232
2233
2234   if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2235     {
2236       page = notebook->first_tab->data;
2237
2238       switch (notebook->tab_pos)
2239         {
2240         case GTK_POS_TOP:
2241           y += page->allocation.height + widget->style->klass->ythickness;
2242         case GTK_POS_BOTTOM:
2243           height -= page->allocation.height + widget->style->klass->ythickness;
2244           break;
2245         case GTK_POS_LEFT:
2246           x += page->allocation.width + widget->style->klass->xthickness;
2247         case GTK_POS_RIGHT:
2248           width -= page->allocation.width + widget->style->klass->xthickness;
2249           break;
2250         }
2251       gtk_paint_box (widget->style, widget->window,
2252                      GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2253                      area, widget, "notebook",
2254                      x, y, width, height);
2255     }
2256   else
2257     {
2258       switch (notebook->tab_pos)
2259         {
2260         case GTK_POS_TOP:
2261           y += notebook->cur_page->allocation.height;
2262         case GTK_POS_BOTTOM:
2263           height -= notebook->cur_page->allocation.height;
2264           break;
2265         case GTK_POS_LEFT:
2266           x += notebook->cur_page->allocation.width;
2267         case GTK_POS_RIGHT:
2268           width -= notebook->cur_page->allocation.width;
2269           break;
2270         }
2271
2272       switch (notebook->tab_pos)
2273         {
2274         case GTK_POS_TOP:
2275           gap_x = (notebook->cur_page->allocation.x -
2276                    GTK_CONTAINER(notebook)->border_width);
2277           gap_width = notebook->cur_page->allocation.width;
2278           break;
2279         case GTK_POS_BOTTOM:
2280           gap_x = (notebook->cur_page->allocation.x -
2281                    GTK_CONTAINER(notebook)->border_width);
2282           gap_width = notebook->cur_page->allocation.width;
2283           break;
2284         case GTK_POS_LEFT:
2285           gap_x = (notebook->cur_page->allocation.y -
2286                    GTK_CONTAINER(notebook)->border_width);
2287           gap_width = notebook->cur_page->allocation.height;
2288           break;
2289         case GTK_POS_RIGHT:
2290           gap_x = (notebook->cur_page->allocation.y -
2291                    GTK_CONTAINER(notebook)->border_width);
2292           gap_width = notebook->cur_page->allocation.height;
2293           break;
2294         }
2295       gtk_paint_box_gap(widget->style, widget->window,
2296                         GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2297                         area, widget, "notebook",
2298                         x, y, width, height,
2299                         notebook->tab_pos, gap_x, gap_width);
2300     }
2301
2302   showarrow = FALSE;
2303   children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2304   while (children)
2305     {
2306       page = children->data;
2307       children = gtk_notebook_search_page (notebook, children,
2308                                            STEP_PREV, TRUE);
2309       if (!GTK_WIDGET_VISIBLE (page->child))
2310         continue;
2311       if (!GTK_WIDGET_MAPPED (page->tab_label))
2312         showarrow = TRUE;
2313       else if (page != notebook->cur_page)
2314         gtk_notebook_draw_tab (notebook, page, area);
2315     }
2316
2317   if (showarrow && notebook->scrollable) 
2318     {
2319       gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2320       gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2321     }
2322   gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2323 }
2324
2325 static void
2326 gtk_notebook_draw_tab (GtkNotebook     *notebook,
2327                        GtkNotebookPage *page,
2328                        GdkRectangle    *area)
2329 {
2330   GdkRectangle child_area;
2331   GdkRectangle page_area;
2332   GtkStateType state_type;
2333   GtkPositionType gap_side;
2334   
2335   g_return_if_fail (notebook != NULL);
2336   g_return_if_fail (page != NULL);
2337   g_return_if_fail (area != NULL);
2338
2339   if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2340       (page->allocation.width == 0) || (page->allocation.height == 0))
2341     return;
2342
2343   page_area.x = page->allocation.x;
2344   page_area.y = page->allocation.y;
2345   page_area.width = page->allocation.width;
2346   page_area.height = page->allocation.height;
2347
2348   if (gdk_rectangle_intersect (&page_area, area, &child_area))
2349     {
2350       GtkWidget *widget;
2351
2352       widget = GTK_WIDGET (notebook);
2353       gap_side = 0;
2354       switch (notebook->tab_pos)
2355         {
2356         case GTK_POS_TOP:
2357           gap_side = GTK_POS_BOTTOM;
2358           break;
2359         case GTK_POS_BOTTOM:
2360           gap_side = GTK_POS_TOP;
2361           break;
2362         case GTK_POS_LEFT:
2363           gap_side = GTK_POS_RIGHT;
2364           break;
2365         case GTK_POS_RIGHT:
2366           gap_side = GTK_POS_LEFT;
2367           break;
2368         }
2369       
2370       if (notebook->cur_page == page)
2371         state_type = GTK_STATE_NORMAL;
2372       else 
2373         state_type = GTK_STATE_ACTIVE;
2374       gtk_paint_extension(widget->style, widget->window,
2375                           state_type, GTK_SHADOW_OUT,
2376                           area, widget, "tab",
2377                           page_area.x, page_area.y,
2378                           page_area.width, page_area.height,
2379                           gap_side);
2380       if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2381           notebook->focus_tab && (notebook->focus_tab->data == page))
2382         {
2383           gtk_paint_focus (widget->style, widget->window,
2384                            area, widget, "tab",
2385                            page->tab_label->allocation.x - 1,
2386                            page->tab_label->allocation.y - 1,
2387                            page->tab_label->allocation.width + 1,
2388                            page->tab_label->allocation.height + 1);
2389         }
2390       if (gtk_widget_intersect (page->tab_label, area, &child_area))
2391         gtk_widget_draw (page->tab_label, &child_area);
2392     }
2393 }
2394
2395 static void
2396 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2397                          guint        arrow)
2398 {
2399   GtkStateType state_type;
2400   GtkShadowType shadow_type;
2401   GtkWidget *widget;
2402
2403   g_return_if_fail (notebook != NULL);
2404   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2405
2406   widget = GTK_WIDGET(notebook);
2407
2408   if (GTK_WIDGET_DRAWABLE (notebook))
2409     {
2410       if (notebook->in_child == arrow)
2411         {
2412           if (notebook->click_child == arrow)
2413             state_type = GTK_STATE_ACTIVE;
2414           else
2415             state_type = GTK_STATE_PRELIGHT;
2416         }
2417       else
2418         state_type = GTK_STATE_NORMAL;
2419
2420       if (notebook->click_child == arrow)
2421         shadow_type = GTK_SHADOW_IN;
2422       else
2423         shadow_type = GTK_SHADOW_OUT;
2424
2425       if (arrow == GTK_ARROW_LEFT)
2426         {
2427           if (notebook->focus_tab &&
2428               !gtk_notebook_search_page (notebook, notebook->focus_tab,
2429                                          STEP_PREV, TRUE))
2430             {
2431               shadow_type = GTK_SHADOW_ETCHED_IN;
2432               state_type = GTK_STATE_NORMAL;
2433             }
2434
2435           if (notebook->tab_pos == GTK_POS_LEFT ||
2436               notebook->tab_pos == GTK_POS_RIGHT)
2437             arrow = GTK_ARROW_UP;
2438
2439           gdk_window_clear_area (notebook->panel, 0, 0, ARROW_SIZE, ARROW_SIZE);
2440           gtk_paint_arrow (widget->style, notebook->panel, state_type, 
2441                            shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2442                            arrow, TRUE, 
2443                            0, 0, ARROW_SIZE, ARROW_SIZE);
2444         }
2445       else
2446         {
2447           if (notebook->focus_tab &&
2448               !gtk_notebook_search_page (notebook, notebook->focus_tab,
2449                                          STEP_NEXT, TRUE))
2450             {
2451               shadow_type = GTK_SHADOW_ETCHED_IN;
2452               state_type = GTK_STATE_NORMAL;
2453             }
2454
2455           if (notebook->tab_pos == GTK_POS_LEFT ||
2456               notebook->tab_pos == GTK_POS_RIGHT)
2457             arrow = GTK_ARROW_DOWN;
2458
2459            gdk_window_clear_area(notebook->panel, ARROW_SIZE + ARROW_SPACING, 
2460                                  0, ARROW_SIZE, ARROW_SIZE);
2461            gtk_paint_arrow (widget->style, notebook->panel, state_type, 
2462                             shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2463                             arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2464                             0, ARROW_SIZE, ARROW_SIZE);
2465         }
2466     }
2467 }
2468
2469 static void
2470 gtk_notebook_set_shape (GtkNotebook *notebook)
2471 {
2472   GtkWidget       *widget = NULL;
2473   GdkPixmap       *pm = NULL;
2474   GdkGC           *pmgc = NULL;
2475   GdkColor         col;
2476   gint             x, y, width, height, w, h, depth;
2477   GtkNotebookPage *page;
2478   GList           *children;
2479
2480   if (!GTK_WIDGET(notebook)->window)
2481     return;
2482
2483   widget = GTK_WIDGET(notebook);
2484
2485   w = widget->allocation.width;
2486   h = widget->allocation.height;
2487
2488   pm = gdk_pixmap_new (widget->window, w, h, 1);
2489   pmgc = gdk_gc_new (pm);
2490
2491   /* clear the shape mask */
2492   col.pixel = 0;
2493   gdk_gc_set_foreground(pmgc, &col);
2494   gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, w, h);
2495
2496   col.pixel = 1;
2497   gdk_gc_set_foreground(pmgc, &col);
2498
2499   /* draw the shape for the notebook page itself */
2500   x = GTK_CONTAINER(notebook)->border_width;
2501   y = GTK_CONTAINER(notebook)->border_width;
2502   width = widget->allocation.width - x * 2;
2503   height = widget->allocation.height - y * 2;
2504
2505   if (notebook->show_tabs && notebook->children)
2506     {
2507       if (!(notebook->show_tabs))
2508         {
2509           page = notebook->first_tab->data;
2510           switch (notebook->tab_pos)
2511             {
2512             case GTK_POS_TOP:
2513               y += page->allocation.height +
2514                 widget->style->klass->ythickness;
2515             case GTK_POS_BOTTOM:
2516               height -= page->allocation.height +
2517                 widget->style->klass->ythickness;
2518               break;
2519             case GTK_POS_LEFT:
2520               x += page->allocation.width +
2521                 widget->style->klass->xthickness;
2522             case GTK_POS_RIGHT:
2523               width -= page->allocation.width +
2524                 widget->style->klass->xthickness;
2525               break;
2526             }
2527         }
2528       else
2529         {
2530           if (notebook->cur_page)
2531             page = notebook->cur_page;
2532           else
2533             page = notebook->children->data;
2534
2535           if (!GTK_WIDGET_MAPPED (page->tab_label))
2536             {
2537               if (notebook->tab_pos == GTK_POS_LEFT)
2538                 {
2539                   x -= widget->style->klass->xthickness * 2;
2540                   width += widget->style->klass->xthickness * 2;
2541                 }
2542               else if (notebook->tab_pos == GTK_POS_RIGHT)
2543                 width += widget->style->klass->xthickness * 2;
2544             }
2545           switch (notebook->tab_pos)
2546             {
2547             case GTK_POS_TOP:
2548               y += page->allocation.height;
2549             case GTK_POS_BOTTOM:
2550               height -= page->allocation.height;
2551               break;
2552             case GTK_POS_LEFT:
2553               x += page->allocation.width;
2554             case GTK_POS_RIGHT:
2555               width -= page->allocation.width;
2556               break;
2557             }
2558         }
2559     }
2560   gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2561
2562   /* if theres an area for scrollign arrows draw the shape for them */
2563   if (notebook->panel)
2564     {
2565       gdk_window_get_geometry(notebook->panel, &x, &y, &width, &height, &depth);
2566       gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2567     }
2568
2569   /* draw the shapes of all the children */
2570   if (notebook->show_tabs)
2571     {
2572       children = notebook->children;
2573       while (children)
2574         {
2575           page = children->data;
2576           if (GTK_WIDGET_MAPPED (page->tab_label))
2577             {
2578               x = page->allocation.x;
2579               y = page->allocation.y;
2580               width = page->allocation.width;
2581               height = page->allocation.height;
2582               gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2583             }
2584           children = children->next;
2585         }
2586     }
2587
2588   /* set the mask */
2589   gdk_window_shape_combine_mask(widget->window, pm, 0, 0);
2590   gdk_pixmap_unref(pm);
2591   gdk_gc_destroy(pmgc);
2592 }
2593
2594 /* Private GtkNotebook Size Allocate Functions:
2595  *
2596  * gtk_notebook_pages_allocate
2597  * gtk_notebook_page_allocate
2598  * gtk_notebook_calc_tabs
2599  */
2600 static void
2601 gtk_notebook_pages_allocate (GtkNotebook   *notebook,
2602                              GtkAllocation *allocation)
2603 {
2604   GtkWidget    *widget;
2605   GtkContainer *container;
2606   GtkNotebookPage *page = NULL;
2607   GtkAllocation child_allocation;
2608   GList *children = NULL;
2609   GList *last_child = NULL;
2610   gboolean showarrow = FALSE;
2611   gint tab_space = 0; 
2612   gint delta; 
2613   gint x = 0;
2614   gint y = 0;
2615   gint i;
2616   gint n = 1;
2617   gint old_fill = 0;
2618   gint new_fill = 0;
2619
2620   if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2621     return;
2622
2623   widget = GTK_WIDGET (notebook);
2624   container = GTK_CONTAINER (notebook);
2625
2626   child_allocation.x = container->border_width;
2627   child_allocation.y = container->border_width;
2628
2629   switch (notebook->tab_pos)
2630     {
2631     case GTK_POS_BOTTOM:
2632       child_allocation.y = (allocation->height -
2633                             notebook->cur_page->requisition.height -
2634                             container->border_width);
2635     case GTK_POS_TOP:
2636       child_allocation.height = notebook->cur_page->requisition.height;
2637       break;
2638     case GTK_POS_RIGHT:
2639       child_allocation.x = (allocation->width -
2640                             notebook->cur_page->requisition.width -
2641                             container->border_width);
2642     case GTK_POS_LEFT:
2643       child_allocation.width = notebook->cur_page->requisition.width;
2644       break;
2645     }
2646   
2647   if (notebook->scrollable) 
2648     {
2649       GList *focus_tab;
2650       
2651       children = notebook->children;
2652       
2653       if (notebook->focus_tab)
2654         focus_tab = notebook->focus_tab;
2655       else if (notebook->first_tab)
2656         focus_tab = notebook->first_tab;
2657       else
2658         focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2659
2660       switch (notebook->tab_pos)
2661         {
2662         case GTK_POS_TOP:
2663         case GTK_POS_BOTTOM:
2664           while (children)
2665             {
2666               page = children->data;
2667               children = children->next;
2668
2669               if (GTK_WIDGET_VISIBLE (page->child))
2670                 tab_space += page->requisition.width;
2671             }
2672           if (tab_space >
2673               allocation->width - 2 * container->border_width - TAB_OVERLAP) 
2674             {
2675               showarrow = TRUE;
2676               page = focus_tab->data; 
2677
2678               tab_space = (allocation->width - TAB_OVERLAP -
2679                            page->requisition.width -
2680                            2 * (container->border_width + ARROW_SPACING +
2681                                 ARROW_SIZE));
2682               x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2683                    container->border_width);
2684
2685               page = notebook->children->data;
2686               if (notebook->tab_pos == GTK_POS_TOP)
2687                 y = (container->border_width +
2688                      (page->requisition.height - ARROW_SIZE) / 2);
2689               else
2690                 y = (allocation->height - container->border_width - 
2691                      ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2692             }
2693           break;
2694         case GTK_POS_LEFT:
2695         case GTK_POS_RIGHT:
2696           while (children)
2697             {
2698               page = children->data;
2699               children = children->next;
2700
2701               if (GTK_WIDGET_VISIBLE (page->child))
2702                 tab_space += page->requisition.height;
2703             }
2704           if (tab_space >
2705               (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2706             {
2707               showarrow = TRUE;
2708               page = focus_tab->data; 
2709               tab_space = (allocation->height -
2710                            ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2711                            2 * container->border_width -
2712                            page->requisition.height);
2713               y = allocation->height - container->border_width - ARROW_SIZE;  
2714
2715               page = notebook->children->data;
2716               if (notebook->tab_pos == GTK_POS_LEFT)
2717                 x = (container->border_width +
2718                      (page->requisition.width -
2719                       (2 * ARROW_SIZE - ARROW_SPACING)) / 2); 
2720               else
2721                 x = (allocation->width - container->border_width -
2722                      (2 * ARROW_SIZE - ARROW_SPACING) -
2723                      (page->requisition.width -
2724                       (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2725             }
2726           break;
2727         }
2728       if (showarrow) /* first_tab <- focus_tab */
2729         { 
2730           if (tab_space <= 0)
2731             {
2732               notebook->first_tab = focus_tab;
2733               last_child = gtk_notebook_search_page (notebook, focus_tab,
2734                                                      STEP_NEXT, TRUE);
2735             }
2736           else
2737             {
2738               children = NULL;
2739               if (notebook->first_tab && notebook->first_tab != focus_tab)
2740                 {
2741                   /* Is first_tab really predecessor of focus_tab  ? */
2742                   page = notebook->first_tab->data;
2743                   if (GTK_WIDGET_VISIBLE (page->child))
2744                     for (children = focus_tab;
2745                          children && children != notebook->first_tab;
2746                          children = gtk_notebook_search_page (notebook,
2747                                                               children,
2748                                                               STEP_PREV,
2749                                                               TRUE));
2750                 }
2751               if (!children)
2752                 notebook->first_tab = focus_tab;
2753               else
2754                 gtk_notebook_calc_tabs (notebook,
2755                                         gtk_notebook_search_page (notebook,
2756                                                                   focus_tab,
2757                                                                   STEP_PREV,
2758                                                                   TRUE), 
2759                                         &(notebook->first_tab), &tab_space,
2760                                         STEP_PREV);
2761
2762               if (tab_space <= 0)
2763                 {
2764                   notebook->first_tab =
2765                     gtk_notebook_search_page (notebook, notebook->first_tab,
2766                                               STEP_NEXT, TRUE);
2767                   if (!notebook->first_tab)
2768                     notebook->first_tab = focus_tab;
2769                   last_child = gtk_notebook_search_page (notebook, focus_tab,
2770                                                          STEP_NEXT, TRUE); 
2771                 }
2772               else /* focus_tab -> end */   
2773                 {
2774                   if (!notebook->first_tab)
2775                     notebook->first_tab = gtk_notebook_search_page (notebook,
2776                                                                     NULL,
2777                                                                     STEP_NEXT,
2778                                                                     TRUE);
2779                   children = NULL;
2780                   gtk_notebook_calc_tabs (notebook,
2781                                           gtk_notebook_search_page (notebook,
2782                                                                     focus_tab,
2783                                                                     STEP_NEXT,
2784                                                                     TRUE),
2785                                           &children, &tab_space, STEP_NEXT);
2786
2787                   if (tab_space <= 0) 
2788                     last_child = children;
2789                   else /* start <- first_tab */
2790                     {
2791                       last_child = NULL;
2792                       children = NULL;
2793                       gtk_notebook_calc_tabs
2794                         (notebook,
2795                          gtk_notebook_search_page (notebook,
2796                                                    notebook->first_tab,
2797                                                    STEP_PREV,
2798                                                    TRUE),
2799                          &children, &tab_space, STEP_PREV);
2800                       notebook->first_tab = gtk_notebook_search_page(notebook,
2801                                                                      children,
2802                                                                      STEP_NEXT,
2803                                                                      TRUE);
2804                     }
2805                 }
2806             }
2807
2808           if (GTK_WIDGET_REALIZED (notebook))
2809             {
2810               gdk_window_move (notebook->panel, x, y);
2811               gdk_window_show (notebook->panel);
2812             }
2813
2814           if (tab_space < 0) 
2815             {
2816               tab_space = -tab_space;
2817               n = 0;
2818               for (children = notebook->first_tab;
2819                    children && children != last_child;
2820                    children = gtk_notebook_search_page (notebook, children,
2821                                                         STEP_NEXT, TRUE))
2822                 n++;
2823             }
2824           else 
2825             tab_space = 0;
2826
2827           /*unmap all non-visible tabs*/
2828           for (children = gtk_notebook_search_page (notebook, NULL,
2829                                                     STEP_NEXT, TRUE);
2830                children && children != notebook->first_tab;
2831                children = gtk_notebook_search_page (notebook, children,
2832                                                     STEP_NEXT, TRUE))
2833             {
2834               page = children->data;
2835               if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2836                 gtk_widget_unmap (page->tab_label);
2837             }
2838           for (children = last_child; children;
2839                children = gtk_notebook_search_page (notebook, children,
2840                                                     STEP_NEXT, TRUE))
2841             {
2842               page = children->data;
2843               if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2844                 gtk_widget_unmap (page->tab_label);
2845             }
2846         }
2847       else /* !showarrow */
2848         {
2849           notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2850                                                           STEP_NEXT, TRUE);
2851           tab_space = 0;
2852           if (GTK_WIDGET_REALIZED (notebook))
2853             gdk_window_hide (notebook->panel);
2854         }
2855     }
2856
2857   if (!showarrow)
2858     {
2859       gint c = 0;
2860
2861       n = 0;
2862       children = notebook->children;
2863       switch (notebook->tab_pos)
2864         {
2865         case GTK_POS_TOP:
2866         case GTK_POS_BOTTOM:
2867           while (children)
2868             {
2869               page = children->data;
2870               children = children->next;
2871
2872               if (GTK_WIDGET_VISIBLE (page->child))
2873                 {
2874                   c++;
2875                   tab_space += page->requisition.width;
2876                   if (page->expand)
2877                     n++;
2878                 }
2879             }
2880           tab_space -= allocation->width;
2881           break;
2882         case GTK_POS_LEFT:
2883         case GTK_POS_RIGHT:
2884           while (children)
2885             {
2886               page = children->data;
2887               children = children->next;
2888
2889               if (GTK_WIDGET_VISIBLE (page->child))
2890                 {
2891                   c++;
2892                   tab_space += page->requisition.height;
2893                   if (page->expand)
2894                     n++;
2895                 }
2896             }
2897           tab_space -= allocation->height;
2898         }
2899       tab_space += 2 * container->border_width + TAB_OVERLAP;
2900       tab_space *= -1;
2901       notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2902                                                       STEP_NEXT, TRUE);
2903       if (notebook->homogeneous && n)
2904         n = c;
2905     }
2906   
2907   children = notebook->first_tab;
2908   i = 1;
2909   while (children)
2910     {
2911       if (children == last_child)
2912         {
2913           gtk_notebook_set_shape (notebook);
2914           return;
2915           children = NULL;
2916           break;
2917         }
2918
2919       page = children->data;
2920       if (!showarrow && page->pack != GTK_PACK_START)
2921         break;
2922       children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
2923       
2924       delta = 0;
2925       if (n && (showarrow || page->expand || notebook->homogeneous))
2926         {
2927           new_fill = (tab_space * i++) / n;
2928           delta = new_fill - old_fill;
2929           old_fill = new_fill;
2930         }
2931       
2932       switch (notebook->tab_pos)
2933         {
2934         case GTK_POS_TOP:
2935         case GTK_POS_BOTTOM:
2936           child_allocation.width = (page->requisition.width +
2937                                     TAB_OVERLAP + delta);
2938           break;
2939         case GTK_POS_LEFT:
2940         case GTK_POS_RIGHT:
2941           child_allocation.height = (page->requisition.height +
2942                                      TAB_OVERLAP + delta);
2943           break;
2944         }
2945
2946       gtk_notebook_page_allocate (notebook, page, &child_allocation);
2947           
2948       switch (notebook->tab_pos)
2949         {
2950         case GTK_POS_TOP:
2951         case GTK_POS_BOTTOM:
2952           child_allocation.x += child_allocation.width - TAB_OVERLAP;
2953           break;
2954         case GTK_POS_LEFT:
2955         case GTK_POS_RIGHT:
2956           child_allocation.y += child_allocation.height - TAB_OVERLAP;
2957           break;
2958         }
2959
2960       if (GTK_WIDGET_REALIZED (notebook) &&
2961           page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2962         {
2963           if (GTK_WIDGET_VISIBLE (page->tab_label))
2964             gtk_widget_map (page->tab_label);
2965           else
2966             gtk_widget_show (page->tab_label);
2967         }
2968     }
2969
2970   if (children)
2971     {
2972       children = notebook->children;
2973       switch (notebook->tab_pos)
2974         {
2975         case GTK_POS_TOP:
2976         case GTK_POS_BOTTOM:
2977           child_allocation.x = (allocation->x + allocation->width -
2978                                 container->border_width);
2979           break;
2980         case GTK_POS_LEFT:
2981         case GTK_POS_RIGHT:
2982           child_allocation.y = (allocation->y + allocation->height -
2983                                 container->border_width);
2984           break;
2985         }
2986
2987       while (children != last_child)
2988         {
2989           page = children->data;
2990           children = children->next;
2991
2992           if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
2993             continue;
2994
2995           delta = 0;
2996           if (n && (page->expand || notebook->homogeneous))
2997             {
2998               new_fill = (tab_space * i++) / n;
2999               delta = new_fill - old_fill;
3000               old_fill = new_fill;
3001             }
3002
3003           switch (notebook->tab_pos)
3004             {
3005             case GTK_POS_TOP:
3006             case GTK_POS_BOTTOM:
3007               child_allocation.width = (page->requisition.width +
3008                                         TAB_OVERLAP + delta);
3009               child_allocation.x -= child_allocation.width;
3010               break;
3011             case GTK_POS_LEFT:
3012             case GTK_POS_RIGHT:
3013               child_allocation.height = (page->requisition.height +
3014                                          TAB_OVERLAP + delta);
3015               child_allocation.y -= child_allocation.height;
3016               break;
3017             }
3018
3019           gtk_notebook_page_allocate (notebook, page, &child_allocation);
3020
3021           switch (notebook->tab_pos)
3022             {
3023             case GTK_POS_TOP:
3024             case GTK_POS_BOTTOM:
3025               child_allocation.x += TAB_OVERLAP;
3026               break;
3027             case GTK_POS_LEFT:
3028             case GTK_POS_RIGHT:
3029               child_allocation.y += TAB_OVERLAP;
3030               break;
3031             }
3032
3033           if (GTK_WIDGET_REALIZED (notebook) && page->tab_label &&
3034               !GTK_WIDGET_MAPPED (page->tab_label))
3035             {
3036               if (GTK_WIDGET_VISIBLE (page->tab_label))
3037                 gtk_widget_map (page->tab_label);
3038               else
3039                 gtk_widget_show (page->tab_label);
3040             }
3041         }
3042     }
3043   gtk_notebook_set_shape (notebook);
3044 }
3045
3046 static void
3047 gtk_notebook_page_allocate (GtkNotebook     *notebook,
3048                             GtkNotebookPage *page,
3049                             GtkAllocation   *allocation)
3050 {
3051   GtkWidget *widget;
3052   GtkAllocation child_allocation;
3053   GtkRequisition tab_requisition;
3054   gint xthickness;
3055   gint ythickness;
3056   gint padding;
3057
3058   g_return_if_fail (notebook != NULL);
3059   g_return_if_fail (page != NULL);
3060   g_return_if_fail (allocation != NULL);
3061
3062   widget = GTK_WIDGET (notebook);
3063
3064   xthickness = widget->style->klass->xthickness;
3065   ythickness = widget->style->klass->ythickness;
3066
3067   /* If the size of the notebook tabs change, we need to queue
3068    * a redraw on the tab area
3069    */
3070   if ((allocation->width != page->allocation.width) ||
3071       (allocation->height != page->allocation.height))
3072     {
3073       gint x, y, width, height, border_width;
3074
3075       border_width = GTK_CONTAINER (notebook)->border_width;
3076
3077       switch (notebook->tab_pos)
3078        {
3079        case GTK_POS_TOP:
3080          width = widget->allocation.width;
3081          height = MAX (page->allocation.height, allocation->height) + ythickness;
3082          x = 0;                              
3083          y = border_width;
3084          break;
3085
3086        case GTK_POS_BOTTOM:
3087          width = widget->allocation.width + xthickness;
3088          height = MAX (page->allocation.height, allocation->height) + ythickness;
3089          x = 0;                              
3090          y = widget->allocation.height - height - border_width;
3091          break;
3092
3093        case GTK_POS_LEFT:
3094          width = MAX (page->allocation.width, allocation->width) + xthickness;
3095          height = widget->allocation.height;
3096          x = border_width;
3097          y = 0;
3098          break;
3099
3100        case GTK_POS_RIGHT:
3101        default:                /* quiet gcc */
3102          width = MAX (page->allocation.width, allocation->width) + xthickness;
3103          height = widget->allocation.height;
3104          x = widget->allocation.width - width - border_width;
3105          y = 0;
3106          break;
3107        }
3108
3109       gtk_widget_queue_clear_area (widget, x, y, width, height);
3110     }
3111
3112   page->allocation = *allocation;
3113   gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3114
3115   if (notebook->cur_page != page)
3116     {
3117       switch (notebook->tab_pos)
3118         {
3119         case GTK_POS_TOP:
3120           page->allocation.y += ythickness;
3121         case GTK_POS_BOTTOM:
3122           if (page->allocation.height > ythickness)
3123             page->allocation.height -= ythickness;
3124           break;
3125         case GTK_POS_LEFT:
3126           page->allocation.x += xthickness;
3127         case GTK_POS_RIGHT:
3128           if (page->allocation.width > xthickness)
3129             page->allocation.width -= xthickness;
3130           break;
3131         }
3132     }
3133
3134   switch (notebook->tab_pos)
3135     {
3136     case GTK_POS_TOP:
3137     case GTK_POS_BOTTOM:
3138       padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_hborder;
3139       if (page->fill)
3140         {
3141           child_allocation.x = (xthickness + FOCUS_WIDTH +
3142                                 notebook->tab_hborder);
3143           child_allocation.width = MAX (1, (((gint) page->allocation.width) -
3144                                             2 * child_allocation.x));
3145           child_allocation.x += page->allocation.x;
3146         }
3147       else
3148         {
3149           child_allocation.x = (page->allocation.x +
3150                                 (page->allocation.width -
3151                                  tab_requisition.width) / 2);
3152           child_allocation.width = tab_requisition.width;
3153         }
3154       child_allocation.y = (notebook->tab_vborder + FOCUS_WIDTH +
3155                             page->allocation.y);
3156       if (notebook->tab_pos == GTK_POS_TOP)
3157         child_allocation.y += ythickness;
3158       child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3159                                          2 * (notebook->tab_vborder + FOCUS_WIDTH)));
3160       break;
3161     case GTK_POS_LEFT:
3162     case GTK_POS_RIGHT:
3163       padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_vborder;
3164       if (page->fill)
3165         {
3166           child_allocation.y = ythickness + padding;
3167           child_allocation.height = MAX (1, (((gint) page->allocation.height) -
3168                                              2 * child_allocation.y));
3169           child_allocation.y += page->allocation.y;
3170         }
3171       else
3172         {
3173           child_allocation.y = (page->allocation.y + (page->allocation.height -
3174                                                       tab_requisition.height) / 2);
3175           child_allocation.height = tab_requisition.height;
3176         }
3177       child_allocation.x = page->allocation.x + notebook->tab_hborder + FOCUS_WIDTH;
3178       if (notebook->tab_pos == GTK_POS_LEFT)
3179         child_allocation.x += xthickness;
3180       child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3181                                         2 * (notebook->tab_hborder + FOCUS_WIDTH)));
3182       break;
3183     }
3184
3185   if (page->tab_label)
3186     gtk_widget_size_allocate (page->tab_label, &child_allocation);
3187 }
3188
3189 static void 
3190 gtk_notebook_calc_tabs (GtkNotebook  *notebook, 
3191                         GList        *start, 
3192                         GList       **end,
3193                         gint         *tab_space,
3194                         guint         direction)
3195 {
3196   GtkNotebookPage *page = NULL;
3197   GList *children;
3198   GList *last_list = NULL;
3199   gboolean pack;
3200
3201   if (!start)
3202     return;
3203
3204   children = start;
3205   pack = GTK_NOTEBOOK_PAGE (start)->pack;
3206   if (pack == GTK_PACK_END)
3207     direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3208
3209   while (1)
3210     {
3211       switch (notebook->tab_pos)
3212         {
3213         case GTK_POS_TOP:
3214         case GTK_POS_BOTTOM:
3215           while (children)
3216             {
3217               page = children->data;
3218               if (GTK_WIDGET_VISIBLE (page->child))
3219                 {
3220                   if (page->pack == pack)
3221                     {
3222                       *tab_space -= page->requisition.width;
3223                       if (*tab_space < 0 || children == *end)
3224                         {
3225                           if (*tab_space < 0) 
3226                             {
3227                               *tab_space = - (*tab_space +
3228                                               page->requisition.width);
3229                               *end = children;
3230                             }
3231                           return;
3232                         }
3233                     }
3234                   last_list = children;
3235                 }
3236               if (direction == STEP_NEXT)
3237                 children = children->next;
3238               else
3239                 children = children->prev;
3240             }
3241           break;
3242         case GTK_POS_LEFT:
3243         case GTK_POS_RIGHT:
3244           while (children)
3245             {
3246               page = children->data;
3247               if (GTK_WIDGET_VISIBLE (page->child))
3248                 {
3249                   if (page->pack == pack)
3250                     {
3251                       *tab_space -= page->requisition.height;
3252                       if (*tab_space < 0 || children == *end)
3253                         {
3254                           if (*tab_space < 0)
3255                             {
3256                               *tab_space = - (*tab_space +
3257                                               page->requisition.height);
3258                               *end = children;
3259                             }
3260                           return;
3261                         }
3262                     }
3263                   last_list = children;
3264                 }
3265               if (direction == STEP_NEXT)
3266                 children = children->next;
3267               else
3268                 children = children->prev;
3269             }
3270           break;
3271         }
3272       if (direction == STEP_PREV)
3273         return;
3274       pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3275       direction = STEP_PREV;
3276       children = last_list;
3277     }
3278 }
3279
3280 /* Private GtkNotebook Page Switch Methods:
3281  *
3282  * gtk_notebook_real_switch_page
3283  */
3284 static void
3285 gtk_notebook_real_switch_page (GtkNotebook     *notebook,
3286                                GtkNotebookPage *page,
3287                                guint            page_num)
3288 {
3289   g_return_if_fail (notebook != NULL);
3290   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3291   g_return_if_fail (page != NULL);
3292
3293   if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3294     return;
3295
3296   if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
3297     gtk_widget_unmap (notebook->cur_page->child);
3298   
3299   notebook->cur_page = page;
3300
3301   if (!notebook->focus_tab ||
3302       notebook->focus_tab->data != (gpointer) notebook->cur_page)
3303     notebook->focus_tab = 
3304       g_list_find (notebook->children, notebook->cur_page);
3305
3306   if (GTK_WIDGET_MAPPED (notebook))
3307     gtk_widget_map (notebook->cur_page->child);
3308
3309   gtk_widget_queue_resize (GTK_WIDGET (notebook));
3310 }
3311
3312 /* Private GtkNotebook Page Switch Functions:
3313  *
3314  * gtk_notebook_switch_page
3315  * gtk_notebook_page_select
3316  * gtk_notebook_switch_focus_tab
3317  * gtk_notebook_menu_switch_page
3318  */
3319 static void
3320 gtk_notebook_switch_page (GtkNotebook     *notebook,
3321                           GtkNotebookPage *page,
3322                           gint             page_num)
3323
3324   g_return_if_fail (notebook != NULL);
3325   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3326   g_return_if_fail (page != NULL);
3327  
3328   if (notebook->cur_page == page)
3329     return;
3330
3331   if (page_num < 0)
3332     page_num = g_list_index (notebook->children, page);
3333
3334   gtk_signal_emit (GTK_OBJECT (notebook), 
3335                    notebook_signals[SWITCH_PAGE], 
3336                    page,
3337                    page_num);
3338 }
3339
3340 static gint
3341 gtk_notebook_page_select (GtkNotebook *notebook)
3342 {
3343   GtkNotebookPage *page;
3344
3345   g_return_val_if_fail (notebook != NULL, FALSE);
3346   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3347
3348   if (!notebook->focus_tab)
3349     return FALSE;
3350
3351   page = notebook->focus_tab->data;
3352   gtk_notebook_switch_page (notebook, page, -1);
3353
3354   if (GTK_WIDGET_VISIBLE (page->child))
3355     {
3356       if (GTK_IS_CONTAINER (page->child))
3357         {
3358           if (gtk_container_focus (GTK_CONTAINER (page->child), 
3359                                    GTK_DIR_TAB_FORWARD))
3360             return TRUE;
3361         }
3362       else if (GTK_WIDGET_CAN_FOCUS (page->child))
3363         {
3364           gtk_widget_grab_focus (page->child);
3365           return TRUE;
3366         }
3367     }
3368   return FALSE;
3369 }
3370
3371 static void
3372 gtk_notebook_switch_focus_tab (GtkNotebook *notebook, 
3373                                GList       *new_child)
3374 {
3375   GList *old_child;
3376   GtkNotebookPage *old_page = NULL;
3377   GtkNotebookPage *page;
3378
3379   g_return_if_fail (notebook != NULL);
3380   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3381
3382   if (notebook->focus_tab == new_child)
3383     return;
3384
3385   old_child = notebook->focus_tab;
3386   notebook->focus_tab = new_child;
3387
3388   if (notebook->scrollable && GTK_WIDGET_DRAWABLE (notebook))
3389     {
3390       if ((new_child == NULL) != (old_child == NULL))
3391         {
3392           gdk_window_clear (notebook->panel);
3393           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3394           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3395         }
3396       else
3397         {
3398           GList *olist;
3399           GList *nlist;
3400
3401           olist = gtk_notebook_search_page (notebook, old_child,
3402                                             STEP_PREV, TRUE);
3403           nlist = gtk_notebook_search_page (notebook, new_child,
3404                                             STEP_PREV, TRUE);
3405
3406           if ((olist == NULL) != (nlist == NULL))
3407             {
3408               gdk_window_clear_area (notebook->panel, 0, 0,
3409                                      ARROW_SIZE, ARROW_SIZE);
3410               gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3411             }
3412
3413           olist = gtk_notebook_search_page (notebook, old_child,
3414                                             STEP_NEXT, TRUE);
3415           nlist = gtk_notebook_search_page (notebook, new_child,
3416                                             STEP_NEXT, TRUE);
3417
3418           if ((olist == NULL) != (nlist == NULL))
3419             {
3420               gdk_window_clear_area (notebook->panel,
3421                                      ARROW_SIZE + ARROW_SPACING, 0,
3422                                      ARROW_SIZE, ARROW_SIZE);
3423               gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3424             }
3425         }
3426     }
3427
3428   if (!notebook->show_tabs || !notebook->focus_tab)
3429     return;
3430
3431   if (old_child)
3432     old_page = old_child->data;
3433
3434   page = notebook->focus_tab->data;
3435   if (GTK_WIDGET_MAPPED (page->tab_label))
3436     gtk_notebook_focus_changed (notebook, old_page);
3437   else
3438     {
3439       gtk_notebook_pages_allocate (notebook,
3440                                    &(GTK_WIDGET (notebook)->allocation));
3441       gtk_notebook_expose_tabs (notebook);
3442     }
3443
3444   gtk_notebook_set_shape (notebook);
3445 }
3446
3447 static void
3448 gtk_notebook_menu_switch_page (GtkWidget       *widget,
3449                                GtkNotebookPage *page)
3450 {
3451   GtkNotebook *notebook;
3452   GList *children;
3453   guint page_num;
3454
3455   g_return_if_fail (widget != NULL);
3456   g_return_if_fail (page != NULL);
3457
3458   notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3459                            (GTK_MENU (widget->parent)));
3460
3461   if (notebook->cur_page == page)
3462     return;
3463
3464   page_num = 0;
3465   children = notebook->children;
3466   while (children && children->data != page)
3467     {
3468       children = children->next;
3469       page_num++;
3470     }
3471
3472   gtk_signal_emit (GTK_OBJECT (notebook), 
3473                    notebook_signals[SWITCH_PAGE], 
3474                    page,
3475                    page_num);
3476 }
3477
3478 /* Private GtkNotebook Menu Functions:
3479  *
3480  * gtk_notebook_menu_item_create
3481  * gtk_notebook_menu_label_unparent
3482  * gtk_notebook_menu_detacher
3483  */
3484 static void
3485 gtk_notebook_menu_item_create (GtkNotebook *notebook, 
3486                                GList       *list)
3487 {       
3488   GtkNotebookPage *page;
3489   GtkWidget *menu_item;
3490
3491   page = list->data;
3492   if (page->default_menu)
3493     {
3494       if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3495         page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3496       else
3497         page->menu_label = gtk_label_new ("");
3498       gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3499     }
3500
3501   gtk_widget_show (page->menu_label);
3502   menu_item = gtk_menu_item_new ();
3503   gtk_widget_lock_accelerators (menu_item);
3504   gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3505   gtk_menu_insert (GTK_MENU (notebook->menu), menu_item,
3506                    gtk_notebook_real_page_position (notebook, list));
3507   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3508                       GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3509   if (GTK_WIDGET_VISIBLE (page->child))
3510     gtk_widget_show (menu_item);
3511 }
3512
3513 static void
3514 gtk_notebook_menu_label_unparent (GtkWidget *widget, 
3515                                   gpointer  data)
3516 {
3517   gtk_widget_unparent (GTK_BIN(widget)->child);
3518   GTK_BIN(widget)->child = NULL;
3519 }
3520
3521 static void
3522 gtk_notebook_menu_detacher (GtkWidget *widget,
3523                             GtkMenu   *menu)
3524 {
3525   GtkNotebook *notebook;
3526
3527   g_return_if_fail (widget != NULL);
3528   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3529
3530   notebook = GTK_NOTEBOOK (widget);
3531   g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3532
3533   notebook->menu = NULL;
3534 }
3535
3536 /* Public GtkNotebook Page Insert/Remove Methods :
3537  *
3538  * gtk_notebook_append_page
3539  * gtk_notebook_append_page_menu
3540  * gtk_notebook_prepend_page
3541  * gtk_notebook_prepend_page_menu
3542  * gtk_notebook_insert_page
3543  * gtk_notebook_insert_page_menu
3544  * gtk_notebook_remove_page
3545  */
3546 void
3547 gtk_notebook_append_page (GtkNotebook *notebook,
3548                           GtkWidget   *child,
3549                           GtkWidget   *tab_label)
3550 {
3551   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3552 }
3553
3554 void
3555 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3556                                GtkWidget   *child,
3557                                GtkWidget   *tab_label,
3558                                GtkWidget   *menu_label)
3559 {
3560   gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3561 }
3562
3563 void
3564 gtk_notebook_prepend_page (GtkNotebook *notebook,
3565                            GtkWidget   *child,
3566                            GtkWidget   *tab_label)
3567 {
3568   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3569 }
3570
3571 void
3572 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3573                                 GtkWidget   *child,
3574                                 GtkWidget   *tab_label,
3575                                 GtkWidget   *menu_label)
3576 {
3577   gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3578 }
3579
3580 void
3581 gtk_notebook_insert_page (GtkNotebook *notebook,
3582                           GtkWidget   *child,
3583                           GtkWidget   *tab_label,
3584                           gint         position)
3585 {
3586   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3587 }
3588
3589 void
3590 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3591                                GtkWidget   *child,
3592                                GtkWidget   *tab_label,
3593                                GtkWidget   *menu_label,
3594                                gint         position)
3595 {
3596   GtkNotebookPage *page;
3597   gint nchildren;
3598
3599   g_return_if_fail (notebook != NULL);
3600   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3601   g_return_if_fail (child != NULL);
3602
3603   page = g_new (GtkNotebookPage, 1);
3604   page->child = child;
3605   page->requisition.width = 0;
3606   page->requisition.height = 0;
3607   page->allocation.x = 0;
3608   page->allocation.y = 0;
3609   page->allocation.width = 0;
3610   page->allocation.height = 0;
3611   page->default_menu = FALSE;
3612   page->default_tab = FALSE;
3613    
3614   nchildren = g_list_length (notebook->children);
3615   if ((position < 0) || (position > nchildren))
3616     position = nchildren;
3617
3618   notebook->children = g_list_insert (notebook->children, page, position);
3619
3620   if (!tab_label)
3621     {
3622       page->default_tab = TRUE;
3623       if (notebook->show_tabs)
3624         tab_label = gtk_label_new ("");
3625     }
3626   page->tab_label = tab_label;
3627   page->menu_label = menu_label;
3628   page->expand = FALSE;
3629   page->fill = TRUE;
3630   page->pack = GTK_PACK_START;
3631
3632   if (!menu_label)
3633     page->default_menu = TRUE;
3634   else  
3635     {
3636       gtk_widget_ref (page->menu_label);
3637       gtk_object_sink (GTK_OBJECT(page->menu_label));
3638     }
3639
3640   if (notebook->menu)
3641     gtk_notebook_menu_item_create (notebook,
3642                                    g_list_find (notebook->children, page));
3643
3644   gtk_notebook_update_labels (notebook);
3645
3646   if (!notebook->first_tab)
3647     notebook->first_tab = notebook->children;
3648
3649   gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3650   if (tab_label)
3651     gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3652
3653   if (!notebook->cur_page)
3654     {
3655       gtk_notebook_switch_page (notebook, page, 0);
3656       gtk_notebook_switch_focus_tab (notebook, NULL);
3657     }
3658
3659   if (GTK_WIDGET_REALIZED (child->parent))
3660     gtk_widget_realize (child);
3661
3662   if (GTK_WIDGET_VISIBLE (notebook))
3663     {
3664       if (GTK_WIDGET_VISIBLE (child))
3665         {
3666           if (GTK_WIDGET_MAPPED (notebook) &&
3667               !GTK_WIDGET_MAPPED (child) &&
3668               notebook->cur_page == page)
3669             gtk_widget_map (child);
3670           
3671           gtk_widget_queue_resize (child);
3672         }
3673
3674       if (tab_label)
3675         {
3676           if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3677             {
3678               if (!GTK_WIDGET_VISIBLE (tab_label))
3679                 gtk_widget_show (tab_label);
3680               
3681               if (GTK_WIDGET_REALIZED (notebook) &&
3682                   !GTK_WIDGET_REALIZED (tab_label))
3683                 gtk_widget_realize (tab_label);
3684               
3685               if (GTK_WIDGET_MAPPED (notebook) &&
3686                   !GTK_WIDGET_MAPPED (tab_label))
3687                 gtk_widget_map (tab_label);
3688             }
3689           else if (GTK_WIDGET_VISIBLE (tab_label))
3690             gtk_widget_hide (tab_label);
3691         }
3692     }
3693 }
3694
3695 void
3696 gtk_notebook_remove_page (GtkNotebook *notebook,
3697                           gint         page_num)
3698 {
3699   GList *list;
3700   
3701   g_return_if_fail (notebook != NULL);
3702   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3703   
3704   if (page_num >= 0)
3705     {
3706       list = g_list_nth (notebook->children, page_num);
3707       if (list)
3708         gtk_notebook_real_remove (notebook, list);
3709     }
3710   else
3711     {
3712       list = g_list_last (notebook->children);
3713       if (list)
3714         gtk_notebook_real_remove (notebook, list);
3715     }
3716 }
3717
3718 /* Public GtkNotebook Page Switch Methods :
3719  * gtk_notebook_get_current_page
3720  * gtk_notebook_page_num
3721  * gtk_notebook_set_page
3722  * gtk_notebook_next_page
3723  * gtk_notebook_prev_page
3724  */
3725 gint
3726 gtk_notebook_get_current_page (GtkNotebook *notebook)
3727 {
3728   g_return_val_if_fail (notebook != NULL, -1);
3729   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3730
3731   if (!notebook->cur_page)
3732     return -1;
3733
3734   return g_list_index (notebook->children, notebook->cur_page);
3735 }
3736
3737 GtkWidget*
3738 gtk_notebook_get_nth_page (GtkNotebook *notebook,
3739                            gint         page_num)
3740 {
3741   GtkNotebookPage *page;
3742
3743   g_return_val_if_fail (notebook != NULL, NULL);
3744   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3745
3746   page = g_list_nth_data (notebook->children, page_num);
3747
3748   if (page)
3749     return page->child;
3750
3751   return NULL;
3752 }
3753
3754 gint
3755 gtk_notebook_page_num (GtkNotebook      *notebook,
3756                        GtkWidget        *child)
3757 {
3758   GList *children;
3759   gint num;
3760
3761   g_return_val_if_fail (notebook != NULL, -1);
3762   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3763
3764   num = 0;
3765   children = notebook->children;
3766   while (children)
3767     {
3768       GtkNotebookPage *page;
3769
3770       page = children->data;
3771       if (page->child == child)
3772         return num;
3773
3774       children = children->next;
3775       num++;
3776     }
3777
3778   return -1;
3779 }
3780
3781 void
3782 gtk_notebook_set_page (GtkNotebook *notebook,
3783                        gint         page_num)
3784 {
3785   GList *list;
3786
3787   g_return_if_fail (notebook != NULL);
3788   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3789
3790   if (page_num >= 0)
3791     list = g_list_nth (notebook->children, page_num);
3792   else
3793     {
3794       list = g_list_last (notebook->children);
3795       page_num = g_list_length (notebook->children) - 1;
3796     }
3797   if (list)
3798     gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
3799 }
3800
3801 void
3802 gtk_notebook_next_page (GtkNotebook *notebook)
3803 {
3804   GList *list;
3805
3806   g_return_if_fail (notebook != NULL);
3807   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3808
3809   list = g_list_find (notebook->children, notebook->cur_page);
3810   if (!list)
3811     return;
3812
3813   list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3814   if (!list)
3815     return;
3816
3817   gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
3818 }
3819
3820 void
3821 gtk_notebook_prev_page (GtkNotebook *notebook)
3822 {
3823   GList *list;
3824
3825   g_return_if_fail (notebook != NULL);
3826   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3827
3828   list = g_list_find (notebook->children, notebook->cur_page);
3829   if (!list)
3830     return;
3831
3832   list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3833   if (!list)
3834     return;
3835
3836   gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
3837 }
3838
3839 /* Public GtkNotebook/Tab Style Functions
3840  *
3841  * gtk_notebook_set_show_border
3842  * gtk_notebook_set_show_tabs
3843  * gtk_notebook_set_tab_pos
3844  * gtk_notebook_set_homogeneous_tabs
3845  * gtk_notebook_set_tab_border
3846  * gtk_notebook_set_tab_hborder
3847  * gtk_notebook_set_tab_vborder
3848  * gtk_notebook_set_scrollable
3849  */
3850 void
3851 gtk_notebook_set_show_border (GtkNotebook *notebook,
3852                               gboolean     show_border)
3853 {
3854   g_return_if_fail (notebook != NULL);
3855   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3856
3857   if (notebook->show_border != show_border)
3858     {
3859       notebook->show_border = show_border;
3860
3861       if (GTK_WIDGET_VISIBLE (notebook))
3862         gtk_widget_queue_resize (GTK_WIDGET (notebook));
3863     }
3864 }
3865
3866 void
3867 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
3868                             gboolean     show_tabs)
3869 {
3870   GtkNotebookPage *page;
3871   GList *children;
3872
3873   g_return_if_fail (notebook != NULL);
3874   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3875
3876   show_tabs = show_tabs != FALSE;
3877
3878   if (notebook->show_tabs == show_tabs)
3879     return;
3880
3881   notebook->show_tabs = show_tabs;
3882   children = notebook->children;
3883
3884   if (!show_tabs)
3885     {
3886       GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
3887       
3888       while (children)
3889         {
3890           page = children->data;
3891           children = children->next;
3892           if (page->default_tab)
3893             {
3894               gtk_widget_destroy (page->tab_label);
3895               page->tab_label = NULL;
3896             }
3897           else
3898             gtk_widget_hide (page->tab_label);
3899         }
3900       
3901       if (notebook->panel)
3902         gdk_window_hide (notebook->panel);
3903     }
3904   else
3905     {
3906       GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
3907       gtk_notebook_update_labels (notebook);
3908     }
3909   gtk_widget_queue_resize (GTK_WIDGET (notebook));
3910 }
3911
3912 void
3913 gtk_notebook_set_tab_pos (GtkNotebook     *notebook,
3914                           GtkPositionType  pos)
3915 {
3916   g_return_if_fail (notebook != NULL);
3917   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3918
3919   if (notebook->tab_pos != pos)
3920     {
3921       notebook->tab_pos = pos;
3922       if (GTK_WIDGET_VISIBLE (notebook))
3923         gtk_widget_queue_resize (GTK_WIDGET (notebook));
3924     }
3925 }
3926
3927 void
3928 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
3929                                    gboolean     homogeneous)
3930 {
3931   g_return_if_fail (notebook != NULL);
3932   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3933
3934   if (homogeneous == notebook->homogeneous)
3935     return;
3936
3937   notebook->homogeneous = homogeneous;
3938   gtk_widget_queue_resize (GTK_WIDGET (notebook));
3939 }
3940
3941 void
3942 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3943                              guint        tab_border)
3944 {
3945   g_return_if_fail (notebook != NULL);
3946   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3947
3948   notebook->tab_hborder = tab_border;
3949   notebook->tab_vborder = tab_border;
3950
3951   if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3952     gtk_widget_queue_resize (GTK_WIDGET (notebook));
3953 }
3954
3955 void
3956 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
3957                               guint        tab_hborder)
3958 {
3959   g_return_if_fail (notebook != NULL);
3960   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3961
3962   if (notebook->tab_hborder == tab_hborder)
3963     return;
3964
3965   notebook->tab_hborder = tab_hborder;
3966
3967   if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3968     gtk_widget_queue_resize (GTK_WIDGET (notebook));
3969 }
3970
3971 void
3972 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
3973                               guint        tab_vborder)
3974 {
3975   g_return_if_fail (notebook != NULL);
3976   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3977
3978   if (notebook->tab_vborder == tab_vborder)
3979     return;
3980
3981   notebook->tab_vborder = tab_vborder;
3982
3983   if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3984     gtk_widget_queue_resize (GTK_WIDGET (notebook));
3985 }
3986
3987 void
3988 gtk_notebook_set_scrollable (GtkNotebook *notebook,
3989                              gboolean     scrollable)
3990 {
3991   g_return_if_fail (notebook != NULL);
3992   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3993
3994   scrollable = (scrollable != FALSE);
3995
3996   if (scrollable != notebook->scrollable)
3997     {
3998       notebook->scrollable = scrollable;
3999
4000       if (GTK_WIDGET_REALIZED (notebook))
4001         {
4002           if (scrollable)
4003             {
4004               gtk_notebook_panel_realize (notebook);
4005             }
4006           else if (notebook->panel)
4007             {
4008               gdk_window_set_user_data (notebook->panel, NULL);
4009               gdk_window_destroy (notebook->panel);
4010               notebook->panel = NULL;
4011             }
4012         }
4013
4014       if (GTK_WIDGET_VISIBLE (notebook))
4015         gtk_widget_queue_resize (GTK_WIDGET(notebook));
4016     }
4017 }
4018
4019 /* Public GtkNotebook Popup Menu Methods:
4020  *
4021  * gtk_notebook_popup_enable
4022  * gtk_notebook_popup_disable
4023  */
4024 void
4025 gtk_notebook_popup_enable (GtkNotebook *notebook)
4026 {
4027   GList *list;
4028
4029   g_return_if_fail (notebook != NULL);
4030   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4031
4032   if (notebook->menu)
4033     return;
4034
4035   notebook->menu = gtk_menu_new ();
4036   for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4037        list;
4038        list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4039     gtk_notebook_menu_item_create (notebook, list);
4040
4041   gtk_notebook_update_labels (notebook);
4042   gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4043                              GTK_WIDGET (notebook),
4044                              gtk_notebook_menu_detacher);
4045 }
4046
4047 void       
4048 gtk_notebook_popup_disable  (GtkNotebook *notebook)
4049 {
4050   g_return_if_fail (notebook != NULL);
4051   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4052
4053   if (!notebook->menu)
4054     return;
4055
4056   gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4057                          (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4058   gtk_widget_destroy (notebook->menu);
4059 }
4060
4061 /* Public GtkNotebook Page Properties Functions:
4062  *
4063  * gtk_notebook_get_tab_label
4064  * gtk_notebook_set_tab_label
4065  * gtk_notebook_set_tab_label_text
4066  * gtk_notebook_get_menu_label
4067  * gtk_notebook_set_menu_label
4068  * gtk_notebook_set_menu_label_text
4069  * gtk_notebook_set_tab_label_packing
4070  * gtk_notebook_query_tab_label_packing
4071  */
4072 GtkWidget *
4073 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4074                             GtkWidget   *child)
4075 {
4076   GList *list;
4077
4078   g_return_val_if_fail (notebook != NULL, NULL);
4079   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4080   g_return_val_if_fail (child != NULL, NULL);
4081
4082   if (!(list = g_list_find_custom (notebook->children, child,
4083                                    gtk_notebook_page_compare)))
4084     return NULL;
4085
4086   if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4087     return NULL;
4088
4089   return GTK_NOTEBOOK_PAGE (list)->tab_label;
4090 }  
4091
4092 void
4093 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4094                             GtkWidget   *child,
4095                             GtkWidget   *tab_label)
4096 {
4097   GtkNotebookPage *page;
4098   GList *list;
4099
4100   g_return_if_fail (notebook != NULL);
4101   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4102   g_return_if_fail (child != NULL);
4103   
4104   if (!(list = g_list_find_custom (notebook->children, child,
4105                                    gtk_notebook_page_compare)))
4106       return;
4107
4108   /* a NULL pointer indicates a default_tab setting, otherwise
4109    * we need to set the associated label
4110    */
4111
4112   page = list->data;
4113   if (page->tab_label)
4114     gtk_widget_unparent (page->tab_label);
4115
4116   if (tab_label)
4117     {
4118       page->default_tab = FALSE;
4119       page->tab_label = tab_label;
4120       gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4121     }
4122   else
4123     {
4124       page->default_tab = TRUE;
4125       page->tab_label = NULL;
4126
4127       if (notebook->show_tabs)
4128         {
4129           gchar string[32];
4130
4131           g_snprintf (string, sizeof(string), _("Page %u"), 
4132                       gtk_notebook_real_page_position (notebook, list));
4133           page->tab_label = gtk_label_new (string);
4134           gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4135         }
4136     }
4137
4138   if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4139     {
4140       gtk_widget_show (page->tab_label);
4141       gtk_widget_queue_resize (GTK_WIDGET (notebook));
4142     }
4143 }
4144
4145 void
4146 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4147                                  GtkWidget   *child,
4148                                  const gchar *tab_text)
4149 {
4150   GtkWidget *tab_label = NULL;
4151
4152   if (tab_text)
4153     tab_label = gtk_label_new (tab_text);
4154   gtk_notebook_set_tab_label (notebook, child, tab_label);
4155 }
4156
4157 GtkWidget*
4158 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4159                              GtkWidget   *child)
4160 {
4161   GList *list;
4162
4163   g_return_val_if_fail (notebook != NULL, NULL);
4164   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4165   g_return_val_if_fail (child != NULL, NULL);
4166
4167   if (!(list = g_list_find_custom (notebook->children, child,
4168                                    gtk_notebook_page_compare)))
4169       return NULL;
4170
4171   if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4172     return NULL;
4173
4174   return GTK_NOTEBOOK_PAGE (list)->menu_label;
4175 }  
4176
4177 void
4178 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4179                              GtkWidget   *child,
4180                              GtkWidget   *menu_label)
4181 {
4182   GtkNotebookPage *page;
4183   GList *list;
4184
4185   g_return_if_fail (notebook != NULL);
4186   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4187   g_return_if_fail (child != NULL);
4188
4189   if (!(list = g_list_find_custom (notebook->children, child,
4190                                    gtk_notebook_page_compare)))
4191       return;
4192
4193   page = list->data;
4194   if (page->menu_label)
4195     {
4196       if (notebook->menu)
4197         {
4198           gtk_container_remove (GTK_CONTAINER (notebook->menu), 
4199                                 page->menu_label->parent);
4200           gtk_widget_queue_resize (notebook->menu);
4201         }
4202       if (!page->default_menu)
4203         gtk_widget_unref (page->menu_label);
4204     }
4205
4206   if (menu_label)
4207     {
4208       page->menu_label = menu_label;
4209       gtk_widget_ref (page->menu_label);
4210       gtk_object_sink (GTK_OBJECT(page->menu_label));
4211       page->default_menu = FALSE;
4212     }
4213   else
4214     page->default_menu = TRUE;
4215
4216   if (notebook->menu)
4217     gtk_notebook_menu_item_create (notebook, list);
4218 }
4219
4220 void
4221 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4222                                   GtkWidget   *child,
4223                                   const gchar *menu_text)
4224 {
4225   GtkWidget *menu_label = NULL;
4226
4227   if (menu_text)
4228     menu_label = gtk_label_new (menu_text);
4229   gtk_notebook_set_menu_label (notebook, child, menu_label);
4230 }
4231
4232 void
4233 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4234                                     GtkWidget   *child,
4235                                     gboolean     expand,
4236                                     gboolean     fill,
4237                                     GtkPackType  pack_type)
4238 {
4239   GtkNotebookPage *page;
4240   GList *list;
4241
4242   g_return_if_fail (notebook != NULL);
4243   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4244   g_return_if_fail (child != NULL);
4245
4246   if (!(list = g_list_find_custom (notebook->children, child,
4247                                    gtk_notebook_page_compare)))
4248       return;
4249
4250   page = list->data;
4251   if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4252     return;
4253
4254   page->expand = expand;
4255   page->fill = fill;
4256
4257   if (page->pack != pack_type)
4258     {
4259       page->pack = pack_type;
4260       if (notebook->menu)
4261         {
4262           GtkWidget *menu_item;
4263
4264           menu_item = page->menu_label->parent;
4265           gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4266           gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4267           gtk_notebook_menu_item_create (notebook, list);
4268           gtk_widget_queue_resize (notebook->menu);
4269         }
4270       gtk_notebook_update_labels (notebook);
4271     }
4272
4273   if (!notebook->show_tabs)
4274     return;
4275
4276   gtk_notebook_pages_allocate (notebook, &(GTK_WIDGET (notebook)->allocation));
4277   gtk_notebook_expose_tabs (notebook);
4278 }  
4279
4280 void
4281 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4282                                       GtkWidget   *child,
4283                                       gboolean    *expand,
4284                                       gboolean    *fill,
4285                                       GtkPackType *pack_type)
4286 {
4287   GList *list;
4288
4289   g_return_if_fail (notebook != NULL);
4290   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4291   g_return_if_fail (child != NULL);
4292
4293   if (!(list = g_list_find_custom (notebook->children, child,
4294                                    gtk_notebook_page_compare)))
4295       return;
4296
4297   if (expand)
4298     *expand = GTK_NOTEBOOK_PAGE (list)->expand;
4299   if (fill)
4300     *fill = GTK_NOTEBOOK_PAGE (list)->fill;
4301   if (pack_type)
4302     *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
4303 }
4304
4305 void
4306 gtk_notebook_reorder_child (GtkNotebook *notebook,
4307                             GtkWidget   *child,
4308                             gint         position)
4309 {
4310   GList *list;
4311   GList *work;
4312   GtkNotebookPage *page = NULL;
4313   gint old_pos;
4314
4315   g_return_if_fail (notebook != NULL);
4316   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4317   g_return_if_fail (child != NULL);
4318   g_return_if_fail (GTK_IS_WIDGET (child));
4319
4320   for (old_pos = 0, list = notebook->children; list;
4321        list = list->next, old_pos++)
4322     {
4323       page = list->data;
4324       if (page->child == child)
4325         break;
4326     }
4327
4328   if (!list || old_pos == position)
4329     return;
4330
4331   notebook->children = g_list_remove_link (notebook->children, list);
4332   
4333   if (position <= 0 || !notebook->children)
4334     {
4335       list->next = notebook->children;
4336       if (list->next)
4337         list->next->prev = list;
4338       notebook->children = list;
4339     }
4340   else if (position > 0 && (work = g_list_nth (notebook->children, position)))
4341     {
4342       list->prev = work->prev;
4343       if (list->prev)
4344         list->prev->next = list;
4345       list->next = work;
4346       work->prev = list;
4347     }
4348   else
4349     {
4350       work = g_list_last (notebook->children);
4351       work->next = list;
4352       list->prev = work;
4353     }
4354
4355   if (notebook->menu)
4356     {
4357       GtkWidget *menu_item;
4358
4359       g_assert(page != NULL);
4360
4361       menu_item = page->menu_label->parent;
4362       gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4363       gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4364       gtk_notebook_menu_item_create (notebook, list);
4365       gtk_widget_queue_resize (notebook->menu);
4366     }
4367
4368   gtk_notebook_update_labels (notebook);
4369
4370   if (notebook->show_tabs)
4371     {
4372       gtk_notebook_pages_allocate (notebook,
4373                                    &(GTK_WIDGET (notebook)->allocation));
4374       gtk_notebook_expose_tabs (notebook);
4375     }
4376 }