diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtkentry.c gtk+-2.2.2/gtk/gtkentry.c
--- gtk+-2.2.2.org/gtk/gtkentry.c	2003-06-08 12:18:02.000000000 -0400
+++ gtk+-2.2.2/gtk/gtkentry.c	2003-07-24 21:37:26.000000000 -0400
@@ -27,7 +27,7 @@
 #include <string.h>
 
 #include <pango/pango.h>
-
+#include <pango/pango-utils.h>
 #include "gdk/gdkkeysyms.h"
 #include "gtkbindings.h"
 #include "gtkcelleditable.h"
@@ -2017,10 +2017,7 @@ get_better_cursor_x (GtkEntry *entry,
                      gint      offset)
 {
   GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
-  GtkTextDirection keymap_direction =
-    (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-  GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
+  PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
   gboolean split_cursor;
   
   PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
@@ -2038,7 +2035,7 @@ get_better_cursor_x (GtkEntry *entry,
   if (split_cursor)
     return strong_pos.x / PANGO_SCALE;
   else
-    return (keymap_direction == widget_direction) ? strong_pos.x / PANGO_SCALE : weak_pos.x / PANGO_SCALE;
+    return (keymap_direction == entry->resolved_dir) ? strong_pos.x / PANGO_SCALE : weak_pos.x / PANGO_SCALE;
 }
 
 static void
@@ -2311,6 +2308,9 @@ static void
 gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
                                     GtkEntry  *entry)
 {
+  gtk_entry_reset_layout (entry);
+  gtk_entry_adjust_scroll (entry);
+  gtk_entry_ensure_layout (entry, FALSE);
   gtk_entry_queue_draw (entry);
 }
 
@@ -2592,6 +2592,24 @@ gtk_entry_create_layout (GtkEntry *entry
     }
   else
     {
+      PangoDirection p_dir;
+      
+      p_dir = pango_find_base_dir(entry->text,
+                                  entry->n_bytes);
+      if (p_dir == PANGO_DIRECTION_NEUTRAL)
+        {
+          if (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry)))
+            p_dir = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry))));
+          else
+            p_dir = gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_LTR ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
+        }
+
+      pango_context_set_base_dir (gtk_widget_get_pango_context (GTK_WIDGET(entry)), p_dir);
+
+      pango_layout_set_alignment (layout, p_dir);
+
+      entry->resolved_dir = p_dir;
+      
       if (entry->visible)
         {
           pango_layout_set_text (layout, entry->text, entry->n_bytes);
@@ -2766,10 +2784,7 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
                        CursorType type)
 {
   GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
-  GtkTextDirection keymap_direction =
-    (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-  GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
+  PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
   
   if (GTK_WIDGET_DRAWABLE (entry))
     {
@@ -2780,8 +2795,8 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
       gint xoffset = INNER_BORDER - entry->scroll_offset;
       gint strong_x, weak_x;
       gint text_area_height;
-      GtkTextDirection dir1 = GTK_TEXT_DIR_NONE;
-      GtkTextDirection dir2 = GTK_TEXT_DIR_NONE;
+      PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+      PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
       gint x1 = 0;
       gint x2 = 0;
       GdkGC *gc;
@@ -2794,7 +2809,7 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
                     "gtk-split-cursor", &split_cursor,
                     NULL);
 
-      dir1 = widget_direction;
+      dir1 = entry->resolved_dir;
       
       if (split_cursor)
         {
@@ -2802,13 +2817,13 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
 
           if (weak_x != strong_x)
             {
-              dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
+              dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
               x2 = weak_x;
             }
         }
       else
         {
-          if (keymap_direction == widget_direction)
+          if (keymap_direction == entry->resolved_dir)
             x1 = strong_x;
           else
             x1 = weak_x;
@@ -2821,16 +2836,18 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
 
       gc = _gtk_get_insertion_cursor_gc (widget, TRUE);
       _gtk_draw_insertion_cursor (widget, entry->text_area, gc,
-                                  &cursor_location, dir1,
-                                  dir2 != GTK_TEXT_DIR_NONE);
+                                  &cursor_location,
+                                  dir1 == PANGO_DIRECTION_LTR ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL ,
+                                  dir2 != PANGO_DIRECTION_NEUTRAL);
       g_object_unref (gc);
       
-      if (dir2 != GTK_TEXT_DIR_NONE)
+      if (dir2 != PANGO_DIRECTION_NEUTRAL)
         {
           cursor_location.x = xoffset + x2;
           gc = _gtk_get_insertion_cursor_gc (widget, FALSE);
           _gtk_draw_insertion_cursor (widget, entry->text_area, gc,
-                                      &cursor_location, dir2,
+                                      &cursor_location,
+                                      dir2 == PANGO_DIRECTION_LTR ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL,
                                       TRUE);
           g_object_unref (gc);
         }
@@ -2964,8 +2981,7 @@ gtk_entry_adjust_scroll (GtkEntry *entry
   pango_layout_line_get_extents (line, NULL, &logical_rect);
 
   /* Display as much text as we can */
-
-  if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_LTR)
+  if (entry->resolved_dir == PANGO_DIRECTION_LTR)
     {
       min_offset = 0;
       max_offset = MAX (min_offset, logical_rect.width / PANGO_SCALE - text_area_width);
@@ -3050,11 +3066,9 @@ gtk_entry_move_visually (GtkEntry *entry
       else
         {
           GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
-          GtkTextDirection keymap_direction =
-            (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-            GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+          PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
 
-          strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (entry));
+          strong = keymap_direction == entry->resolved_dir;
         }
       
       if (count > 0)
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtkentry.h gtk+-2.2.2/gtk/gtkentry.h
--- gtk+-2.2.2.org/gtk/gtkentry.h	2002-10-09 18:25:17.000000000 -0400
+++ gtk+-2.2.2/gtk/gtkentry.h	2003-07-23 21:45:16.000000000 -0400
@@ -73,6 +73,7 @@ struct _GtkEntry
   gint         selection_bound;
   
   PangoLayout *cached_layout;
+  PangoDirection resolved_dir;
   guint        cache_includes_preedit : 1;
 
   guint        need_im_reset : 1;
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtklabel.c gtk+-2.2.2/gtk/gtklabel.c
--- gtk+-2.2.2.org/gtk/gtklabel.c	2002-12-10 07:02:43.000000000 -0500
+++ gtk+-2.2.2/gtk/gtklabel.c	2003-07-23 22:45:07.000000000 -0400
@@ -32,6 +32,7 @@
 #include "gdk/gdkkeysyms.h"
 #include "gtkclipboard.h"
 #include <pango/pango.h>
+#include <pango/pango-utils.h>
 #include "gtkimagemenuitem.h"
 #include "gtkintl.h"
 #include "gtkseparatormenuitem.h"
@@ -1416,26 +1417,58 @@ gtk_label_ensure_layout (GtkLabel *label
   if (!label->layout)
     {
       PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
+      PangoDirection dir = pango_find_base_dir(label->text,
+                                               strlen(label->text));
+      gboolean flip_dir = FALSE;
+      PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(label));
+      
+      if (dir == PANGO_DIRECTION_RTL)
+        {
+          flip_dir = TRUE;
+          pango_context_set_base_dir(context, PANGO_DIRECTION_RTL);
+        }
+      else if (dir == PANGO_DIRECTION_LTR)
+        {
+          pango_context_set_base_dir(context, PANGO_DIRECTION_LTR);
+        }
+      else
+        {
+          /* Set dir according to widget dir. */
+          dir = (gtk_widget_get_direction (GTK_WIDGET (label)) == GTK_TEXT_DIR_LTR) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
+        }
+      label->resolved_dir = dir;
 
-      label->layout = gtk_widget_create_pango_layout (widget, label->text);
+      pango_context_set_base_dir(context, dir);
+          
 
+      label->layout = gtk_widget_create_pango_layout (widget, label->text);
+      
       if (label->effective_attrs)
         pango_layout_set_attributes (label->layout, label->effective_attrs);
       
       switch (label->jtype)
         {
         case GTK_JUSTIFY_LEFT:
-          align = PANGO_ALIGN_LEFT;
+          if (flip_dir)
+            align = PANGO_ALIGN_RIGHT;
+          else
+            align = PANGO_ALIGN_LEFT;
           break;
         case GTK_JUSTIFY_RIGHT:
-          align = PANGO_ALIGN_RIGHT;
+          if (flip_dir)
+            align = PANGO_ALIGN_LEFT;
+          else
+            align = PANGO_ALIGN_RIGHT;
           break;
         case GTK_JUSTIFY_CENTER:
           align = PANGO_ALIGN_CENTER;
           break;
         case GTK_JUSTIFY_FILL:
           /* FIXME: This just doesn't work to do this */
-          align = PANGO_ALIGN_LEFT;
+          if (flip_dir)
+            align = PANGO_ALIGN_RIGHT;
+          else
+            align = PANGO_ALIGN_LEFT;
           pango_layout_set_justify (label->layout, TRUE);
           break;
         default:
@@ -1670,7 +1703,7 @@ get_layout_location (GtkLabel  *label,
   misc = GTK_MISC (label);
   widget = GTK_WIDGET (label);
   
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+  if (label->resolved_dir == PANGO_DIRECTION_LTR)
     xalign = misc->xalign;
   else
     xalign = 1.0 - misc->xalign;
@@ -1679,7 +1712,7 @@ get_layout_location (GtkLabel  *label,
              xalign * (widget->allocation.width - widget->requisition.width)
              + 0.5);
 
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+  if (label->resolved_dir == PANGO_DIRECTION_LTR)
     x = MAX (x, widget->allocation.x + misc->xpad);
   else
     x = MIN (x,
@@ -1707,22 +1740,17 @@ gtk_label_draw_cursor (GtkLabel  *label,
     {
       GtkWidget *widget = GTK_WIDGET (label);
 
-      GtkTextDirection keymap_direction;
-      GtkTextDirection widget_direction;
+      PangoDirection keymap_direction;
       PangoRectangle strong_pos, weak_pos;
       gboolean split_cursor;
       PangoRectangle *cursor1 = NULL;
       PangoRectangle *cursor2 = NULL;
       GdkRectangle cursor_location;
-      GtkTextDirection dir1 = GTK_TEXT_DIR_NONE;
-      GtkTextDirection dir2 = GTK_TEXT_DIR_NONE;
+      PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+      PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
       GdkGC *gc;
 
-      keymap_direction =
-        (gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget))) == PANGO_DIRECTION_LTR) ?
-        GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-
-      widget_direction = gtk_widget_get_direction (widget);
+      keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget)));
 
       gtk_label_ensure_layout (label);
       
@@ -1733,7 +1761,7 @@ gtk_label_draw_cursor (GtkLabel  *label,
                     "gtk-split-cursor", &split_cursor,
                     NULL);
 
-      dir1 = widget_direction;
+      dir1 = label->resolved_dir;
       
       if (split_cursor)
         {
@@ -1742,13 +1770,13 @@ gtk_label_draw_cursor (GtkLabel  *label,
           if (strong_pos.x != weak_pos.x ||
               strong_pos.y != weak_pos.y)
             {
-              dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
+              dir2 = (label->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
               cursor2 = &weak_pos;
             }
         }
       else
         {
-          if (keymap_direction == widget_direction)
+          if (keymap_direction == label->resolved_dir)
             cursor1 = &strong_pos;
           else
             cursor1 = &weak_pos;
@@ -1761,11 +1789,12 @@ gtk_label_draw_cursor (GtkLabel  *label,
 
       gc = _gtk_get_insertion_cursor_gc (widget, TRUE);
       _gtk_draw_insertion_cursor (widget, widget->window, gc,
-                                  &cursor_location, dir1,
-                                  dir2 != GTK_TEXT_DIR_NONE);
+                                  &cursor_location,
+                                  dir1 == PANGO_DIRECTION_LTR ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL,
+                                  dir2 != PANGO_DIRECTION_NEUTRAL);
       g_object_unref (gc);
       
-      if (dir2 != GTK_TEXT_DIR_NONE)
+      if (dir2 != PANGO_DIRECTION_NEUTRAL)
         {
           cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
           cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
@@ -1774,7 +1803,9 @@ gtk_label_draw_cursor (GtkLabel  *label,
 
           gc = _gtk_get_insertion_cursor_gc (widget, FALSE);
           _gtk_draw_insertion_cursor (widget, widget->window, gc,
-                                      &cursor_location, dir2, TRUE);
+                                      &cursor_location,
+                                      dir2 == PANGO_DIRECTION_LTR ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL,
+                                      TRUE);
           g_object_unref (gc);
         }
     }
@@ -2784,10 +2815,7 @@ get_better_cursor (GtkLabel *label,
                    gint      *y)
 {
   GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (label)));
-  GtkTextDirection keymap_direction =
-    (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-  GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (label));
+  PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
   gboolean split_cursor;
   PangoRectangle strong_pos, weak_pos;
   
@@ -2807,7 +2835,7 @@ get_better_cursor (GtkLabel *label,
     }
   else
     {
-      if (keymap_direction == widget_direction)
+      if (keymap_direction == label->resolved_dir)
         {
           *x = strong_pos.x / PANGO_SCALE;
           *y = strong_pos.y / PANGO_SCALE;
@@ -2890,11 +2918,10 @@ gtk_label_move_visually (GtkLabel *label
       else
         {
           GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (label)));
-          GtkTextDirection keymap_direction =
-            (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-            GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+          PangoDirection keymap_direction =
+            gdk_keymap_get_direction (keymap);
 
-          strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (label));
+          strong = keymap_direction == label->resolved_dir;
         }
       
       if (count > 0)
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtklabel.h gtk+-2.2.2/gtk/gtklabel.h
--- gtk+-2.2.2.org/gtk/gtklabel.h	2002-10-05 19:15:36.000000000 -0400
+++ gtk+-2.2.2/gtk/gtklabel.h	2003-07-23 21:44:54.000000000 -0400
@@ -64,6 +64,7 @@ struct _GtkLabel
   guint   mnemonic_keyval;
   
   gchar  *text; 
+  PangoDirection resolved_dir;
   PangoAttrList *attrs;
   PangoAttrList *effective_attrs;
   
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtktextbtree.c gtk+-2.2.2/gtk/gtktextbtree.c
--- gtk+-2.2.2.org/gtk/gtktextbtree.c	2003-05-27 17:10:13.000000000 -0400
+++ gtk+-2.2.2/gtk/gtktextbtree.c	2003-07-17 20:51:47.000000000 -0400
@@ -57,13 +57,13 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <pango/pango-utils.h>
 #include "gtktexttag.h"
 #include "gtktexttagtable.h"
 #include "gtktextlayout.h"
 #include "gtktextiterprivate.h"
 #include "gtkdebug.h"
 #include "gtktextmarkprivate.h"
-
 /*
  * Types
  */
@@ -554,6 +554,178 @@ _gtk_text_btree_segments_changed (GtkTex
  * Indexable segment mutation
  */
 
+/*
+ *  The following function is responsible for resolving the bidi direction
+ *  for the lines between start and end. But it also calculates any
+ *  dependent bidi direction for surrounding lines that change as a result
+ *  of the bidi direction decisions within the range. The function is
+ *  trying to do as little propagation as is needed.
+ */
+static void
+_gtk_text_btree_resolve_bidi(GtkTextIter *start,
+                             GtkTextIter *end)
+{
+  GtkTextBTree *tree = _gtk_text_iter_get_btree (start);
+  GtkTextLine *start_line, *end_line, *start_line_prev, *end_line_next, *line;
+  PangoDirection last_strong, dir_above_propagated, dir_below_propagated;
+
+  /* Resolve the strong bidi direction for all lines between
+   * start and end.
+  */
+  start_line = _gtk_text_iter_get_text_line(start);
+  start_line_prev = _gtk_text_line_previous(start_line);
+  end_line = _gtk_text_iter_get_text_line (end);
+  end_line_next = _gtk_text_line_next(end_line);
+  
+  line = start_line;
+  last_strong = PANGO_DIRECTION_NEUTRAL;
+  while(line && line != end_line_next)
+    {
+      PangoDirection p_dir;
+      
+      /* Loop through the segments and search for a strong character
+       */
+      GtkTextLineSegment *seg = line->segments;
+      line->dir_strong = PANGO_DIRECTION_NEUTRAL;
+      
+      while(seg)
+        {
+          if (seg->byte_count > 0)
+            {
+              p_dir = pango_find_base_dir(seg->body.chars,
+                                          seg->byte_count);
+              if (p_dir != PANGO_DIRECTION_NEUTRAL)
+                {
+                  line->dir_strong = p_dir;
+
+                  /* Remember the first resolved non-neutral paragraph */
+                  if (last_strong == PANGO_DIRECTION_NEUTRAL)
+                    last_strong = PANGO_DIRECTION_NEUTRAL;
+                  break;
+                }
+            }
+          seg = seg->next;
+        }
+
+      line = _gtk_text_line_next(line);
+    }
+
+  /* Sweep forward */
+
+  /* The variable above_strong contains the forward propagated direction
+   * before start. It is neutral if start is in the beginning of the buffer.
+   */
+  dir_above_propagated = PANGO_DIRECTION_NEUTRAL;
+  if (start_line_prev)
+    dir_above_propagated = start_line_prev->dir_propagated_forward;
+
+  /* Loop forward and propagate the direction of each paragraph 
+   * to all neutral lines.
+   */
+  line = start_line;
+  last_strong = dir_above_propagated;
+  while(line != end_line_next)
+    {
+      if (line->dir_strong != PANGO_DIRECTION_NEUTRAL)
+        last_strong = line->dir_strong;
+
+      line->dir_propagated_forward = last_strong;
+
+      line = _gtk_text_line_next(line);
+    }
+
+  /* Continue propagating as long as the previous resolved forward
+   * is different from last_strong.
+   */
+  {
+    GtkTextIter end_propagate;
+    
+    while(line
+          && line->dir_strong == PANGO_DIRECTION_NEUTRAL
+          && line->dir_propagated_forward != last_strong
+          )
+      {
+        GtkTextLine *prev = line;
+        line->dir_propagated_forward = last_strong;
+        
+        line = _gtk_text_line_next(line);
+        if (!line)
+          {
+            line = prev;
+            break;
+          }
+      }
+
+    /* The last character to invalidate is the last line before the
+     * line with the strong character. Or in case of the end of the
+     * buffer, the last line of the buffer. (There seems to be an
+     * extra "virtual" last line in the buffer that must not be used
+     * calling _gtk_text_btree_get_iter_at_line (causes crash). Thus the
+     * _gtk_text_line_previous is ok in that case as well.)
+     */
+    line = _gtk_text_line_previous(line);
+    _gtk_text_btree_get_iter_at_line (tree, &end_propagate, line, 0);
+    _gtk_text_btree_invalidate_region(tree, end, &end_propagate);
+  }
+  
+  /* Sweep backward */
+
+  /* The variable below_strong contains the backward propagated direction
+   * after end. It is neutral if end is at the beginning of the buffer.
+  */
+  dir_below_propagated = PANGO_DIRECTION_NEUTRAL;
+  if (end_line_next)
+    dir_below_propagated = end_line_next->dir_propagated_back;
+
+  /* Loop backward and propagate the direction of each paragraph 
+   * to all neutral lines.
+   */
+  line = end_line;
+  last_strong = dir_below_propagated;
+  while (line != start_line_prev)
+    {
+      if (line->dir_strong != PANGO_DIRECTION_NEUTRAL)
+        last_strong = line->dir_strong;
+
+      line->dir_propagated_back = last_strong;
+
+      line = _gtk_text_line_previous(line);
+    }
+
+  /* Continue propagating as long as the resolved backward dir
+   * is different from last_strong.
+   */
+  {
+    GtkTextIter start_propagate;
+
+    while (line
+           && line->dir_strong == PANGO_DIRECTION_NEUTRAL
+           && line->dir_propagated_back != last_strong)
+      {
+        GtkTextLine *prev = line;
+        line->dir_propagated_back = last_strong;
+
+        line = _gtk_text_line_previous(line);
+        if (!line)
+          {
+            line = prev;
+            break;
+          }
+      }
+
+    /* We only need to invalidate for backwards propagation if on
+     * the line we ended up at, there is no valid dir_propagated_forward.
+     * rendering.
+     */
+    if (line && line->dir_propagated_forward == PANGO_DIRECTION_NEUTRAL)
+      {
+        _gtk_text_btree_get_iter_at_line (tree, &start_propagate, line, 0);
+        _gtk_text_btree_invalidate_region(tree, &start_propagate, start);
+      }
+  }
+}
+
 void
 _gtk_text_btree_delete (GtkTextIter *start,
                         GtkTextIter *end)
@@ -884,6 +1056,8 @@ _gtk_text_btree_delete (GtkTextIter *sta
   /* Re-initialize our iterators */
   _gtk_text_btree_get_iter_at_line (tree, start, start_line, start_byte_offset);
   *end = *start;
+  
+  _gtk_text_btree_resolve_bidi(start, end);
 }
 
 void
@@ -1031,7 +1205,6 @@ _gtk_text_btree_insert (GtkTextIter *ite
     GtkTextIter start;
     GtkTextIter end;
 
-
     _gtk_text_btree_get_iter_at_line (tree,
                                       &start,
                                       start_line,
@@ -1050,6 +1223,8 @@ _gtk_text_btree_insert (GtkTextIter *ite
 
     /* Convenience for the user */
     *iter = end;
+    
+    _gtk_text_btree_resolve_bidi(&start, &end);
   }
 }
 
@@ -4489,6 +4664,9 @@ gtk_text_line_new (void)
   GtkTextLine *line;
 
   line = g_new0(GtkTextLine, 1);
+  line->dir_strong = PANGO_DIRECTION_NEUTRAL;
+  line->dir_propagated_forward = PANGO_DIRECTION_NEUTRAL;
+  line->dir_propagated_back = PANGO_DIRECTION_NEUTRAL;
 
   return line;
 }
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtktextbtree.h gtk+-2.2.2/gtk/gtktextbtree.h
--- gtk+-2.2.2.org/gtk/gtktextbtree.h	2002-09-23 15:20:48.000000000 -0400
+++ gtk+-2.2.2/gtk/gtktextbtree.h	2003-07-16 20:01:33.000000000 -0400
@@ -212,6 +212,9 @@ struct _GtkTextLine {
   GtkTextLineSegment *segments; /* First in ordered list of segments
                                  * that make up the line. */
   GtkTextLineData *views;      /* data stored here by views */
+  PangoDirection dir_strong;                /* BiDi algo dir of line */
+  PangoDirection dir_propagated_back;       /* BiDi algo dir of next line */
+  PangoDirection dir_propagated_forward;    /* BiDi algo dir of prev line */
 };
 
 
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtktextlayout.c gtk+-2.2.2/gtk/gtktextlayout.c
--- gtk+-2.2.2.org/gtk/gtktextlayout.c	2003-06-05 19:08:57.000000000 -0400
+++ gtk+-2.2.2/gtk/gtktextlayout.c	2003-07-16 20:26:08.000000000 -0400
@@ -110,6 +110,24 @@ static void gtk_text_layout_invalidate_a
 
 static PangoAttribute *gtk_text_attr_appearance_new (const GtkTextAppearance *appearance);
 
+static void gtk_text_layout_mark_set_handler (GtkTextBuffer     *buffer,
+                                              const GtkTextIter *location,
+                                              GtkTextMark       *mark,
+                                              gpointer           data);
+
+static void gtk_text_layout_buffer_insert_text(GtkTextBuffer *textbuffer,
+                                               GtkTextIter   *iter,
+                                               gchar         *str,
+                                               gint           len,
+                                               gpointer data);
+
+static void gtk_text_layout_buffer_delete_range (GtkTextBuffer *textbuffer,
+                                                GtkTextIter *start,
+                                                GtkTextIter *end,
+                                                gpointer data);
+
+static void gtk_text_layout_update_cursor_line (GtkTextLayout     *layout);
+
 enum {
   INVALIDATED,
   CHANGED,
@@ -282,6 +300,16 @@ gtk_text_layout_set_buffer (GtkTextLayou
       _gtk_text_btree_remove_view (_gtk_text_buffer_get_btree (layout->buffer),
                                   layout);
 
+      g_signal_handlers_disconnect_by_func (layout->buffer, 
+                                            G_CALLBACK (gtk_text_layout_mark_set_handler), 
+                                            layout);
+      g_signal_handlers_disconnect_by_func (layout->buffer, 
+                                            G_CALLBACK (gtk_text_layout_buffer_insert_text), 
+                                            layout);
+      g_signal_handlers_disconnect_by_func (layout->buffer, 
+                                            G_CALLBACK (gtk_text_layout_buffer_delete_range), 
+                                            layout);
+
       g_object_unref (layout->buffer);
       layout->buffer = NULL;
     }
@@ -293,6 +321,14 @@ gtk_text_layout_set_buffer (GtkTextLayou
       g_object_ref (buffer);
 
       _gtk_text_btree_add_view (_gtk_text_buffer_get_btree (buffer), layout);
+
+      /* Bind to all signals that move the insert mark. */
+      g_signal_connect_after (layout->buffer, "mark_set",
+                              G_CALLBACK (gtk_text_layout_mark_set_handler), layout);
+      g_signal_connect_after (layout->buffer, "insert_text",
+                              G_CALLBACK (gtk_text_layout_buffer_insert_text), layout);
+      g_signal_connect_after (layout->buffer, "delete_range",
+                              G_CALLBACK (gtk_text_layout_buffer_delete_range), layout);
     }
 }
 
@@ -349,11 +385,14 @@ gtk_text_layout_set_contexts (GtkTextLay
 }
 
 /**
- * gtk_text_layout_set_cursor_direction:
- * @direction: the new direction(s) for which to draw cursors.
+ * gtk_text_layout_set_cursor_and_keyboard_direction:
+ * @cursor_dir: the new direction(s) for which to draw cursors.
  *             %GTK_TEXT_DIR_NONE means draw cursors for both
  *             left-to-right insertion and right-to-left insertion.
  *             (The two cursors will be visually distinguished.)
+ * @keyboard_dir: the current direction of the keyboard. This direction
+ *              is used for setting the BiDi base direction if the
+ *              line contains only neutral characters.
  * 
  * Sets which text directions (left-to-right and/or right-to-left) for
  * which cursors will be drawn for the insertion point. The visual
@@ -362,16 +401,20 @@ gtk_text_layout_set_contexts (GtkTextLay
  * make the drawn position of the cursor depend on the keyboard state.
  **/
 void
-gtk_text_layout_set_cursor_direction (GtkTextLayout   *layout,
-                                      GtkTextDirection direction)
+gtk_text_layout_set_cursor_and_keyboard_direction (GtkTextLayout   *layout,
+                                                   GtkTextDirection cursor_dir,
+                                                   GtkTextDirection keyboard_dir)
 {
-  if (direction != layout->cursor_direction)
+  if (cursor_dir != layout->cursor_direction
+      || keyboard_dir != layout->keyboard_direction)
     {
-      layout->cursor_direction = direction;
+      layout->cursor_direction = cursor_dir;
+      layout->keyboard_direction = keyboard_dir;
       gtk_text_layout_invalidate_cursor_line (layout);
     }
 }
 
+
 /**
  * gtk_text_layout_get_buffer:
  * @layout: a #GtkTextLayout
@@ -702,24 +745,32 @@ gtk_text_layout_invalidate_cache (GtkTex
 static void
 gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout)
 {
-  GtkTextIter iter;
-  GtkTextLine *line;
   GtkTextLineData *line_data;
 
-  gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
-                                    gtk_text_buffer_get_mark (layout->buffer, "insert"));
+  if (layout->cursor_line == NULL)
+    return;
   
-  line = _gtk_text_iter_get_text_line (&iter);
-  line_data = _gtk_text_line_get_data (line, layout);
+  line_data = _gtk_text_line_get_data (layout->cursor_line, layout);
   if (line_data)
     {
-      gtk_text_layout_invalidate_cache (layout, line);
-      _gtk_text_line_invalidate_wrap (line, line_data);
+      gtk_text_layout_invalidate_cache (layout, layout->cursor_line);
+      _gtk_text_line_invalidate_wrap (layout->cursor_line, line_data);
       gtk_text_layout_invalidated (layout);
     }
 }
 
 static void
+gtk_text_layout_update_cursor_line(GtkTextLayout *layout)
+{
+  GtkTextIter iter;
+
+  gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
+                                    gtk_text_buffer_get_mark (layout->buffer, "insert"));
+  
+  layout->cursor_line = _gtk_text_iter_get_text_line (&iter);
+}
+
+static void
 gtk_text_layout_real_invalidate (GtkTextLayout *layout,
                                  const GtkTextIter *start,
                                  const GtkTextIter *end)
@@ -1128,26 +1179,46 @@ totally_invisible_line (GtkTextLayout *l
 
 static void
 set_para_values (GtkTextLayout      *layout,
+                 PangoDirection base_dir,
                  GtkTextAttributes *style,
                  GtkTextLineDisplay *display)
 {
   PangoAlignment pango_align = PANGO_ALIGN_LEFT;
   int layout_width;
 
+  switch (base_dir)
+    {
+    /* If no base direction was found, then use the style direction */
+    case PANGO_DIRECTION_NEUTRAL :
-   display->direction = style->direction;
+      display->direction = style->direction;
 
-  if (display->direction == GTK_TEXT_DIR_LTR)
-    display->layout = pango_layout_new (layout->ltr_context);
+      /* Override the base direction */
+      if (display->direction == GTK_TEXT_DIR_RTL)
+        base_dir = PANGO_DIRECTION_RTL;
-   else
+      else
+        base_dir = PANGO_DIRECTION_LTR;
+      
+      break;
+    case PANGO_DIRECTION_RTL :
+      display->direction = GTK_TEXT_DIR_RTL;
+      break;
+    default:
+      display->direction = GTK_TEXT_DIR_LTR;
+      break;
+    }
+  
+  if (display->direction == GTK_TEXT_DIR_RTL)
     display->layout = pango_layout_new (layout->rtl_context);
+  else
+    display->layout = pango_layout_new (layout->ltr_context);
 
   switch (style->justification)
     {
     case GTK_JUSTIFY_LEFT:
-      pango_align = (style->direction == GTK_TEXT_DIR_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
+      pango_align = (base_dir == PANGO_DIRECTION_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
       break;
     case GTK_JUSTIFY_RIGHT:
-      pango_align = (style->direction == GTK_TEXT_DIR_LTR) ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+      pango_align = (base_dir == PANGO_DIRECTION_LTR) ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
       break;
     case GTK_JUSTIFY_CENTER:
       pango_align = PANGO_ALIGN_CENTER;
@@ -1697,6 +1768,7 @@ gtk_text_layout_get_line_display (GtkTex
   GSList *cursor_segs = NULL;
   GSList *tmp_list1, *tmp_list2;
   gboolean saw_widget = FALSE;
+  PangoDirection base_dir;
   
   g_return_val_if_fail (line != NULL, NULL);
 
@@ -1729,6 +1801,19 @@ gtk_text_layout_get_line_display (GtkTex
   if (totally_invisible_line (layout, line, &iter))
     return display;
 
+  /* Find the bidi base direction */
+  base_dir = line->dir_propagated_forward;
+  if (base_dir == PANGO_DIRECTION_NEUTRAL)
+      base_dir = line->dir_propagated_back;
+
+  if (line == layout->cursor_line &&
+      line->dir_strong == PANGO_DIRECTION_NEUTRAL)
+    {
+      GtkTextDirection dir = layout->keyboard_direction;
+
+      base_dir = (dir == GTK_TEXT_DIR_LTR) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
+    }
+  
   /* Allocate space for flat text for buffer
    */
   text_allocated = _gtk_text_line_byte_count (line);
@@ -1759,7 +1844,7 @@ gtk_text_layout_get_line_display (GtkTex
            */
           if (!para_values_set)
             {
-              set_para_values (layout, style, display);
+              set_para_values (layout, base_dir, style, display);
               para_values_set = TRUE;
             }
 
@@ -1928,7 +2013,7 @@ gtk_text_layout_get_line_display (GtkTex
   if (!para_values_set)
     {
       style = get_style (layout, &iter);
-      set_para_values (layout, style, display);
+      set_para_values (layout, base_dir, style, display);
       release_style (layout, style);
     }
   
@@ -3065,3 +3150,40 @@ gtk_text_layout_spew (GtkTextLayout *lay
           layout->height, layout->screen_width);
 #endif
 }
+
+/* Catch all situations that move the insertion point.
+ */
+static void
+gtk_text_layout_mark_set_handler (GtkTextBuffer     *buffer,
+                                  const GtkTextIter *location,
+                                  GtkTextMark       *mark,
+                                  gpointer           data)
+{
+  GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
+
+  if (mark == gtk_text_buffer_get_insert (buffer))
+    gtk_text_layout_update_cursor_line(layout);
+}
+
+static void
+gtk_text_layout_buffer_insert_text(GtkTextBuffer *textbuffer,
+                                   GtkTextIter   *iter,
+                                   gchar         *str,
+                                   gint           len,
+                                   gpointer       data)
+{
+  GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
+
+  gtk_text_layout_update_cursor_line(layout);
+}
+
+static void
+gtk_text_layout_buffer_delete_range(GtkTextBuffer *textbuffer,
+                                    GtkTextIter *start,
+                                    GtkTextIter *end,
+                                    gpointer data)
+{
+  GtkTextLayout *layout = GTK_TEXT_LAYOUT (data);
+
+  gtk_text_layout_update_cursor_line(layout);
+}
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtktextlayout.h gtk+-2.2.2/gtk/gtktextlayout.h
--- gtk+-2.2.2.org/gtk/gtktextlayout.h	2002-11-08 14:41:50.000000000 -0500
+++ gtk+-2.2.2/gtk/gtktextlayout.h	2003-07-16 20:01:33.000000000 -0400
@@ -165,6 +165,16 @@ struct _GtkTextLayout
    */
   guint cursor_direction : 2;
 
+  /* The keyboard direction is used to default the alignment when
+     there are no strong characters.
+  */
+  guint keyboard_direction : 2;
+
+  /* Cache the line that the cursor is positioned on, as the keyboard
+     direction only influences the direction of the cursor line.
+  */
+  GtkTextLine *cursor_line;
+  
   /* The preedit string and attributes, if any */
 
   gchar *preedit_string;
@@ -264,8 +274,9 @@ void               gtk_text_layout_set_d
 void               gtk_text_layout_set_contexts          (GtkTextLayout     *layout,
                                                           PangoContext      *ltr_context,
                                                           PangoContext      *rtl_context);
-void               gtk_text_layout_set_cursor_direction  (GtkTextLayout     *layout,
-                                                          GtkTextDirection   direction);
+void               gtk_text_layout_set_cursor_and_keyboard_direction  (GtkTextLayout     *layout,
+                                                          GtkTextDirection   cursor_dir,
+                                                          GtkTextDirection keyboard_dir);
 void               gtk_text_layout_default_style_changed (GtkTextLayout     *layout);
 
 void gtk_text_layout_set_screen_width       (GtkTextLayout     *layout,
diff --expand-tabs -r -up gtk+-2.2.2.org/gtk/gtktextview.c gtk+-2.2.2/gtk/gtktextview.c
--- gtk+-2.2.2.org/gtk/gtktextview.c	2003-06-05 19:04:36.000000000 -0400
+++ gtk+-2.2.2/gtk/gtktextview.c	2003-07-22 21:12:58.000000000 -0400
+      keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
+      
+      new_keyboard_dir 
+	  = (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
+	    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+
       if (split_cursor)
 	{
-	  new_dir = GTK_TEXT_DIR_NONE;
+	  new_cursor_dir = GTK_TEXT_DIR_NONE;
 	}
       else
 	{
-	  GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
-	  new_dir = (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
-	    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+	  new_cursor_dir = new_keyboard_dir;
 	}
-      
-      if (text_view->layout->cursor_direction != new_dir)
-	gtk_text_layout_set_cursor_direction (text_view->layout, new_dir);
+      gtk_text_layout_set_cursor_and_keyboard_direction (text_view->layout,
+							 new_cursor_dir,
+							 new_keyboard_dir);
     }
 }
