Index: configure.in
===================================================================
--- configure.in	(revision 1426)
+++ configure.in	(working copy)
@@ -56,7 +56,7 @@
 
 # Use Xft2 if Pango has Xft2 support and it isn't disabled.
 if test "$have_x" = yes ; then
-	AC_ARG_WITH(xft2,[AS_HELP_STRING(--with-xft2,enable drawing using Xft2)],with_xft2=$withval,with_xft2=yes)
+	AC_ARG_WITH(xft2,[AS_HELP_STRING(--with-xft2,enable drawing using Xft2 [default=enabled])],with_xft2=$withval,with_xft2=yes)
 	if test $with_xft2 = yes ; then
 		if pkg-config --exists pangoxft '>=' 1.1.0 ; then
 			AC_DEFINE(HAVE_XFT2,1,[Whether we have Xft2])
@@ -70,7 +70,7 @@
 
 # Use PangoX if we have it and it isn't disabled.
 if test "$have_x" = yes ; then
-	AC_ARG_WITH(pangox,[AS_HELP_STRING(--with-pangox,enable drawing using PangoX)],with_pangox=$withval,with_pangox=yes)
+	AC_ARG_WITH(pangox,[AS_HELP_STRING(--with-pangox,enable drawing using PangoX [default=enabled])],with_pangox=$withval,with_pangox=yes)
 	if test $with_pangox = yes ; then
 		if pkg-config --exists pangox ; then
 			AC_DEFINE(HAVE_PANGOX,1,[Whether we have PangoX])
@@ -83,7 +83,7 @@
 
 # Use glX if we have it and it isn't disabled.
 if test "$have_x" = yes ; then
-	AC_ARG_WITH(glX,[AS_HELP_STRING(--with-glX,enable drawing using glX)],with_glx=$withval,with_glx=no)
+	AC_ARG_WITH(glX,[AS_HELP_STRING(--with-glX,enable drawing using glX[default=disabled])],with_glx=$withval,with_glx=no)
 	if test $with_glx = yes ; then
 		have_gl=0
 		have_libgl=0
@@ -95,7 +95,7 @@
 			AC_DEFINE(HAVE_GL,1,[Whether we have GL and glX.])
 		fi
 		if test $have_libgl = 1 ; then
-			LIBS="-lGLU -lGL $LIBS"
+			LIBS="-lGL $LIBS"
 		fi
 	fi
 fi
Index: src/vteft2.c
===================================================================
--- src/vteft2.c	(revision 1426)
+++ src/vteft2.c	(working copy)
@@ -54,13 +54,7 @@
 static void
 _vte_ft2_create(struct _vte_draw *draw, GtkWidget *widget)
 {
-	struct _vte_ft2_data *data;
-	data = g_slice_new0(struct _vte_ft2_data);
-	draw->impl_data = data;
-	data->rgb = NULL;
-	memset(&data->color, 0, sizeof(data->color));
-	data->pixbuf = NULL;
-	data->scrollx = data->scrolly = 0;
+	draw->impl_data = g_slice_new0(struct _vte_ft2_data);
 }
 
 static void
@@ -70,17 +64,13 @@
 	data = (struct _vte_ft2_data*) draw->impl_data;
 	if (data->cache != NULL) {
 		_vte_glyph_cache_free(data->cache);
-		data->cache = NULL;
 	}
 	if (data->rgb != NULL) {
 		_vte_rgb_buffer_free(data->rgb);
 	}
-	memset(&data->color, 0, sizeof(data->color));
-	if (GDK_IS_PIXBUF(data->pixbuf)) {
-		g_object_unref(G_OBJECT(data->pixbuf));
-		data->pixbuf = NULL;
+	if (data->pixbuf != NULL) {
+		g_object_unref(data->pixbuf);
 	}
-	data->scrollx = data->scrolly = 0;
 	g_slice_free(struct _vte_ft2_data, data);
 }
 
@@ -103,37 +93,32 @@
 	guint width, height;
 	data = (struct _vte_ft2_data*) draw->impl_data;
 
-	gdk_window_get_geometry(draw->widget->window,
-				NULL, NULL, &width, &height, NULL);
+	width = draw->widget->allocation.width;
+	height = draw->widget->allocation.height;
 	if (data->rgb == NULL) {
 		data->rgb = _vte_rgb_buffer_new(width, height);
 	} else {
 		_vte_rgb_buffer_resize(data->rgb, width, height);
 	}
-	data->left = data->right = data->top = data->bottom = -1;
+	data->left = data->top = G_MAXINT;
+	data->right = data->bottom = -G_MAXINT;
 }
 
 static void
 _vte_ft2_end(struct _vte_draw *draw)
 {
 	struct _vte_ft2_data *data;
-	guint width, height;
 	GtkWidget *widget;
 	GtkStateType state;
 	data = (struct _vte_ft2_data*) draw->impl_data;
 	widget = draw->widget;
-	gdk_window_get_geometry(widget->window,
-				NULL, NULL, &width, &height, NULL);
-	gtk_widget_ensure_style(widget);
 	state = GTK_WIDGET_STATE(widget);
-	if ((data->left == -1) &&
-	    (data->right == -1) &&
-	    (data->top == -1) &&
-	    (data->bottom == -1)) {
+	if (data->right < data->left) {
 		_vte_rgb_draw_on_drawable(widget->window,
 					  widget->style->fg_gc[state],
 					  0, 0,
-					  width, height,
+						widget->allocation.width,
+						widget->allocation.height,
 					  data->rgb,
 					  0, 0);
 	} else {
@@ -174,23 +159,22 @@
 	bgpixbuf = vte_bg_get_pixbuf(vte_bg_get_for_screen(screen),
 				     type, pixbuf, file,
 				     color, saturation);
-	if (GDK_IS_PIXBUF(data->pixbuf)) {
-		g_object_unref(G_OBJECT(data->pixbuf));
+	if (data->pixbuf != NULL) {
+		g_object_unref(data->pixbuf);
 	}
 	data->pixbuf = bgpixbuf;
 }
 
-static void
+static inline void
 update_bbox(struct _vte_ft2_data *data, gint x, gint y, gint width, gint height)
 {
-	data->left = (data->left == -1) ?
-		     x : MIN(data->left, x);
-	data->right = (data->right == -1) ?
-		      x + width - 1 : MAX(data->right, x + width - 1);
-	data->top = (data->top == -1) ?
-		    y : MIN(data->top, y);
-	data->bottom = (data->bottom == -1) ?
-		       y + height - 1 : MAX(data->bottom, y + height - 1);
+	if (x < data->left) data->left = x;
+	x += width - 1;
+	if (x > data->right) data->right = x;
+
+	if (y < data->top) data->top = y;
+	y += height - 1;
+	if (y > data->bottom) data->bottom = y;
 }
 
 static void
@@ -200,7 +184,7 @@
 	struct _vte_ft2_data *data;
 	data = (struct _vte_ft2_data*) draw->impl_data;
 
-	if (GDK_IS_PIXBUF(data->pixbuf)) {
+	if (data->pixbuf != NULL) {
 		/* Tile a pixbuf in. */
 		_vte_rgb_draw_pixbuf(data->rgb, x, y, width, height,
 				     data->pixbuf,
@@ -224,7 +208,6 @@
 
 	if (data->cache != NULL) {
 		_vte_glyph_cache_free(data->cache);
-		data->cache = NULL;
 	}
 	data->cache = _vte_glyph_cache_new();
 	_vte_glyph_cache_set_font_description(draw->widget, NULL,
@@ -284,11 +267,13 @@
 		   GdkColor *color, guchar alpha)
 {
 	struct _vte_ft2_data *data;
-	int i;
+	int i, j;
 
 	data = (struct _vte_ft2_data*) draw->impl_data;
 
 	for (i = 0; i < n_requests; i++) {
+		if (requests[i].c == -1)
+			continue;
 		_vte_glyph_draw(data->cache, requests[i].c, color,
 				requests[i].x, requests[i].y,
 				requests[i].columns,
@@ -297,6 +282,18 @@
 		update_bbox(data, requests[i].x, requests[i].y,
 			    data->cache->width * requests[i].columns,
 			    data->cache->height);
+		for (j = i + 1; j < n_requests; j++) {
+			if (requests[j].c == requests[i].c) {
+				_vte_rgb_copy(data->rgb,
+						requests[i].x, requests[i].y,
+						requests[i].columns * data->cache->width, data->cache->height,
+						requests[j].x, requests[j].y);
+				update_bbox(data, requests[j].x, requests[j].y,
+						data->cache->width * requests[j].columns,
+						data->cache->height);
+				requests[j].c = -1;
+			}
+		}
 	}
 }
 
Index: src/vtexft.c
===================================================================
--- src/vtexft.c	(revision 1426)
+++ src/vtexft.c	(working copy)
@@ -116,7 +116,6 @@
 static void
 _vte_xft_font_close(struct _vte_xft_font *font)
 {
-	GdkDisplay *gdisplay;
 	Display *display;
 	XftFont *ftfont;
 	FcPattern *pattern;
@@ -132,8 +131,7 @@
 	g_array_free(font->patterns, TRUE);
 	font->patterns = NULL;
 
-	gdisplay = gdk_display_get_default();
-	display = gdk_x11_display_get_xdisplay(gdisplay);
+	display = GDK_DISPLAY_XDISPLAY(font->display);
 	for (i = 0; i < font->fonts->len; i++) {
 		ftfont = g_array_index(font->fonts, XftFont*, i);
 		if (ftfont != NULL) {
@@ -157,7 +155,6 @@
 	int i;
 	XftFont *ftfont;
 	FcPattern **patternp;
-	GdkDisplay *gdisplay;
 	Display *display;
 	gpointer p = GINT_TO_POINTER(c);
 
@@ -184,8 +181,6 @@
 	}
 
 	/* Look the character up in the fonts we have. */
-	gdisplay = gdk_display_get_default();
-	display = gdk_x11_display_get_xdisplay(gdisplay);
 	for (i = 0; i < font->fonts->len; i++) {
 		ftfont = g_array_index(font->fonts, XftFont *, i);
 		if ((ftfont != NULL) &&
@@ -208,6 +203,7 @@
 	}
 
 	/* Look the character up in other fonts. */
+	display = GDK_DISPLAY_XDISPLAY(font->display);
 	for (i = font->fonts->len; i < font->patterns->len; i++) {
 		patternp = &g_array_index(font->patterns, FcPattern *, i);
 		ftfont = XftFontOpenPattern(display, *patternp);
@@ -292,19 +288,11 @@
 	struct _vte_xft_data *data;
 	data = g_slice_new0(struct _vte_xft_data);
 	draw->impl_data = data;
-	data->font = NULL;
-	data->display = NULL;
 	data->drawable = -1;
-	data->visual = NULL;
 	data->colormap = -1;
-	data->draw = NULL;
-	data->gc = NULL;
-	memset(&data->color, 0, sizeof(data->color));
 	data->opacity = 0xffff;
-	data->pixmap = NULL;
 	data->xpixmap = -1;
 	data->pixmapw = data->pixmaph = -1;
-	data->scrollx = data->scrolly = 0;
 }
 
 static void
@@ -314,30 +302,13 @@
 	data = (struct _vte_xft_data*) draw->impl_data;
 	if (data->font != NULL) {
 		_vte_xft_font_close(data->font);
-		data->font = NULL;
 	}
-	data->display = NULL;
-	data->drawable = -1;
-	data->x_offs = data->y_offs = 0;
-	data->visual = NULL;
-	data->colormap = -1;
 	if (data->draw != NULL) {
 		XftDrawDestroy(data->draw);
-		data->draw = NULL;
-		data->display = NULL;
-		data->drawable = -1;
-		data->visual = NULL;
-		data->colormap = -1;
 	}
 	if (data->gc != NULL) {
 		XFreeGC(data->display, data->gc);
-		data->gc = NULL;
 	}
-	memset(&data->color, 0, sizeof(data->color));
-	data->pixmap = NULL;
-	data->xpixmap = -1;
-	data->pixmapw = data->pixmaph = -1;
-	data->scrollx = data->scrolly = 0;
 	g_slice_free(struct _vte_xft_data, data);
 }
 
@@ -434,11 +405,11 @@
 	pixmap = vte_bg_get_pixmap(vte_bg_get_for_screen(screen), type,
 				   pixbuf, file, color, saturation,
 				   _vte_draw_get_colormap(draw, TRUE));
-	if (GDK_IS_PIXMAP(data->pixmap)) {
-		g_object_unref(G_OBJECT(data->pixmap));
+	if (data->pixmap != NULL) {
+		g_object_unref(data->pixmap);
 	}
 	data->pixmap = NULL;
-	if (GDK_IS_PIXMAP(pixmap)) {
+	if (pixmap != NULL) {
 		data->pixmap = pixmap;
 		data->xpixmap = gdk_x11_drawable_get_xid(pixmap);
 		gdk_drawable_get_size(pixmap, &data->pixmapw, &data->pixmaph);
@@ -456,7 +427,7 @@
 
 	data = (struct _vte_xft_data*) draw->impl_data;
 
-	if (!GDK_IS_PIXMAP(data->pixmap) ||
+	if (data->pixmap == NULL ||
 	    (data->pixmapw <= 0) ||
 	    (data->pixmaph <= 0)) {
 		rcolor.red = data->color.red * data->opacity / 0xffff;
Index: src/vteglyph.c
===================================================================
--- src/vteglyph.c	(revision 1426)
+++ src/vteglyph.c	(working copy)
@@ -38,17 +38,24 @@
 
 #define FONT_INDEX_FUDGE 10
 #define CHAR_WIDTH_FUDGE 10
-#define INVALID_GLYPH    -1
+#define INVALID_GLYPH    GINT_TO_POINTER(-1)
 
 static FT_Face _vte_glyph_cache_face_for_char(struct _vte_glyph_cache *cache,
 					      gunichar c);
 
-static int
-_vte_direct_compare(gconstpointer a, gconstpointer b)
+void
+_vte_glyph_free(struct _vte_glyph *glyph)
 {
-	return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
+	g_free(glyph);
 }
 
+static void
+_vte_cached_glyph_free(gpointer glyph)
+{
+	if (glyph != INVALID_GLYPH)
+		_vte_glyph_free(glyph);
+}
+
 struct _vte_glyph_cache *
 _vte_glyph_cache_new(void)
 {
@@ -59,7 +66,7 @@
 
 	ret->patterns = g_array_new(TRUE, TRUE, sizeof(FcPattern*));
 	ret->faces = NULL;
-	ret->cache = g_tree_new(_vte_direct_compare);
+	ret->cache = g_hash_table_new_full(NULL, NULL, NULL, _vte_cached_glyph_free);
 	ret->ft_load_flags = 0;
 	ret->ft_render_flags = 0;
 	ret->width = 0;
@@ -72,21 +79,7 @@
 	return ret;
 }
 
-void
-_vte_glyph_free(struct _vte_glyph *glyph)
-{
-	g_free(glyph);
-}
 
-static gboolean
-free_tree_value(gpointer key, gpointer value, gpointer data)
-{
-	if (GPOINTER_TO_INT(value) != INVALID_GLYPH) {
-		_vte_glyph_free(value);
-	}
-	return FALSE;
-}
-
 void
 _vte_glyph_cache_free(struct _vte_glyph_cache *cache)
 {
@@ -103,32 +96,22 @@
 						       i));
 		}
 		g_array_free(cache->patterns, TRUE);
-		cache->patterns = NULL;
 	}
 
 	/* Close all faces. */
 	for (iter = cache->faces; iter != NULL; iter = g_list_next(iter)) {
 		FT_Done_Face((FT_Face) iter->data);
-		iter->data = NULL;
 	}
-	cache->faces = NULL;
+	g_list_free(cache->faces);
 
 	/* Free the glyph tree. */
-	g_tree_foreach(cache->cache, free_tree_value, NULL);
-	cache->cache = NULL;
+	g_hash_table_destroy(cache->cache);
 
 	/* Close the FT library. */
 	if (cache->ft_library) {
 		FT_Done_FreeType(cache->ft_library);
-		cache->ft_library = NULL;
 	}
 
-	/* Free the cache. */
-	cache->ft_load_flags = 0;
-	cache->ft_render_flags = 0;
-	cache->width = 0;
-	cache->height = 0;
-	cache->ascent = 0;
 	g_slice_free(struct _vte_glyph_cache, cache);
 }
 
@@ -179,9 +162,8 @@
 	cache->faces = NULL;
 
 	/* Clear the glyph tree. */
-	g_tree_foreach(cache->cache, free_tree_value, NULL);
-	g_tree_destroy(cache->cache);
-	cache->cache = g_tree_new(_vte_direct_compare);
+	g_hash_table_destroy(cache->cache);
+	cache->cache = g_hash_table_new_full(NULL, NULL, NULL, _vte_cached_glyph_free);
 
 	/* Clear the load and render flags. */
 	cache->ft_load_flags = 0;
@@ -392,8 +374,8 @@
 	GList *iter;
 	gpointer p;
 
-	if ((p = g_tree_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
-		if (GPOINTER_TO_INT(p) == INVALID_GLYPH) {
+	if ((p = g_hash_table_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
+		if (p == INVALID_GLYPH) {
 			return FALSE;
 		}
 	}
@@ -408,14 +390,10 @@
 }
 
 static gunichar
-_vte_glyph_remap_char(struct _vte_glyph_cache *cache, gunichar origc)
+_vte_glyph_remap_char(gunichar origc)
 {
 	gunichar newc;
 
-	if (_vte_glyph_cache_has_char(cache, origc)) {
-		return origc;
-	}
-
 	switch (origc) {
 	case 0:			/* NUL */
 	case 0x00A0:		/* NO-BREAK SPACE */
@@ -434,11 +412,7 @@
 		break;
 	}
 
-	if (_vte_glyph_cache_has_char(cache, newc)) {
-		return newc;
-	} else {
-		return origc;
-	}
+	return newc;
 }
 
 #define DEFAULT_BYTES_PER_PIXEL 3
@@ -496,8 +470,8 @@
 
 	/* Bail if we weren't able to load the glyph. */
 	if (face == NULL) {
-		g_tree_insert(cache->cache, GINT_TO_POINTER(c),
-			      GINT_TO_POINTER(INVALID_GLYPH));
+		g_hash_table_insert(cache->cache, GINT_TO_POINTER(c),
+			      INVALID_GLYPH);
 		return NULL;
 	}
 
@@ -512,9 +486,6 @@
 			  face->glyph->bitmap_top, 0);
 	glyph->bytes_per_pixel = DEFAULT_BYTES_PER_PIXEL;
 
-	memset(glyph->bytes, 0,
-	       glyph->width * glyph->height * DEFAULT_BYTES_PER_PIXEL);
-
 	for (y = 0; y < face->glyph->bitmap.rows; y++)
 	for (x = 0; x < face->glyph->bitmap.width; x++) {
 		ooffset = (y * glyph->width + x) * DEFAULT_BYTES_PER_PIXEL;
@@ -604,11 +575,11 @@
 	struct _vte_glyph *glyph = NULL;
 	gpointer p;
 
-	g_return_val_if_fail(cache != NULL, NULL);
+	g_assert(cache != NULL);
 
 	/* See if we already have a glyph for this character. */
-	if ((p = g_tree_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
-		if (GPOINTER_TO_INT(p) == INVALID_GLYPH) {
+	if ((p = g_hash_table_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
+		if (p == INVALID_GLYPH) {
 			return NULL;
 		} else {
 			return p;
@@ -620,26 +591,26 @@
 
 	/* Bail if we weren't able to load the glyph. */
 	if (glyph == NULL) {
-		g_tree_insert(cache->cache, GINT_TO_POINTER(c),
-			      GINT_TO_POINTER(INVALID_GLYPH));
+		g_hash_table_insert(cache->cache, GINT_TO_POINTER(c),
+			      INVALID_GLYPH);
 		return NULL;
 	}
 
 	/* Cache it. */
-	g_tree_insert(cache->cache, GINT_TO_POINTER(c), glyph);
+	g_hash_table_insert(cache->cache, GINT_TO_POINTER(c), glyph);
 
 	return glyph;
 }
 
 void
 _vte_glyph_draw(struct _vte_glyph_cache *cache,
-		gunichar c, GdkColor *color,
+		gunichar c, const GdkColor *color,
 		gint x, gint y, gint columns,
 		enum vte_glyph_flags flags,
 		struct _vte_rgb_buffer *buffer)
 {
 	const struct _vte_glyph *glyph;
-	gint col, row, ioffset, ooffset, icol, ocol, ecol;
+	gint col, row, erow, ioffset, ooffset, icol, ocol, ecol;
 	gint strikethrough, underline, underline2;
 	gint32 r, g, b, ar, ag, ab;
 	guchar *pixels;
@@ -647,9 +618,14 @@
 	if (cache == NULL) {
 		return;
 	}
-	glyph = _vte_glyph_get(cache, _vte_glyph_remap_char(cache, c));
+	glyph = _vte_glyph_get(cache, c);
 	if (glyph == NULL) {
-		return;
+		gunichar cc = _vte_glyph_remap_char(c);
+		if(cc != c)
+			glyph = _vte_glyph_get(cache, cc);
+		if (glyph == NULL) {
+			return;
+		}
 	}
 
 	if (x > buffer->width) {
@@ -679,21 +655,18 @@
 
 _vte_glyph_draw_loop:
 
+	erow = MIN(cache->height, glyph->skip + glyph->height);
+	erow = MIN(erow, buffer->height - y);
 	for (row = glyph->skip;
-	     row < MIN(cache->height, glyph->skip + glyph->height);
+	     row < erow;
 	     row++) {
-		if (row + y >= buffer->height) {
-			break;
-		}
 		ooffset = (y + row) * buffer->stride +
 			  ((x + ocol) * 3);
 		ioffset = (((row - glyph->skip) * glyph->width) + icol) *
 			  DEFAULT_BYTES_PER_PIXEL;
 		ecol = MIN(cache->width * columns, glyph->width);
+		ecol = MIN(ecol, buffer->width - x);
 		for (col = 0; col < ecol; col++) {
-			if (col + x >= buffer->width) {
-				break;
-			}
 			ar = glyph->bytes[ioffset + 0];
 			ag = glyph->bytes[ioffset + 1];
 			ab = glyph->bytes[ioffset + 2];
@@ -799,7 +772,7 @@
 
 void
 _vte_glyph_draw_string(struct _vte_glyph_cache *cache,
-		       const char *s, GdkColor *color,
+		       const char *s, const GdkColor *color,
 		       gint x, gint y,
 		       enum vte_glyph_flags flags,
 		       struct _vte_rgb_buffer *buffer)
Index: src/vteglyph.h
===================================================================
--- src/vteglyph.h	(revision 1426)
+++ src/vteglyph.h	(working copy)
@@ -56,7 +56,7 @@
 struct _vte_glyph_cache {
 	GArray *patterns;
 	GList *faces;
-	GTree *cache;
+	GHashTable *cache;
 	gint ft_load_flags;
 	gint ft_render_flags;
 	glong width, height, ascent;
@@ -79,12 +79,12 @@
 					   gunichar c);
 void _vte_glyph_free(struct _vte_glyph *glyph);
 void _vte_glyph_draw(struct _vte_glyph_cache *cache,
-		     gunichar c, GdkColor *color,
+		     gunichar c, const GdkColor *color,
 		     gint x, gint y, gint columns,
 		     enum vte_glyph_flags flags,
 		     struct _vte_rgb_buffer *buffer);
 void _vte_glyph_draw_string(struct _vte_glyph_cache *cache,
-			    const char *s, GdkColor *color,
+			    const char *s, const GdkColor *color,
 			    gint x, gint y,
 			    enum vte_glyph_flags flags,
 			    struct _vte_rgb_buffer *buffer);
Index: src/vte-private.h
===================================================================
--- src/vte-private.h	(revision 1426)
+++ src/vte-private.h	(working copy)
@@ -81,11 +81,13 @@
 #define VTE_REGEXEC_FLAGS		0
 #define VTE_INPUT_CHUNK_SIZE		0x1000
 #define VTE_INVALID_BYTE		'?'
-#define VTE_COALESCE_TIMEOUT		10
+#define VTE_COALESCE_TIMEOUT	20
 #define VTE_DISPLAY_TIMEOUT		10
 #define VTE_UPDATE_TIMEOUT		10
 #define VTE_UPDATE_REPEAT_TIMEOUT	25
 
+#define VTE_INVALID_CONV ((VteConv)-1)
+
 /* The structure we use to hold characters we're supposed to display -- this
  * includes any supported visible attributes. */
 struct vte_charcell {
@@ -183,7 +185,7 @@
 	gint coalesce_timeout;
 	gint display_timeout;
 	gint update_timeout;
-	GdkRegion *update_region;
+	GSList *update_regions;
 
 
 	/* Output data queue. */
@@ -307,6 +309,7 @@
 	 * resources and which can be kept after unrealizing. */
 	PangoFontDescription *fontdesc;
 	VteTerminalAntiAlias fontantialias;
+	gboolean fontdirty;
 	GtkSettings *connected_settings;
 
 	/* Data used when rendering the text which reflects server resources
@@ -365,7 +368,7 @@
 void _vte_invalidate_cells(VteTerminal *terminal,
 			   glong column_start, gint column_count,
 			   glong row_start, gint row_count);
-void _vte_invalidate_cursor_once(gpointer data, gboolean periodic);
+void _vte_invalidate_cursor_once(VteTerminal *terminal, gboolean periodic);
 VteRowData * _vte_new_row_data(VteTerminal *terminal);
 VteRowData * _vte_new_row_data_sized(VteTerminal *terminal, gboolean fill);
 void _vte_terminal_adjust_adjustments(VteTerminal *terminal, gboolean immediate);
Index: src/vtedraw.c
===================================================================
--- src/vtedraw.c	(revision 1426)
+++ src/vtedraw.c	(working copy)
@@ -34,7 +34,7 @@
 #include "vteskel.h"
 #include "vtexft.h"
 
-struct _vte_draw_impl
+static const struct _vte_draw_impl
 *_vte_draw_impls[] = {
 	&_vte_draw_skel,
 #ifndef X_DISPLAY_MISSING
@@ -65,8 +65,7 @@
 
 	/* Create the structure. */
 	draw = g_slice_new0(struct _vte_draw);
-	g_object_ref(G_OBJECT(widget));
-	draw->widget = widget;
+	draw->widget = g_object_ref(widget);
 	draw->started = FALSE;
 
 	/* Let each implementation decide if it's right for the job. */
@@ -106,7 +105,7 @@
 	draw->impl_data = NULL;
 
 	if (GTK_IS_WIDGET(draw->widget)) {
-		g_object_unref(G_OBJECT(draw->widget));
+		g_object_unref(draw->widget);
 		draw->widget = NULL;
 	}
 	draw->started = FALSE;
@@ -151,7 +150,7 @@
 	g_return_if_fail(GTK_WIDGET_REALIZED(draw->widget));
 	g_return_if_fail(draw->impl != NULL);
 	g_return_if_fail(draw->impl->start != NULL);
-	g_object_ref(G_OBJECT(draw->widget->window));
+	g_object_ref(draw->widget->window);
 	draw->impl->start(draw);
 	draw->started = TRUE;
 }
@@ -163,7 +162,7 @@
 	g_return_if_fail(draw->impl != NULL);
 	g_return_if_fail(draw->impl->end != NULL);
 	draw->impl->end(draw);
-	g_object_unref(G_OBJECT(draw->widget->window));
+	g_object_unref(draw->widget->window);
 	draw->started = FALSE;
 }
 
Index: src/vtedraw.h
===================================================================
--- src/vtedraw.h	(revision 1426)
+++ src/vtedraw.h	(working copy)
@@ -93,7 +93,7 @@
 	GtkWidget *widget;
 	gboolean started;
 	gint width, height, ascent;
-	struct _vte_draw_impl *impl;
+	const struct _vte_draw_impl *impl;
 	gpointer impl_data;
 };
 
Index: src/iso2022.c
===================================================================
--- src/iso2022.c	(revision 1426)
+++ src/iso2022.c	(working copy)
@@ -1076,13 +1076,16 @@
 	return sequence_length;
 }
 
-static void
-_vte_iso2022_fragment_input(struct _vte_buffer *input, GArray *blocks)
+static GArray*
+_vte_iso2022_fragment_input(struct _vte_buffer *input)
 {
 	unsigned char *nextctl = NULL, *p, *q;
 	glong sequence_length = 0;
 	struct _vte_iso2022_block block;
 	gboolean quit;
+	GArray  *blocks;
+ 
+	blocks	= g_array_new(FALSE, FALSE, sizeof(struct _vte_iso2022_block));
 
 	p = input->bytes;
 	q = input->bytes + _vte_buffer_length(input);
@@ -1139,6 +1142,8 @@
 			break;
 		}
 	}
+
+	return blocks;
 }
 
 static int
@@ -1722,10 +1727,8 @@
 	gboolean preserve_last = FALSE;
 	int i, initial;
 
-	blocks = g_array_new(TRUE, TRUE, sizeof(struct _vte_iso2022_block));
+	blocks = _vte_iso2022_fragment_input(input);
 
-	_vte_iso2022_fragment_input(input, blocks);
-
 	for (i = 0; i < blocks->len; i++) {
 		block = &g_array_index(blocks, struct _vte_iso2022_block, i);
 		switch (block->type) {
Index: src/vtergb.c
===================================================================
--- src/vtergb.c	(revision 1426)
+++ src/vtergb.c	(working copy)
@@ -26,6 +26,8 @@
 #include FT_FREETYPE_H
 #include "vtergb.h"
 
+#define ALIGN(x, a) (((x)+((a)-1))&~((a)-1))
+
 struct _vte_rgb_buffer_p {
 	guchar *pixels;
 	gint width, height, stride;
@@ -37,15 +39,16 @@
 {
 	struct _vte_rgb_buffer_p *ret;
 
-	ret = g_malloc0(sizeof(*ret));
+	ret = g_slice_new(struct _vte_rgb_buffer_p);
 
 	width = MAX(width, 1);
 	height = MAX(height, 1);
 
-	ret->width = width;
+	ret->width  = width;
 	ret->height = height;
-	ret->stride = width * 3;
-	ret->length = width * height * 3;
+	/* gdk_rgb prefers a row-alignment of 4 */
+	ret->stride = 3 * ALIGN(width, 4);
+	ret->length = ret->stride * height;
 	ret->pixels = g_malloc(ret->length);
 
 	return (struct _vte_rgb_buffer *) ret;
@@ -58,13 +61,7 @@
 
 	g_free(buf->pixels);
 
-	buf->length = 0;
-	buf->stride = 0;
-	buf->height = 0;
-	buf->width = 0;
-	buf->pixels = NULL;
-
-	g_free(buf);
+	g_slice_free(struct _vte_rgb_buffer_p, buf);
 }
 
 void
@@ -73,8 +70,10 @@
 		       gint minimum_height)
 {
 	struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
-	gssize size = minimum_width * minimum_height * 3;
-
+	gint stride, size;
+	
+	stride = 3 * ALIGN(minimum_width, 4);
+	size = stride * minimum_height;
 	if (size > buf->length) {
 		g_free(buf->pixels);
 		buf->length = size;
@@ -83,7 +82,7 @@
 
 	buf->width = minimum_width;
 	buf->height = minimum_height;
-	buf->stride = buf->width * 3;
+	buf->stride = stride;
 }
 
 void
@@ -91,8 +90,8 @@
 			gint x, gint y, gint width, gint height,
 			guchar r, guchar g, guchar b)
 {
-	gint row, rows, col, cols;
-	gint offset, dest, count;
+	gint i, cols, rows;
+	gint count, stride;
 	guchar *pixels;
 
 	/* Perform a simple clipping check. */
@@ -115,27 +114,30 @@
 	if (cols <= x) {
 		return;
 	}
+	cols = cols - x;
+	rows = rows - y;
 
+	stride = buffer->stride;
+	pixels += y * stride + x * 3;
+	count = cols * 3;
 	/* Draw the first row by iteration. */
-	dest = y * buffer->stride + x * 3;
-	offset = dest;
-	for (col = x; col < cols; col++) {
-		pixels[dest++] = r;
-		pixels[dest++] = g;
-		pixels[dest++] = b;
+	i = 0;
+	while(cols--) {
+		pixels[i++] = r;
+		pixels[i++] = g;
+		pixels[i++] = b;
 	}
-
 	/* Draw the other rows by copying the data. */
-	count = width * 3;
-	for (row = y + 1; row < rows; row++) {
-		dest = row * buffer->stride + x * 3;
-		memmove(pixels + dest, pixels + offset, count);
+	i = 0;
+	while (--rows) {
+		i += stride;
+		memcpy(pixels + i, pixels, count);
 	}
 }
 
 void
 _vte_rgb_draw_color(struct _vte_rgb_buffer *buffer,
-		    gint x, gint y, gint width, gint height, GdkColor *color)
+		    gint x, gint y, gint width, gint height, const GdkColor *color)
 {
 	guchar r, g, b;
 	r = MIN(color->red >> 8, 0xff);
@@ -147,7 +149,7 @@
 void
 _vte_rgb_draw_pixbuf(struct _vte_rgb_buffer *buffer,
 		     gint x, gint y, gint width, gint height,
-		     GdkPixbuf *pixbuf, gint xbias, gint ybias)
+		     const GdkPixbuf *pixbuf, gint xbias, gint ybias)
 {
 	struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
 	gint row, col, rows, cols;
@@ -253,6 +255,30 @@
 }
 
 void
+_vte_rgb_copy(struct _vte_rgb_buffer *buffer,
+		int src_x, int src_y, int width, int height, int dst_x, int dst_y)
+{
+	struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
+	guchar *src, *dst;
+	gint stride;
+
+	g_assert (src_x > 0);
+	g_assert (dst_x >= src_x + width);
+	g_assert (dst_x <= buffer->width);
+
+	stride = buffer->stride;
+	src = buffer->pixels + src_y * stride + 3 * src_x;
+	dst = buffer->pixels + dst_y * stride + 3 * dst_x;
+	width *= 3;
+
+	while (height--) {
+		memcpy (dst, src, width);
+		src += stride;
+		dst += stride;
+	}
+}
+
+void
 _vte_rgb_buffer_clear(struct _vte_rgb_buffer *buffer)
 {
 	struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
Index: src/vte.c
===================================================================
--- src/vte.c	(revision 1426)
+++ src/vte.c	(working copy)
@@ -28,6 +28,7 @@
 #include <sys/syslimits.h>
 #endif
 #include <glib.h>
+#include <glib/gstdio.h>
 #include <glib-object.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
@@ -58,16 +59,16 @@
 static void vte_terminal_paste(VteTerminal *terminal, GdkAtom board);
 static gboolean vte_terminal_io_read(GIOChannel *channel,
 				     GIOCondition condition,
-				     gpointer data);
+				     VteTerminal *terminal);
 static gboolean vte_terminal_io_write(GIOChannel *channel,
 				      GIOCondition condition,
-				      gpointer data);
+				      VteTerminal *terminal);
 static void vte_terminal_match_hilite_clear(VteTerminal *terminal);
-static gboolean vte_terminal_background_update(gpointer data);
+static gboolean vte_terminal_background_update(VteTerminal *terminal);
 static void vte_terminal_queue_background_update(VteTerminal *terminal);
 static void vte_terminal_queue_adjustment_changed(VteTerminal *terminal);
 static gboolean vte_terminal_process_incoming(VteTerminal *terminal);
-static gboolean vte_cell_is_selected(VteTerminal *terminal,
+static inline gboolean vte_cell_is_selected(VteTerminal *terminal,
 				     glong col, glong row, gpointer data);
 static char *vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
 						       glong start_row,
@@ -97,6 +98,11 @@
 static void vte_terminal_start_processing (VteTerminal *terminal);
 static gboolean vte_terminal_is_processing (VteTerminal *terminal);
 
+static void add_update_timeout (VteTerminal *terminal);
+static void remove_update_timeout (VteTerminal *terminal);
+static void reset_update_regions (VteTerminal *terminal);
+
+
 static gpointer parent_class;
 
 /* Indexes in the "palette" color array for the dim colors.
@@ -135,7 +141,7 @@
 _vte_new_row_data(VteTerminal *terminal)
 {
 	VteRowData *row = NULL;
-	row = g_slice_new0(VteRowData);
+	row = g_slice_new(VteRowData);
 #ifdef VTE_DEBUG
 	row->cells = g_array_new(FALSE, TRUE, sizeof(struct vte_charcell));
 #else
@@ -150,7 +156,7 @@
 _vte_new_row_data_sized(VteTerminal *terminal, gboolean fill)
 {
 	VteRowData *row = NULL;
-	row = g_slice_new0(VteRowData);
+	row = g_slice_new(VteRowData);
 #ifdef VTE_DEBUG
 	row->cells = g_array_sized_new(FALSE, TRUE,
 				       sizeof(struct vte_charcell),
@@ -173,52 +179,63 @@
 void
 _vte_terminal_set_default_attributes(VteTerminal *terminal)
 {
+	VteScreen *screen;
+
 	g_assert(VTE_IS_TERMINAL(terminal));
-	terminal->pvt->screen->defaults.c = ' ';
-	terminal->pvt->screen->defaults.columns = 1;
-	terminal->pvt->screen->defaults.fragment = 0;
-	terminal->pvt->screen->defaults.empty = 1;
-	terminal->pvt->screen->defaults.fore = VTE_DEF_FG;
-	terminal->pvt->screen->defaults.back = VTE_DEF_BG;
-	terminal->pvt->screen->defaults.reverse = 0;
-	terminal->pvt->screen->defaults.bold = 0;
-	terminal->pvt->screen->defaults.invisible = 0;
-	terminal->pvt->screen->defaults.protect = 0;
-	terminal->pvt->screen->defaults.standout = 0;
-	terminal->pvt->screen->defaults.underline = 0;
-	terminal->pvt->screen->defaults.strikethrough = 0;
-	terminal->pvt->screen->defaults.half = 0;
-	terminal->pvt->screen->defaults.blink = 0;
+
+	screen = terminal->pvt->screen;
+
+	screen->defaults.c = ' ';
+	screen->defaults.columns = 1;
+	screen->defaults.fragment = 0;
+	screen->defaults.empty = 1;
+	screen->defaults.fore = VTE_DEF_FG;
+	screen->defaults.back = VTE_DEF_BG;
+	screen->defaults.reverse = 0;
+	screen->defaults.bold = 0;
+	screen->defaults.invisible = 0;
+	screen->defaults.protect = 0;
+	screen->defaults.standout = 0;
+	screen->defaults.underline = 0;
+	screen->defaults.strikethrough = 0;
+	screen->defaults.half = 0;
+	screen->defaults.blink = 0;
 	/* Alternate charset isn't an attribute, though we treat it as one.
-	 * terminal->pvt->screen->defaults.alternate = 0; */
-	terminal->pvt->screen->basic_defaults = terminal->pvt->screen->defaults;
-	terminal->pvt->screen->color_defaults = terminal->pvt->screen->defaults;
-	terminal->pvt->screen->fill_defaults = terminal->pvt->screen->defaults;
+	 * screen->defaults.alternate = 0; */
+	screen->basic_defaults = screen->defaults;
+	screen->color_defaults = screen->defaults;
+	screen->fill_defaults = screen->defaults;
 }
 
 static gboolean
-vte_invalidate_region(VteTerminal *terminal)
+update_regions (VteTerminal *terminal)
 {
-	if (G_UNLIKELY (!GTK_WIDGET_REALIZED(terminal)))
-		return FALSE;
+	GdkWindow *window;
+	GSList *l;
 
-	if (G_UNLIKELY (GTK_WIDGET(terminal)->window == NULL))
+	if (G_UNLIKELY (!GTK_WIDGET_DRAWABLE(terminal) ||
+				terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED)) {
+		reset_update_regions (terminal);
 		return FALSE;
+	}
 
-	if (!terminal->pvt->update_region)
+	if (!terminal->pvt->update_regions)
 		return FALSE;
 
-	gdk_window_invalidate_region(GTK_WIDGET(terminal)->window,
-				     terminal->pvt->update_region, FALSE);
-	gdk_region_destroy (terminal->pvt->update_region);
-	terminal->pvt->update_region = NULL;
+	window = terminal->widget.window;
+	for (l = terminal->pvt->update_regions; l; l = g_slist_next(l)) {
+		GdkRegion *region = l->data;
+		gdk_window_invalidate_region (window, region, FALSE);
+		gdk_region_destroy (region);
+	}
+	g_slist_free (terminal->pvt->update_regions);
+	terminal->pvt->update_regions = NULL;
 
+	gdk_window_process_all_updates ();
+
 	return TRUE;
 }
 
-static void add_update_timeout (VteTerminal *terminal);
-static void remove_update_timeout (VteTerminal *terminal);
-
 /* Cause certain cells to be repainted. */
 void
 _vte_invalidate_cells(VteTerminal *terminal,
@@ -226,12 +243,13 @@
 		      glong row_start, gint row_count)
 {
 	GdkRectangle rect;
-	GtkWidget *widget;
 	gint i;
 
+	if(!column_count || !row_count)
+		return;
+
 	g_assert(VTE_IS_TERMINAL(terminal));
-	widget = GTK_WIDGET(terminal);
-	if (!GTK_WIDGET_REALIZED(widget)) {
+	if (!GTK_WIDGET_DRAWABLE(terminal)) {
 		return;
 	}
 	if (terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
@@ -252,6 +270,9 @@
 	column_start = MAX (0, column_start);
 	column_count = CLAMP (i - column_start, 0 , terminal->column_count);
 
+	if(!column_count || !row_count)
+		return;
+
 	/* Convert the column and row start and end to pixel values
 	 * by multiplying by the size of a character cell. */
 	rect.x = column_start * terminal->char_width + VTE_PAD_WIDTH;
@@ -278,50 +299,38 @@
 		rect.height += VTE_PAD_WIDTH;
 	}
 
-	if (terminal->pvt->update_timeout != VTE_INVALID_SOURCE) {
-		if (!terminal->pvt->update_region)
-			terminal->pvt->update_region = gdk_region_rectangle (&rect);
-		else
-			gdk_region_union_with_rect (terminal->pvt->update_region, &rect);
-	} else {
-		terminal->pvt->update_region = gdk_region_rectangle (&rect);
+	terminal->pvt->update_regions = g_slist_prepend (
+			terminal->pvt->update_regions, gdk_region_rectangle (&rect));
+	if (terminal->pvt->update_timeout == VTE_INVALID_SOURCE) {
 		/* Wait a bit before doing any invalidation, just in
 		 * case updates are coming in really soon. */
 		add_update_timeout (terminal);
 	}
-
 }
 
 /* Redraw the entire visible portion of the window. */
 void
 _vte_invalidate_all(VteTerminal *terminal)
 {
-	GdkRectangle rect;
-	GtkWidget *widget;
-	int width, height;
-
 	g_assert(VTE_IS_TERMINAL(terminal));
-	if (!GTK_IS_WIDGET(terminal)) {
-	       return;
-	}
-	widget = GTK_WIDGET(terminal);
-	if (!GTK_WIDGET_REALIZED(widget)) {
+
+	if (!GTK_WIDGET_DRAWABLE(terminal)) {
 		return;
 	}
 	if (terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
 		return;
 	}
 
-	remove_update_timeout (terminal);
+	/* replace invalid regions with one covering the whole terminal */
+	reset_update_regions (terminal);
+	terminal->pvt->update_regions = g_slist_prepend (NULL,
+			gdk_region_rectangle (&terminal->widget.allocation));
 
-	/* Expose the entire widget area. */
-	width = height = 0;
-	gdk_drawable_get_size(widget->window, &width, &height);
-	rect.x = 0;
-	rect.y = 0;
-	rect.width = width;
-	rect.height = height;
-	gdk_window_invalidate_rect(widget->window, &rect, FALSE);
+	if (terminal->pvt->update_timeout == VTE_INVALID_SOURCE) {
+		/* Wait a bit before doing any invalidation, just in
+		 * case updates are coming in really soon. */
+		add_update_timeout (terminal);
+	}
 }
 
 /* Scroll a rectangular region up or down by a fixed number of lines,
@@ -330,6 +339,8 @@
 _vte_terminal_scroll_region(VteTerminal *terminal,
 			   long row, glong count, glong delta)
 {
+	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if ((delta == 0) || (count == 0)) {
 		/* Shenanigans! */
 		return;
@@ -341,21 +352,31 @@
 	} else {
 		/* We have to repaint the area which is to be
 		 * scrolled. */
+		reset_update_regions (terminal);
 		_vte_invalidate_cells(terminal,
 				     0, terminal->column_count,
 				     row, count);
 	}
 }
 
+/* Find the row in the given position in the backscroll buffer. */
+static inline VteRowData *
+_vte_terminal_find_row_data(VteTerminal *terminal, glong row)
+{
+	VteRowData *rowdata = NULL;
+	VteScreen *screen = terminal->pvt->screen;
+	if (_vte_ring_contains(screen->row_data, row)) {
+		rowdata = _vte_ring_index(screen->row_data, VteRowData *, row);
+	}
+	return rowdata;
+}
 /* Find the character an the given position in the backscroll buffer. */
 static struct vte_charcell *
 vte_terminal_find_charcell(VteTerminal *terminal, glong col, glong row)
 {
 	VteRowData *rowdata;
 	struct vte_charcell *ret = NULL;
-	VteScreen *screen;
-	g_assert(VTE_IS_TERMINAL(terminal));
-	screen = terminal->pvt->screen;
+	VteScreen *screen = terminal->pvt->screen;
 	if (_vte_ring_contains(screen->row_data, row)) {
 		rowdata = _vte_ring_index(screen->row_data, VteRowData *, row);
 		if (rowdata->cells->len > col) {
@@ -367,6 +388,19 @@
 	return ret;
 }
 
+/* Find the character in the given position in the given row. */
+static inline struct vte_charcell *
+_vte_row_data_find_charcell(VteRowData *rowdata, glong col)
+{
+	struct vte_charcell *ret = NULL;
+	if (rowdata && rowdata->cells->len > col) {
+		ret = &g_array_index(rowdata->cells,
+				struct vte_charcell,
+				col);
+	}
+	return ret;
+}
+
 /* Determine the width of the portion of the preedit string which lies
  * to the left of the cursor, or the entire string, in columns. */
 static gssize
@@ -377,8 +411,6 @@
 	gssize ret = 0;
 	const char *preedit = NULL;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-
 	if (terminal->pvt->im_preedit != NULL) {
 		preedit = terminal->pvt->im_preedit;
 		for (i = 0;
@@ -403,8 +435,6 @@
 	int i = 0;
 	const char *preedit = NULL;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-
 	if (terminal->pvt->im_preedit != NULL) {
 		preedit = terminal->pvt->im_preedit;
 		for (i = 0;
@@ -421,20 +451,15 @@
 
 /* Cause the cursor to be redrawn. */
 void
-_vte_invalidate_cursor_once(gpointer data, gboolean periodic)
+_vte_invalidate_cursor_once(VteTerminal *terminal, gboolean periodic)
 {
-	VteTerminal *terminal;
 	VteScreen *screen;
 	struct vte_charcell *cell;
 	gssize preedit_width;
 	int column, columns, row;
 
-	if (!VTE_IS_TERMINAL(data)) {
-		return;
-	}
+	g_assert(VTE_IS_TERMINAL(terminal));
 
-	terminal = VTE_TERMINAL(data);
-
 	if (terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
 		return;
 	}
@@ -445,8 +470,7 @@
 		}
 	}
 
-	if (terminal->pvt->cursor_visible &&
-	    GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
+	if (terminal->pvt->cursor_visible && GTK_WIDGET_DRAWABLE(terminal)) {
 		preedit_width = vte_terminal_preedit_width(terminal, FALSE);
 
 		screen = terminal->pvt->screen;
@@ -501,10 +525,8 @@
 	static gboolean have_timeout;
 	static gboolean have_queried_timeout;
 
-	g_assert(VTE_IS_TERMINAL(data));
+	terminal = data;
 
-	terminal = VTE_TERMINAL (data);
-
 	settings = gtk_widget_get_settings (GTK_WIDGET (data));
 
 	terminal->pvt->cursor_blink_state = !terminal->pvt->cursor_blink_state;
@@ -587,13 +609,15 @@
 		length = strlen(text);
 		result = text;
 	} else {
-		result = wrapped = g_malloc0(length + 1);
+		result = wrapped = g_slice_alloc(length + 1);
 		memcpy(wrapped, text, length);
+		wrapped[length] = '\0';
 	}
 
 	g_signal_emit_by_name(terminal, "commit", result, length);
 
-        g_free(wrapped);
+	if(wrapped)
+		g_slice_free1(length+1, wrapped);
 }
 
 /* Emit an "emulation-changed" signal. */
@@ -782,7 +806,6 @@
 static void
 vte_terminal_deselect_all(VteTerminal *terminal)
 {
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (terminal->pvt->has_selection) {
 		terminal->pvt->has_selection = FALSE;
 #ifdef VTE_DEBUG
@@ -800,6 +823,7 @@
 _vte_terminal_clear_tabstop(VteTerminal *terminal, int column)
 {
 	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if (terminal->pvt->tabstops != NULL) {
 		/* Remove a tab stop from the hash table. */
 		g_hash_table_remove(terminal->pvt->tabstops,
@@ -812,7 +836,9 @@
 _vte_terminal_get_tabstop(VteTerminal *terminal, int column)
 {
 	gpointer hash;
+
 	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if (terminal->pvt->tabstops != NULL) {
 		hash = g_hash_table_lookup(terminal->pvt->tabstops,
 					   GINT_TO_POINTER(2 * column + 1));
@@ -827,6 +853,7 @@
 _vte_terminal_set_tabstop(VteTerminal *terminal, int column)
 {
 	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if (terminal->pvt->tabstops != NULL) {
 		/* Just set a non-NULL pointer for this column number. */
 		g_hash_table_insert(terminal->pvt->tabstops,
@@ -840,12 +867,10 @@
 vte_terminal_set_default_tabstops(VteTerminal *terminal)
 {
 	int i, width;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (terminal->pvt->tabstops != NULL) {
 		g_hash_table_destroy(terminal->pvt->tabstops);
 	}
-	terminal->pvt->tabstops = g_hash_table_new(g_direct_hash,
-						   g_direct_equal);
+	terminal->pvt->tabstops = g_hash_table_new(NULL, NULL);
 	width = _vte_termcap_find_numeric(terminal->pvt->termcap,
 					  terminal->pvt->emulation,
 					  "it");
@@ -862,6 +887,7 @@
 _vte_terminal_match_contents_clear(VteTerminal *terminal)
 {
 	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if (terminal->pvt->match_contents != NULL) {
 		g_free(terminal->pvt->match_contents);
 		terminal->pvt->match_contents = NULL;;
@@ -883,9 +909,8 @@
 vte_terminal_match_contents_refresh(VteTerminal *terminal)
 {
 	GArray *array;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	_vte_terminal_match_contents_clear(terminal);
-	array = g_array_new(FALSE, TRUE, sizeof(struct _VteCharAttributes));
+	array = g_array_new(FALSE, FALSE, sizeof(struct _VteCharAttributes));
 	terminal->pvt->match_contents = vte_terminal_get_text(terminal,
 							      always_selected,
 							      NULL,
@@ -906,7 +931,9 @@
 {
 	struct vte_match_regex *regex;
 	int i;
+
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	for (i = 0; i < terminal->pvt->match_regexes->len; i++) {
 		regex = &g_array_index(terminal->pvt->match_regexes,
 				       struct vte_match_regex,
@@ -940,7 +967,9 @@
 vte_terminal_match_remove(VteTerminal *terminal, int tag)
 {
 	struct vte_match_regex *regex;
+
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	if (terminal->pvt->match_regexes->len > tag) {
 		/* The tag is an index, so find the corresponding struct. */
 		regex = &g_array_index(terminal->pvt->match_regexes,
@@ -968,9 +997,7 @@
 	GdkDisplay *display;
 	GdkCursor *cursor;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-
-	display = gtk_widget_get_display(GTK_WIDGET(terminal));
+	display = gtk_widget_get_display(&terminal->widget);
 	cursor = gdk_cursor_new_for_display(display, cursor_type);
 	return cursor;
 }
@@ -991,9 +1018,11 @@
 {
 	struct vte_match_regex new_regex, *regex;
 	int ret;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
 	g_return_val_if_fail(match != NULL, -1);
 	g_return_val_if_fail(strlen(match) > 0, -1);
+
 	memset(&new_regex, 0, sizeof(new_regex));
 	new_regex.reg = _vte_regex_compile(match);
 	if (new_regex.reg == NULL) {
@@ -1044,8 +1073,10 @@
 vte_terminal_match_set_cursor(VteTerminal *terminal, int tag, GdkCursor *cursor)
 {
 	struct vte_match_regex *regex;
+
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	g_return_if_fail(tag < terminal->pvt->match_regexes->len);
+
 	regex = &g_array_index(terminal->pvt->match_regexes,
 			       struct vte_match_regex,
 			       tag);
@@ -1224,8 +1255,8 @@
 						*end = coffset +
 						       matches[j].rm_eo - 1;
 					}
-					if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
-						gdk_window_set_cursor((GTK_WIDGET(terminal))->window,
+					if (GTK_WIDGET_REALIZED(terminal)) {
+						gdk_window_set_cursor(terminal->widget.window,
 								      regex->cursor);
 					}
 					terminal->pvt->match_previous = regex->tag;
@@ -1272,7 +1303,9 @@
 {
 	long delta;
 	char *ret;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
+
 	delta = terminal->pvt->screen->scroll_delta;
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
@@ -1296,7 +1329,7 @@
 vte_terminal_emit_adjustment_changed(gpointer data)
 {
 	VteTerminal *terminal;
-	terminal = VTE_TERMINAL(data);
+	terminal = data;
 	if (terminal->pvt->adjustment_changed_tag) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_SIGNALS)) {
@@ -1339,6 +1372,7 @@
 	long delta;
 	long rows;
 
+	g_assert(VTE_IS_TERMINAL(terminal));
 	g_assert(terminal->pvt->screen != NULL);
 	g_assert(terminal->pvt->screen->row_data != NULL);
 
@@ -1487,7 +1521,6 @@
 vte_terminal_scroll_pages(VteTerminal *terminal, gint pages)
 {
 	glong destination;
-	g_assert(VTE_IS_TERMINAL(terminal));
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_IO)) {
 		fprintf(stderr, "Scrolling %d pages.\n", pages);
@@ -1513,7 +1546,6 @@
 vte_terminal_maybe_scroll_to_top(VteTerminal *terminal)
 {
 	long delta;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (floor(gtk_adjustment_get_value(terminal->adjustment)) !=
 	    _vte_ring_delta(terminal->pvt->screen->row_data)) {
 		delta = _vte_ring_delta(terminal->pvt->screen->row_data);
@@ -1525,7 +1557,6 @@
 vte_terminal_maybe_scroll_to_bottom(VteTerminal *terminal)
 {
 	glong delta;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if ((terminal->pvt->screen->scroll_delta !=
 	    terminal->pvt->screen->insert_delta)) {
 		delta = terminal->pvt->screen->insert_delta;
@@ -1561,11 +1592,12 @@
 vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset)
 {
 	const char *old_codeset;
-	GQuark encoding_quark;
 	VteConv conv;
 	char *obuf1, *obuf2;
 	gsize bytes_written;
 
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	old_codeset = terminal->pvt->encoding;
 	if (codeset == NULL) {
 		g_get_charset(&codeset);
@@ -1577,19 +1609,18 @@
 
 	/* Open new conversions. */
 	conv = _vte_conv_open(codeset, "UTF-8");
-	if (conv == ((VteConv) -1)) {
+	if (conv == VTE_INVALID_CONV) {
 		g_warning(_("Unable to convert characters from %s to %s."),
 			  "UTF-8", codeset);
 		return;
 	}
-	if (terminal->pvt->outgoing_conv != (VteConv) -1) {
+	if (terminal->pvt->outgoing_conv != VTE_INVALID_CONV) {
 		_vte_conv_close(terminal->pvt->outgoing_conv);
 	}
 	terminal->pvt->outgoing_conv = conv;
 
 	/* Set the terminal's encoding to the new value. */
-	encoding_quark = g_quark_from_string(codeset);
-	terminal->pvt->encoding = g_quark_to_string(encoding_quark);
+	terminal->pvt->encoding = g_intern_string(codeset);
 
 	/* Convert any buffered output bytes. */
 	if ((_vte_buffer_length(terminal->pvt->outgoing) > 0) &&
@@ -1659,11 +1690,13 @@
 	VteScreen *screen;
 	gboolean readjust = FALSE, fill = FALSE;
 
+	g_assert(VTE_IS_TERMINAL(terminal));
+
 	/* Must make sure we're in a sane area. */
 	screen = terminal->pvt->screen;
 
 	/* Figure out how many rows we need to add. */
-	fill = (terminal->pvt->screen->defaults.back != VTE_DEF_BG);
+	fill = screen->defaults.back != VTE_DEF_BG;
 	while (screen->cursor_current.row >= _vte_ring_next(screen->row_data)) {
 		/* Create a new row. */
 		if (fill) {
@@ -1709,6 +1742,8 @@
 	long delta, rows;
 	VteScreen *screen;
 
+	g_assert(VTE_IS_TERMINAL(terminal));
+
 	screen = terminal->pvt->screen;
 
 	/* The total number of lines.  Add one to the cursor offset
@@ -1739,6 +1774,9 @@
 {
 	GdkCursor *cursor = NULL;
 	struct vte_match_regex *regex = NULL;
+
+	g_assert(VTE_IS_TERMINAL(terminal));
+
 	if (visible || !terminal->pvt->mouse_autohide) {
 		if (terminal->pvt->mouse_send_xy_on_click ||
 		    terminal->pvt->mouse_send_xy_on_button ||
@@ -1776,8 +1814,8 @@
 		cursor = terminal->pvt->mouse_inviso_cursor;
 	}
 	if (cursor) {
-		if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
-			gdk_window_set_cursor((GTK_WIDGET(terminal))->window,
+		if (GTK_WIDGET_REALIZED(terminal)) {
+			gdk_window_set_cursor(terminal->widget.window,
 					      cursor);
 		}
 	}
@@ -1800,7 +1838,7 @@
 	}
 #endif
 
-	return GTK_WIDGET(g_object_new(vte_terminal_get_type(), NULL));
+	return g_object_new(vte_terminal_get_type(), NULL);
 }
 
 /* Set up a palette entry with a more-or-less match for the requested color. */
@@ -1808,20 +1846,13 @@
 vte_terminal_set_color_internal(VteTerminal *terminal, int entry,
 				const GdkColor *proposed)
 {
-	GtkWidget *widget;
-
-	g_assert(VTE_IS_TERMINAL(terminal));
-	g_assert(entry >= 0);
-	g_assert(entry < G_N_ELEMENTS(terminal->pvt->palette));
-
 	/* Save the requested color. */
 	terminal->pvt->palette[entry].red = proposed->red;
 	terminal->pvt->palette[entry].green = proposed->green;
 	terminal->pvt->palette[entry].blue = proposed->blue;
 
 	/* If we're not realized yet, there's nothing else to do. */
-	widget = GTK_WIDGET(terminal);
-	if (!GTK_WIDGET_REALIZED(widget)) {
+	if (!GTK_WIDGET_REALIZED(terminal)) {
 		return;
 	}
 
@@ -1839,9 +1870,6 @@
 			   GdkColor *bold)
 {
 	double fy, fcb, fcr, by, bcb, bcr, r, g, b;
-	g_assert(foreground != NULL);
-	g_assert(background != NULL);
-	g_assert(bold != NULL);
 	fy =   0.2990 * foreground->red +
 	       0.5870 * foreground->green +
 	       0.1140 * foreground->blue;
@@ -1895,6 +1923,8 @@
 void
 vte_terminal_set_color_bold(VteTerminal *terminal, const GdkColor *bold)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(bold!=NULL);
 	vte_terminal_set_color_internal(terminal, VTE_BOLD_FG, bold);
 }
 
@@ -1909,6 +1939,8 @@
 void
 vte_terminal_set_color_dim(VteTerminal *terminal, const GdkColor *dim)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(dim!=NULL);
 	vte_terminal_set_color_internal(terminal, VTE_DIM_FG, dim);
 }
 
@@ -1924,6 +1956,8 @@
 vte_terminal_set_color_foreground(VteTerminal *terminal,
 				  const GdkColor *foreground)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(foreground!=NULL);
 	vte_terminal_set_color_internal(terminal, VTE_DEF_FG, foreground);
 }
 
@@ -1941,6 +1975,8 @@
 vte_terminal_set_color_background(VteTerminal *terminal,
 				  const GdkColor *background)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(background!=NULL);
 	vte_terminal_set_color_internal(terminal, VTE_DEF_BG, background);
 }
 
@@ -1960,6 +1996,8 @@
 vte_terminal_set_color_cursor(VteTerminal *terminal,
 			      const GdkColor *cursor_background)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	if (cursor_background != NULL) {
 		vte_terminal_set_color_internal(terminal, VTE_CUR_BG,
 						cursor_background);
@@ -1985,6 +2023,8 @@
 vte_terminal_set_color_highlight(VteTerminal *terminal,
 				 const GdkColor *highlight_background)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	if (highlight_background != NULL) {
 		vte_terminal_set_color_internal(terminal, VTE_DEF_HL,
 						highlight_background);
@@ -2144,6 +2184,7 @@
 void
 vte_terminal_set_opacity(VteTerminal *terminal, guint16 opacity)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	terminal->pvt->bg_opacity = opacity;
 }
 
@@ -2157,6 +2198,7 @@
 void
 vte_terminal_set_default_colors(VteTerminal *terminal)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	vte_terminal_set_colors(terminal, NULL, NULL, NULL, 0);
 }
 
@@ -2168,15 +2210,17 @@
 			 gint forced_width)
 {
 	VteRowData *row;
-	struct vte_charcell cell, *pcell;
+	struct vte_charcell cell;
 	int columns, i;
 	long col;
 	VteScreen *screen;
 	gboolean insert, clean;
 
+	g_assert(VTE_IS_TERMINAL(terminal));
+
 	screen = terminal->pvt->screen;
-	insert = screen->insert_mode || force_insert_mode;
-	invalidate_now = insert || invalidate_now;
+	insert = screen->insert_mode | force_insert_mode;
+	invalidate_now |= insert;
 
 	/* If we've enabled the special drawing set, map the characters to
 	 * Unicode. */
@@ -2197,9 +2241,8 @@
 	}
 
 	/* If this character is destined for the status line, save it. */
-	if (terminal->pvt->screen->status_line) {
-		g_string_append_unichar(terminal->pvt->screen->status_line_contents,
-					c);
+	if (screen->status_line) {
+		g_string_append_unichar(screen->status_line_contents, c);
 		_vte_terminal_emit_status_line_changed(terminal);
 		return;
 	}
@@ -2291,41 +2334,46 @@
 		/* Set the character cell's attributes to match the current
 		 * defaults, preserving any previous contents. */
 		cell = g_array_index(row->cells, struct vte_charcell, col);
-		pcell = &g_array_index(row->cells, struct vte_charcell, col);
-		*pcell = screen->defaults;
-		if (!paint_cells) {
-			pcell->fore = cell.fore;
-			pcell->back = cell.back;
+		if (paint_cells) {
+			cell.fore = screen->defaults.fore;
+			cell.back = screen->defaults.back;
 		}
-		pcell->c = cell.c;
-		pcell->columns = cell.columns;
-		pcell->fragment = cell.fragment;
-		pcell->empty = cell.empty;
-		pcell->alternate = 0;
+		cell.standout = screen->defaults.standout;
+		cell.underline = screen->defaults.underline;
+		cell.strikethrough = screen->defaults.strikethrough;
+		cell.reverse = screen->defaults.reverse;
+		cell.blink = screen->defaults.blink;
+		cell.half = screen->defaults.half;
+		cell.bold = screen->defaults.bold;
+		cell.bold = screen->defaults.bold;
+		cell.invisible = screen->defaults.invisible;
+		cell.protect = screen->defaults.protect;
+		cell.alternate = 0;
 
 		/* Now set the character and column count. */
 		if (i == 0) {
 			/* This is an entire character or the first column of
 			 * a multi-column character. */
-			if ((pcell->c != 0) &&
+			if ((cell.c != 0) &&
 			    (c == '_') &&
 			    (terminal->pvt->flags.ul)) {
 				/* Handle overstrike-style underlining. */
-				pcell->underline = 1;
+				cell.underline = 1;
 			} else {
 				/* Insert the character. */
-				pcell->c = c;
-				pcell->columns = columns;
-				pcell->fragment = 0;
-				pcell->empty = 0;
+				cell.c = c;
+				cell.columns = columns;
+				cell.fragment = 0;
+				cell.empty = 0;
 			}
 		} else {
 			/* This is a continuation cell. */
-			pcell->c = c;
-			pcell->columns = columns;
-			pcell->fragment = 1;
-			pcell->empty = 0;
+			cell.c = c;
+			cell.columns = columns;
+			cell.fragment = 1;
+			cell.empty = 0;
 		}
+		g_array_index(row->cells, struct vte_charcell, col) = cell;
 
 		/* And take a step to the to the right. */
 		screen->cursor_current.col++;
@@ -2424,38 +2472,23 @@
 
 /* Handle a terminal control sequence and its parameters. */
 static gboolean
-vte_terminal_handle_sequence(GtkWidget *widget,
+vte_terminal_handle_sequence(VteTerminal *terminal,
 			     const char *match_s,
 			     GQuark match,
 			     GValueArray *params)
 {
-	VteTerminal *terminal;
 	VteTerminalSequenceHandler handler;
-	VteScreen *screen;
-	struct vte_cursor_position position;
 	gboolean ret;
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
-	terminal = VTE_TERMINAL(widget);
-	screen = terminal->pvt->screen;
-
-	/* This may generate multiple redraws, so freeze it while we do them. */
-	if (GTK_WIDGET_REALIZED (widget)) {
-		gdk_window_freeze_updates(widget->window);
-	}
-
-	/* Save the cursor's current position for future use. */
-	position = screen->cursor_current;
-
-	/* Find the handler for this control sequence. */
-	handler = _vte_sequence_get_handler (match_s, match);
-
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_PARSE)) {
 		display_control_sequence(match_s, params);
 	}
 #endif
+
+	/* Find the handler for this control sequence. */
+	handler = _vte_sequence_get_handler (match_s, match);
+
 	if (handler != NULL) {
 		/* Let the handler handle it. */
 		ret = handler(terminal, match_s, match, params);
@@ -2465,21 +2498,16 @@
 				match_s);
 #else
 		/* suppress multiple warnings for each widget */
-		if (!g_object_get_qdata(G_OBJECT (widget), match)) {
+		if (!g_object_get_qdata(G_OBJECT (terminal), match)) {
 			g_warning(_("No handler for control sequence `%s' defined."),
 					match_s);
-			g_object_set_qdata(G_OBJECT (widget),
+			g_object_set_qdata(G_OBJECT (terminal),
 					match, (gpointer)0x1);
 		}
 #endif
 		ret = FALSE;
 	}
 
-	/* Let the updating begin. */
-	if (GTK_WIDGET_REALIZED (widget)) {
-		gdk_window_thaw_updates(widget->window);
-	}
-
 	return ret;
 }
 
@@ -2487,18 +2515,15 @@
  * looking for, emit one of our own. */
 static void
 vte_terminal_catch_child_exited(VteReaper *reaper, int pid, int status,
-				VteTerminal *data)
+				VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
 	if (pid == terminal->pvt->pty_pid) {
 		/* Disconnect from the reaper. */
 		if (VTE_IS_REAPER(terminal->pvt->pty_reaper)) {
 			g_signal_handlers_disconnect_by_func(terminal->pvt->pty_reaper,
-							     (gpointer)vte_terminal_catch_child_exited,
+							     vte_terminal_catch_child_exited,
 							     terminal);
-			g_object_unref(G_OBJECT(terminal->pvt->pty_reaper));
+			g_object_unref(terminal->pvt->pty_reaper);
 		}
 		terminal->pvt->pty_reaper = NULL;
 		terminal->pvt->pty_pid = -1;
@@ -2545,7 +2570,7 @@
 			g_io_add_watch_full(terminal->pvt->pty_input,
 					    VTE_CHILD_INPUT_PRIORITY,
 					    G_IO_IN | G_IO_HUP,
-					    vte_terminal_io_read,
+					    (GIOFunc)vte_terminal_io_read,
 					    terminal,
 					    NULL);
 	}
@@ -2561,17 +2586,17 @@
 		terminal->pvt->pty_output =
 			g_io_channel_unix_new(terminal->pvt->pty_master);
 	}
-	g_static_mutex_lock (&(terminal->pvt->pty_output_source_mutex));
+	g_static_mutex_lock (&terminal->pvt->pty_output_source_mutex);
 	if (terminal->pvt->pty_output_source == VTE_INVALID_SOURCE) {
 		terminal->pvt->pty_output_source =
 			g_io_add_watch_full(terminal->pvt->pty_output,
 					    VTE_CHILD_OUTPUT_PRIORITY,
 					    G_IO_OUT,
-					    vte_terminal_io_write,
+					    (GIOFunc)vte_terminal_io_write,
 					    terminal,
 					    NULL);
 	}
-	g_static_mutex_unlock (&(terminal->pvt->pty_output_source_mutex));
+	g_static_mutex_unlock (&terminal->pvt->pty_output_source_mutex);
 }
 
 static void
@@ -2600,12 +2625,12 @@
 		g_io_channel_unref(terminal->pvt->pty_output);
 		terminal->pvt->pty_output = NULL;
 	}
-	g_static_mutex_lock (&(terminal->pvt->pty_output_source_mutex));
+	g_static_mutex_lock (&terminal->pvt->pty_output_source_mutex);
 	if (terminal->pvt->pty_output_source != VTE_INVALID_SOURCE) {
 		g_source_remove(terminal->pvt->pty_output_source);
 		terminal->pvt->pty_output_source = VTE_INVALID_SOURCE;
 	}
-	g_static_mutex_unlock (&(terminal->pvt->pty_output_source_mutex));
+	g_static_mutex_unlock (&terminal->pvt->pty_output_source_mutex);
 }
 
 /* Basic wrapper around _vte_pty_open, which handles the pipefitting. */
@@ -2618,16 +2643,13 @@
 	char **env_add;
 	int i;
 	pid_t pid;
-	GtkWidget *widget;
 	VteReaper *reaper;
 
-	widget = GTK_WIDGET(terminal);
-
 	/* Duplicate the environment, and add one more variable. */
 	for (i = 0; (envv != NULL) && (envv[i] != NULL); i++) {
 		/* nothing */ ;
 	}
-	env_add = g_malloc0(sizeof(char*) * (i + 2));
+	env_add = g_malloc(sizeof(char*) * (i + 2));
 	env_add[0] = g_strdup_printf("TERM=%s", terminal->pvt->emulation);
 	for (i = 0; (envv != NULL) && (envv[i] != NULL); i++) {
 		env_add[i + 1] = g_strdup(envv[i]);
@@ -2665,28 +2687,29 @@
 		/* Catch a child-exited signal from the child pid. */
 		reaper = vte_reaper_get();
 		vte_reaper_add_child((GPid) pid);
-		g_object_ref(G_OBJECT(reaper));
+		g_object_ref(reaper);
 		if (VTE_IS_REAPER(terminal->pvt->pty_reaper)) {
 			g_signal_handlers_disconnect_by_func(terminal->pvt->pty_reaper,
-							     (gpointer)vte_terminal_catch_child_exited,
+							     vte_terminal_catch_child_exited,
 							     terminal);
-			g_object_unref(G_OBJECT(terminal->pvt->pty_reaper));
+			g_object_unref(terminal->pvt->pty_reaper);
 		}
-		g_signal_connect(G_OBJECT(reaper), "child-exited",
+		g_signal_connect(reaper, "child-exited",
 				 G_CALLBACK(vte_terminal_catch_child_exited),
 				 terminal);
 		terminal->pvt->pty_reaper = reaper;
 
 		/* Set the pty to be non-blocking. */
 		i = fcntl(terminal->pvt->pty_master, F_GETFL);
-		fcntl(terminal->pvt->pty_master, F_SETFL, i | O_NONBLOCK);
+		if ((i&O_NONBLOCK) == FALSE)
+			fcntl(terminal->pvt->pty_master, F_SETFL, i | O_NONBLOCK);
 
 		/* Set the PTY size. */
 		vte_terminal_set_size(terminal,
 				      terminal->column_count,
 				      terminal->row_count);
-		if (GTK_WIDGET_REALIZED(widget)) {
-			gtk_widget_queue_resize(widget);
+		if (GTK_WIDGET_REALIZED(terminal)) {
+			gtk_widget_queue_resize(&terminal->widget);
 		}
 
 		/* Open a channel to listen for input on. */
@@ -2814,13 +2837,8 @@
 
 /* Handle an EOF from the client. */
 static void
-vte_terminal_eof(GIOChannel *channel, gpointer data)
+vte_terminal_eof(GIOChannel *channel, VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-
 	/* Close the connections to the child -- note that the source channel
 	 * has already been dereferenced. */
 	if (channel == terminal->pvt->pty_input) {
@@ -2856,8 +2874,7 @@
 static void
 vte_terminal_im_reset(VteTerminal *terminal)
 {
-	g_assert(VTE_IS_TERMINAL(terminal));
-	if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
+	if (GTK_WIDGET_REALIZED(terminal)) {
 		gtk_im_context_reset(terminal->pvt->im_context);
 		if (terminal->pvt->im_preedit != NULL) {
 			g_free(terminal->pvt->im_preedit);
@@ -2893,7 +2910,7 @@
 	if (quark != 0) {
 		for (i = 0; i < G_N_ELEMENTS(non_visual_quarks); i++) {
 			if (non_visual_quarks[i].quark == 0) {
-				tmp = g_quark_from_string(non_visual_quarks[i].name);
+				tmp = g_quark_from_static_string(non_visual_quarks[i].name);
 				non_visual_quarks[i].quark = tmp;
 			}
 			if (quark == non_visual_quarks[i].quark) {
@@ -2941,7 +2958,6 @@
 	GValueArray *params = NULL;
 	VteScreen *screen;
 	struct vte_cursor_position cursor;
-	GtkWidget *widget;
 	GdkRectangle rect;
 	GdkPoint bbox_topleft, bbox_bottomright;
 	gunichar *wbuf, c;
@@ -2952,10 +2968,6 @@
 	gboolean leftovers, modified, bottom, inserted, again;
 	GArray *unichars;
 
-	g_assert(GTK_IS_WIDGET(terminal));
-	g_assert(VTE_IS_TERMINAL(terminal));
-	widget = GTK_WIDGET(terminal);
-
 	bottom = (terminal->pvt->screen->insert_delta ==
 		  terminal->pvt->screen->scroll_delta);
 
@@ -2969,11 +2981,8 @@
 	screen = terminal->pvt->screen;
 	cursor = screen->cursor_current;
 
-	/* Estimate how much of the screen we'll need to update. */
-	bbox_topleft.x = cursor.col;
-	bbox_topleft.y = cursor.row;
-	bbox_bottomright.x = cursor.col + 1; /* Assume it's on a wide char. */
-	bbox_bottomright.y = cursor.row;
+	/* invalidate the current cursor position */
+	_vte_invalidate_cells(terminal, cursor.col, 2, cursor.row, 1);
 
 	/* We're going to check if the text was modified once we're done here,
 	 * so keep a flag. */
@@ -3000,6 +3009,13 @@
 	modified = leftovers = inserted = again = FALSE;
 
 	while ((start < wcount) && !leftovers && !again) {
+		gboolean invalidate_text = FALSE;
+
+		bbox_topleft.x = screen->cursor_current.col;
+		bbox_topleft.y = screen->cursor_current.row;
+		bbox_bottomright.x = screen->cursor_current.col;
+		bbox_bottomright.y = screen->cursor_current.row;
+
 		/* Try to match any control sequences. */
 		_vte_matcher_match(terminal->pvt->matcher,
 				   &wbuf[start],
@@ -3021,7 +3037,7 @@
 			}
 			/* Call the right sequence handler for the requested
 			 * behavior. */
-			again = vte_terminal_handle_sequence(GTK_WIDGET(terminal),
+			again = vte_terminal_handle_sequence(terminal,
 							     match,
 							     quark,
 							     params);
@@ -3100,6 +3116,7 @@
 
 			/* We *don't* emit flush pending signals here. */
 			modified = TRUE;
+			invalidate_text = TRUE;
 			start++;
 		} else {
 			/* Case three: the read broke in the middle of a
@@ -3125,17 +3142,34 @@
 			}
 		}
 
-		/* Add the cell into which we just moved to the region which we
-		 * need to refresh for the user. */
-		bbox_topleft.x = MIN(bbox_topleft.x,
-				     screen->cursor_current.col);
-		bbox_topleft.y = MIN(bbox_topleft.y,
-				     screen->cursor_current.row);
-		bbox_bottomright.x = MAX(bbox_bottomright.x,
-					 screen->cursor_current.col + 1);
-		bbox_bottomright.y = MAX(bbox_bottomright.y,
-					 screen->cursor_current.row);
+		if (invalidate_text) {
+			/* Add the cell into which we just moved to the region which we
+			 * need to refresh for the user. */
+			bbox_topleft.x = MIN(bbox_topleft.x,
+					screen->cursor_current.col);
+			bbox_topleft.y = MIN(bbox_topleft.y,
+					screen->cursor_current.row);
+			bbox_bottomright.x = MAX(bbox_bottomright.x,
+					screen->cursor_current.col + 1);
+			bbox_bottomright.y = MAX(bbox_bottomright.y,
+					screen->cursor_current.row);
 
+			/* Clip off any part of the box which isn't already on-screen. */
+			bbox_topleft.x = MAX(bbox_topleft.x, 1) - 1;
+			bbox_topleft.y = MAX(bbox_topleft.y, screen->scroll_delta);
+			bbox_bottomright.x = MIN(bbox_bottomright.x,
+					terminal->column_count - 1);
+			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_topleft.y,
+					bbox_bottomright.y - bbox_topleft.y + 1);
+		}
+
 #ifdef VTE_DEBUG
 		/* Some safety checks: ensure the visible parts of the buffer
 		 * are all in the buffer. */
@@ -3159,7 +3193,7 @@
 
 	/* Remove most of the processed characters. */
 	if (start < wcount) {
-		unichars = g_array_new(TRUE, TRUE, sizeof(gunichar));
+		unichars = g_array_new(FALSE, FALSE, sizeof(gunichar));
 		g_array_append_vals(unichars,
 				    &g_array_index(terminal->pvt->pending,
 						   gunichar,
@@ -3178,23 +3212,6 @@
 	/* Flush any pending "inserted" signals. */
 	vte_terminal_emit_pending_text_signals(terminal, 0);
 
-	/* Clip off any part of the box which isn't already on-screen. */
-	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);
-	bbox_bottomright.y = MIN(bbox_bottomright.y,
-				 screen->scroll_delta +
-				 terminal->row_count);
-
-	/* Update the screen to draw any modified areas.  This includes
-	 * the current location of the cursor. */
-	_vte_invalidate_cells(terminal,
-			     bbox_topleft.x - 1,
-			     bbox_bottomright.x - (bbox_topleft.x - 1) + 1,
-			     bbox_topleft.y,
-			     bbox_bottomright.y - bbox_topleft.y + 1);
-
 	if (modified) {
 		/* Keep the cursor on-screen if we scroll on output, or if
 		 * we're currently at the bottom of the buffer. */
@@ -3236,7 +3253,7 @@
 	}
 
 	/* Tell the input method where the cursor is. */
-	if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
+	if (GTK_WIDGET_REALIZED(terminal)) {
 		rect.x = terminal->pvt->screen->cursor_current.col *
 			 terminal->char_width + VTE_PAD_WIDTH;
 		rect.width = terminal->char_width;
@@ -3262,74 +3279,58 @@
 static gboolean
 vte_terminal_io_read(GIOChannel *channel,
 		     GIOCondition condition,
-		     gpointer data)
+		     VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-	GtkWidget *widget;
-	char buf[VTE_INPUT_CHUNK_SIZE];
-	int bcount, fd;
+	char buf[VTE_INPUT_CHUNK_SIZE], *bp = buf;
+	int err = 0;
 	gboolean eof, leave_open = TRUE;
 
-	g_assert(VTE_IS_TERMINAL(data));
-	widget = GTK_WIDGET(data);
-	terminal = VTE_TERMINAL(data);
-
-	/* Check that the channel is still open. */
-	fd = g_io_channel_unix_get_fd(channel);
-
-	/* Read some data in from this channel. */
-	bcount = 0;
-	if (condition & G_IO_IN) {
-		/* We try not to overfill the incoming buffer below by cutting
-		 * down the read size if we already have pending data. */
-		bcount = sizeof(buf);
-		if (_vte_buffer_length(terminal->pvt->incoming) < sizeof(buf)) {
-			/* Shoot for exactly one "chunk" for processing. */
-			bcount -= _vte_buffer_length(terminal->pvt->incoming);
-		} else {
-			/* Read half of the chunk size. */
-			bcount = sizeof(buf) / 2;
-		}
-		g_assert(bcount >= 0);
-		g_assert(bcount <= sizeof(buf));
-		bcount = read(fd, buf, MAX(bcount, sizeof(buf) / 2));
-	}
-
 	/* Check for end-of-file. */
 	eof = FALSE;
 	if (condition & G_IO_HUP) {
 		eof = TRUE;
 	}
 
-	/* Catch errors. */
-	switch (bcount) {
-	case 0:
-		/* EOF */
-		eof = TRUE;
-		break;
-	case -1:
-		/* Error! */
-		switch (errno) {
-			case EIO: /* Fake an EOF. */
-				eof = TRUE;
+	/* Read some data in from this channel. */
+	if (condition & G_IO_IN) {
+		const int fd = g_io_channel_unix_get_fd(channel);
+		int rem = sizeof(buf);
+		while (rem){
+			int ret = read(fd, bp, rem);
+			if(ret <= 0){
+				if(ret == 0)
+					eof = TRUE;
+				else
+					err = errno;
 				break;
-			case EAGAIN:
-			case EBUSY: /* do nothing */
-				break;
-			default:
-				/* Translators: %s is replaced with error message returned by strerror(). */
-				g_warning(_("Error reading from child: "
-					    "%s."), strerror(errno));
-				leave_open = TRUE;
-				break;
+			}
+			rem -= ret;
+			bp += ret;
 		}
-		break;
-	default:
+	}
+
+	if (bp != buf) {
 		/* Queue up the data for processing. */
-		vte_terminal_feed(terminal, buf, bcount);
-		break;
+		vte_terminal_feed(terminal, buf, bp - buf);
 	}
 
+	/* Error? */
+	switch (err) {
+		case 0: /* no error */
+			break;
+		case EIO: /* Fake an EOF. */
+			eof = TRUE;
+			break;
+		case EAGAIN:
+		case EBUSY: /* do nothing */
+			break;
+		default:
+			/* Translators: %s is replaced with error message returned by strerror(). */
+			g_warning(_("Error reading from child: " "%s."), strerror(err));
+			leave_open = TRUE;
+			break;
+	}
+
 	/* If we detected an eof condition, signal one. */
 	if (eof) {
 		vte_terminal_eof(channel, terminal);
@@ -3371,16 +3372,12 @@
 static gboolean
 vte_terminal_io_write(GIOChannel *channel,
 		      GIOCondition condition,
-		      gpointer data)
+		      VteTerminal *terminal)
 {
-	VteTerminal *terminal;
 	gssize count;
 	int fd;
 	gboolean leave_open;
 
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-
 	fd = g_io_channel_unix_get_fd(channel);
 
 	count = write(fd, terminal->pvt->outgoing->bytes,
@@ -3420,18 +3417,13 @@
 {
 	gssize icount, ocount;
 	char *ibuf, *obuf, *obufptr, *cooked;
-	VteConv *conv;
+	VteConv conv;
 	long crcount, cooked_length, i;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-	g_assert(encoding && strcmp(encoding, "UTF-8") == 0);
-
 	conv = NULL;
 	if (strcmp(encoding, "UTF-8") == 0) {
-		conv = &terminal->pvt->outgoing_conv;
+		conv = terminal->pvt->outgoing_conv;
 	}
-	g_assert(conv != NULL);
-	g_assert(*conv != ((VteConv) -1));
 
 	icount = length;
 	ibuf = (char *) data;
@@ -3439,7 +3431,7 @@
 	_vte_buffer_set_minimum_size(terminal->pvt->conv_buffer, ocount);
 	obuf = obufptr = terminal->pvt->conv_buffer->bytes;
 
-	if (_vte_conv(*conv, &ibuf, &icount, &obuf, &ocount) == -1) {
+	if (_vte_conv(conv, &ibuf, &icount, &obuf, &ocount) == -1) {
 		g_warning(_("Error (%s) converting data for child, dropping."),
 			  strerror(errno));
 	} else {
@@ -3567,7 +3559,7 @@
 void
 vte_terminal_feed_child_binary(VteTerminal *terminal, const char *data, glong length)
 {
-	g_assert(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 
 	/* Tell observers that we're sending this to the child. */
 	if (length > 0) {
@@ -3590,7 +3582,6 @@
 vte_terminal_feed_child_using_modes(VteTerminal *terminal,
 				    const char *data, glong length)
 {
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (length == ((gssize)-1)) {
 		length = strlen(data);
 	}
@@ -3603,18 +3594,13 @@
 
 /* Send text from the input method to the child. */
 static void
-vte_terminal_im_commit(GtkIMContext *im_context, gchar *text, gpointer data)
+vte_terminal_im_commit(GtkIMContext *im_context, gchar *text, VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-
-	g_assert(VTE_IS_TERMINAL(data));
-	g_assert(GTK_IS_IM_CONTEXT(im_context));
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Input method committed `%s'.\n", text);
 	}
 #endif
-	terminal = VTE_TERMINAL(data);
 	vte_terminal_feed_child_using_modes(terminal, text, -1);
 	/* Committed text was committed because the user pressed a key, so
 	 * we need to obey the scroll-on-keystroke setting. */
@@ -3625,14 +3611,8 @@
 
 /* We've started pre-editing. */
 static void
-vte_terminal_im_preedit_start(GtkIMContext *im_context, gpointer data)
+vte_terminal_im_preedit_start(GtkIMContext *im_context, VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-	g_assert(GTK_IS_IM_CONTEXT(im_context));
-
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Input method pre-edit started.\n");
@@ -3643,14 +3623,8 @@
 
 /* We've stopped pre-editing. */
 static void
-vte_terminal_im_preedit_end(GtkIMContext *im_context, gpointer data)
+vte_terminal_im_preedit_end(GtkIMContext *im_context, VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-	g_assert(GTK_IS_IM_CONTEXT(im_context));
-
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Input method pre-edit ended.\n");
@@ -3661,17 +3635,12 @@
 
 /* The pre-edit string changed. */
 static void
-vte_terminal_im_preedit_changed(GtkIMContext *im_context, gpointer data)
+vte_terminal_im_preedit_changed(GtkIMContext *im_context, VteTerminal *terminal)
 {
 	gchar *str;
 	PangoAttrList *attrs;
-	VteTerminal *terminal;
 	gint cursor;
 
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-	g_assert(GTK_IS_IM_CONTEXT(im_context));
-
 	gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor);
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
@@ -3702,20 +3671,13 @@
 /* Handle the toplevel being reconfigured. */
 static gboolean
 vte_terminal_configure_toplevel(GtkWidget *widget, GdkEventConfigure *event,
-				gpointer data)
+				VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Top level parent configured.\n");
 	}
 #endif
-	g_assert(GTK_IS_WIDGET(widget));
-	g_assert(GTK_WIDGET_TOPLEVEL(widget));
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
-
 	if (terminal->pvt->bg_transparent) {
 		/* We have to repaint the entire window, because we don't get
 		 * an expose event unless some portion of our visible area
@@ -3731,7 +3693,6 @@
 vte_terminal_hierarchy_changed(GtkWidget *widget, GtkWidget *old_toplevel,
 			       gpointer data)
 {
-	VteTerminal *terminal;
 	GtkWidget *toplevel;
 
 #ifdef VTE_DEBUG
@@ -3740,20 +3701,17 @@
 	}
 #endif
 
-	g_assert(VTE_IS_TERMINAL(widget));
-	terminal = VTE_TERMINAL(widget);
-
 	if (GTK_IS_WIDGET(old_toplevel)) {
-		g_signal_handlers_disconnect_by_func(G_OBJECT(old_toplevel),
-						     (gpointer)vte_terminal_configure_toplevel,
-						     terminal);
+		g_signal_handlers_disconnect_by_func(old_toplevel,
+						     vte_terminal_configure_toplevel,
+						     widget);
 	}
 
 	toplevel = gtk_widget_get_toplevel(widget);
 	if (GTK_IS_WIDGET(toplevel)) {
-		g_signal_connect(G_OBJECT(toplevel), "configure-event",
+		g_signal_connect(toplevel, "configure-event",
 				 G_CALLBACK(vte_terminal_configure_toplevel),
-				 terminal);
+				 widget);
 	}
 }
 
@@ -3762,7 +3720,6 @@
 vte_terminal_style_changed(GtkWidget *widget, GtkStyle *style, gpointer data)
 {
 	VteTerminal *terminal;
-	g_assert(VTE_IS_TERMINAL(widget));
 	if (!GTK_WIDGET_REALIZED(widget)) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_MISC)) {
@@ -3790,8 +3747,8 @@
 	GtkSettings *settings;
 
 	/* Setup cursor blink */
-	settings = gtk_widget_get_settings(GTK_WIDGET(terminal));
-	if (G_IS_OBJECT(settings)) {
+	settings = gtk_widget_get_settings(&terminal->widget);
+	if (settings) {
 		gint blink_cycle = 1000;
 		g_object_get(G_OBJECT(settings), "gtk-cursor-blink-time",
 			     &blink_cycle, NULL);
@@ -3834,17 +3791,13 @@
 	gunichar keychar = 0;
 	char keybuf[VTE_UTF8_BPC];
 	GdkModifierType modifiers;
-	GtkWidgetClass *widget_class;
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	/* First, check if GtkWidget's behavior already does something with
 	 * this key. */
-	widget_class = g_type_class_peek(GTK_TYPE_WIDGET);
-	if (GTK_WIDGET_CLASS(widget_class)->key_press_event) {
-		if ((GTK_WIDGET_CLASS(widget_class))->key_press_event(widget,
+	if (GTK_WIDGET_CLASS(parent_class)->key_press_event) {
+		if ((GTK_WIDGET_CLASS(parent_class))->key_press_event(widget,
 								      event)) {
 			return TRUE;
 		}
@@ -4230,6 +4183,7 @@
 {
 	int i;
 	VteWordCharRange *range;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
 
 	if (terminal->pvt->word_chars != NULL) {
@@ -4262,7 +4216,6 @@
 {
 	struct vte_charcell *pcell = NULL;
 	gboolean word_char;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if ((pcell = vte_terminal_find_charcell(terminal, acol, arow)) != NULL && !pcell->empty) {
 		word_char = vte_terminal_is_word_char(terminal, pcell->c);
 
@@ -4289,7 +4242,6 @@
 {
 	VteRowData *rowdata;
 	VteScreen *screen;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	screen = terminal->pvt->screen;
 	if (_vte_ring_contains(screen->row_data, row)) {
 		rowdata = _vte_ring_index(screen->row_data, VteRowData *, row);
@@ -4362,7 +4314,7 @@
 }
 
 /* Check if a cell is selected or not. */
-static gboolean
+static inline gboolean
 vte_cell_is_selected(VteTerminal *terminal, glong col, glong row, gpointer data)
 {
 	struct selection_cell_coords ss, se;
@@ -4398,8 +4350,7 @@
 	VteTerminal *terminal;
 	gchar *paste, *p;
 	long length;
-	g_assert(VTE_IS_TERMINAL(data));
-	terminal = VTE_TERMINAL(data);
+	terminal = data;
 	if (text != NULL) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_SELECTION)) {
@@ -4438,8 +4389,6 @@
 	unsigned char cb = 0, cx = 0, cy = 0;
 	char buf[LINE_MAX];
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-
 	/* Encode the button information in cb. */
 	switch (button) {
 	case 0:			/* Release/no buttons. */
@@ -4536,8 +4485,6 @@
 	unsigned char cb = 0, cx = 0, cy = 0;
 	char buf[LINE_MAX];
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-
 	/* First determine if we even want to send notification. */
 	switch (event->type) {
 	case GDK_MOTION_NOTIFY:
@@ -4720,8 +4667,7 @@
 vte_terminal_clear_cb(GtkClipboard *clipboard, gpointer owner)
 {
 	VteTerminal *terminal;
-	g_assert(VTE_IS_TERMINAL(owner));
-	terminal = VTE_TERMINAL(owner);
+	terminal = owner;
 	if (terminal->pvt->has_selection) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_SELECTION)) {
@@ -4738,8 +4684,7 @@
 		     guint info, gpointer owner)
 {
 	VteTerminal *terminal;
-	g_assert(VTE_IS_TERMINAL(owner));
-	terminal = VTE_TERMINAL(owner);
+	terminal = owner;
 	if (terminal->pvt->selection != NULL) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_SELECTION)) {
@@ -4819,8 +4764,6 @@
 	struct _VteCharAttributes attr;
 	struct vte_palette_entry fore, back, *palette;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-	g_assert(is_selected != NULL);
 	screen = terminal->pvt->screen;
 
 	if (attributes)
@@ -5069,7 +5012,7 @@
 vte_terminal_clipboard_get(VteTerminal *terminal, GdkAtom board)
 {
 	GdkDisplay *display;
-	display = gtk_widget_get_display(GTK_WIDGET(terminal));
+	display = gtk_widget_get_display(&terminal->widget);
 	return gtk_clipboard_get_for_display(display, board);
 }
 
@@ -5082,7 +5025,6 @@
 	static GtkTargetEntry *targets = NULL;
 	static gint n_targets = 0;
 
-	g_assert(VTE_IS_TERMINAL(terminal));
 	clipboard = vte_terminal_clipboard_get(terminal, board);
 
 	/* Chuck old selected text and retrieve the newly-selected text. */
@@ -5139,7 +5081,6 @@
 vte_terminal_paste(VteTerminal *terminal, GdkAtom board)
 {
 	GtkClipboard *clipboard;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	clipboard = vte_terminal_clipboard_get(terminal, board);
 	if (clipboard != NULL) {
 #ifdef VTE_DEBUG
@@ -5630,7 +5571,7 @@
 	glong adj;
 
 	terminal = VTE_TERMINAL(data);
-	widget = GTK_WIDGET(terminal);
+	widget = &terminal->widget;
 
 	/* Provide an immediate effect for mouse wigglers. */
 	if (terminal->pvt->mouse_last_y < 0) {
@@ -5722,7 +5663,6 @@
 	GdkModifierType modifiers;
 	gboolean event_mode;
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	event_mode = terminal->pvt->mouse_send_xy_on_click ||
@@ -5828,7 +5768,6 @@
 	gboolean start_selecting = FALSE, extend_selecting = FALSE;
 	long cellx, celly;
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 	height = terminal->char_height;
 	width = terminal->char_width;
@@ -6021,7 +5960,6 @@
 	gboolean handled = FALSE;
 	gboolean event_mode;
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 	_vte_terminal_set_pointer_visible(terminal, TRUE);
 
@@ -6104,8 +6042,6 @@
 {
 	VteTerminal *terminal;
 	GdkModifierType modifiers;
-	g_assert(GTK_IS_WIDGET(widget));
-	g_assert(VTE_IS_TERMINAL(widget));
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Focus in.\n");
@@ -6139,8 +6075,6 @@
 {
 	VteTerminal *terminal;
 	GdkModifierType modifiers;
-	g_assert(GTK_WIDGET(widget));
-	g_assert(VTE_IS_TERMINAL(widget));
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
 		fprintf(stderr, "Focus out.\n");
@@ -6165,16 +6099,18 @@
 	return FALSE;
 }
 
-static gint
+static gboolean
 vte_terminal_visibility_notify(GtkWidget *widget, GdkEventVisibility *event)
 {
 	VteTerminal *terminal;
-	g_assert(GTK_WIDGET(widget));
-	g_assert(VTE_IS_TERMINAL(widget));
+
 	terminal = VTE_TERMINAL(widget);
 	terminal->pvt->visibility_state = event->state;
 	if (terminal->pvt->visibility_state == GDK_VISIBILITY_UNOBSCURED)
 		_vte_invalidate_all(terminal);
+	else if (terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED)
+		remove_update_timeout (terminal);
+
 	return FALSE;
 }
 
@@ -6210,8 +6146,8 @@
 	}
 	/* Queue a resize if anything's changed. */
 	if (resize) {
-		if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
-			gtk_widget_queue_resize(GTK_WIDGET(terminal));
+		if (GTK_WIDGET_REALIZED(terminal)) {
+			gtk_widget_queue_resize_no_redraw(&terminal->widget);
 		}
 	}
 	/* Emit a signal that the font changed. */
@@ -6220,7 +6156,7 @@
 						    terminal->char_width,
 						    terminal->char_height);
 	}
-	/* Repaint. */
+
 	_vte_invalidate_all(terminal);
 }
 
@@ -6246,12 +6182,9 @@
 	GtkWidget *widget;
 	PangoFontDescription *desc;
 
-	g_return_if_fail(terminal != NULL);
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
-	widget = GTK_WIDGET(terminal);
+	widget = &terminal->widget;
 
-	terminal->pvt->has_fonts = TRUE;
-
 	/* Create an owned font description. */
 	if (font_desc != NULL) {
 		desc = pango_font_description_copy(font_desc);
@@ -6276,27 +6209,36 @@
 		}
 #endif
 	}
-	terminal->pvt->fontantialias = antialias;
 
+	/* check for any change */
+	if (antialias == terminal->pvt->fontantialias &&
+			terminal->pvt->fontdesc &&
+			pango_font_description_equal(desc, terminal->pvt->fontdesc)) {
+		pango_font_description_free(desc);
+		return;
+	}
+
 	/* Free the old font description and save the new one. */
 	if (terminal->pvt->fontdesc != NULL) {
 		pango_font_description_free(terminal->pvt->fontdesc);
 	}
 	terminal->pvt->fontdesc = desc;
 	terminal->pvt->fontantialias = antialias;
+	terminal->pvt->fontdirty = TRUE;
+	terminal->pvt->has_fonts = TRUE;
 
-	/* Set the drawing font. */
-	_vte_draw_set_text_font(terminal->pvt->draw,
-				terminal->pvt->fontdesc,
-				antialias);
-	vte_terminal_apply_metrics(terminal,
-				   _vte_draw_get_text_width(terminal->pvt->draw),
-				   _vte_draw_get_text_height(terminal->pvt->draw),
-				   _vte_draw_get_text_ascent(terminal->pvt->draw),
-				   _vte_draw_get_text_height(terminal->pvt->draw) -
-				   _vte_draw_get_text_ascent(terminal->pvt->draw));
-	/* vte_terminal_apply_metrics already called _vte_invalidate_all so
-	 * we don't. */
+	if(GTK_WIDGET_REALIZED(terminal)){
+		terminal->pvt->fontdirty = FALSE;
+		/* Set the drawing font. */
+		_vte_draw_set_text_font(terminal->pvt->draw,
+				desc, antialias);
+		vte_terminal_apply_metrics(terminal,
+				_vte_draw_get_text_width(terminal->pvt->draw),
+				_vte_draw_get_text_height(terminal->pvt->draw),
+				_vte_draw_get_text_ascent(terminal->pvt->draw),
+				_vte_draw_get_text_height(terminal->pvt->draw) -
+				_vte_draw_get_text_ascent(terminal->pvt->draw));
+	}
 }
 
 /**
@@ -6315,6 +6257,7 @@
 vte_terminal_set_font(VteTerminal *terminal,
 		      const PangoFontDescription *font_desc)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	vte_terminal_set_font_full(terminal, font_desc,
 				   VTE_ANTI_ALIAS_USE_DEFAULT);
 }
@@ -6335,6 +6278,7 @@
 				       VteTerminalAntiAlias antialias)
 {
 	PangoFontDescription *font_desc;
+
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	g_return_if_fail(name != NULL);
 
@@ -6355,6 +6299,8 @@
 void
 vte_terminal_set_font_from_string(VteTerminal *terminal, const char *name)
 {
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+	g_return_if_fail(name != NULL);
 	vte_terminal_set_font_from_string_full(terminal, name,
 					       VTE_ANTI_ALIAS_USE_DEFAULT);
 }
@@ -6381,7 +6327,6 @@
 vte_terminal_refresh_size(VteTerminal *terminal)
 {
 	int rows, columns;
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (terminal->pvt->pty_master != -1) {
 		/* Use an ioctl to read the size of the terminal. */
 		if (_vte_pty_get_size(terminal->pvt->pty_master, &columns, &rows) != 0) {
@@ -6407,8 +6352,8 @@
 void
 vte_terminal_set_size(VteTerminal *terminal, glong columns, glong rows)
 {
-	struct winsize size;
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_MISC)) {
 		fprintf(stderr, "Setting PTY size to %ldx%ld.\n",
@@ -6416,9 +6361,6 @@
 	}
 #endif
 	if (terminal->pvt->pty_master != -1) {
-		memset(&size, 0, sizeof(size));
-		size.ws_row = rows;
-		size.ws_col = columns;
 		/* Try to set the terminal size. */
 		if (_vte_pty_set_size(terminal->pvt->pty_master, columns, rows) != 0) {
 			g_warning(_("Error setting PTY size: %s."),
@@ -6443,16 +6385,13 @@
 	VteScreen *screen;
 
 	/* Sanity checks. */
-	g_assert(GTK_IS_WIDGET(terminal));
-	widget = GTK_WIDGET(terminal);
+	widget = &terminal->widget;
 	screen = terminal->pvt->screen;
-	if (GTK_WIDGET_REALIZED(widget) == FALSE) {
+	if (GTK_WIDGET_DRAWABLE(widget) == FALSE ||
+			terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
 		return;
 	}
 
-	/* This may generate multiple redraws, so freeze it while we do them. */
-	gdk_window_freeze_updates(widget->window);
-
 	/* Read the new adjustment value and save the difference. */
 	adj = floor(gtk_adjustment_get_value(terminal->adjustment));
 	dy = adj - screen->scroll_delta;
@@ -6474,9 +6413,6 @@
 	      fprintf(stderr, "Not scrolling\n");
 	}
 #endif
-
-	/* Let the refreshing begin. */
-	gdk_window_thaw_updates(widget->window);
 }
 
 /* Set the adjustment objects used by the terminal widget. */
@@ -6484,7 +6420,6 @@
 vte_terminal_set_scroll_adjustment(VteTerminal *terminal,
 				   GtkAdjustment *adjustment)
 {
-	g_assert(VTE_IS_TERMINAL(terminal));
 	if (adjustment != NULL) {
 		/* Add a reference to the new adjustment object. */
 		g_object_ref(adjustment);
@@ -6492,7 +6427,7 @@
 		if (terminal->adjustment != NULL) {
 			/* Disconnect our signal handlers from this object. */
 			g_signal_handlers_disconnect_by_func(terminal->adjustment,
-							     (gpointer)vte_terminal_handle_scroll,
+							     vte_terminal_handle_scroll,
 							     terminal);
 			g_object_unref(terminal->adjustment);
 		}
@@ -6501,7 +6436,7 @@
 
 		/* We care about the offset, not the top or bottom. */
 		g_signal_connect_swapped(terminal->adjustment,
-					 "value_changed",
+					 "value-changed",
 					 G_CALLBACK(vte_terminal_handle_scroll),
 					 terminal);
 	}
@@ -6521,14 +6456,14 @@
 vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
 {
 	int columns, rows;
-	GQuark quark;
 
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
 	/* Set the emulation type, for reference. */
 	if (emulation == NULL) {
 		emulation = vte_terminal_get_default_emulation(terminal);
 	}
-	quark = g_quark_from_string(emulation);
-	terminal->pvt->emulation = g_quark_to_string(quark);
+	terminal->pvt->emulation = g_intern_string(emulation);
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_MISC)) {
 		fprintf(stderr, "Setting emulation to `%s'...", emulation);
@@ -6614,23 +6549,22 @@
 {
 	struct stat st;
 	char *wpath;
-	GQuark q = 0;
 
 	if (path == NULL) {
 		wpath = g_strdup_printf(DATADIR "/" PACKAGE "/termcap/%s",
 					terminal->pvt->emulation ?
 					terminal->pvt->emulation :
 					vte_terminal_get_default_emulation(terminal));
-		if (stat(wpath, &st) != 0) {
+		if (g_stat(wpath, &st) != 0) {
 			g_free(wpath);
 			wpath = g_strdup("/etc/termcap");
 		}
-		q = g_quark_from_string(wpath);
+		path = g_intern_string (wpath);
 		g_free(wpath);
 	} else {
-		q = g_quark_from_string(path);
+		path = g_intern_string (path);
 	}
-	terminal->pvt->termcap_path = g_quark_to_string(q);
+	terminal->pvt->termcap_path = path;
 
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_MISC)) {
@@ -6705,16 +6639,15 @@
 {
 	GtkSettings *settings;
 	GObjectClass *klass;
-	gpointer func;
 
-	gtk_widget_ensure_style(GTK_WIDGET(terminal));
-	settings = gtk_widget_get_settings(GTK_WIDGET(terminal));
+	gtk_widget_ensure_style(&terminal->widget);
+	settings = gtk_widget_get_settings(&terminal->widget);
 	if (settings == NULL) {
 		return;
 	}
 
 	/* Check that the properties we're looking at are defined. */
-	klass = G_OBJECT_CLASS(GTK_SETTINGS_GET_CLASS(settings));
+	klass = G_OBJECT_GET_CLASS(settings);
 	if (g_object_class_find_property(klass, "gtk-xft-antialias") == NULL) {
 		return;
 	}
@@ -6722,23 +6655,13 @@
 	/* If this is our first time in here, start listening for changes
 	 * to the Xft settings. */
 	if (terminal->pvt->connected_settings == NULL) {
+		GCallback func = G_CALLBACK(vte_terminal_fc_settings_changed);
 		terminal->pvt->connected_settings = settings;
-		func = (gpointer) vte_terminal_fc_settings_changed;
-		g_signal_connect(G_OBJECT(settings),
-				"notify::gtk-xft-antialias",
-				G_CALLBACK(func), terminal);
-		g_signal_connect(G_OBJECT(settings),
-				"notify::gtk-xft-hinting",
-				G_CALLBACK(func), terminal);
-		g_signal_connect(G_OBJECT(settings),
-				"notify::gtk-xft-hintstyle",
-				G_CALLBACK(func), terminal);
-		g_signal_connect(G_OBJECT(settings),
-				"notify::gtk-xft-rgba",
-				G_CALLBACK(func), terminal);
-		g_signal_connect(G_OBJECT(settings),
-				"notify::gtk-xft-dpi",
-				G_CALLBACK(func), terminal);
+		g_signal_connect(settings, "notify::gtk-xft-antialias", func, terminal);
+		g_signal_connect(settings, "notify::gtk-xft-hinting", func, terminal);
+		g_signal_connect(settings, "notify::gtk-xft-hintstyle", func, terminal);
+		g_signal_connect(settings, "notify::gtk-xft-rgba", func, terminal);
+		g_signal_connect(settings, "notify::gtk-xft-dpi", func, terminal);
 	}
 }
 
@@ -6748,13 +6671,11 @@
 vte_terminal_disconnect_xft_settings(VteTerminal *terminal)
 {
 	GtkSettings *settings;
-	gpointer func;
 
 	if (terminal->pvt->connected_settings != NULL) {
 		settings = terminal->pvt->connected_settings;
-		func = (gpointer) vte_terminal_fc_settings_changed;
-		g_signal_handlers_disconnect_by_func(G_OBJECT(settings),
-						     func,
+		g_signal_handlers_disconnect_by_func(settings,
+						     vte_terminal_fc_settings_changed,
 						     terminal);
 		terminal->pvt->connected_settings = NULL;
 	}
@@ -6763,8 +6684,7 @@
 static void
 _vte_terminal_codeset_changed_cb(struct _vte_iso2022_state *state, gpointer p)
 {
-	g_assert(VTE_IS_TERMINAL(p));
-	vte_terminal_set_encoding(VTE_TERMINAL(p),
+	vte_terminal_set_encoding(p,
 				  _vte_iso2022_state_get_codeset(state));
 }
 
@@ -6772,7 +6692,7 @@
  * We need to create a new psuedo-terminal pair, read in the termcap file, and
  * set ourselves up to do the interpretation of sequences. */
 static void
-vte_terminal_init(VteTerminal *terminal, gpointer *klass)
+vte_terminal_init(VteTerminal *terminal)
 {
 	VteTerminalPrivate *pvt;
 	GtkWidget *widget;
@@ -6786,8 +6706,7 @@
 	}
 #endif
 
-	g_assert(VTE_IS_TERMINAL(terminal));
-	widget = GTK_WIDGET(terminal);
+	widget = &terminal->widget;
 	GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
 
 	/* We do our own redrawing. */
@@ -6816,7 +6735,7 @@
 	memset(&pvt->flags, 0, sizeof(pvt->flags));
 	pvt->keypad_mode = VTE_KEYMODE_NORMAL;
 	pvt->cursor_mode = VTE_KEYMODE_NORMAL;
-	pvt->dec_saved = g_hash_table_new(g_direct_hash, g_direct_equal);
+	pvt->dec_saved = g_hash_table_new(NULL, NULL);
 	pvt->default_column_count = 80;
 	pvt->default_row_count = 24;
 
@@ -6825,26 +6744,26 @@
 	pvt->pty_master = -1;
 	vte_terminal_set_emulation(terminal, NULL);
 	vte_terminal_set_size(terminal,
-			      pvt->default_column_count,
-			      pvt->default_row_count);
-	pvt->pty_master = -1;
+			pvt->default_row_count,
+			pvt->default_column_count);
+	g_assert (pvt->pty_master == -1);
 	pvt->pty_input_source = VTE_INVALID_SOURCE;
 	pvt->pty_output_source = VTE_INVALID_SOURCE;
-	g_static_mutex_init( &(pvt->pty_output_source_mutex) );
+	g_static_mutex_init(&pvt->pty_output_source_mutex);
 	pvt->pty_pid = -1;
 
 	/* Set up I/O encodings. */
 	pvt->iso2022 = _vte_iso2022_state_new(pvt->encoding,
 					      &_vte_terminal_codeset_changed_cb,
-					      (gpointer)terminal);
+					      terminal);
 	pvt->incoming = _vte_buffer_new();
-	pvt->pending = g_array_new(TRUE, TRUE, sizeof(gunichar));
+	pvt->pending = g_array_new(FALSE, FALSE, sizeof(gunichar));
 	pvt->cursor_blink_tag = VTE_INVALID_SOURCE;
 	pvt->coalesce_timeout = VTE_INVALID_SOURCE;
 	pvt->display_timeout = VTE_INVALID_SOURCE;
 	pvt->update_timeout = VTE_INVALID_SOURCE;
 	pvt->outgoing = _vte_buffer_new();
-	pvt->outgoing_conv = (VteConv) -1;
+	pvt->outgoing_conv = VTE_INVALID_CONV;
 	pvt->conv_buffer = _vte_buffer_new();
 	vte_terminal_set_encoding(terminal, NULL);
 	g_assert(terminal->pvt->encoding != NULL);
@@ -6888,13 +6807,13 @@
 	pvt->cursor_blink_timeout = 500;
 
 	/* Matching data. */
-	pvt->match_regexes = g_array_new(FALSE, TRUE,
+	pvt->match_regexes = g_array_new(FALSE, FALSE,
 					 sizeof(struct vte_match_regex));
 	pvt->match_previous = -1;
 	vte_terminal_match_hilite_clear(terminal);
 
 	/* Rendering data.  Try everything. */
-	pvt->draw = _vte_draw_new(GTK_WIDGET(terminal));
+	pvt->draw = _vte_draw_new(&terminal->widget);
 
 	/* The font description. */
 	pvt->fontantialias = VTE_ANTI_ALIAS_USE_DEFAULT;
@@ -6916,18 +6835,18 @@
 	pvt->visibility_state = GDK_VISIBILITY_UNOBSCURED;
 
 	/* Listen for hierarchy change notifications. */
-	g_signal_connect(G_OBJECT(terminal), "hierarchy-changed",
+	g_signal_connect(terminal, "hierarchy-changed",
 			 G_CALLBACK(vte_terminal_hierarchy_changed),
 			 NULL);
 
 	/* Listen for style changes. */
-	g_signal_connect(G_OBJECT(terminal), "style-set",
+	g_signal_connect(terminal, "style-set",
 			 G_CALLBACK(vte_terminal_style_changed),
 			 NULL);
 
 #ifdef VTE_DEBUG
 	/* In debuggable mode, we always do this. */
-	/* gtk_widget_get_accessible(GTK_WIDGET(terminal)); */
+	/* gtk_widget_get_accessible(&terminal->widget); */
 #endif
 }
 
@@ -6943,8 +6862,6 @@
 	}
 #endif
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	if (terminal->pvt->pty_master != -1) {
@@ -6986,9 +6903,6 @@
 	}
 #endif
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
-
 	terminal = VTE_TERMINAL(widget);
 
 	snapped_to_bottom = (terminal->pvt->screen->insert_delta ==
@@ -7038,10 +6952,8 @@
 				       allocation->y,
 				       allocation->width,
 				       allocation->height);
-		/* Repaint if we were resized or moved. */
-		if ((x != allocation->x) ||
-		    (y != allocation->y) ||
-		    (w != allocation->width) ||
+		/* Repaint if we were resized. */
+		if ((w != allocation->width) ||
 		    (h != allocation->height)) {
 			_vte_invalidate_all(terminal);
 		}
@@ -7061,7 +6973,6 @@
 static void
 vte_terminal_show(GtkWidget *widget)
 {
-	GtkWidgetClass *widget_class;
 	VteTerminal *terminal;
 
 #ifdef VTE_DEBUG
@@ -7070,7 +6981,6 @@
 	}
 #endif
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	/* Load default fonts, if no fonts have been loaded. */
@@ -7079,22 +6989,17 @@
 					   terminal->pvt->fontantialias);
    	}
 
-	widget_class = g_type_class_peek(GTK_TYPE_WIDGET);
-	if (GTK_WIDGET_CLASS(widget_class)->show) {
-		(GTK_WIDGET_CLASS(widget_class))->show(widget);
+	if (GTK_WIDGET_CLASS(parent_class)->show) {
+		(GTK_WIDGET_CLASS(parent_class))->show(widget);
 	}
 }
 
 /* Queue a background update. */
 static void
-root_pixmap_changed_cb(VteBg *bg, gpointer data)
+root_pixmap_changed_cb(VteBg *bg, VteTerminal *terminal)
 {
-	VteTerminal *terminal;
-	if (VTE_IS_TERMINAL(data)) {
-		terminal = VTE_TERMINAL(data);
-		if (terminal->pvt->bg_transparent) {
-			vte_terminal_queue_background_update(terminal);
-		}
+	if (terminal->pvt->bg_transparent) {
+		vte_terminal_queue_background_update(terminal);
 	}
 }
 
@@ -7111,13 +7016,11 @@
 	}
 #endif
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	/* Disconnect from background-change events. */
 	bg = vte_bg_get_for_screen(gtk_widget_get_screen(widget));
-	g_signal_handlers_disconnect_by_func(G_OBJECT(bg),
+	g_signal_handlers_disconnect_by_func(bg,
 					     root_pixmap_changed_cb,
 					     widget);
 
@@ -7132,13 +7035,13 @@
 
 	/* Shut down input methods. */
 	if (terminal->pvt->im_context != NULL) {
-	        g_signal_handlers_disconnect_by_func (G_OBJECT(terminal->pvt->im_context), 
+	        g_signal_handlers_disconnect_by_func (terminal->pvt->im_context,
 						      vte_terminal_im_preedit_changed,
 						      terminal);
 		vte_terminal_im_reset(terminal);
 		gtk_im_context_set_client_window(terminal->pvt->im_context,
 						 NULL);
-		g_object_unref(G_OBJECT(terminal->pvt->im_context));
+		g_object_unref(terminal->pvt->im_context);
 		terminal->pvt->im_context = NULL;
 	}
 	terminal->pvt->im_preedit_active = FALSE;
@@ -7155,8 +7058,8 @@
 	/* Clean up our draw structure. */
 	if (terminal->pvt->draw != NULL) {
 		_vte_draw_free(terminal->pvt->draw);
+		terminal->pvt->draw = NULL;
 	}
-	terminal->pvt->draw = NULL;
 	terminal->pvt->has_fonts = FALSE;
 
 	/* Unmap the widget if it hasn't been already. */
@@ -7189,6 +7092,9 @@
 		terminal->pvt->bg_update_pending = FALSE;
 	}
 
+	/* Cancel any pending redraws. */
+	remove_update_timeout (terminal);
+
 	/* Clear modifiers. */
 	terminal->pvt->modifiers = 0;
 
@@ -7202,8 +7108,6 @@
 {
 	VteTerminal *terminal;
 	GtkWidget *toplevel;
-	GObjectClass *object_class;
-	GtkWidgetClass *widget_class;
 	GtkClipboard *clipboard;
 	struct vte_match_regex *regex;
 	int i;
@@ -7214,10 +7118,7 @@
 	}
 #endif
 
-	g_assert(VTE_IS_TERMINAL(object));
 	terminal = VTE_TERMINAL(object);
-	object_class = G_OBJECT_GET_CLASS(G_OBJECT(object));
-	widget_class = g_type_class_peek(GTK_TYPE_WIDGET);
 
 	/* Free the draw structure. */
 	if (terminal->pvt->draw != NULL) {
@@ -7279,10 +7180,10 @@
 	}
 
 	/* Disconnect from toplevel window configure events. */
-	toplevel = gtk_widget_get_toplevel(GTK_WIDGET(object));
-	if ((toplevel != NULL) && (G_OBJECT(toplevel) != G_OBJECT(object))) {
+	toplevel = gtk_widget_get_toplevel(&terminal->widget);
+	if ((toplevel != NULL) && (G_OBJECT(toplevel) != object)) {
 		g_signal_handlers_disconnect_by_func(toplevel,
-						     (gpointer)vte_terminal_configure_toplevel,
+						     vte_terminal_configure_toplevel,
 						     terminal);
 	}
 
@@ -7310,7 +7211,7 @@
 	if (terminal->pvt->selection != NULL) {
 		clipboard = vte_terminal_clipboard_get(terminal,
 						       GDK_SELECTION_PRIMARY);
-		if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(terminal)) {
+		if (gtk_clipboard_get_owner(clipboard) == object) {
 			gtk_clipboard_set_text(clipboard,
 					       terminal->pvt->selection,
 					       -1);
@@ -7338,17 +7239,17 @@
 		      TRUE);
 
 	/* Free conversion descriptors. */
-	if (terminal->pvt->outgoing_conv != ((VteConv) -1)) {
+	if (terminal->pvt->outgoing_conv != VTE_INVALID_CONV) {
 		_vte_conv_close(terminal->pvt->outgoing_conv);
 	}
-	terminal->pvt->outgoing_conv = ((VteConv) -1);
+	terminal->pvt->outgoing_conv = VTE_INVALID_CONV;
 
 	/* Stop listening for child-exited signals. */
 	if (VTE_IS_REAPER(terminal->pvt->pty_reaper)) {
 		g_signal_handlers_disconnect_by_func(terminal->pvt->pty_reaper,
-						     (gpointer)vte_terminal_catch_child_exited,
+						     vte_terminal_catch_child_exited,
 						     terminal);
-		g_object_unref(G_OBJECT(terminal->pvt->pty_reaper));
+		g_object_unref(terminal->pvt->pty_reaper);
 	}
 	terminal->pvt->pty_reaper = NULL;
 
@@ -7433,16 +7334,14 @@
 	}
 
 	/* Call the inherited finalize() method. */
-	if (G_OBJECT_CLASS(widget_class)->finalize) {
-		(G_OBJECT_CLASS(widget_class))->finalize(object);
-	}
+	G_OBJECT_CLASS(parent_class)->finalize(object);
 }
 
 /* Handle realizing the widget.  Most of this is copy-paste from GGAD. */
 static void
 vte_terminal_realize(GtkWidget *widget)
 {
-	VteTerminal *terminal = NULL;
+	VteTerminal *terminal;
 	GdkWindowAttr attributes;
 	GdkPixmap *bitmap;
 	GdkColor black = {0,0,0}, color;
@@ -7455,13 +7354,11 @@
 	}
 #endif
 
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	/* Create the draw structure if we don't already have one. */
 	if (terminal->pvt->draw == NULL) {
-		terminal->pvt->draw = _vte_draw_new(GTK_WIDGET(terminal));
+		terminal->pvt->draw = _vte_draw_new(&terminal->widget);
 	}
 
 	/* Create the stock cursors. */
@@ -7530,6 +7427,19 @@
 		vte_terminal_set_font_full(terminal, terminal->pvt->fontdesc,
 					   terminal->pvt->fontantialias);
    	}
+	/* load the initial font cache */
+	if(terminal->pvt->fontdirty){
+		terminal->pvt->fontdirty = FALSE;
+		_vte_draw_set_text_font(terminal->pvt->draw,
+				terminal->pvt->fontdesc,
+				terminal->pvt->fontantialias);
+		vte_terminal_apply_metrics(terminal,
+				_vte_draw_get_text_width(terminal->pvt->draw),
+				_vte_draw_get_text_height(terminal->pvt->draw),
+				_vte_draw_get_text_ascent(terminal->pvt->draw),
+				_vte_draw_get_text_height(terminal->pvt->draw) -
+				_vte_draw_get_text_ascent(terminal->pvt->draw));
+	}
 
 	/* Allocate colors. */
 	for (i = 0; i < G_N_ELEMENTS(terminal->pvt->palette); i++) {
@@ -7544,23 +7454,23 @@
 	 * "retrieve-surrounding" and "delete-surrounding" events? */
 	if (terminal->pvt->im_context != NULL) {
 		vte_terminal_im_reset(terminal);
-		g_object_unref(G_OBJECT(terminal->pvt->im_context));
+		g_object_unref(terminal->pvt->im_context);
 		terminal->pvt->im_context = NULL;
 	}
 	terminal->pvt->im_preedit_active = FALSE;
 	terminal->pvt->im_context = gtk_im_multicontext_new();
 	gtk_im_context_set_client_window(terminal->pvt->im_context,
 					 widget->window);
-	g_signal_connect(G_OBJECT(terminal->pvt->im_context), "commit",
-			 GTK_SIGNAL_FUNC(vte_terminal_im_commit), terminal);
-	g_signal_connect(G_OBJECT(terminal->pvt->im_context), "preedit-start",
-			 GTK_SIGNAL_FUNC(vte_terminal_im_preedit_start),
+	g_signal_connect(terminal->pvt->im_context, "commit",
+			 G_CALLBACK(vte_terminal_im_commit), terminal);
+	g_signal_connect(terminal->pvt->im_context, "preedit-start",
+			 G_CALLBACK(vte_terminal_im_preedit_start),
 			 terminal);
-	g_signal_connect(G_OBJECT(terminal->pvt->im_context), "preedit-changed",
-			 GTK_SIGNAL_FUNC(vte_terminal_im_preedit_changed),
+	g_signal_connect(terminal->pvt->im_context, "preedit-changed",
+			 G_CALLBACK(vte_terminal_im_preedit_changed),
 			 terminal);
-	g_signal_connect(G_OBJECT(terminal->pvt->im_context), "preedit-end",
-			 GTK_SIGNAL_FUNC(vte_terminal_im_preedit_end),
+	g_signal_connect(terminal->pvt->im_context, "preedit-end",
+			 G_CALLBACK(vte_terminal_im_preedit_end),
 			 terminal);
 	gtk_im_context_set_use_preedit(terminal->pvt->im_context, TRUE);
 
@@ -7577,10 +7487,10 @@
 									&black,
 									&black,
 									0, 0);
+	g_object_unref(bitmap);
 
 	/* Connect to background-change events. */
-	bg = vte_bg_get_for_screen(gtk_widget_get_screen(widget));
-	g_signal_connect(G_OBJECT(bg),
+	g_signal_connect(vte_bg_get_for_screen(gtk_widget_get_screen(widget)),
 			 "root-pixmap-changed",
 			 G_CALLBACK(root_pixmap_changed_cb),
 			 terminal);
@@ -7588,9 +7498,7 @@
 	/* Set up the background, *now*. */
 	vte_terminal_background_update(terminal);
 	
-	gtk_style_attach(widget->style, widget->window);
-
-	g_object_unref(G_OBJECT(bitmap));
+	widget->style = gtk_style_attach(widget->style, widget->window);
 }
 
 static void
@@ -7601,9 +7509,6 @@
 			      gboolean cursor,
 			      int *fore, int *back)
 {
-	g_assert(fore != NULL);
-	g_assert(back != NULL);
-
 	/* Determine what the foreground and background colors for rendering
 	 * text should be.  If highlight is set and we have a highlight color,
 	 * use that scheme.  If cursor is set and we have a cursor color, use
@@ -7655,7 +7560,7 @@
 
 /* Check if a unicode character is actually a graphic character we draw
  * ourselves to handle cases where fonts don't have glyphs for them. */
-static gboolean
+static inline gboolean
 vte_unichar_is_local_graphic(gunichar c)
 {
 	if ((c >= 0x2500) && (c <= 0x257f)) {
@@ -8910,37 +8815,41 @@
 	struct _vte_draw_text_request *items, item;
 	guint item_count = 0;
 	struct vte_charcell *cell;
+	VteRowData *row_data;
 
+	reverse = terminal->pvt->screen->reverse_mode;
+
 	/* Allocate an array to hold draw requests. */
 	/* FIXME: can this get too big for alloca? */
 	items = g_newa (struct _vte_draw_text_request, column_count);
 
+	row_data = _vte_terminal_find_row_data(terminal, row);
+
 	/* Back up in case this is a multicolumn character, making the drawing
 	 * area a little wider. */
-	cell = vte_terminal_find_charcell(terminal, column, row);
+	cell = _vte_row_data_find_charcell(row_data, column);
 	while ((cell != NULL) && (cell->fragment) && (column > 0)) {
 		column--;
 		column_count++;
 		x -= column_width;
-		cell = vte_terminal_find_charcell(terminal, column, row);
+		cell = _vte_row_data_find_charcell(row_data, column);
 	}
 
 	/* Walk the line. */
 	i = column;
 	while (i < column + column_count) {
 		/* Get the character cell's contents. */
-		cell = vte_terminal_find_charcell(terminal, i, row);
+		cell = _vte_row_data_find_charcell(row_data, i);
 		/* Find the colors for this cell. */
-		reverse = terminal->pvt->screen->reverse_mode;
 		selected = vte_cell_is_selected(terminal, i, row, NULL);
 		vte_terminal_determine_colors(terminal, cell,
-					      reverse || selected,
+					      reverse|selected,
 					      selected,
 					      FALSE,
 					      &fore, &back);
-		underline = (cell != NULL) ? (cell->underline != 0) : FALSE;
-		strikethrough = (cell != NULL) ? (cell->strikethrough != 0) : FALSE;
-		bold = (cell != NULL) ? (cell->bold != 0) : FALSE;
+		underline = cell && cell->underline;
+		strikethrough = cell && cell->strikethrough;
+		bold = cell && cell->bold;
 		if ((cell != NULL) && (terminal->pvt->match_contents != NULL)) {
 			hilite = vte_cell_is_between(i, row,
 						     terminal->pvt->match_start.column,
@@ -8983,23 +8892,20 @@
 		while ((j < column + column_count) &&
 		       (j - i < VTE_DRAW_MAX_LENGTH)) {
 			/* Retrieve the cell. */
-			cell = vte_terminal_find_charcell(terminal, j, row);
+			cell = _vte_row_data_find_charcell(row_data, j);
 			/* Resolve attributes to colors where possible and
 			 * compare visual attributes to the first character
 			 * in this chunk. */
-			reverse = terminal->pvt->screen->reverse_mode;
 			selected = vte_cell_is_selected(terminal, j, row, NULL);
 			vte_terminal_determine_colors(terminal, cell,
-						      reverse || selected,
+						      reverse|selected,
 						      selected,
 						      FALSE,
 						      &nfore, &nback);
 			if ((nfore != fore) || (nback != back)) {
 				break;
 			}
-			nbold = (cell != NULL) ?
-				(cell->bold != 0) :
-				FALSE;
+			nbold = cell && cell->bold != 0;
 			if (nbold != bold) {
 				break;
 			}
@@ -9016,15 +8922,11 @@
 				continue;
 			}
 			/* Break up underlined/not-underlined text. */
-			nunderline = (cell != NULL) ?
-				     (cell->underline != 0) :
-				     FALSE;
+			nunderline = cell && cell->underline != 0;
 			if (nunderline != underline) {
 				break;
 			}
-			nstrikethrough = (cell != NULL) ?
-					 (cell->strikethrough != 0) :
-					 FALSE;
+			nstrikethrough = cell && cell->strikethrough != 0;
 			if (nstrikethrough != strikethrough) {
 				break;
 			}
@@ -9044,7 +8946,7 @@
 				break;
 			}
 			/* Add this cell to the draw list. */
-			item.c = cell ? (cell->c ? cell->c : ' ') : ' ';
+			item.c = (cell && cell->c) ? cell->c : ' ';
 			item.columns = cell ? cell->columns : 1;
 			item.x = x + ((j - column) * column_width);
 			item.y = y;
@@ -9070,7 +8972,7 @@
 static void
 vte_terminal_paint(GtkWidget *widget, GdkRectangle *area)
 {
-	VteTerminal *terminal = NULL;
+	VteTerminal *terminal;
 	VteScreen *screen;
 	struct vte_charcell *cell;
 	struct _vte_draw_text_request item, *items;
@@ -9088,10 +8990,6 @@
 	}
 #endif
 
-	/* Make a few sanity checks. */
-	g_assert(widget != NULL);
-	g_assert(VTE_IS_TERMINAL(widget));
-	g_assert(area != NULL);
 	terminal = VTE_TERMINAL(widget);
 	
 	/* Update whole selection if terminal is in block mode. */
@@ -9201,7 +9099,7 @@
 								    cell->c,
 								    cell->columns));
 		}
-		if (GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(terminal))) {
+		if (GTK_WIDGET_HAS_FOCUS(terminal)) {
 			selected = vte_cell_is_selected(terminal, col, drow,
 							NULL);
 			blink = terminal->pvt->cursor_blink_state ^
@@ -9375,15 +9273,11 @@
 static gint
 vte_terminal_expose(GtkWidget *widget, GdkEventExpose *event)
 {
-	g_assert(VTE_IS_TERMINAL(widget));
 	if (event->window == widget->window) {
-		if (GTK_WIDGET_REALIZED(widget) &&
-		    GTK_WIDGET_VISIBLE(widget) &&
-		    GTK_WIDGET_MAPPED(widget)) {
+		if (GTK_WIDGET_DRAWABLE(widget) ||
+				VTE_TERMINAL(widget)->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
 			vte_terminal_paint(widget, &event->area);
 		}
-	} else {
-		g_assert_not_reached();
 	}
 	return FALSE;
 }
@@ -9398,7 +9292,6 @@
 	GdkModifierType modifiers;
 	int button;
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	/* Read the modifiers. */
@@ -9487,7 +9380,6 @@
 	VteTerminal *terminal;
 	static gboolean first_time = TRUE;
 
-	g_assert(VTE_IS_TERMINAL(widget));
 	terminal = VTE_TERMINAL(widget);
 
 	if (first_time) {
@@ -10174,24 +10066,21 @@
 {
 	GtkIMMulticontext *context;
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
-	g_return_if_fail(GTK_WIDGET_REALIZED(GTK_WIDGET((terminal))));
+	g_return_if_fail(GTK_WIDGET_REALIZED((terminal)));
 	context = GTK_IM_MULTICONTEXT(terminal->pvt->im_context);
 	gtk_im_multicontext_append_menuitems(context, menushell);
 }
 
 /* Set up whatever background we wanted. */
 static gboolean
-vte_terminal_background_update(gpointer data)
+vte_terminal_background_update(VteTerminal *terminal)
 {
-	VteTerminal *terminal;
 	GtkWidget *widget;
 	GdkColormap *colormap;
 	GdkColor bgcolor;
 	double saturation;
 
-	g_assert(VTE_IS_TERMINAL(data));
-	widget = GTK_WIDGET(data);
-	terminal = VTE_TERMINAL(data);
+	widget = &terminal->widget;
 
 	/* If we're not realized yet, don't worry about it, because we get
 	 * called when we realize. */
@@ -10285,7 +10174,7 @@
 		terminal->pvt->bg_update_pending = TRUE;
 		terminal->pvt->bg_update_tag =
 				g_idle_add_full(VTE_FX_PRIORITY,
-						vte_terminal_background_update,
+						(GSourceFunc)vte_terminal_background_update,
 						terminal,
 						NULL);
 #ifdef VTE_DEBUG
@@ -10390,11 +10279,14 @@
 			transparent ? "on" : "off");
 	}
 #endif
-	/* Save this background type. */
-	terminal->pvt->bg_transparent = transparent;
+	transparent = !!transparent;
+	if(transparent != terminal->pvt->bg_transparent) {
+		/* Save this background type. */
+		terminal->pvt->bg_transparent = transparent;
 
-	/* Update the background. */
-	vte_terminal_queue_background_update(terminal);
+		/* Update the background. */
+		vte_terminal_queue_background_update(terminal);
+	}
 }
 
 /**
@@ -10425,12 +10317,12 @@
 	/* Get a ref to the new image if there is one.  Do it here just in
 	 * case we're actually given the same one we're already using. */
 	if (GDK_IS_PIXBUF(image)) {
-		g_object_ref(G_OBJECT(image));
+		g_object_ref(image);
 	}
 
 	/* Unref the previous background image. */
 	if (GDK_IS_PIXBUF(terminal->pvt->bg_pixbuf)) {
-		g_object_unref(G_OBJECT(terminal->pvt->bg_pixbuf));
+		g_object_unref(terminal->pvt->bg_pixbuf);
 	}
 
 	/* Clear a background file name, if one was set. */
@@ -10472,7 +10364,7 @@
 
 	/* Turn off other background types. */
 	if (GDK_IS_PIXBUF(terminal->pvt->bg_pixbuf)) {
-		g_object_unref(G_OBJECT(terminal->pvt->bg_pixbuf));
+		g_object_unref(terminal->pvt->bg_pixbuf);
 		terminal->pvt->bg_pixbuf = NULL;
 	}
 
@@ -10529,13 +10421,14 @@
 {
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 
+	blink = !!blink;
 	if (terminal->pvt->cursor_blinks == blink)
 		return;
 
 	terminal->pvt->cursor_blinks = blink;
 
 	if (!GTK_WIDGET_REALIZED (terminal) ||
-	    !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (terminal)))
+	    !GTK_WIDGET_HAS_FOCUS (terminal))
 		return;
 
 	if (blink)
@@ -10570,6 +10463,9 @@
 	lines = MAX(lines, VTE_SCROLLBACK_MIN);
 	lines = MAX(lines, terminal->row_count);
 
+	if (terminal->pvt->scrollback_lines == lines)
+		return;
+
 	/* We need to resize both scrollback buffers, and this beats copying
 	 * and pasting the same code twice. */
 	screens[0] = &terminal->pvt->normal_screen;
@@ -10640,7 +10536,7 @@
 	if (terminal->pvt->word_chars != NULL) {
 		g_array_free(terminal->pvt->word_chars, TRUE);
 	}
-	terminal->pvt->word_chars = g_array_new(FALSE, TRUE,
+	terminal->pvt->word_chars = g_array_new(FALSE, FALSE,
 						sizeof(VteWordCharRange));
 	/* Special case: if spec is NULL, try to do the right thing. */
 	if ((spec == NULL) || (strlen(spec) == 0)) {
@@ -10648,7 +10544,7 @@
 	}
 	/* Convert the spec from UTF-8 to a string of gunichars . */
 	conv = _vte_conv_open(VTE_CONV_GUNICHAR_TYPE, "UTF-8");
-	if (conv == ((VteConv) -1)) {
+	if (conv == VTE_INVALID_CONV) {
 		/* Aaargh.  We're screwed. */
 		g_warning(_("_vte_conv_open() failed setting word characters"));
 		return;
@@ -10818,7 +10714,7 @@
 	}
 	terminal->pvt->iso2022 = _vte_iso2022_state_new(NULL,
 							&_vte_terminal_codeset_changed_cb,
-							(gpointer)terminal);
+							terminal);
 	_vte_iso2022_state_set_codeset(terminal->pvt->iso2022,
 				       terminal->pvt->encoding);
 	/* Reset keypad/cursor/function key modes. */
@@ -10839,8 +10735,7 @@
 	/* Reset saved settings. */
 	if (terminal->pvt->dec_saved != NULL) {
 		g_hash_table_destroy(terminal->pvt->dec_saved);
-		terminal->pvt->dec_saved = g_hash_table_new(g_direct_hash,
-							    g_direct_equal);
+		terminal->pvt->dec_saved = g_hash_table_new(NULL, NULL);
 	}
 	/* Reset the color palette. */
 	/* vte_terminal_set_default_colors(terminal); */
@@ -11139,11 +11034,9 @@
 void
 vte_terminal_set_pty(VteTerminal *terminal, int pty_master)
 {
-       GtkWidget *widget;
        int i;
 
        g_return_if_fail(VTE_IS_TERMINAL(terminal));
-       widget = GTK_WIDGET(terminal);
 
        if (terminal->pvt->pty_master != -1) {
                _vte_pty_close(terminal->pvt->pty_master);
@@ -11293,6 +11186,17 @@
 }
 
 static void
+reset_update_regions (VteTerminal *terminal)
+{
+	if (terminal->pvt->update_regions != NULL) {
+		g_slist_foreach (terminal->pvt->update_regions,
+			 	(GFunc)gdk_region_destroy, NULL);
+		g_slist_free (terminal->pvt->update_regions);
+		terminal->pvt->update_regions = NULL;
+	}
+}
+
+static void
 remove_update_timeout (VteTerminal *terminal)
 {
 	if (terminal->pvt->update_timeout != VTE_INVALID_SOURCE) {
@@ -11300,10 +11204,7 @@
 		terminal->pvt->update_timeout = VTE_INVALID_SOURCE;
 	}
 
-	if (terminal->pvt->update_region != NULL) {
-		gdk_region_destroy (terminal->pvt->update_region);
-		terminal->pvt->update_region = NULL;
-	}
+	reset_update_regions (terminal);
 }
 
 static void
@@ -11316,12 +11217,7 @@
 static void
 vte_terminal_start_processing (VteTerminal *terminal)
 {
-	if (vte_terminal_is_processing (terminal)) {
-		remove_coalesce_timeout (terminal);
-		add_coalesce_timeout (terminal);
-	}
-	else {
-		add_coalesce_timeout (terminal);
+	if (!vte_terminal_is_processing (terminal)) {
 		add_display_timeout (terminal);
 	}
 }
@@ -11329,20 +11225,21 @@
 static gboolean
 vte_terminal_is_processing (VteTerminal *terminal)
 {
-	return terminal->pvt->coalesce_timeout != VTE_INVALID_SOURCE;
+	return terminal->pvt->display_timeout != VTE_INVALID_SOURCE
+		|| terminal->pvt->coalesce_timeout != VTE_INVALID_SOURCE;
 }
 
 
-/* This function is called every DISPLAY_TIMEOUT ms.
- * It makes sure output is never delayed by more than DISPLAY_TIMEOUT
- */
-static gboolean
+static inline gboolean
 need_processing (VteTerminal *terminal)
 {
 	return _vte_buffer_length(terminal->pvt->incoming) > 0 ||
 		(terminal->pvt->pending->len > 0);
 }
 	
+/* This function is called every DISPLAY_TIMEOUT ms.
+ * It makes sure initial output is never delayed by more than DISPLAY_TIMEOUT
+ */
 static gboolean
 display_timeout (gpointer data)
 {
@@ -11350,19 +11247,14 @@
 
 	if (need_processing (terminal) && 
 	    vte_terminal_process_incoming(terminal)) {
-		remove_coalesce_timeout (terminal);
 		add_coalesce_timeout (terminal);
-		return TRUE;
 	}
 
-	remove_coalesce_timeout (terminal);
 	terminal->pvt->display_timeout = VTE_INVALID_SOURCE;
-	
 	return FALSE;
 }
 
-/* This function is called whenever data haven't arrived for
- * COALESCE_TIMEOUT ms
+/* This function is polled every COALESCE_TIMEOUT ms for incoming updates.
  */
 static gboolean
 coalesce_timeout (gpointer data)
@@ -11370,23 +11262,19 @@
 	VteTerminal *terminal = data;
 
 	if (need_processing (terminal) &&
-	    vte_terminal_process_incoming(terminal)) {
-		remove_display_timeout (terminal);
-		add_display_timeout (terminal);
+			vte_terminal_process_incoming(terminal)) {
 		return TRUE;
 	}
 
-	remove_display_timeout (terminal);
 	terminal->pvt->coalesce_timeout = VTE_INVALID_SOURCE;
-
 	return FALSE;
- }
+}
 
 static gboolean
 update_repeat_timeout (gpointer data)
 {
 	VteTerminal *terminal = data;
-	gboolean updated = vte_invalidate_region (terminal);
+	gboolean updated = update_regions (terminal);
 
 	/* We only stop the timer if no update request was received in this
 	 * past cycle.
@@ -11404,7 +11292,7 @@
 {
 	VteTerminal *terminal = data;
 
-	vte_invalidate_region(terminal);
+	update_regions (terminal);
 
 	/* Set a timer such that we do not invalidate for a while. */
 	/* This limits the number of times we draw to ~40fps. */
Index: src/vtergb.h
===================================================================
--- src/vtergb.h	(revision 1426)
+++ src/vtergb.h	(working copy)
@@ -39,13 +39,15 @@
 			     guchar r, guchar g, guchar b);
 void _vte_rgb_draw_color(struct _vte_rgb_buffer *buffer,
 			 gint x, gint y, gint width, gint height,
-			 GdkColor *color);
+			 const GdkColor *color);
 void _vte_rgb_draw_pixbuf(struct _vte_rgb_buffer *buffer,
 			  gint x, gint y, gint width, gint height,
-			  GdkPixbuf *pixbuf, gint xbias, gint ybias);
+			  const GdkPixbuf *pixbuf, gint xbias, gint ybias);
 void _vte_rgb_draw_on_drawable(GdkDrawable *drawable, GdkGC *gc,
 			       gint x, gint y, gint width, gint height,
 			       struct _vte_rgb_buffer *buffer,
 			       gint xbias, gint ybias);
+void _vte_rgb_copy(struct _vte_rgb_buffer *buffer,
+		int src_x, int src_y, int width, int height, int dst_x, int dst_y);
 
 #endif
Index: src/vteseq.c
===================================================================
--- src/vteseq.c	(revision 1426)
+++ src/vteseq.c	(working copy)
@@ -755,6 +755,7 @@
 		terminal->pvt->screen->cursor_current.col = 0;
 		terminal->pvt->screen->cursor_current.row =
 			terminal->pvt->screen->insert_delta;
+		_vte_invalidate_cursor_once(terminal, FALSE);
 		break;
 	case 25:
 	case 1048:
@@ -1092,6 +1093,7 @@
 	}
 #endif
 	terminal->pvt->screen->cursor_current.col = newcol;
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -1261,6 +1263,7 @@
 				    terminal->column_count - 1);
 			/* Move the cursor. */
 			screen->cursor_current.col = val;
+			_vte_invalidate_cursor_once(terminal, FALSE);
 		}
 	}
 	return FALSE;
@@ -1313,6 +1316,7 @@
 			screen->cursor_current.row = rowval +
 						     screen->insert_delta;
 			screen->cursor_current.col = colval;
+			_vte_invalidate_cursor_once(terminal, FALSE);
 		}
 	}
 	return FALSE;
@@ -1366,6 +1370,7 @@
 			GValueArray *params)
 {
 	terminal->pvt->screen->cursor_current.col = 0;
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -1412,6 +1417,7 @@
 	screen->cursor_current.row = CLAMP(screen->cursor_current.row,
 					   screen->insert_delta + start,
 					   screen->insert_delta + end);
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	_vte_terminal_ensure_cursor(terminal, TRUE);
 	return FALSE;
 }
@@ -1454,6 +1460,7 @@
 	screen->cursor_current.row = CLAMP(screen->cursor_current.row,
 					   screen->insert_delta + start,
 					   screen->insert_delta + end);
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	_vte_terminal_ensure_cursor(terminal, TRUE);
 	return FALSE;
 }
@@ -1485,6 +1492,7 @@
 	row = MAX(0, terminal->row_count - 1);
 	screen->cursor_current.row = screen->insert_delta + row;
 	screen->cursor_current.col = 0;
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	_vte_terminal_ensure_cursor(terminal, TRUE);
 	return FALSE;
 }
@@ -1670,6 +1678,7 @@
 
 	/* Move the cursor down. */
 	screen->cursor_current.row = MIN(screen->cursor_current.row + 1, end);
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -1801,6 +1810,7 @@
 	screen = terminal->pvt->screen;
 	screen->cursor_current.row = screen->insert_delta;
 	screen->cursor_current.col = 0;
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -1930,6 +1940,7 @@
 			screen->cursor_current.col = 0;
 		}
 	}
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -1957,6 +1968,7 @@
 					 screen->insert_delta +
 					 terminal->row_count - 1);
 	screen->cursor_current.col = 0;
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -2051,6 +2063,7 @@
 	if ((screen->cursor_current.col + 1) < terminal->column_count) {
 		/* There's room to move right. */
 		screen->cursor_current.col++;
+		_vte_invalidate_cursor_once(terminal, FALSE);
 	}
 	return FALSE;
 }
@@ -2101,6 +2114,7 @@
 					   screen->insert_delta,
 					   screen->insert_delta +
 					   terminal->row_count - 1);
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -2460,6 +2474,7 @@
 	} else {
 		/* Otherwise, just move the cursor up. */
 		screen->cursor_current.row--;
+		_vte_invalidate_cursor_once(terminal, FALSE);
 	}
 	/* Adjust the scrollbars if necessary. */
 	_vte_terminal_adjust_adjustments(terminal, FALSE);
@@ -2642,6 +2657,7 @@
 	}
 
 	screen->cursor_current.row = MAX(screen->cursor_current.row - 1, start);
+	_vte_invalidate_cursor_once(terminal, FALSE);
 	return FALSE;
 }
 
@@ -2675,23 +2691,19 @@
 			GValueArray *params)
 {
 	GtkWidget *widget;
-	gint width, height, state;
 
 	widget = GTK_WIDGET(terminal);
 	if (GTK_WIDGET_REALIZED(widget)) {
-		gdk_drawable_get_size(widget->window, &width, &height);
-		state = GTK_WIDGET_STATE(widget);
 		/* Fill the screen with the default foreground color, and then
 		 * repaint everything, to provide visual bell. */
 		gdk_draw_rectangle(widget->window,
-				   widget->style->fg_gc[state],
+				   widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
 				   TRUE,
 				   0, 0,
-				   width, height);
+				   widget->allocation.width, widget->allocation.height);
 		gdk_window_process_updates(widget->window, TRUE);
 		/* Force the repaint. */
-		_vte_invalidate_all(terminal);
-		gdk_window_process_updates(widget->window, TRUE);
+		_vte_invalidate_all(terminal); /* max delay of UPDATE_REPEAT_TIMEOUT */
 	}
 	return FALSE;
 }
@@ -3939,12 +3951,10 @@
 			break;
 		case 14:
 			/* Send window size, in pixels. */
-			gdk_drawable_get_size(widget->window,
-					      &width, &height);
 			snprintf(buf, sizeof(buf),
 				 "%s%d;%dt", _VTE_CAP_CSI,
-				 height - 2 * VTE_PAD_WIDTH,
-				 width - 2 * VTE_PAD_WIDTH);
+				 widget->allocation.height - 2 * VTE_PAD_WIDTH,
+				 widget->allocation.width - 2 * VTE_PAD_WIDTH);
 #ifdef VTE_DEBUG
 			if (_vte_debug_on(VTE_DEBUG_PARSE)) {
 				fprintf(stderr, "Reporting window size "
