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