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