Index: gtk/gtkcalendar.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcalendar.c,v
retrieving revision 1.51
diff -u -p -r1.51 gtkcalendar.c
--- gtk/gtkcalendar.c	3 Jul 2003 01:02:03 -0000	1.51
+++ gtk/gtkcalendar.c	20 Jul 2003 22:00:19 -0000
@@ -43,6 +43,7 @@
 #include "gtkintl.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
+#include "gtkintl.h"
 #include "gdk/gdkkeysyms.h"
 
 /***************************************************************************/
@@ -269,6 +270,8 @@ struct _GtkCalendarPrivateData
   guint dirty_main : 1;
   guint dirty_week : 1;
 
+  guint year_before : 1;
+
   guint need_timer  : 1;
 
   guint32 timer;
@@ -577,6 +580,7 @@ gtk_calendar_init (GtkCalendar *calendar
   time_t tmp_time;
   GtkWidget *widget;
   GtkCalendarPrivateData *private_data;
+  gchar *year_before;
   
   widget = GTK_WIDGET (calendar);
   GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
@@ -639,10 +643,23 @@ gtk_calendar_init (GtkCalendar *calendar
   private_data->dirty_day_names = 0;
   private_data->dirty_week = 0;
   private_data->dirty_main = 0;
-
+  
   private_data->need_timer = 0;
   private_data->timer = 0;
   private_data->click_child = -1;
+
+  private_data->year_before = 0;
+
+  /* Translate to calendar:YM if you want years to be displayed
+   * before months; otherwise translate to calendar:MY.
+   * Do *not* translate it to anything else, if it
+   * it isn't calendar:YM or calendar:MY it will not work.
+   */
+  year_before = _("calendar:MY");
+  if (strcmp (year_before, "calendar:YM") == 0)
+    private_data->year_before = 1;
+  else if (strcmp (year_before, "calendar:MY") != 0)
+    g_warning ("Whoever translated calendar:MY did so wrongly.\n");
 }
 
 GtkWidget*
@@ -996,12 +1013,18 @@ gtk_calendar_realize_arrows (GtkWidget *
   GdkWindowAttr attributes;
   gint attributes_mask;
   gint i;
+  gboolean year_left;
   
   g_return_if_fail (GTK_IS_CALENDAR (widget));
   
   calendar = GTK_CALENDAR (widget);
   private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
 
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+    year_left = private_data->year_before;
+  else
+    year_left = !private_data->year_before;
+    
   /* Arrow windows ------------------------------------- */
   if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
       && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
@@ -1022,18 +1045,34 @@ gtk_calendar_realize_arrows (GtkWidget *
 	  switch (i)
 	    {
 	    case ARROW_MONTH_LEFT:
+	      if (year_left) 
+		attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
+				- (3 + 2*private_data->arrow_width 
+				   + private_data->max_month_width));
+	      else
 	      attributes.x = 3;
 	      break;
 	    case ARROW_MONTH_RIGHT:
+	      if (year_left) 
+		attributes.x = (widget->allocation.width - 2 * widget->style->xthickness 
+				- 3 - private_data->arrow_width);
+	      else
 	      attributes.x = (private_data->arrow_width 
 			      + private_data->max_month_width);
 	      break;
 	    case ARROW_YEAR_LEFT:
+	      if (year_left) 
+		attributes.x = 3;
+	      else
 	      attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
 			      - (3 + 2*private_data->arrow_width 
 				 + private_data->max_year_width));
 	      break;
 	    case ARROW_YEAR_RIGHT:
+	      if (year_left) 
+		attributes.x = (private_data->arrow_width 
+				+ private_data->max_year_width);
+	      else
 	      attributes.x = (widget->allocation.width - 2 * widget->style->xthickness 
 			      - 3 - private_data->arrow_width);
 	      break;
@@ -1477,11 +1516,17 @@ gtk_calendar_size_allocate (GtkWidget	  
   GtkCalendarPrivateData *private_data;
   gint xthickness = widget->style->xthickness;
   gint ythickness = widget->style->xthickness;
+  gboolean year_left;
   
   widget->allocation = *allocation;
   
   calendar = GTK_CALENDAR (widget);
   private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+    year_left = private_data->year_before;
+  else
+    year_left = !private_data->year_before;
   
   if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
     {
@@ -1512,53 +1557,115 @@ gtk_calendar_size_allocate (GtkWidget	  
 				xthickness, ythickness,
 				allocation->width - 2 * xthickness, private_data->header_h);
       if (private_data->arrow_win[ARROW_MONTH_LEFT])
-	gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
-				3, 3,
-				private_data->arrow_width,
-				private_data->header_h - 7);
+	{
+	  if (year_left)
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
+				    (allocation->width - 2 * xthickness
+				     - (3 + 2*private_data->arrow_width 
+					+ private_data->max_month_width)),
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	  else
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
+				    3, 3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	}
       if (private_data->arrow_win[ARROW_MONTH_RIGHT])
-	gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
-				(private_data->arrow_width 
-				 + private_data->max_month_width), 
-				3,
-				private_data->arrow_width,
-				private_data->header_h - 7);
+	{
+	  if (year_left)
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
+				    (allocation->width - 2 * xthickness 
+				     - 3 - private_data->arrow_width), 
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	  else
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
+				    (private_data->arrow_width 
+				     + private_data->max_month_width), 
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	}
       if (private_data->arrow_win[ARROW_YEAR_LEFT])
-	gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
-				(allocation->width - 2 * xthickness
-				 - (3 + 2*private_data->arrow_width 
-				    + private_data->max_year_width)),
-				3,
-				private_data->arrow_width,
-				private_data->header_h - 7);
+	{
+	  if (year_left)
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
+				    3, 3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	  else
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
+				    (allocation->width - 2 * xthickness
+				     - (3 + 2*private_data->arrow_width 
+					+ private_data->max_year_width)),
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	}
       if (private_data->arrow_win[ARROW_YEAR_RIGHT])
-	gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
-				(allocation->width - 2 * xthickness 
-				 - 3 - private_data->arrow_width), 
-				3,
-				private_data->arrow_width,
-				private_data->header_h - 7);
+	{
+	  if (year_left)
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
+				    (private_data->arrow_width 
+				     + private_data->max_year_width), 
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	  else
+	    gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
+				    (allocation->width - 2 * xthickness 
+				     - 3 - private_data->arrow_width), 
+				    3,
+				    private_data->arrow_width,
+				    private_data->header_h - 7);
+	}
       if (private_data->day_name_win)
 	gdk_window_move_resize (private_data->day_name_win,
 				xthickness + INNER_BORDER,
 				private_data->header_h + (widget->style->ythickness + INNER_BORDER),
 				allocation->width - (xthickness + INNER_BORDER) * 2,
 				private_data->day_name_h);
-      if (private_data->week_win)
-	gdk_window_move_resize (private_data->week_win,
-				(xthickness + INNER_BORDER),
-				private_data->header_h + private_data->day_name_h
-				+ (widget->style->ythickness + INNER_BORDER),
-				private_data->week_width,
-				private_data->main_h);
-      gdk_window_move_resize (private_data->main_win,
-			      private_data->week_width + (xthickness + INNER_BORDER),
-			      private_data->header_h + private_data->day_name_h
-			      + (widget->style->ythickness + INNER_BORDER),
-			      allocation->width 
-			      - private_data->week_width 
-			      - (xthickness + INNER_BORDER) * 2,
-			      private_data->main_h);
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+	{
+	  if (private_data->week_win)
+	    gdk_window_move_resize (private_data->week_win,
+				    (xthickness + INNER_BORDER),
+				    private_data->header_h + private_data->day_name_h
+				    + (widget->style->ythickness + INNER_BORDER),
+				    private_data->week_width,
+				    private_data->main_h);
+	  gdk_window_move_resize (private_data->main_win,
+				  private_data->week_width + (xthickness + INNER_BORDER),
+				  private_data->header_h + private_data->day_name_h
+				  + (widget->style->ythickness + INNER_BORDER),
+				  allocation->width 
+				  - private_data->week_width 
+				  - (xthickness + INNER_BORDER) * 2,
+				  private_data->main_h);
+	}
+      else 
+	{
+	  gdk_window_move_resize (private_data->main_win,
+				  (xthickness + INNER_BORDER),
+				  private_data->header_h + private_data->day_name_h
+				  + (widget->style->ythickness + INNER_BORDER),
+				  allocation->width 
+				  - private_data->week_width 
+				  - (xthickness + INNER_BORDER) * 2,
+				  private_data->main_h);
+	  if (private_data->week_win)
+	    gdk_window_move_resize (private_data->week_win,
+				    allocation->width 
+				    - private_data->week_width 
+				    - (xthickness + INNER_BORDER),
+				    private_data->header_h + private_data->day_name_h
+				    + (widget->style->ythickness + INNER_BORDER),
+				    private_data->week_width,
+				    private_data->main_h);
+	}
     }
 }
 
@@ -1609,6 +1716,7 @@ gtk_calendar_paint_header (GtkWidget *wi
   GtkCalendarPrivateData *private_data;
   PangoLayout *layout;
   PangoRectangle logical_rect;
+  gboolean year_left;
 
   calendar = GTK_CALENDAR (widget);
   private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
@@ -1618,6 +1726,12 @@ gtk_calendar_paint_header (GtkWidget *wi
       private_data->dirty_header = 1;
       return;
     }
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+    year_left = private_data->year_before;
+  else
+    year_left = !private_data->year_before;
+
   private_data->dirty_header = 0;
   gc = calendar->gc;
   
@@ -1647,12 +1761,18 @@ gtk_calendar_paint_header (GtkWidget *wi
   /* Draw year and its arrows */
   
   if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
-    x = header_width - (3 + max_year_width
-			- (max_year_width - logical_rect.width)/2);
+    if (year_left)
+      x = 3 + (max_year_width - logical_rect.width)/2;
+    else
+      x = header_width - (3 + max_year_width
+			  - (max_year_width - logical_rect.width)/2);
   else
-    x = header_width - (3 + private_data->arrow_width + max_year_width
-			- (max_year_width - logical_rect.width)/2);
-    
+    if (year_left)
+      x = 3 + private_data->arrow_width + (max_year_width - logical_rect.width)/2;
+    else
+      x = header_width - (3 + private_data->arrow_width + max_year_width
+			  - (max_year_width - logical_rect.width)/2);
+  
   
   gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
   gdk_draw_layout (private_data->header_win, gc, x, y, layout);
@@ -1663,8 +1783,16 @@ gtk_calendar_paint_header (GtkWidget *wi
   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
 
   if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
+    if (year_left)
+      x = header_width - (3 + max_month_width
+			  - (max_month_width - logical_rect.width)/2);      
+    else
     x = 3 + (max_month_width - logical_rect.width) / 2;
   else
+    if (year_left)
+      x = header_width - (3 + private_data->arrow_width + max_month_width
+			  - (max_month_width - logical_rect.width)/2);
+    else
     x = 3 + private_data->arrow_width + (max_month_width - logical_rect.width)/2;
 
   gdk_draw_layout (private_data->header_win, gc, x, y, layout);
@@ -1765,8 +1893,9 @@ gtk_calendar_paint_day_names (GtkWidget 
 
       gdk_draw_layout (private_data->day_name_win, gc, 
 		       (CALENDAR_MARGIN +
-			+ private_data->week_width
-			+ (private_data->week_width ? CALENDAR_XSEP : 0)
+			+ (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
+			   (private_data->week_width + (private_data->week_width ? CALENDAR_XSEP : 0))
+			   : 0)
 			+ day_wid_sep * i
 			+ (day_width - logical_rect.width)/2),
 		       CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y,
@@ -2895,6 +3024,35 @@ gtk_calendar_finalize (GObject *object)
     (* G_OBJECT_CLASS (parent_class)->finalize) (object);
 }
 
+static void 
+move_focus (GtkCalendar *calendar, 
+	    gint direction)
+{
+  GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar));
+
+  if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) ||
+      (text_dir == GTK_TEXT_DIR_RTL && direction == 1)) 
+    {
+      if (calendar->focus_col > 0)
+	  calendar->focus_col--;
+      else if (calendar->focus_row > 0)
+	{
+	  calendar->focus_col = 6;
+	  calendar->focus_row--;
+	}
+    }
+  else 
+    {
+      if (calendar->focus_col < 6)
+	calendar->focus_col++;
+      else if (calendar->focus_row < 5)
+	{
+	  calendar->focus_col = 0;
+	  calendar->focus_row++;
+	}
+    }
+}
+
 static gboolean
 gtk_calendar_key_press (GtkWidget   *widget,
 			GdkEventKey *event)
@@ -2917,20 +3075,10 @@ gtk_calendar_key_press (GtkWidget   *wid
     case GDK_Left:
       return_val = TRUE;
       if (event->state & GDK_CONTROL_MASK)
-	{
-	  gtk_calendar_set_month_prev (calendar);
-	}
+	gtk_calendar_set_month_prev (calendar);
       else
 	{
-	  if (calendar->focus_col > 0)
-	    {
-	      calendar->focus_col--;
-	    }
-	  else if (calendar->focus_row > 0)
-	    {
-	      calendar->focus_col = 6;
-	      calendar->focus_row--;
-	    }
+	  move_focus (calendar, -1);
 	  gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
 	  gtk_calendar_paint_day (widget, calendar->focus_row,
 				  calendar->focus_col);
@@ -2940,20 +3088,10 @@ gtk_calendar_key_press (GtkWidget   *wid
     case GDK_Right:
       return_val = TRUE;
       if (event->state & GDK_CONTROL_MASK)
-	{
 	gtk_calendar_set_month_next (calendar);
-	}
       else
 	{
-	  if (calendar->focus_col < 6)
-	    {
-	      calendar->focus_col++;
-	    }
-	  else if (calendar->focus_row < 5)
-	    {
-	      calendar->focus_col = 0;
-	      calendar->focus_row++;
-	    }
+	  move_focus (calendar, 1);
 	  gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
 	  gtk_calendar_paint_day (widget, calendar->focus_row,
 				  calendar->focus_col);
@@ -2963,15 +3101,11 @@ gtk_calendar_key_press (GtkWidget   *wid
     case GDK_Up:
       return_val = TRUE;
       if (event->state & GDK_CONTROL_MASK)
-	{
-	  gtk_calendar_set_year_prev (calendar);
-	}
+	gtk_calendar_set_year_prev (calendar);
       else
 	{
 	  if (calendar->focus_row > 0)
-	    {
-	      calendar->focus_row--;
-	    }
+	    calendar->focus_row--;
 	  gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
 	  gtk_calendar_paint_day (widget, calendar->focus_row,
 				  calendar->focus_col);
@@ -2981,15 +3115,11 @@ gtk_calendar_key_press (GtkWidget   *wid
     case GDK_Down:
       return_val = TRUE;
       if (event->state & GDK_CONTROL_MASK)
-	{
-	  gtk_calendar_set_year_next (calendar);
-	}
+	gtk_calendar_set_year_next (calendar);
       else
 	{
 	  if (calendar->focus_row < 5)
-	    {
-	      calendar->focus_row++;
-	    }
+	    calendar->focus_row++;
 	  gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
 	  gtk_calendar_paint_day (widget, calendar->focus_row,
 				  calendar->focus_col);
@@ -3007,13 +3137,9 @@ gtk_calendar_key_press (GtkWidget   *wid
 	  gtk_calendar_freeze (calendar);	  
 
 	  if (calendar->day_month[row][col] == MONTH_PREV)
-	    {
-	      gtk_calendar_set_month_prev (calendar);
-	    }
+	    gtk_calendar_set_month_prev (calendar);
 	  else if (calendar->day_month[row][col] == MONTH_NEXT)
-	    {
-	      gtk_calendar_set_month_next (calendar);
-	    }
+	    gtk_calendar_set_month_next (calendar);
 
 	  gtk_calendar_select_and_focus_day (calendar, day);
 	  
