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