Index: src/vteft2.c
===================================================================
--- src/vteft2.c	(revision 1482)
+++ src/vteft2.c	(working copy)
@@ -130,6 +130,7 @@
 					  data->rgb,
 					  data->left, data->top);
 	}
+	gdk_gc_set_clip_region(widget->style->fg_gc[state], NULL);
 }
 
 static void
@@ -165,6 +166,14 @@
 	data->pixbuf = bgpixbuf;
 }
 
+static void
+_vte_ft2_clip(struct _vte_draw *draw, GdkRegion *region)
+{
+	gdk_gc_set_clip_region(
+			draw->widget->style->fg_gc[GTK_WIDGET_STATE(draw->widget)],
+		       	region);
+}
+
 static inline void
 update_bbox(struct _vte_ft2_data *data, gint x, gint y, gint width, gint height)
 {
@@ -377,6 +386,7 @@
 	_vte_ft2_set_background_color,
 	_vte_ft2_set_background_image,
 	FALSE,
+	_vte_ft2_clip,
 	_vte_ft2_clear,
 	_vte_ft2_set_text_font,
 	_vte_ft2_get_text_width,
Index: src/vtexft.c
===================================================================
--- src/vtexft.c	(revision 1482)
+++ src/vtexft.c	(working copy)
@@ -420,6 +420,32 @@
 }
 
 static void
+_vte_xft_clip(struct _vte_draw *draw,
+	       GdkRegion *region)
+{
+	struct _vte_xft_data *data = draw->impl_data;
+	GdkRectangle *rect;
+	gint i, n;
+
+	gdk_region_get_rectangles(region, &rect, &n);
+	if (n>0) {
+		XRectangle *xrect = g_new (XRectangle, n);
+		for (i=0; i<n; i++) {
+			xrect[i].x = rect[i].x;
+			xrect[i].y = rect[i].y;
+			xrect[i].width = rect[i].width;
+			xrect[i].height = rect[i].height;
+		}
+		XSetClipRectangles(data->display, data->gc,
+				0, 0,
+				xrect, n,
+				YXBanded);
+		g_free (xrect);
+	}
+	g_free(rect);
+}
+
+static void
 _vte_xft_clear(struct _vte_draw *draw,
 	       gint x, gint y, gint width, gint height)
 {
@@ -774,6 +800,7 @@
 	_vte_xft_set_background_color,
 	_vte_xft_set_background_image,
 	FALSE,
+	_vte_xft_clip,
 	_vte_xft_clear,
 	_vte_xft_set_text_font,
 	_vte_xft_get_text_width,
Index: src/vtegl.c
===================================================================
--- src/vtegl.c	(revision 1482)
+++ src/vtegl.c	(working copy)
@@ -606,6 +606,7 @@
 	_vte_gl_set_background_color,
 	_vte_gl_set_background_image,
 	TRUE,
+	NULL,
 	_vte_gl_clear,
 	_vte_gl_set_text_font,
 	_vte_gl_get_text_width,
Index: src/vtedraw.c
===================================================================
--- src/vtedraw.c	(revision 1482)
+++ src/vtedraw.c	(working copy)
@@ -233,6 +233,19 @@
 	return draw->impl->requires_repaint;
 }
 
+gboolean
+_vte_draw_clip(struct _vte_draw *draw, GdkRegion *clip)
+{
+	g_return_val_if_fail(draw->impl != NULL, FALSE);
+	if (draw->impl->requires_repaint) {
+		return FALSE;
+	}
+	if (draw->impl->clip) {
+		draw->impl->clip (draw, clip);
+	}
+	return TRUE;
+}
+
 void
 _vte_draw_clear(struct _vte_draw *draw, gint x, gint y, gint width, gint height)
 {
Index: src/vtedraw.h
===================================================================
--- src/vtedraw.h	(revision 1482)
+++ src/vtedraw.h	(working copy)
@@ -65,6 +65,7 @@
 				     const GdkColor *color,
 				     double saturation);
 	gboolean requires_repaint;
+	void (*clip)(struct _vte_draw *, GdkRegion *region);
 	void (*clear)(struct _vte_draw *, gint, gint, gint, gint);
 	void (*set_text_font)(struct _vte_draw *,
 			      const PangoFontDescription *,
@@ -125,6 +126,7 @@
 				    const GdkColor *color,
 				    double saturation);
 gboolean _vte_draw_requires_repaint(struct _vte_draw *draw);
+gboolean _vte_draw_clip(struct _vte_draw *draw, GdkRegion *region);
 void _vte_draw_clear(struct _vte_draw *draw,
 		     gint x, gint y, gint width, gint height);
 
Index: src/vtepangox.c
===================================================================
--- src/vtepangox.c	(revision 1482)
+++ src/vtepangox.c	(working copy)
@@ -217,6 +217,13 @@
 }
 
 static void
+_vte_pango_x_clip(struct _vte_draw *draw, GdkRegion *region)
+{
+	struct _vte_pango_x_data *data = draw->impl_data;
+	gdk_gc_set_clip_region(data->gc, region);
+}
+
+static void
 _vte_pango_x_clear(struct _vte_draw *draw,
 		   gint x, gint y, gint width, gint height)
 {
@@ -472,6 +479,7 @@
 	_vte_pango_x_set_background_color,
 	_vte_pango_x_set_background_image,
 	FALSE,
+	_vte_pango_x_clip,
 	_vte_pango_x_clear,
 	_vte_pango_x_set_text_font,
 	_vte_pango_x_get_text_width,
Index: src/vtepango.c
===================================================================
--- src/vtepango.c	(revision 1482)
+++ src/vtepango.c	(working copy)
@@ -199,6 +199,13 @@
 }
 
 static void
+_vte_pango_clip(struct _vte_draw *draw, GdkRegion *region)
+{
+	struct _vte_pango_data *data = draw->impl_data;
+	gdk_gc_set_clip_region(data->gc, region);
+}
+
+static void
 _vte_pango_clear(struct _vte_draw *draw,
 		 gint x, gint y, gint width, gint height)
 {
@@ -451,6 +458,7 @@
 	_vte_pango_set_background_color,
 	_vte_pango_set_background_image,
 	FALSE,
+	_vte_pango_clip,
 	_vte_pango_clear,
 	_vte_pango_set_text_font,
 	_vte_pango_get_text_width,
Index: src/vte.c
===================================================================
--- src/vte.c	(revision 1482)
+++ src/vte.c	(working copy)
@@ -3105,19 +3105,19 @@
 					 screen->cursor_current.row > bbox_bottomright.y + VTE_CELL_BBOX_SLACK ||
 					 screen->cursor_current.row < bbox_topleft.y - VTE_CELL_BBOX_SLACK)) {
 				/* Clip off any part of the box which isn't already on-screen. */
-				bbox_topleft.x = MAX(bbox_topleft.x, 1) - 1;
+				bbox_topleft.x = MAX(bbox_topleft.x, 0);
 				bbox_topleft.y = MAX(bbox_topleft.y, screen->scroll_delta);
 				bbox_bottomright.x = MIN(bbox_bottomright.x,
-						terminal->column_count - 1);
+						terminal->column_count);
 				bbox_bottomright.y = MIN(bbox_bottomright.y,
 						screen->scroll_delta +
 						terminal->row_count);
 
 				_vte_invalidate_cells(terminal,
 						bbox_topleft.x,
-						bbox_bottomright.x - bbox_topleft.x + 1,
+						bbox_bottomright.x - bbox_topleft.x,
 						bbox_topleft.y,
-						bbox_bottomright.y - bbox_topleft.y + 1);
+						bbox_bottomright.y - bbox_topleft.y);
 
 				invalidated_text = FALSE;
 				bbox_bottomright.x = bbox_bottomright.y = -G_MAXINT;
@@ -3201,7 +3201,7 @@
 				bbox_bottomright.x = MAX(bbox_bottomright.x,
 						screen->cursor_current.col + 1);
 				bbox_bottomright.y = MAX(bbox_bottomright.y,
-						screen->cursor_current.row);
+						screen->cursor_current.row + 1);
 				invalidated_text = TRUE;
 			}
 
@@ -3251,19 +3251,19 @@
 
 	if (invalidated_text) {
 		/* Clip off any part of the box which isn't already on-screen. */
-		bbox_topleft.x = MAX(bbox_topleft.x, 1) - 1;
+		bbox_topleft.x = MAX(bbox_topleft.x, 0);
 		bbox_topleft.y = MAX(bbox_topleft.y, screen->scroll_delta);
 		bbox_bottomright.x = MIN(bbox_bottomright.x,
-				terminal->column_count - 1);
+				terminal->column_count);
 		bbox_bottomright.y = MIN(bbox_bottomright.y,
 				screen->scroll_delta +
 				terminal->row_count);
 
 		_vte_invalidate_cells(terminal,
 				bbox_topleft.x,
-				bbox_bottomright.x - bbox_topleft.x + 1,
+				bbox_bottomright.x - bbox_topleft.x,
 				bbox_topleft.y,
-				bbox_bottomright.y - bbox_topleft.y + 1);
+				bbox_bottomright.y - bbox_topleft.y);
 	}
 
 	/* If we inserted text without sanity-checking the buffer, do so now. */
@@ -8972,7 +8972,7 @@
 
 /* Draw the widget. */
 static void
-vte_terminal_paint(GtkWidget *widget, GdkRectangle *area)
+vte_terminal_paint(GtkWidget *widget, GdkRegion *region)
 {
 	VteTerminal *terminal;
 	VteScreen *screen;
@@ -8983,7 +8983,7 @@
 	int preedit_cursor;
 	long width, height, ascent, descent, delta, cursor_width;
 	int i, len, fore, back, x, y;
-	GdkRectangle all_area, selected_area;
+	GdkRectangle area, selected_area;
 	gboolean blink, selected;
 
 #ifdef VTE_DEBUG
@@ -9009,7 +9009,7 @@
 				       terminal->char_height;
 		selected_area.width -= selected_area.x;
 		selected_area.height -= selected_area.y;
-		gdk_rectangle_union(area, &selected_area, area);
+		gdk_region_union_with_rect(region, &selected_area);
 	}
 
 	/* Get going. */
@@ -9022,27 +9022,29 @@
 	descent = terminal->char_descent;
 	delta = screen->scroll_delta;
 
+	/* Designate the start of the drawing operation and clear the area. */
+	_vte_draw_start(terminal->pvt->draw);
+
 	/* Calculate the bounding rectangle. */
-	if (_vte_draw_requires_repaint(terminal->pvt->draw)) {
-		all_area.x = 0;
-		all_area.y = 0;
-		all_area.width = terminal->char_width * terminal->column_count;
-		all_area.width += 2 * VTE_PAD_WIDTH;
-		all_area.height = terminal->char_height * terminal->row_count;
-		all_area.height += 2 * VTE_PAD_WIDTH;
-		area = &all_area;
+	if (!_vte_draw_clip(terminal->pvt->draw, region)) {
+		area.x = 0;
+		area.y = 0;
+		area.width = terminal->char_width * terminal->column_count;
+		area.width += 2 * VTE_PAD_WIDTH;
+		area.height = terminal->char_height * terminal->row_count;
+		area.height += 2 * VTE_PAD_WIDTH;
+	} else {
+		gdk_region_get_clipbox(region, &area);
 	}
-	row = MAX(0, (area->y - VTE_PAD_WIDTH) / height);
-	row_stop = MIN(howmany((area->y - VTE_PAD_WIDTH) + area->height,
+	row = MAX(0, (area.y - VTE_PAD_WIDTH) / height);
+	row_stop = MIN(howmany((area.y - VTE_PAD_WIDTH) + area.height,
 			       height),
 		       terminal->row_count - 1);
-	col = MAX(0, (area->x - VTE_PAD_WIDTH) / width);
-	col_stop = MIN(howmany((area->x - VTE_PAD_WIDTH) + area->width,
+	col = MAX(1, (area.x - VTE_PAD_WIDTH) / width)-1;
+	col_stop = MIN(howmany((area.x - VTE_PAD_WIDTH) + area.width,
 			       width),
-		       terminal->column_count - 1);
+		       terminal->column_count - 2)+1;
 
-	/* Designate the start of the drawing operation and clear the area. */
-	_vte_draw_start(terminal->pvt->draw);
 	if (terminal->pvt->bg_transparent) {
 		gdk_window_get_origin(widget->window, &x, &y);
 		_vte_draw_set_scroll(terminal->pvt->draw, x, y);
@@ -9056,7 +9058,7 @@
 		}
 	}
 	_vte_draw_clear(terminal->pvt->draw,
-			area->x, area->y, area->width, area->height);
+			area.x, area.y, area.width, area.height);
 
 	/* Now we're ready to draw the text.  Iterate over the rows we
 	 * need to draw. */
@@ -9294,7 +9296,12 @@
 					g_slist_prepend (terminal->pvt->update_regions,
 							gdk_region_copy (event->region));
 			} else {
-				vte_terminal_paint(widget, &event->area);
+				/* skip to the end if we have to redraw the 
+				 * entire terminal anyway */
+				if(event->count == 1 ||
+						!_vte_draw_requires_repaint (terminal->pvt->draw)) {
+					vte_terminal_paint(widget, event->region);
+				}
 			}
 		}
 	}
