Index: gtk/gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.154
diff -u -b -B -p -r1.154 gtknotebook.c
--- gtk/gtknotebook.c	29 Mar 2003 00:19:49 -0000	1.154
+++ gtk/gtknotebook.c	14 May 2003 00:00:58 -0000
@@ -58,6 +58,14 @@ enum {
   STEP_NEXT
 };
 
+enum
+{
+  ARROW_LEFT = GTK_ARROW_LEFT,
+  ARROW_RIGHT = GTK_ARROW_RIGHT,
+  ARROW_LEFT_BEFORE = GTK_ARROW_LEFT | 4,
+  ARROW_RIGHT_BEFORE = GTK_ARROW_RIGHT | 4
+};
+
 enum {
   PROP_0,
   PROP_TAB_POS,
@@ -165,6 +173,8 @@ static void gtk_notebook_state_changed  
 static void gtk_notebook_draw_focus          (GtkWidget        *widget);
 static gint gtk_notebook_focus               (GtkWidget        *widget,
 					      GtkDirectionType  direction);
+static void gtk_notebook_style_set           (GtkWidget        *widget,
+					      GtkStyle         *previous);
 
 /*** GtkContainer Methods ***/
 static void gtk_notebook_set_child_property  (GtkContainer     *container,
@@ -356,6 +366,7 @@ gtk_notebook_class_init (GtkNotebookClas
   widget_class->state_changed = gtk_notebook_state_changed;
   widget_class->focus_in_event = gtk_notebook_focus_in;
   widget_class->focus = gtk_notebook_focus;
+  widget_class->style_set = gtk_notebook_style_set;
   
   container_class->add = gtk_notebook_add;
   container_class->remove = gtk_notebook_remove;
@@ -495,6 +506,38 @@ gtk_notebook_class_init (GtkNotebookClas
 								 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
 								 G_PARAM_READWRITE));
   
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_boolean ("has_secondary backward_stepper",
+								 _("Secondary backward stepper"),
+								 _("Display a second backward arrow button on the opposite end of the tab area"),
+								 FALSE,
+								 
+								 G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_boolean ("has_secondary_forward_stepper",
+								 _("Secondary forward stepper"),
+								 _("Display a second forward arrow button on the opposite end of the tab area"),
+								 FALSE,
+								 
+								 G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_boolean ("has_backward_stepper",
+								 _("Backward stepper"),
+								 _("Display the standard backward arrow button"),
+								 TRUE,
+								 
+                                                                   G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_boolean ("has_forward_stepper",
+								 _("Forward stepper"),
+								 _("Display the standard forward arrow button"),
+								 TRUE,
+								 
+                                                                   G_PARAM_READABLE));
+
   notebook_signals[SWITCH_PAGE] =
     g_signal_new ("switch_page",
 		  G_TYPE_FROM_CLASS (gobject_class),
@@ -624,6 +667,11 @@ gtk_notebook_init (GtkNotebook *notebook
   notebook->child_has_focus = FALSE;
   notebook->have_visible_child = FALSE;
   notebook->focus_out = FALSE;
+
+  notebook->has_before_previous = 0;
+  notebook->has_before_next     = 0;
+  notebook->has_after_previous  = 1;
+  notebook->has_after_next      = 1;
 }
 
 static gboolean
@@ -1459,56 +1507,89 @@ gtk_notebook_show_arrows (GtkNotebook *n
 
 static void
 gtk_notebook_get_arrow_rect (GtkNotebook  *notebook,
-			     GdkRectangle *rectangle)
+			     GdkRectangle *rectangle,
+			     guint         arrow)
 {
   GdkRectangle event_window_pos;
+  gboolean before = ((arrow & 4) != 0);
+  arrow = arrow & 3;
 
   if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
     {
-      rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
+      rectangle->width = ARROW_SIZE;
       rectangle->height = ARROW_SIZE;
 
       switch (notebook->tab_pos)
 	{
 	case GTK_POS_LEFT:
 	case GTK_POS_RIGHT:
+	  if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
+	      (!before && (notebook->has_after_previous != notebook->has_after_next))) 
 	  rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
-	  rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
+	  else if (arrow == GTK_ARROW_LEFT)
+	    rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
+	  else 
+	    rectangle->x = event_window_pos.x + event_window_pos.width / 2;
+	  rectangle->y = event_window_pos.y;
+	  if (!before)
+	    rectangle->y += event_window_pos.height - rectangle->height;
 	  break;
 	case GTK_POS_TOP:
 	case GTK_POS_BOTTOM:
+	  if (before)
+	    {
+	      if (arrow == GTK_ARROW_LEFT || !notebook->has_before_previous)
+		rectangle->x = event_window_pos.x;
+	      else
+		rectangle->x = event_window_pos.x + rectangle->width;
+	    }
+	  else
+	    {
+	      if (arrow == GTK_ARROW_RIGHT || !notebook->has_after_next)
 	  rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
+	      else
+		rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
+	    }
 	  rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
 	  break;
 	}
     }
 }
 
-static GtkArrowType
+static guint
 gtk_notebook_get_arrow (GtkNotebook *notebook,
 			gint         x,
 			gint         y)
 {
   GdkRectangle arrow_rect;
   GdkRectangle event_window_pos;
+  gint i;
+  gint x0, y0;
+  guint arrow[4];
+
+  arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : 0;
+  arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : 0;
+  arrow[2] = notebook->has_after_previous ? ARROW_LEFT : 0;
+  arrow[3] = notebook->has_after_next ? ARROW_RIGHT : 0;
 
   if (gtk_notebook_show_arrows (notebook))
     {
       gtk_notebook_get_event_window_position (notebook, &event_window_pos);
-      gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
+      for (i = 0; i < 4; i++) 
+	{ 
+	  if (arrow[i] == 0)
+	    continue;
       
-      x -= arrow_rect.x;
-      y -= arrow_rect.y;
+	  gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
       
-      if (y >= 0 && y < arrow_rect.height)
-	{
-	  if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
-	    return GTK_ARROW_LEFT;
-	  else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
-	    return GTK_ARROW_RIGHT;
+	  x0 = x - arrow_rect.x;
+	  y0 = y - arrow_rect.y;
+	  
+	  if (y0 >= 0 && y0 < arrow_rect.height &&
+	      x0 >= 0 && x0 < arrow_rect.width)
+	    return arrow[i];
 	}
     }
-      
   return 0;
 }
 
@@ -1535,7 +1616,7 @@ gtk_notebook_do_arrow (GtkNotebook    *n
 
 static gboolean
 gtk_notebook_arrow_button_press (GtkNotebook    *notebook,
-				 GtkArrowType    arrow,
+				 guint           arrow,
 				 GdkEventButton *event)
 {
   GtkWidget *widget = GTK_WIDGET (notebook);
@@ -1545,6 +1626,7 @@ gtk_notebook_arrow_button_press (GtkNote
   
   notebook->button = event->button;
   notebook->click_child = arrow;
+  arrow = arrow & 3;
   
   if (event->button == 1)
     {
@@ -1834,6 +1916,34 @@ gtk_notebook_draw_focus (GtkWidget *widg
     }
 }
 
+static void
+gtk_notebook_style_set  (GtkWidget *widget,
+			 GtkStyle  *previous)
+{
+  GtkNotebook *notebook;
+
+  gboolean has_before_previous;
+  gboolean has_before_next;
+  gboolean has_after_previous;
+  gboolean has_after_next;
+
+  notebook = GTK_NOTEBOOK (widget);
+  
+  gtk_widget_style_get (widget,
+                        "has_secondary_backward_stepper", &has_before_previous,
+                        "has_secondary_forward_stepper", &has_before_next,
+                        "has_backward_stepper", &has_after_previous,
+                        "has_forward_stepper", &has_after_next,
+                        NULL);
+  
+  notebook->has_before_previous = has_before_previous;
+  notebook->has_before_next = has_before_next;
+  notebook->has_after_previous = has_after_previous;
+  notebook->has_after_next = has_after_next;
+  
+  (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
+}
+
 /* Private GtkContainer Methods :
  * 
  * gtk_notebook_set_child_arg
@@ -2326,10 +2436,23 @@ gtk_notebook_redraw_arrows (GtkNotebook 
   if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
     {
       GdkRectangle rect;
+      gint i;
+      guint arrow[4];
 
-      gtk_notebook_get_arrow_rect (notebook, &rect);
+      arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : 0;
+      arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : 0;
+      arrow[2] = notebook->has_after_previous ? ARROW_LEFT : 0;
+      arrow[3] = notebook->has_after_next ? ARROW_RIGHT : 0;
+
+      for (i = 0; i < 4; i++) 
+	{
+	  if (arrow[i] == 0)
+	    continue;
+
+	  gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
       gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
     }
+    }
 }
 
 static gint
@@ -2341,7 +2464,7 @@ gtk_notebook_timer (GtkNotebook *noteboo
 
   if (notebook->timer)
     {
-      gtk_notebook_do_arrow (notebook, notebook->click_child);
+      gtk_notebook_do_arrow (notebook, notebook->click_child & 3);
 
       if (notebook->need_timer) 
 	{
@@ -2713,8 +2836,14 @@ gtk_notebook_paint (GtkWidget    *widget
 
   if (showarrow && notebook->scrollable) 
     {
-      gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
-      gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
+      if (notebook->has_after_previous)
+	gtk_notebook_draw_arrow (notebook, ARROW_LEFT);
+      if (notebook->has_after_next)
+	gtk_notebook_draw_arrow (notebook, ARROW_RIGHT);
+      if (notebook->has_before_previous)
+	gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
+      if (notebook->has_before_next)
+	gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
     }
   gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
 }
@@ -2817,11 +2946,9 @@ gtk_notebook_draw_arrow (GtkNotebook *no
   GtkWidget *widget;
   GdkRectangle arrow_rect;
 
-  gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
+  gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow);
 
-  g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
-  widget = GTK_WIDGET(notebook);
+  widget = GTK_WIDGET (notebook);
 
   if (GTK_WIDGET_DRAWABLE (notebook))
     {
@@ -2840,30 +2967,10 @@ gtk_notebook_draw_arrow (GtkNotebook *no
       else
         shadow_type = GTK_SHADOW_OUT;
 
-      if (arrow == GTK_ARROW_LEFT)
-	{
-	  if (notebook->focus_tab &&
-	      !gtk_notebook_search_page (notebook, notebook->focus_tab,
-					 STEP_PREV, TRUE))
-	    {
-	      shadow_type = GTK_SHADOW_ETCHED_IN;
-	      state_type = GTK_STATE_INSENSITIVE;
-	    }
-
-	  if (notebook->tab_pos == GTK_POS_LEFT ||
-	      notebook->tab_pos == GTK_POS_RIGHT)
-	    arrow = GTK_ARROW_UP;
-
-	  gtk_paint_arrow (widget->style, widget->window, state_type, 
-			   shadow_type, NULL, widget, "notebook",
-			   arrow, TRUE, 
-			   arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
-	}
-      else
-	{
+      arrow = arrow & 3;
 	  if (notebook->focus_tab &&
 	      !gtk_notebook_search_page (notebook, notebook->focus_tab,
-					 STEP_NEXT, TRUE))
+				     arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT, TRUE))
 	    {
 	      shadow_type = GTK_SHADOW_ETCHED_IN;
 	      state_type = GTK_STATE_INSENSITIVE;
@@ -2871,13 +2978,12 @@ gtk_notebook_draw_arrow (GtkNotebook *no
 
 	  if (notebook->tab_pos == GTK_POS_LEFT ||
 	      notebook->tab_pos == GTK_POS_RIGHT)
-	    arrow = GTK_ARROW_DOWN;
+	arrow = (arrow == GTK_ARROW_LEFT ? GTK_ARROW_UP : GTK_ARROW_DOWN);
 
 	   gtk_paint_arrow (widget->style, widget->window, state_type, 
 			    shadow_type, NULL, widget, "notebook",
-			    arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
-			    arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
-	}
+		       arrow, TRUE, arrow_rect.x, arrow_rect.y, 
+		       ARROW_SIZE, ARROW_SIZE);
     }
 }
 
@@ -2900,8 +3006,6 @@ gtk_notebook_pages_allocate (GtkNotebook
   gboolean showarrow = FALSE;
   gint tab_space = 0; 
   gint delta; 
-  gint x = 0;
-  gint y = 0;
   gint i;
   gint n = 1;
   gint old_fill = 0;
@@ -2967,20 +3071,22 @@ gtk_notebook_pages_allocate (GtkNotebook
 	      showarrow = TRUE;
 	      page = focus_tab->data; 
 
-	      tab_space = (allocation->width - TAB_OVERLAP -
-			   page->requisition.width -
-			   2 * (container->border_width + ARROW_SPACING +
-				ARROW_SIZE));
-	      x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
-		   container->border_width);
-
-	      page = notebook->children->data;
-	      if (notebook->tab_pos == GTK_POS_TOP)
-		y = (container->border_width +
-		     (page->requisition.height - ARROW_SIZE) / 2);
-	      else
-		y = (allocation->height - container->border_width - 
-		     ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
+	      tab_space = allocation->width - TAB_OVERLAP -
+		page->requisition.width - 2 * container->border_width;
+	      if (notebook->has_after_previous)
+		tab_space -= ARROW_SPACING + ARROW_SIZE;
+	      if (notebook->has_after_next)
+		tab_space -= ARROW_SPACING + ARROW_SIZE;
+	      if (notebook->has_before_previous)
+		{
+		  tab_space -= ARROW_SPACING + ARROW_SIZE;
+		  child_allocation.x += ARROW_SPACING + ARROW_SIZE;
+		}
+	      if (notebook->has_before_next)
+		{
+		  tab_space -= ARROW_SPACING + ARROW_SIZE;
+		  child_allocation.x += ARROW_SPACING + ARROW_SIZE;
+		}
 	    }
 	  break;
 	case GTK_POS_LEFT:
@@ -2998,22 +3104,16 @@ gtk_notebook_pages_allocate (GtkNotebook
 	    {
 	      showarrow = TRUE;
 	      page = focus_tab->data; 
-	      tab_space = (allocation->height -
-			   ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
-			   2 * container->border_width -
-			   page->requisition.height);
-	      y = allocation->height - container->border_width - ARROW_SIZE;  
-
-	      page = notebook->children->data;
-	      if (notebook->tab_pos == GTK_POS_LEFT)
-		x = (container->border_width +
-		     (page->requisition.width -
-		      (2 * ARROW_SIZE - ARROW_SPACING)) / 2); 
-	      else
-		x = (allocation->width - container->border_width -
-		     (2 * ARROW_SIZE - ARROW_SPACING) -
-		     (page->requisition.width -
-		      (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
+	      tab_space = allocation->height
+		- TAB_OVERLAP - 2 * container->border_width
+		- page->requisition.height;
+	      if (notebook->has_after_previous || notebook->has_after_next)
+		tab_space -= ARROW_SPACING + ARROW_SIZE;
+	      if (notebook->has_before_previous || notebook->has_before_next)
+		{
+		  tab_space -= ARROW_SPACING + ARROW_SIZE;
+		  child_allocation.y += ARROW_SPACING + ARROW_SIZE;
+		}
 	    }
 	  break;
 	}
Index: gtk/gtknotebook.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.h,v
retrieving revision 1.34
diff -u -b -B -p -r1.34 gtknotebook.h
--- gtk/gtknotebook.h	5 Oct 2002 23:15:39 -0000	1.34
+++ gtk/gtknotebook.h	14 May 2003 00:00:58 -0000
@@ -77,13 +77,18 @@ struct _GtkNotebook
   guint show_border        : 1;
   guint tab_pos            : 2;
   guint scrollable         : 1;
-  guint in_child           : 2;
-  guint click_child        : 2;
+  guint in_child           : 3;
+  guint click_child        : 3;
   guint button             : 2;
   guint need_timer         : 1;
   guint child_has_focus    : 1;
   guint have_visible_child : 1;
   guint focus_out          : 1;	/* Flag used by ::move-focus-out implementation */
+
+  guint has_before_previous : 1;
+  guint has_before_next     : 1;
+  guint has_after_previous  : 1;
+  guint has_after_next      : 1;
 };
 
 struct _GtkNotebookClass
