diff --git gtk/gtktextdisplay.c gtk/gtktextdisplay.c
index 42928f1..e65003c 100644
--- gtk/gtktextdisplay.c
+++ gtk/gtktextdisplay.c
@@ -81,6 +81,7 @@
 #include "gtkstylecontextprivate.h"
 #include "gtkintl.h"
 
+#include <math.h>
 /* DO NOT go putting private headers in here. This file should only
  * use the semi-public headers, as with gtktextview.c.
  */
@@ -572,6 +573,8 @@ render_para (GtkTextRenderer    *text_renderer,
   GdkRGBA selection;
   gboolean first = TRUE;
 
+  gboolean write_vertical = FALSE;
+
   iter = pango_layout_get_iter (layout);
 
   pango_layout_iter_get_layout_extents (iter, NULL, &layout_logical);
@@ -585,6 +588,7 @@ render_para (GtkTextRenderer    *text_renderer,
 
   context = gtk_widget_get_style_context (text_renderer->widget);
   state = gtk_widget_get_state_flags (text_renderer->widget);
+  write_vertical = gtk_text_view_get_write_vertical (GTK_TEXT_VIEW(text_renderer->widget));
 
   state |= GTK_STATE_FLAG_SELECTED;
 
@@ -634,17 +638,27 @@ render_para (GtkTextRenderer    *text_renderer,
 
           cairo_save (cr);
           gdk_cairo_set_source_rgba (cr, &selection);
-          cairo_rectangle (cr, 
+
+          if(write_vertical)
+            cairo_rotate(cr, M_PI/2);
+          
+          cairo_rectangle (cr,
                            line_display->left_margin, selection_y,
                            screen_width, selection_height);
           cairo_fill (cr);
           cairo_restore(cr);
 
-	  text_renderer_set_state (text_renderer, SELECTED);
-	  pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
-					   line, 
-					   line_rect.x,
-					   baseline);
+          text_renderer_set_state (text_renderer, SELECTED);
+          cairo_save(text_renderer->cr);
+
+          if(write_vertical)
+            cairo_rotate(text_renderer->cr, M_PI/2);
+    
+          pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
+                                           line, 
+                                           line_rect.x,
+                                           baseline);
+          cairo_restore(text_renderer->cr);
         }
       else
         {
@@ -654,7 +668,7 @@ render_para (GtkTextRenderer    *text_renderer,
 
               cairo_save (cr);
  
-	      gdk_cairo_set_source_rgba (text_renderer->cr, line_display->pg_bg_rgba);
+              gdk_cairo_set_source_rgba (text_renderer->cr, line_display->pg_bg_rgba);
               cairo_rectangle (cr, 
                                line_display->left_margin, selection_y,
                                screen_width, selection_height);
@@ -663,26 +677,34 @@ render_para (GtkTextRenderer    *text_renderer,
               cairo_restore (cr);
             }
         
-	  text_renderer_set_state (text_renderer, NORMAL);
-	  pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
-					   line, 
-					   line_rect.x,
-					   baseline);
-
-	  /* Check if some part of the line is selected; the newline
-	   * that is after line->length for the last line of the
-	   * paragraph counts as part of the line for this
-	   */
+          text_renderer_set_state (text_renderer, NORMAL);
+
+          cairo_save(text_renderer->cr);
+
+          if(write_vertical)
+            cairo_rotate(text_renderer->cr, M_PI/2);
+
+          pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
+                                           line, 
+                                           line_rect.x,
+                                           baseline);
+
+          cairo_restore(text_renderer->cr);
+
+          /* Check if some part of the line is selected; the newline
+           * that is after line->length for the last line of the
+           * paragraph counts as part of the line for this
+           */
           if ((selection_start_index < byte_offset + line->length ||
-	       (selection_start_index == byte_offset + line->length && pango_layout_iter_at_last_line (iter))) &&
-	      selection_end_index > byte_offset)
+               (selection_start_index == byte_offset + line->length && pango_layout_iter_at_last_line (iter))) &&
+              selection_end_index > byte_offset)
             {
               cairo_t *cr = text_renderer->cr;
               cairo_region_t *clip_region = get_selected_clip (text_renderer, layout, line,
-                                                          line_display->x_offset,
-                                                          selection_y,
-                                                          selection_height,
-                                                          selection_start_index, selection_end_index);
+                                                               line_display->x_offset,
+                                                               selection_y,
+                                                               selection_height,
+                                                               selection_start_index, selection_end_index);
 
               cairo_save (cr);
               gdk_cairo_region (cr, clip_region);
@@ -690,6 +712,10 @@ render_para (GtkTextRenderer    *text_renderer,
               cairo_region_destroy (clip_region);
 
               gdk_cairo_set_source_rgba (cr, &selection);
+
+              if(write_vertical )
+                cairo_rotate(cr, M_PI/2);
+
               cairo_rectangle (cr,
                                PANGO_PIXELS (line_rect.x),
                                selection_y,
@@ -697,11 +723,15 @@ render_para (GtkTextRenderer    *text_renderer,
                                selection_height);
               cairo_fill (cr);
 
-	      text_renderer_set_state (text_renderer, SELECTED);
-	      pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
-					       line, 
-					       line_rect.x,
-					       baseline);
+              text_renderer_set_state (text_renderer, SELECTED);
+
+              if(write_vertical)
+                cairo_rotate(text_renderer->cr, M_PI/2);
+
+              pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
+                                               line, 
+                                               line_rect.x,
+                                               baseline);
 
               cairo_restore (cr);
 
@@ -713,6 +743,10 @@ render_para (GtkTextRenderer    *text_renderer,
                   cairo_save (cr);
 
                   gdk_cairo_set_source_rgba (cr, &selection);
+
+                  if(write_vertical)
+                    cairo_rotate(cr, M_PI/2);
+
                   cairo_rectangle (cr,
                                    line_display->left_margin,
                                    selection_y,
@@ -737,6 +771,10 @@ render_para (GtkTextRenderer    *text_renderer,
                   cairo_save (cr);
 
                   gdk_cairo_set_source_rgba (cr, &selection);
+
+                  if(write_vertical)
+                    cairo_rotate(cr, M_PI/2);
+
                   cairo_rectangle (cr,
                                    PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width),
                                    selection_y,
@@ -747,13 +785,13 @@ render_para (GtkTextRenderer    *text_renderer,
                   cairo_restore (cr);
                 }
             }
-	  else if (line_display->has_block_cursor &&
-		   gtk_widget_has_focus (text_renderer->widget) &&
-		   byte_offset <= line_display->insert_index &&
-		   (line_display->insert_index < byte_offset + line->length ||
-		    (at_last_line && line_display->insert_index == byte_offset + line->length)))
-	    {
-	      GdkRectangle cursor_rect;
+          else if (line_display->has_block_cursor &&
+                   gtk_widget_has_focus (text_renderer->widget) &&
+                   byte_offset <= line_display->insert_index &&
+                   (line_display->insert_index < byte_offset + line->length ||
+                    (at_last_line && line_display->insert_index == byte_offset + line->length)))
+            {
+              GdkRectangle cursor_rect;
               GdkRGBA cursor_color;
               cairo_t *cr = text_renderer->cr;
 
@@ -761,13 +799,16 @@ render_para (GtkTextRenderer    *text_renderer,
                * (normally white on black) */
               _gtk_style_context_get_cursor_color (context, &cursor_color, NULL);
 
-	      cursor_rect.x = line_display->x_offset + line_display->block_cursor.x;
-	      cursor_rect.y = line_display->block_cursor.y + line_display->top_margin;
-	      cursor_rect.width = line_display->block_cursor.width;
-	      cursor_rect.height = line_display->block_cursor.height;
+              cursor_rect.x = line_display->x_offset + line_display->block_cursor.x;
+              cursor_rect.y = line_display->block_cursor.y + line_display->top_margin;
+              cursor_rect.width = line_display->block_cursor.width;
+              cursor_rect.height = line_display->block_cursor.height;
 
               cairo_save (cr);
 
+              if(write_vertical)
+                cairo_rotate(cr, M_PI/2);
+
               gdk_cairo_rectangle (cr, &cursor_rect);
               cairo_clip (cr);
 
@@ -784,16 +825,16 @@ render_para (GtkTextRenderer    *text_renderer,
 
                   gdk_cairo_set_source_rgba (cr, &color);
 
-		  text_renderer_set_state (text_renderer, CURSOR);
+                  text_renderer_set_state (text_renderer, CURSOR);
 
-		  pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
-						   line,
-						   line_rect.x,
-						   baseline);
+                  pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer),
+                                                   line,
+                                                   line_rect.x,
+                                                   baseline);
                 }
 
               cairo_restore (cr);
-	    }
+            }
         }
 
       byte_offset += line->length;
@@ -829,6 +870,8 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   GSList *tmp_list;
   GList *tmp_widgets;
   GdkRectangle clip;
+  gboolean write_vertical;
+  gboolean first = TRUE;
 
   g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
   g_return_if_fail (layout->default_style != NULL);
@@ -838,6 +881,7 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   if (!gdk_cairo_get_clip_rectangle (cr, &clip))
     return;
 
+  write_vertical = gtk_text_view_get_write_vertical(GTK_TEXT_VIEW(widget));
   context = gtk_widget_get_style_context (widget);
 
   line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, &offset_y);
@@ -849,6 +893,7 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   text_renderer_begin (text_renderer, widget, cr);
 
   /* text_renderer_begin/end does cairo_save/restore */
+  
   cairo_translate (cr, 0, offset_y);
 
   gtk_text_layout_wrap_loop_start (layout);
@@ -881,8 +926,8 @@ gtk_text_layout_draw (GtkTextLayout *layout,
                                                 &line_start,
                                                 line, 0);
               line_end = line_start;
-	      if (!gtk_text_iter_ends_line (&line_end))
-		gtk_text_iter_forward_to_line_end (&line_end);
+              if (!gtk_text_iter_ends_line (&line_end))
+                gtk_text_iter_forward_to_line_end (&line_end);
               byte_count = gtk_text_iter_get_visible_line_index (&line_end);     
 
               if (gtk_text_iter_compare (&selection_start, &line_end) <= 0 &&
@@ -900,6 +945,12 @@ gtk_text_layout_draw (GtkTextLayout *layout,
                 }
             }
 
+          if (first && write_vertical)
+            {
+              cairo_translate(cr, line_display->height, offset_y);
+              first = FALSE;
+            }
+
           render_para (text_renderer, line_display,
                        selection_start_index, selection_end_index);
 
@@ -917,14 +968,26 @@ gtk_text_layout_draw (GtkTextLayout *layout,
 
                   index = g_array_index(line_display->cursors, int, i);
                   dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
-                  gtk_render_insertion_cursor (context, cr,
-                                               line_display->x_offset, line_display->top_margin,
-                                               line_display->layout, index, dir);
+                  if (!write_vertical)
+                    {
+                      gtk_render_insertion_cursor (context, cr,
+                                                   line_display->x_offset, line_display->top_margin,
+                                                   line_display->layout, index, dir);
+                    }
+                  else
+                    {
+                      cairo_save(cr);
+                      cairo_rotate(cr, M_PI/2);
+                      gtk_render_insertion_cursor (context, cr,
+                                                   line_display->x_offset, line_display->top_margin,
+                                                   line_display->layout, index, dir);
+                      cairo_restore(cr);
+                    }
                 }
             }
         } /* line_display->height > 0 */
-
-      cairo_translate (cr, 0, line_display->height);
+      write_vertical ? cairo_translate (cr, line_display->height, 0) : cairo_translate (cr, 0, line_display->height);
+      
       gtk_text_layout_free_line_display (layout, line_display);
       
       tmp_list = g_slist_next (tmp_list);
diff --git gtk/gtktextview.c gtk/gtktextview.c
index 61961ec..f16f04f 100644
--- gtk/gtktextview.c
+++ gtk/gtktextview.c
@@ -52,6 +52,7 @@
 #include "gtkwindow.h"
 #include "gtkscrollable.h"
 #include "gtktypebuiltins.h"
+#include <math.h>
 
 #include "a11y/gtktextviewaccessible.h"
 
@@ -231,6 +232,9 @@ struct _GtkTextViewPrivate
    * driving the scrollable adjustment values */
   guint hscroll_policy : 1;
   guint vscroll_policy : 1;
+
+  /* vertical writing */
+  guint write_vertical : 1;
 };
 
 struct _GtkTextPendingScroll
@@ -283,7 +287,8 @@ enum
   PROP_HADJUSTMENT,
   PROP_VADJUSTMENT,
   PROP_HSCROLL_POLICY,
-  PROP_VSCROLL_POLICY
+  PROP_VSCROLL_POLICY,
+  PROP_WRITE_VERTICAL
 };
 
 static void gtk_text_view_finalize             (GObject          *object);
@@ -811,6 +816,14 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
 							       P_("Color with which to draw error-indication underlines"),
 							       GDK_TYPE_COLOR,
 							       GTK_PARAM_READABLE));
+  /* Write vertical */
+  g_object_class_install_property (gobject_class,
+                                   PROP_WRITE_VERTICAL,
+                                   g_param_spec_boolean ("write-vertical",
+							 P_("Write vertical"),
+							 P_("Writes in top to bottom direction"),
+							 TRUE,
+							 GTK_PARAM_READWRITE));
   
   /*
    * Signals
@@ -1418,6 +1431,9 @@ gtk_text_view_init (GtkTextView *text_view)
 
   priv->pending_place_cursor_button = 0;
 
+  /* default, no vertical write */
+  priv->write_vertical = FALSE;
+
   /* We handle all our own redrawing */
   gtk_widget_set_redraw_on_allocate (widget, FALSE);
 }
@@ -1665,10 +1681,13 @@ gtk_text_view_get_cursor_locations (GtkTextView       *text_view,
                                     GdkRectangle      *weak)
 {
   GtkTextIter insert;
+  gboolean write_vertical = FALSE;
+  int tmp;
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
   g_return_if_fail (iter == NULL ||
                     gtk_text_iter_get_buffer (iter) == get_buffer (text_view));
+  write_vertical = gtk_text_view_get_write_vertical (text_view);
 
   gtk_text_view_ensure_layout (text_view);
 
@@ -1680,6 +1699,28 @@ gtk_text_view_get_cursor_locations (GtkTextView       *text_view,
 
   gtk_text_layout_get_cursor_locations (text_view->priv->layout, &insert,
                                         strong, weak);
+  if (write_vertical)
+    {
+      if (strong )
+        {
+          tmp = strong->x;
+          strong->x = strong->y;
+          strong->y = tmp;
+          tmp = strong->height;
+          strong->height = strong->width;
+          strong->width = tmp;
+        }
+      if ( weak )
+        {
+          tmp = weak->x;
+          weak->x = weak->y;
+          weak->y = tmp;
+          tmp = weak->height;
+          weak->height = weak->width;
+          weak->width = tmp;
+        }
+    }
+
 }
 
 /**
@@ -3172,6 +3213,10 @@ gtk_text_view_set_property (GObject         *object,
       gtk_widget_queue_resize (GTK_WIDGET (text_view));
       break;
 
+    case PROP_WRITE_VERTICAL:
+      gtk_text_view_set_write_vertical(text_view, g_value_get_boolean(value));
+      break;
+      
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -4563,10 +4608,15 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
           GtkTextIter iter;
           GtkTextIter start, end;
 
-          gtk_text_layout_get_iter_at_pixel (priv->layout,
-                                             &iter,
-                                             event->x + priv->xoffset,
-                                             event->y + priv->yoffset);
+          priv->write_vertical ?
+            gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                               &iter,
+                                               event->y + priv->yoffset,
+                                               event->x + priv->xoffset)
+            : gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                                 &iter,
+                                                 event->x + priv->xoffset,
+                                                 event->y + priv->yoffset);
 
           if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
                                                     &start, &end) &&
@@ -4594,7 +4644,12 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
              with the middle button */
           priv->scroll_after_paste = FALSE;
 
-          gtk_text_layout_get_iter_at_pixel (priv->layout,
+          priv->write_vertical ?
+            gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                               &iter,
+                                               event->y + priv->yoffset,
+                                               event->x + priv->xoffset)
+            : gtk_text_layout_get_iter_at_pixel (priv->layout,
                                              &iter,
                                              event->x + priv->xoffset,
                                              event->y + priv->yoffset);
@@ -4614,10 +4669,15 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
 
       gtk_text_view_end_selection_drag (text_view);
 
-      gtk_text_layout_get_iter_at_pixel (priv->layout,
-					 &iter,
-					 event->x + priv->xoffset,
-					 event->y + priv->yoffset);
+      priv->write_vertical ?
+            gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                               &iter,
+                                               event->y + priv->yoffset,
+                                               event->x + priv->xoffset)
+            : gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                             &iter,
+                                             event->x + priv->xoffset,
+                                             event->y + priv->yoffset);
       
       gtk_text_view_start_selection_drag (text_view, &iter, event);
       return TRUE;
@@ -4631,10 +4691,11 @@ gtk_text_view_button_release_event (GtkWidget *widget, GdkEventButton *event)
 {
   GtkTextView *text_view;
   GtkTextViewPrivate *priv;
-
+  gboolean write_vertical = FALSE;
   text_view = GTK_TEXT_VIEW (widget);
   priv = text_view->priv;
 
+  write_vertical = priv->write_vertical;
   if (event->window != priv->text_window->bin_window)
     return FALSE;
 
@@ -4656,10 +4717,15 @@ gtk_text_view_button_release_event (GtkWidget *widget, GdkEventButton *event)
            * didn't move by the drag threshold, so just clear selection
            * and place cursor.
            */
-	  gtk_text_layout_get_iter_at_pixel (priv->layout,
-					     &iter,
-					     event->x + priv->xoffset,
-					     event->y + priv->yoffset);
+          write_vertical
+            ? gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                                 &iter,
+                                                 event->y + priv->yoffset,
+                                                 event->x + priv->xoffset)
+            : gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                                 &iter,
+                                                 event->x + priv->xoffset,
+                                                 event->y + priv->yoffset);
 
 	  gtk_text_buffer_place_cursor (get_buffer (text_view), &iter);
 	  gtk_text_view_check_cursor_blink (text_view);
@@ -6143,6 +6209,34 @@ gtk_text_view_set_accepts_tab (GtkTextView *text_view,
 }
 
 /**
+ *
+ * Write in top to bottom direction
+ *
+ **/
+void
+gtk_text_view_set_write_vertical (GtkTextView *text_view,
+                                  gboolean wv)
+{
+  GdkRectangle visible_rect;
+  g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+  wv = wv != FALSE;
+  if (text_view->priv->write_vertical != wv)
+    {
+      text_view->priv->write_vertical = wv;
+
+      gtk_text_view_get_visible_rect (text_view, &visible_rect);
+      text_window_invalidate_rect (text_view->priv->text_window,
+                                       &visible_rect);
+      queue_update_im_spot_location (text_view);
+    }
+}
+gboolean
+gtk_text_view_get_write_vertical(GtkTextView *text_view)
+{
+  g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+  return text_view->priv->write_vertical;
+}
+/**
  * gtk_text_view_get_accepts_tab:
  * @text_view: A #GtkTextView
  * 
@@ -8550,6 +8644,7 @@ text_window_invalidate_rect (GtkTextWindow *win,
                              GdkRectangle  *rect)
 {
   GdkRectangle window_rect;
+  gboolean write_vertical = FALSE;
 
   gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (win->widget),
                                          win->type,
@@ -8558,8 +8653,17 @@ text_window_invalidate_rect (GtkTextWindow *win,
                                          &window_rect.x,
                                          &window_rect.y);
 
-  window_rect.width = rect->width;
-  window_rect.height = rect->height;
+  write_vertical = gtk_text_view_get_write_vertical (GTK_TEXT_VIEW (win->widget));
+  if (write_vertical )
+    {
+      window_rect.width = rect->height;
+      window_rect.height = rect->width;
+    }
+  else
+    {
+      window_rect.width = rect->width;
+      window_rect.height = rect->height;
+    }
   
   /* Adjust the rect as appropriate */
   
@@ -8611,15 +8715,27 @@ text_window_invalidate_cursors (GtkTextWindow *win)
   gfloat       cursor_aspect_ratio;
   gint         stem_width;
   gint         arrow_width;
-
+  gboolean write_vertical = FALSE;
+  gint tmp;
   text_view = GTK_TEXT_VIEW (win->widget);
   priv = text_view->priv;
 
+  write_vertical = priv->write_vertical;
+
   gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter,
                                     gtk_text_buffer_get_insert (priv->buffer));
 
   if (_gtk_text_layout_get_block_cursor (priv->layout, &strong))
     {
+      if(write_vertical)
+        {
+          tmp = strong.x;
+          strong.x = strong.y;
+          strong.y = tmp;
+          tmp = strong.height;
+          strong.height = strong.width;
+          strong.width = tmp;
+        }
       text_window_invalidate_rect (win, &strong);
       return;
     }
@@ -8655,6 +8771,16 @@ text_window_invalidate_cursors (GtkTextWindow *win)
       strong.width += arrow_width * 2;
     }
 
+  if(write_vertical)
+    {
+      tmp = strong.x;
+      strong.x = strong.y;
+      strong.y = tmp;
+      tmp = strong.height;
+      strong.height = strong.width;
+      strong.width = tmp;
+    }
+
   text_window_invalidate_rect (win, &strong);
 
   if (draw_arrow) /* == have weak */
@@ -8674,6 +8800,15 @@ text_window_invalidate_cursors (GtkTextWindow *win)
       weak.x     -= arrow_width;
       weak.width += arrow_width * 2;
 
+      if(write_vertical)
+        {
+          tmp = weak.x;
+          weak.x = weak.y;
+          weak.y = tmp;
+          tmp = weak.height;
+          weak.height = weak.width;
+          weak.width = tmp;
+        }
       text_window_invalidate_rect (win, &weak);
     }
 }
@@ -8806,17 +8941,34 @@ buffer_to_widget (GtkTextView      *text_view,
                   gint             *window_y)
 {
   GtkTextViewPrivate *priv = text_view->priv;
-
-  if (window_x)
+  gboolean write_vertical = gtk_text_view_get_write_vertical (text_view);
+  if (!write_vertical)
     {
-      *window_x = buffer_x - priv->xoffset;
-      *window_x += priv->text_window->allocation.x;
-    }
+      if (window_x)
+        {
+          *window_x = buffer_x - priv->xoffset;
+          *window_x += priv->text_window->allocation.x;
+        }
 
-  if (window_y)
+      if (window_y)
+        {
+          *window_y = buffer_y - priv->yoffset;
+          *window_y += priv->text_window->allocation.y;
+        }
+    }
+  else
     {
-      *window_y = buffer_y - priv->yoffset;
-      *window_y += priv->text_window->allocation.y;
+      if (window_x)
+        {
+          *window_x = buffer_y - priv->yoffset;
+          *window_x += priv->text_window->allocation.y;
+        }
+
+      if (window_y)
+        {
+          *window_y = buffer_x - priv->xoffset;
+          *window_y += priv->text_window->allocation.x;
+        }
     }
 }
 
@@ -8884,7 +9036,8 @@ gtk_text_view_buffer_to_window_coords (GtkTextView      *text_view,
                                        gint             *window_y)
 {
   GtkTextViewPrivate *priv = text_view->priv;
-
+  gboolean write_vertical = gtk_text_view_get_write_vertical (text_view);
+  
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
 
   switch (win)
@@ -8897,9 +9050,9 @@ gtk_text_view_buffer_to_window_coords (GtkTextView      *text_view,
 
     case GTK_TEXT_WINDOW_TEXT:
       if (window_x)
-        *window_x = buffer_x - priv->xoffset;
+        *window_x = (write_vertical) ? buffer_y - priv->yoffset : buffer_x - priv->xoffset;
       if (window_y)
-        *window_y = buffer_y - priv->yoffset;
+        *window_y = (write_vertical) ? buffer_x - priv->xoffset : buffer_y - priv->yoffset;
       break;
 
     case GTK_TEXT_WINDOW_LEFT:
diff --git gtk/gtktextview.h gtk/gtktextview.h
index 62bd8d1..4bb82e3 100644
--- gtk/gtktextview.h
+++ gtk/gtktextview.h
@@ -253,6 +253,11 @@ void             gtk_text_view_set_overwrite          (GtkTextView      *text_vi
 gboolean         gtk_text_view_get_overwrite          (GtkTextView      *text_view);
 void		 gtk_text_view_set_accepts_tab        (GtkTextView	*text_view,
 						       gboolean		 accepts_tab);
+/* write vertical */
+void             gtk_text_view_set_write_vertical     (GtkTextView	    *text_view,
+						       gboolean		 wv);
+gboolean         gtk_text_view_get_write_vertical     (GtkTextView      *text_view);
+
 gboolean	 gtk_text_view_get_accepts_tab        (GtkTextView	*text_view);
 void             gtk_text_view_set_pixels_above_lines (GtkTextView      *text_view,
                                                        gint              pixels_above_lines);
