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