aboutsummaryrefslogtreecommitdiff
path: root/x11-toolkits/vte
diff options
context:
space:
mode:
authorJoe Marcus Clarke <marcus@FreeBSD.org>2007-03-23 17:07:05 +0000
committerJoe Marcus Clarke <marcus@FreeBSD.org>2007-03-23 17:07:05 +0000
commit4e6fc3a9fb8514caf52452b3801d57bba83b0dc5 (patch)
treeb5ddd375aa623d91dfcc9ab34dc328e817a98d3f /x11-toolkits/vte
parentdd93c747f868392b43a1396d2b6a8772f7a764dc (diff)
downloadports-4e6fc3a9fb8514caf52452b3801d57bba83b0dc5.tar.gz
ports-4e6fc3a9fb8514caf52452b3801d57bba83b0dc5.zip
Sync vte with GNOME SVN to fix quite a few outstanding problems. In
particular, terminal refreshes no longer leave artifacts, and zoom seems to work a bit better.
Notes
Notes: svn path=/head/; revision=188108
Diffstat (limited to 'x11-toolkits/vte')
-rw-r--r--x11-toolkits/vte/Makefile2
-rw-r--r--x11-toolkits/vte/files/patch-vte_svn2786
2 files changed, 2787 insertions, 1 deletions
diff --git a/x11-toolkits/vte/Makefile b/x11-toolkits/vte/Makefile
index 74e71b984516..da7597ec6c08 100644
--- a/x11-toolkits/vte/Makefile
+++ b/x11-toolkits/vte/Makefile
@@ -8,7 +8,7 @@
PORTNAME= vte
PORTVERSION= 0.16.0
-PORTREVISION?= 0
+PORTREVISION?= 1
CATEGORIES= x11-toolkits gnome
MASTER_SITES= ${MASTER_SITE_GNOME}
MASTER_SITE_SUBDIR= sources/${PORTNAME}/${PORTVERSION:C/^([0-9]+\.[0-9]+).*/\1/}
diff --git a/x11-toolkits/vte/files/patch-vte_svn b/x11-toolkits/vte/files/patch-vte_svn
new file mode 100644
index 000000000000..c18aa06de330
--- /dev/null
+++ b/x11-toolkits/vte/files/patch-vte_svn
@@ -0,0 +1,2786 @@
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/cp437.py src/cp437.py
+--- ../vte-0.16.0/src/cp437.py Wed Dec 31 19:00:00 1969
++++ src/cp437.py Fri Mar 23 12:53:52 2007
+@@ -0,0 +1,9 @@
++#!/usr/bin/python
++print '%s' % '(U'
++i = 128
++while (i < 256):
++ print "%c" % i,
++ if ((i % 32) == 31):
++ print ""
++ i = i + 1
++print '%s' % '(B)0*B+B'
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/genwidths.py src/genwidths.py
+--- ../vte-0.16.0/src/genwidths.py Wed Dec 31 19:00:00 1969
++++ src/genwidths.py Fri Mar 23 12:53:52 2007
+@@ -0,0 +1,35 @@
++#!/usr/bin/python
++import os, re, string
++
++try:
++ unidata = open("EastAsianWidth.txt", "r")
++except:
++ os.system("wget --passive-ftp -c ftp://ftp.unicode.org/Public/UNIDATA/EastAsianWidth.txt")
++ unidata = open("EastAsianWidth.txt", "r")
++out = open("uniwidths", "w")
++ranges = []
++specifics = []
++rangere = re.compile("^([0123456789ABCDEF]+)\.\.([0123456789ABCDEF]+);A")
++specificre = re.compile("^([0123456789ABCDEF]+);A")
++for line in unidata.readlines():
++ match = re.match(specificre, line)
++ if match:
++ if match.groups().__len__() > 0:
++ specifics.append(match.groups()[0])
++ match = re.match(rangere, line)
++ if match:
++ if match.groups().__len__() > 1:
++ ranges.append((match.groups()[0], match.groups()[1]))
++
++print >> out, "static const struct {"
++print >> out, "\tgunichar start, end;"
++print >> out, "} _vte_iso2022_ambiguous_ranges[] = {"
++for range in ranges:
++ print >> out, "\t{0x%x, 0x%x}," % (string.atol(range[0], 16), string.atol(range[1], 16))
++print >> out, "};"
++
++print >> out, "static const gunichar _vte_iso2022_ambiguous_chars[] = {"
++for specific in specifics:
++ print >> out, "\t0x%x," % (string.atol(specific, 16))
++print >> out, "};"
++
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/marshal.c src/marshal.c
+--- ../vte-0.16.0/src/marshal.c Mon Feb 26 16:06:36 2007
++++ src/marshal.c Wed Dec 31 19:00:00 1969
+@@ -1,203 +0,0 @@
+-
+-#include <glib-object.h>
+-
+-
+-#ifdef G_ENABLE_DEBUG
+-#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+-#define g_marshal_value_peek_char(v) g_value_get_char (v)
+-#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+-#define g_marshal_value_peek_int(v) g_value_get_int (v)
+-#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+-#define g_marshal_value_peek_long(v) g_value_get_long (v)
+-#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+-#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+-#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+-#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+-#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+-#define g_marshal_value_peek_float(v) g_value_get_float (v)
+-#define g_marshal_value_peek_double(v) g_value_get_double (v)
+-#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+-#define g_marshal_value_peek_param(v) g_value_get_param (v)
+-#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+-#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+-#define g_marshal_value_peek_object(v) g_value_get_object (v)
+-#else /* !G_ENABLE_DEBUG */
+-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+- * Do not access GValues directly in your code. Instead, use the
+- * g_value_get_*() functions
+- */
+-#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+-#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+-#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+-#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+-#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+-#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+-#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+-#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+-#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+-#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+-#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+-#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+-#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+-#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+-#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+-#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+-#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+-#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+-#endif /* !G_ENABLE_DEBUG */
+-
+-
+-/* VOID:VOID (marshal.list:1) */
+-
+-/* VOID:STRING (marshal.list:2) */
+-
+-/* VOID:STRING,UINT (marshal.list:3) */
+-void
+-_vte_marshal_VOID__STRING_UINT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data)
+-{
+- typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer data1,
+- gpointer arg_1,
+- guint arg_2,
+- gpointer data2);
+- register GMarshalFunc_VOID__STRING_UINT callback;
+- register GCClosure *cc = (GCClosure*) closure;
+- register gpointer data1, data2;
+-
+- g_return_if_fail (n_param_values == 3);
+-
+- if (G_CCLOSURE_SWAP_DATA (closure))
+- {
+- data1 = closure->data;
+- data2 = g_value_peek_pointer (param_values + 0);
+- }
+- else
+- {
+- data1 = g_value_peek_pointer (param_values + 0);
+- data2 = closure->data;
+- }
+- callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
+-
+- callback (data1,
+- g_marshal_value_peek_string (param_values + 1),
+- g_marshal_value_peek_uint (param_values + 2),
+- data2);
+-}
+-
+-/* VOID:INT (marshal.list:4) */
+-
+-/* VOID:INT,INT (marshal.list:5) */
+-void
+-_vte_marshal_VOID__INT_INT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data)
+-{
+- typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer data1,
+- gint arg_1,
+- gint arg_2,
+- gpointer data2);
+- register GMarshalFunc_VOID__INT_INT callback;
+- register GCClosure *cc = (GCClosure*) closure;
+- register gpointer data1, data2;
+-
+- g_return_if_fail (n_param_values == 3);
+-
+- if (G_CCLOSURE_SWAP_DATA (closure))
+- {
+- data1 = closure->data;
+- data2 = g_value_peek_pointer (param_values + 0);
+- }
+- else
+- {
+- data1 = g_value_peek_pointer (param_values + 0);
+- data2 = closure->data;
+- }
+- callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
+-
+- callback (data1,
+- g_marshal_value_peek_int (param_values + 1),
+- g_marshal_value_peek_int (param_values + 2),
+- data2);
+-}
+-
+-/* VOID:UINT,UINT (marshal.list:6) */
+-void
+-_vte_marshal_VOID__UINT_UINT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data)
+-{
+- typedef void (*GMarshalFunc_VOID__UINT_UINT) (gpointer data1,
+- guint arg_1,
+- guint arg_2,
+- gpointer data2);
+- register GMarshalFunc_VOID__UINT_UINT callback;
+- register GCClosure *cc = (GCClosure*) closure;
+- register gpointer data1, data2;
+-
+- g_return_if_fail (n_param_values == 3);
+-
+- if (G_CCLOSURE_SWAP_DATA (closure))
+- {
+- data1 = closure->data;
+- data2 = g_value_peek_pointer (param_values + 0);
+- }
+- else
+- {
+- data1 = g_value_peek_pointer (param_values + 0);
+- data2 = closure->data;
+- }
+- callback = (GMarshalFunc_VOID__UINT_UINT) (marshal_data ? marshal_data : cc->callback);
+-
+- callback (data1,
+- g_marshal_value_peek_uint (param_values + 1),
+- g_marshal_value_peek_uint (param_values + 2),
+- data2);
+-}
+-
+-/* VOID:OBJECT,OBJECT (marshal.list:7) */
+-void
+-_vte_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data)
+-{
+- typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
+- gpointer arg_1,
+- gpointer arg_2,
+- gpointer data2);
+- register GMarshalFunc_VOID__OBJECT_OBJECT callback;
+- register GCClosure *cc = (GCClosure*) closure;
+- register gpointer data1, data2;
+-
+- g_return_if_fail (n_param_values == 3);
+-
+- if (G_CCLOSURE_SWAP_DATA (closure))
+- {
+- data1 = closure->data;
+- data2 = g_value_peek_pointer (param_values + 0);
+- }
+- else
+- {
+- data1 = g_value_peek_pointer (param_values + 0);
+- data2 = closure->data;
+- }
+- callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+-
+- callback (data1,
+- g_marshal_value_peek_object (param_values + 1),
+- g_marshal_value_peek_object (param_values + 2),
+- data2);
+-}
+-
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/marshal.h src/marshal.h
+--- ../vte-0.16.0/src/marshal.h Mon Feb 26 16:06:36 2007
++++ src/marshal.h Wed Dec 31 19:00:00 1969
+@@ -1,53 +0,0 @@
+-
+-#ifndef ___vte_marshal_MARSHAL_H__
+-#define ___vte_marshal_MARSHAL_H__
+-
+-#include <glib-object.h>
+-
+-G_BEGIN_DECLS
+-
+-/* VOID:VOID (marshal.list:1) */
+-#define _vte_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
+-
+-/* VOID:STRING (marshal.list:2) */
+-#define _vte_marshal_VOID__STRING g_cclosure_marshal_VOID__STRING
+-
+-/* VOID:STRING,UINT (marshal.list:3) */
+-extern void _vte_marshal_VOID__STRING_UINT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data);
+-
+-/* VOID:INT (marshal.list:4) */
+-#define _vte_marshal_VOID__INT g_cclosure_marshal_VOID__INT
+-
+-/* VOID:INT,INT (marshal.list:5) */
+-extern void _vte_marshal_VOID__INT_INT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data);
+-
+-/* VOID:UINT,UINT (marshal.list:6) */
+-extern void _vte_marshal_VOID__UINT_UINT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data);
+-
+-/* VOID:OBJECT,OBJECT (marshal.list:7) */
+-extern void _vte_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+- GValue *return_value,
+- guint n_param_values,
+- const GValue *param_values,
+- gpointer invocation_hint,
+- gpointer marshal_data);
+-
+-G_END_DECLS
+-
+-#endif /* ___vte_marshal_MARSHAL_H__ */
+-
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vte-private.h src/vte-private.h
+--- ../vte-0.16.0/src/vte-private.h Thu Mar 8 11:47:15 2007
++++ src/vte-private.h Fri Mar 23 12:53:52 2007
+@@ -95,27 +95,29 @@ G_BEGIN_DECLS
+ struct vte_charcell {
+ gunichar c; /* The Unicode character. */
+
+- guint32 columns: 2; /* Number of visible columns (as determined
+- by g_unicode_iswide(c)). */
+- guint32 fore: 9; /* Indices in the color palette for the */
+- guint32 back: 9; /* foreground and background of the cell. */
+-
+- guint32 fragment: 1; /* The nth fragment of a wide character. */
+- guint32 standout: 1; /* Single-bit attributes. */
+- guint32 underline: 1;
+- guint32 strikethrough: 1;
+-
+- guint32 reverse: 1;
+- guint32 blink: 1;
+- guint32 half: 1;
+- guint32 bold: 1;
+-
+- guint32 invisible: 1;
+- guint32 protect: 1;
+- guint32 alternate: 1;
+- guint32 empty : 1;
++ struct vte_charcell_attr {
++ guint32 columns: 2; /* Number of visible columns
++ (as determined
++ by g_unicode_iswide(c)). */
++ guint32 fore: 9; /* Index into color palette */
++ guint32 back: 9; /* Index into color palette. */
++
++ guint32 fragment: 1; /* A continuation cell. */
++ guint32 standout: 1; /* Single-bit attributes. */
++ guint32 underline: 1;
++ guint32 strikethrough: 1;
++
++ guint32 reverse: 1;
++ guint32 blink: 1;
++ guint32 half: 1;
++ guint32 bold: 1;
++
++ guint32 invisible: 1;
++ guint32 protect: 1;
++ guint32 alternate: 1;
+
+- /* no more bits left. any addition will enlarge the struct */
++ /* 31 bits */
++ } attr;
+ };
+
+ /* A match regex, with a tag. */
+@@ -275,8 +277,8 @@ struct _VteTerminalPrivate {
+ gboolean smooth_scroll;
+ GHashTable *tabstops;
+ gboolean text_modified_flag;
+- glong text_inserted_count;
+- glong text_deleted_count;
++ gboolean text_inserted_flag;
++ gboolean text_deleted_flag;
+
+ /* Scrolling options. */
+ gboolean scroll_background;
+@@ -395,11 +397,9 @@ void _vte_terminal_adjust_adjustments(Vt
+ void _vte_terminal_queue_contents_changed(VteTerminal *terminal);
+ void _vte_terminal_emit_text_deleted(VteTerminal *terminal);
+ void _vte_terminal_emit_text_inserted(VteTerminal *terminal);
+-void _vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
++gboolean _vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
+ gboolean force_insert_mode,
+- gboolean invalidate_cells,
+- gboolean paint_cells,
+- gint forced_width);
++ gboolean invalidate_cells);
+ void _vte_terminal_scroll_region(VteTerminal *terminal,
+ long row, glong count, glong delta);
+ void _vte_terminal_set_default_attributes(VteTerminal *terminal);
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vte.c src/vte.c
+--- ../vte-0.16.0/src/vte.c Thu Mar 8 11:47:15 2007
++++ src/vte.c Fri Mar 23 12:53:53 2007
+@@ -18,6 +18,8 @@
+
+ #include "../config.h"
+
++#include <math.h>
++
+ #include "vte.h"
+ #include "vte-private.h"
+
+@@ -78,8 +80,7 @@ static void vte_terminal_match_hilite_up
+ static void vte_terminal_match_contents_clear(VteTerminal *terminal);
+ static gboolean vte_terminal_background_update(VteTerminal *data);
+ 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 void vte_terminal_process_incoming(VteTerminal *terminal);
+ static void vte_terminal_emit_pending_signals(VteTerminal *terminal);
+ static inline gboolean vte_cell_is_selected(VteTerminal *terminal,
+ glong col, glong row, gpointer data);
+@@ -245,7 +246,7 @@ vte_free_row_data(gpointer freeing, gpoi
+ /* Append a single item to a GArray a given number of times. Centralizing all
+ * of the places we do this may let me do something more clever later. */
+ static void
+-vte_g_array_fill(GArray *array, gpointer item, guint final_size)
++vte_g_array_fill(GArray *array, gconstpointer item, guint final_size)
+ {
+ if (array->len >= final_size) {
+ return;
+@@ -318,22 +319,21 @@ _vte_terminal_set_default_attributes(Vte
+ screen = terminal->pvt->screen;
+
+ screen->defaults.c = 0;
+- 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;
++ screen->defaults.attr.columns = 1;
++ screen->defaults.attr.fragment = 0;
++ screen->defaults.attr.fore = VTE_DEF_FG;
++ screen->defaults.attr.back = VTE_DEF_BG;
++ screen->defaults.attr.reverse = 0;
++ screen->defaults.attr.bold = 0;
++ screen->defaults.attr.invisible = 0;
++ screen->defaults.attr.protect = 0;
++ screen->defaults.attr.standout = 0;
++ screen->defaults.attr.underline = 0;
++ screen->defaults.attr.strikethrough = 0;
++ screen->defaults.attr.half = 0;
++ screen->defaults.attr.blink = 0;
+ /* Alternate charset isn't an attribute, though we treat it as one.
+- * screen->defaults.alternate = 0; */
++ * screen->defaults.attr.alternate = 0; */
+ screen->basic_defaults = screen->defaults;
+ screen->color_defaults = screen->defaults;
+ screen->fill_defaults = screen->defaults;
+@@ -612,13 +612,13 @@ _vte_invalidate_cell(VteTerminal *termin
+ struct vte_charcell *cell;
+ cell = _vte_row_data_find_charcell(row_data, col);
+ if (cell != NULL) {
+- while (cell->fragment && col> 0) {
++ while (cell->attr.fragment && col> 0) {
+ cell = _vte_row_data_find_charcell(row_data, --col);
+ }
+- columns = cell->columns;
++ columns = cell->attr.columns;
+ if (_vte_draw_get_char_width(terminal->pvt->draw,
+ cell->c,
+- cell->columns) >
++ cell->attr.columns) >
+ terminal->char_width * columns) {
+ columns++;
+ }
+@@ -664,17 +664,17 @@ _vte_invalidate_cursor_once(VteTerminal
+ cell = vte_terminal_find_charcell(terminal,
+ column,
+ screen->cursor_current.row);
+- while ((cell != NULL) && (cell->fragment) && (column > 0)) {
++ while ((cell != NULL) && (cell->attr.fragment) && (column > 0)) {
+ column--;
+ cell = vte_terminal_find_charcell(terminal,
+ column,
+ row);
+ }
+ if (cell != NULL) {
+- columns = cell->columns;
++ columns = cell->attr.columns;
+ if (_vte_draw_get_char_width(terminal->pvt->draw,
+ cell->c,
+- cell->columns) >
++ cell->attr.columns) >
+ terminal->char_width * columns) {
+ columns++;
+ }
+@@ -1613,19 +1613,19 @@ vte_terminal_emit_adjustment_changed(Vte
+ }
+
+ /* Queue an adjustment-changed signal to be delivered when convenient. */
+-static void
++static inline void
+ vte_terminal_queue_adjustment_changed(VteTerminal *terminal)
+ {
+ terminal->pvt->adjustment_changed_pending = TRUE;
+- vte_terminal_start_processing (terminal);
++ add_update_timeout (terminal);
+ }
+-static void
++static inline void
+ vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, glong v)
+ {
+ if (v != terminal->pvt->screen->scroll_delta) {
+ terminal->pvt->screen->scroll_delta = v;
+ terminal->pvt->adjustment_value_changed_pending = TRUE;
+- vte_terminal_start_processing (terminal);
++ add_update_timeout (terminal);
+ }
+ }
+
+@@ -1725,8 +1725,6 @@ vte_terminal_scroll_pages(VteTerminal *t
+ /* Tell the scrollbar to adjust itself. */
+ vte_terminal_queue_adjustment_value_changed (terminal,
+ destination);
+- /* Notify viewers that the contents have changed. */
+- _vte_terminal_queue_contents_changed(terminal);
+ }
+
+ /* Scroll so that the scroll delta is the minimum value. */
+@@ -1855,13 +1853,32 @@ vte_terminal_get_encoding(VteTerminal *t
+ return terminal->pvt->encoding;
+ }
+
++static inline VteRowData*
++vte_terminal_insert_rows (VteTerminal *terminal, guint cnt)
++{
++ const VteScreen *screen = terminal->pvt->screen;
++ VteRowData *old_row, *row;
++ old_row = terminal->pvt->free_row;
++ do {
++ if (old_row) {
++ row = _vte_reset_row_data (terminal, old_row, FALSE);
++ } else {
++ row = _vte_new_row_data_sized (terminal, FALSE);
++ }
++ old_row = _vte_ring_append(screen->row_data, row);
++ } while(--cnt);
++ terminal->pvt->free_row = old_row;
++ return row;
++}
++
++
+ /* Make sure we have enough rows and columns to hold data at the current
+ * cursor position. */
+ VteRowData *
+ _vte_terminal_ensure_row (VteTerminal *terminal)
+ {
+ VteRowData *row;
+- VteScreen *screen;
++ const VteScreen *screen;
+ gint delta;
+ glong v;
+
+@@ -1875,18 +1892,7 @@ _vte_terminal_ensure_row (VteTerminal *t
+ /* Figure out how many rows we need to add. */
+ delta = v - _vte_ring_next(screen->row_data) + 1;
+ if (delta > 0) {
+- VteRowData *old_row;
+-
+- old_row = terminal->pvt->free_row;
+- do {
+- if (old_row) {
+- row = _vte_reset_row_data (terminal, old_row, FALSE);
+- } else {
+- row = _vte_new_row_data_sized (terminal, FALSE);
+- }
+- old_row = _vte_ring_append(screen->row_data, row);
+- } while(--delta);
+- terminal->pvt->free_row = old_row;
++ row = vte_terminal_insert_rows (terminal, delta);
+ _vte_terminal_adjust_adjustments(terminal);
+ } else {
+ /* Find the row the cursor is in. */
+@@ -1920,18 +1926,7 @@ vte_terminal_ensure_cursor(VteTerminal *
+ /* Figure out how many rows we need to add. */
+ delta = v - _vte_ring_next(screen->row_data) + 1;
+ if (delta > 0) {
+- VteRowData *old_row;
+-
+- old_row = terminal->pvt->free_row;
+- do {
+- if (old_row) {
+- row = _vte_reset_row_data (terminal, old_row, FALSE);
+- } else {
+- row = _vte_new_row_data_sized (terminal, FALSE);
+- }
+- old_row = _vte_ring_append(screen->row_data, row);
+- } while(--delta);
+- terminal->pvt->free_row = old_row;
++ row = vte_terminal_insert_rows (terminal, delta);
+ _vte_terminal_adjust_adjustments(terminal);
+ } else {
+ /* Find the row the cursor is in. */
+@@ -1950,7 +1945,7 @@ vte_terminal_ensure_cursor(VteTerminal *
+ }
+ v += columns;
+ if (G_LIKELY (row->cells->len < v)) { /* expand for character */
+- vte_g_array_fill (row->cells, &screen->color_defaults, v);
++ g_array_set_size (row->cells, v);
+ }
+ screen->cursor_current.col = v;
+
+@@ -1969,8 +1964,12 @@ _vte_terminal_update_insert_delta(VteTer
+
+ /* The total number of lines. Add one to the cursor offset
+ * because it's zero-based. */
+- rows = MAX(_vte_ring_next(terminal->pvt->screen->row_data),
+- terminal->pvt->screen->cursor_current.row + 1);
++ rows = _vte_ring_next (screen->row_data);
++ delta = screen->cursor_current.row - rows + 1;
++ if (G_UNLIKELY (delta > 0)) {
++ vte_terminal_insert_rows (terminal, delta);
++ rows = _vte_ring_next (screen->row_data);
++ }
+
+ /* Make sure that the bottom row is visible, and that it's in
+ * the buffer (even if it's empty). This usually causes the
+@@ -2444,55 +2443,45 @@ vte_terminal_set_default_colors(VteTermi
+ }
+
+ /* Insert a single character into the stored data array. */
+-void
++gboolean
+ _vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
+- gboolean force_insert_mode, gboolean invalidate_now,
+- gboolean paint_cells, gint forced_width)
++ gboolean insert, gboolean invalidate_now)
+ {
++ struct vte_charcell_attr attr;
+ VteRowData *row;
+- struct vte_charcell cell;
+- int columns, i;
+ long col;
++ int columns, i;
+ VteScreen *screen;
+- gboolean insert;
++ gboolean line_wrapped = FALSE; /* cursor moved before char inserted */
+
+ screen = terminal->pvt->screen;
+- insert = screen->insert_mode | force_insert_mode;
++ insert |= screen->insert_mode;
+ invalidate_now |= insert;
+
+ /* If we've enabled the special drawing set, map the characters to
+ * Unicode. */
+- if (G_UNLIKELY (screen->defaults.alternate)) {
++ if (G_UNLIKELY (screen->defaults.attr.alternate)) {
+ _vte_debug_print(VTE_DEBUG_SUBSTITUTION,
+ "Attempting charset substitution"
+ "for 0x%04x.\n", c);
+ /* See if there's a mapping for it. */
+- cell.c = _vte_iso2022_process_single(terminal->pvt->iso2022,
+- c, '0');
+- if (cell.c != c) {
+- forced_width = _vte_iso2022_get_encoded_width(cell.c);
+- c = cell.c & ~(VTE_ISO2022_ENCODED_WIDTH_MASK);
+- }
++ c = _vte_iso2022_process_single(terminal->pvt->iso2022, c, '0');
+ }
+
+ /* If this character is destined for the status line, save it. */
+ if (G_UNLIKELY (screen->status_line)) {
+ g_string_append_unichar(screen->status_line_contents, c);
+ screen->status_line_changed = TRUE;
+- return;
++ return FALSE;
+ }
+
+ /* Figure out how many columns this character should occupy. */
+- if (G_LIKELY (forced_width == 0)) {
+- if (VTE_ISO2022_HAS_ENCODED_WIDTH(c)) {
+- columns = _vte_iso2022_get_encoded_width(c);
+- } else {
+- columns = _vte_iso2022_unichar_width(c);
+- }
++ if (G_UNLIKELY (VTE_ISO2022_HAS_ENCODED_WIDTH(c))) {
++ columns = _vte_iso2022_get_encoded_width(c);
++ c &= ~VTE_ISO2022_ENCODED_WIDTH_MASK;
+ } else {
+- columns = MIN(forced_width, 1);
++ columns = _vte_iso2022_unichar_width(c);
+ }
+- c &= ~(VTE_ISO2022_ENCODED_WIDTH_MASK);
+
+ /* If we're autowrapping here, do it. */
+ col = screen->cursor_current.col;
+@@ -2511,6 +2500,7 @@ _vte_terminal_insert_char(VteTerminal *t
+ col = screen->cursor_current.col =
+ terminal->column_count - columns;
+ }
++ line_wrapped = TRUE;
+ }
+
+ /* Make sure we have enough rows to hold this data. */
+@@ -2520,76 +2510,56 @@ _vte_terminal_insert_char(VteTerminal *t
+ _vte_debug_print(VTE_DEBUG_IO|VTE_DEBUG_PARSE,
+ "Inserting %ld '%c' (%d/%d) (%ld+%d, %ld), delta = %ld; ",
+ (long)c, c < 256 ? c : ' ',
+- screen->defaults.fore, screen->defaults.back,
++ screen->defaults.attr.fore,
++ screen->defaults.attr.back,
+ col, columns, (long)screen->cursor_current.row,
+ (long)screen->insert_delta);
+
+- /* Make sure we're not getting random stuff past the right
+- * edge of the screen at this point, because the user can't
+- * see it. */
+- i = 0;
+- do {
+- /* If we're in insert mode, insert a new cell here
+- * and use it. */
++ if (insert) {
++ g_array_insert_val(row->cells, col,
++ screen->color_defaults);
++ }
++ memcpy (&attr, &screen->defaults.attr, sizeof (attr));
++ attr.columns = columns;
++
++ if (G_UNLIKELY (c == '_' && terminal->pvt->flags.ul)) {
++ struct vte_charcell *pcell =
++ &g_array_index (row->cells, struct vte_charcell, col);
++ /* Handle overstrike-style underlining. */
++ if (pcell->c != 0) {
++ /* restore previous contents */
++ c = pcell->c;
++ attr.columns = pcell->attr.columns;
++ attr.fragment = pcell->attr.fragment;
++
++ attr.underline = 1;
++ }
++ }
++ g_array_index(row->cells, struct vte_charcell, col).c = c;
++ g_array_index(row->cells, struct vte_charcell, col).attr = attr;
++ col++;
++
++ /* insert wide-char fragments */
++ for (i = 1; i < columns; i++) {
++ attr.fragment = 1;
+ if (insert) {
+- cell = screen->color_defaults;
+- g_array_insert_val(row->cells, col, cell);
+- }
+- cell.c = c;
+- cell.columns = columns;
+- if (paint_cells) {
+- cell.fore = screen->defaults.fore;
+- cell.back = screen->defaults.back;
+- }
+- 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.invisible = screen->defaults.invisible;
+- cell.protect = screen->defaults.protect;
+- cell.alternate = 0;
+- cell.empty = 0;
+- cell.fragment = i != 0;
+-
+- if (G_UNLIKELY (i == 0 &&
+- c == '_' &&
+- terminal->pvt->flags.ul)) {
+- struct vte_charcell *pcell =
+- &g_array_index (row->cells, struct vte_charcell, col);
+- /* Handle overstrike-style underlining. */
+- if (pcell->c != 0) {
+- /* restore previous contents */
+- cell.c = pcell->c;
+- cell.columns = pcell->columns;
+- cell.fragment = pcell->fragment;
+- cell.empty = pcell->empty;
+-
+- cell.underline = 1;
+- }
++ g_array_insert_val(row->cells, col,
++ screen->color_defaults);
+ }
+- g_array_index(row->cells, struct vte_charcell, col) = cell;
+-
+- /* And take a step to the to the right. */
++ g_array_index(row->cells, struct vte_charcell, col).c = c;
++ g_array_index(row->cells, struct vte_charcell, col).attr = attr;
+ col++;
+- } while (++i < columns);
++ }
+ if (G_UNLIKELY (row->cells->len > terminal->column_count)) {
+ g_array_set_size(row->cells, terminal->column_count);
+ }
+
+ /* Signal that this part of the window needs drawing. */
+- if (invalidate_now) {
+- if (insert) {
+- _vte_invalidate_cells(terminal,
+- col - columns, terminal->column_count,
+- screen->cursor_current.row, 1);
+- } else {
+- _vte_invalidate_cells(terminal,
+- col - columns, columns,
+- screen->cursor_current.row, 1);
+- }
++ if (G_UNLIKELY (invalidate_now)) {
++ _vte_invalidate_cells(terminal,
++ col - columns,
++ insert ? terminal->column_count : columns,
++ screen->cursor_current.row, 1);
+ }
+
+
+@@ -2605,11 +2575,12 @@ _vte_terminal_insert_char(VteTerminal *t
+ }
+
+ /* We added text, so make a note of it. */
+- terminal->pvt->text_inserted_count++;
++ terminal->pvt->text_inserted_flag = TRUE;
+
+ _vte_debug_print(VTE_DEBUG_IO|VTE_DEBUG_PARSE,
+ "insertion delta => %ld.\n",
+ (long)screen->insert_delta);
++ return line_wrapped;
+ }
+
+ static void
+@@ -2730,10 +2701,7 @@ vte_terminal_catch_child_exited(VteReape
+ * then flush the buffers in case we're about to run a new
+ * command, disconnecting the timeout. */
+ if (terminal->pvt->incoming != NULL) {
+- gboolean again;
+- do {
+- again = vte_terminal_process_incoming(terminal);
+- } while (again);
++ vte_terminal_process_incoming(terminal);
+ _vte_incoming_chunks_release (terminal->pvt->incoming);
+ terminal->pvt->incoming = NULL;
+ terminal->pvt->input_bytes = 0;
+@@ -3042,12 +3010,8 @@ vte_terminal_eof(GIOChannel *channel, Vt
+ * disconnecting the timeout. */
+ vte_terminal_stop_processing (terminal);
+ if (terminal->pvt->incoming) {
+- gboolean again;
+- do {
+- again = vte_terminal_process_incoming(terminal);
+- } while (again);
++ vte_terminal_process_incoming(terminal);
+ terminal->pvt->input_bytes = 0;
+- vte_terminal_emit_pending_signals (terminal);
+ }
+ g_array_set_size(terminal->pvt->pending, 0);
+
+@@ -3112,29 +3076,23 @@ vte_terminal_emit_pending_text_signals(V
+ vte_terminal_emit_text_modified(terminal);
+ terminal->pvt->text_modified_flag = FALSE;
+ }
+- if (terminal->pvt->text_inserted_count) {
++ if (terminal->pvt->text_inserted_flag) {
+ _vte_debug_print(VTE_DEBUG_SIGNALS,
+- "Emitting buffered `text-inserted' "
+- "(%ld).\n", terminal->pvt->text_inserted_count);
++ "Emitting buffered `text-inserted'\n");
+ _vte_terminal_emit_text_inserted(terminal);
+- terminal->pvt->text_inserted_count = 0;
++ terminal->pvt->text_inserted_flag = FALSE;
+ }
+- if (terminal->pvt->text_deleted_count) {
++ if (terminal->pvt->text_deleted_flag) {
+ _vte_debug_print(VTE_DEBUG_SIGNALS,
+- "Emitting buffered `text-deleted' "
+- "(%ld).\n", terminal->pvt->text_deleted_count);
++ "Emitting buffered `text-deleted'\n");
+ _vte_terminal_emit_text_deleted(terminal);
+- terminal->pvt->text_deleted_count = 0;
++ terminal->pvt->text_deleted_flag = FALSE;
+ }
+-
+- terminal->pvt->text_modified_flag = FALSE;
+- terminal->pvt->text_inserted_count = 0;
+- terminal->pvt->text_deleted_count = 0;
+ }
+
+ /* Process incoming data, first converting it to unicode characters, and then
+ * processing control sequences. */
+-static gboolean
++static void
+ vte_terminal_process_incoming(VteTerminal *terminal)
+ {
+ VteScreen *screen;
+@@ -3244,7 +3202,7 @@ skip_chunk:
+ bbox_bottomright.x = bbox_bottomright.y = -G_MAXINT;
+ bbox_topleft.x = bbox_topleft.y = G_MAXINT;
+
+- while (start < wcount && !leftovers && !again) {
++ while (start < wcount && !leftovers) {
+ const char *match;
+ GQuark quark;
+ const gunichar *next;
+@@ -3265,10 +3223,10 @@ skip_chunk:
+ if ((match != NULL) && (match[0] != '\0')) {
+ /* Call the right sequence handler for the requested
+ * behavior. */
+- again = vte_terminal_handle_sequence(terminal,
+- match,
+- quark,
+- params);
++ vte_terminal_handle_sequence(terminal,
++ match,
++ quark,
++ params);
+ /* Skip over the proper number of unicode chars. */
+ start = (next - wbuf);
+ modified = TRUE;
+@@ -3364,9 +3322,36 @@ skip_chunk:
+ screen->cursor_current.row);
+
+ /* Insert the character. */
+- _vte_terminal_insert_char(terminal, c,
+- FALSE, FALSE,
+- TRUE, 0);
++ if (G_UNLIKELY (_vte_terminal_insert_char(terminal, c,
++ FALSE, FALSE))) {
++ /* line wrapped, correct bbox */
++ if (invalidated_text &&
++ (screen->cursor_current.col > bbox_bottomright.x + VTE_CELL_BBOX_SLACK ||
++ screen->cursor_current.col < bbox_topleft.x - VTE_CELL_BBOX_SLACK ||
++ screen->cursor_current.row > bbox_bottomright.y + VTE_CELL_BBOX_SLACK ||
++ screen->cursor_current.row < bbox_topleft.y - VTE_CELL_BBOX_SLACK)) {
++ /* Clip off any part of the box which isn't already on-screen. */
++ bbox_topleft.x = MAX(bbox_topleft.x, 0);
++ bbox_topleft.y = MAX(bbox_topleft.y, delta);
++ bbox_bottomright.x = MIN(bbox_bottomright.x,
++ terminal->column_count);
++ /* lazily apply the +1 to the cursor_row */
++ bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
++ delta + terminal->row_count);
++
++ _vte_invalidate_cells(terminal,
++ bbox_topleft.x,
++ bbox_bottomright.x - bbox_topleft.x,
++ bbox_topleft.y,
++ bbox_bottomright.y - bbox_topleft.y);
++ bbox_bottomright.x = bbox_bottomright.y = -G_MAXINT;
++ bbox_topleft.x = bbox_topleft.y = G_MAXINT;
++
++ }
++ bbox_topleft.x = MIN(bbox_topleft.x, 0);
++ bbox_topleft.y = MIN(bbox_topleft.y,
++ screen->cursor_current.row);
++ }
+ /* Add the cells over which we have moved to the region
+ * which we need to refresh for the user. */
+ bbox_bottomright.x = MAX(bbox_bottomright.x,
+@@ -3418,23 +3403,6 @@ next_match:
+ }
+ }
+
+- if (invalidated_text) {
+- /* 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, delta);
+- bbox_bottomright.x = MIN(bbox_bottomright.x,
+- terminal->column_count);
+- /* lazily apply the +1 to the cursor_row */
+- bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
+- delta + terminal->row_count);
+-
+- _vte_invalidate_cells(terminal,
+- bbox_topleft.x,
+- bbox_bottomright.x - bbox_topleft.x,
+- bbox_topleft.y,
+- bbox_bottomright.y - bbox_topleft.y);
+- }
+-
+ /* Remove most of the processed characters. */
+ if (start < wcount) {
+ unichars = g_array_new(FALSE, FALSE, sizeof(gunichar));
+@@ -3450,7 +3418,6 @@ next_match:
+ /* If we're out of data, we needn't pause to let the
+ * controlling application respond to incoming data, because
+ * the main loop is already going to do that. */
+- again = FALSE;
+ }
+
+ if (modified) {
+@@ -3486,6 +3453,26 @@ next_match:
+ _vte_terminal_queue_contents_changed(terminal);
+ }
+
++ vte_terminal_emit_pending_signals (terminal);
++
++ if (invalidated_text) {
++ /* 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, delta);
++ bbox_bottomright.x = MIN(bbox_bottomright.x,
++ terminal->column_count);
++ /* lazily apply the +1 to the cursor_row */
++ bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
++ delta + terminal->row_count);
++
++ _vte_invalidate_cells(terminal,
++ bbox_topleft.x,
++ bbox_bottomright.x - bbox_topleft.x,
++ bbox_topleft.y,
++ bbox_bottomright.y - bbox_topleft.y);
++ }
++
++
+ if ((cursor.col != terminal->pvt->screen->cursor_current.col) ||
+ (cursor.row != terminal->pvt->screen->cursor_current.row)) {
+ /* invalidate the old and new cursor positions */
+@@ -3517,7 +3504,6 @@ next_match:
+ (long) unichars->len,
+ (long) _vte_incoming_chunks_length(terminal->pvt->incoming),
+ _vte_incoming_chunks_count(terminal->pvt->incoming));
+- return again;
+ }
+
+ static inline void
+@@ -3643,7 +3629,7 @@ out:
+ }
+
+ return !eof &&
+- (active_terminals ? g_list_length (active_terminals) : 1) *
++ g_list_length (active_terminals) *
+ terminal->pvt->input_bytes < terminal->pvt->max_input_bytes;
+ }
+
+@@ -3712,7 +3698,6 @@ vte_terminal_io_write(GIOChannel *channe
+ }
+
+ if (_vte_buffer_length(terminal->pvt->outgoing) == 0) {
+- _vte_terminal_disconnect_pty_write(terminal);
+ leave_open = FALSE;
+ } else {
+ leave_open = TRUE;
+@@ -3803,9 +3788,7 @@ vte_terminal_send(VteTerminal *terminal,
+ _vte_terminal_insert_char(terminal,
+ ucs4[i],
+ FALSE,
+- TRUE,
+- TRUE,
+- 0);
++ TRUE);
+ }
+ g_free(ucs4);
+ }
+@@ -4538,7 +4521,7 @@ vte_same_class(VteTerminal *terminal, gl
+ {
+ struct vte_charcell *pcell = NULL;
+ gboolean word_char;
+- if ((pcell = vte_terminal_find_charcell(terminal, acol, arow)) != NULL && !pcell->empty) {
++ if ((pcell = vte_terminal_find_charcell(terminal, acol, arow)) != NULL && pcell->c != 0) {
+ word_char = vte_terminal_is_word_char(terminal, pcell->c);
+
+ /* Lets not group non-wordchars together (bug #25290) */
+@@ -4546,7 +4529,7 @@ vte_same_class(VteTerminal *terminal, gl
+ return FALSE;
+
+ pcell = vte_terminal_find_charcell(terminal, bcol, brow);
+- if (pcell == NULL || pcell->empty) {
++ if (pcell == NULL || pcell->c == 0) {
+ return FALSE;
+ }
+ if (word_char != vte_terminal_is_word_char(terminal,
+@@ -5197,26 +5180,26 @@ vte_terminal_get_text_range_maybe_wrappe
+ /* If it's not part of a multi-column character,
+ * and passes the selection criterion, add it to
+ * the selection. */
+- if (!pcell->fragment &&
++ if (!pcell->attr.fragment &&
+ is_selected(terminal, col, row, data)) {
+ /* Store the attributes of this character. */
+- fore = palette[pcell->fore];
+- back = palette[pcell->back];
++ fore = palette[pcell->attr.fore];
++ back = palette[pcell->attr.back];
+ attr.fore.red = fore.red;
+ attr.fore.green = fore.green;
+ attr.fore.blue = fore.blue;
+ attr.back.red = back.red;
+ attr.back.green = back.green;
+ attr.back.blue = back.blue;
+- attr.underline = pcell->underline;
+- attr.strikethrough = pcell->strikethrough;
++ attr.underline = pcell->attr.underline;
++ attr.strikethrough = pcell->attr.strikethrough;
+
+ /* Store the character. */
+ string = g_string_append_unichar(string,
+ pcell->c ?
+ pcell->c :
+ ' ');
+- if (pcell->empty) {
++ if (pcell->c == 0) {
+ last_empty = string->len;
+ last_emptycol = col;
+ } else {
+@@ -5252,10 +5235,10 @@ vte_terminal_get_text_range_maybe_wrappe
+ while ((pcell = _vte_row_data_find_charcell(row_data, col))) {
+ col++;
+
+- if (pcell->fragment)
++ if (pcell->attr.fragment)
+ continue;
+
+- if (!pcell->empty)
++ if (pcell->c != 0)
+ break;
+ }
+ }
+@@ -5502,7 +5485,7 @@ find_start_column (VteTerminal *terminal
+ VteRowData *row_data = _vte_terminal_find_row_data (terminal, row);
+ if (row_data != NULL) {
+ struct vte_charcell *cell = _vte_row_data_find_charcell(row_data, col);
+- while (cell != NULL && cell->fragment && col > 0) {
++ while (cell != NULL && cell->attr.fragment && col > 0) {
+ cell = _vte_row_data_find_charcell(row_data, --col);
+ }
+ }
+@@ -5515,11 +5498,11 @@ find_end_column (VteTerminal *terminal,
+ gint columns = 0;
+ if (row_data != NULL) {
+ struct vte_charcell *cell = _vte_row_data_find_charcell(row_data, col);
+- while (cell != NULL && cell->fragment && col > 0) {
++ while (cell != NULL && cell->attr.fragment && col > 0) {
+ cell = _vte_row_data_find_charcell(row_data, --col);
+ }
+ if (cell) {
+- columns = cell->columns - 1;
++ columns = cell->attr.columns - 1;
+ }
+ }
+ return MIN(col + columns, terminal->column_count);
+@@ -5725,7 +5708,7 @@ vte_terminal_extend_selection(VteTermina
+ for (i = 0; i < rowdata->cells->len; i++) {
+ cell = &g_array_index(rowdata->cells,
+ struct vte_charcell, i);
+- if (!cell->empty)
++ if (cell->c != 0)
+ last_nonempty = i;
+ }
+ /* Now find the first empty after it. */
+@@ -5759,7 +5742,7 @@ vte_terminal_extend_selection(VteTermina
+ for (i = 0; i < rowdata->cells->len; i++) {
+ cell = &g_array_index(rowdata->cells,
+ struct vte_charcell, i);
+- if (!cell->empty)
++ if (cell->c != 0)
+ last_nonempty = i;
+ }
+ /* Now find the first empty after it. */
+@@ -7203,11 +7186,20 @@ static void
+ vte_terminal_fc_settings_changed(GtkSettings *settings, GParamSpec *spec,
+ VteTerminal *terminal)
+ {
++ PangoFontDescription *fontdesc;
++
+ _vte_debug_print(VTE_DEBUG_MISC,
+ "Fontconfig setting \"%s\" changed.\n",
+ spec->name);
+- vte_terminal_set_font_full(terminal, terminal->pvt->fontdesc,
++
++ /* force an update... */
++ fontdesc = terminal->pvt->fontdesc;
++ terminal->pvt->fontdesc = NULL;
++
++ vte_terminal_set_font_full(terminal, fontdesc,
+ terminal->pvt->fontantialias);
++
++ pango_font_description_free(fontdesc);
+ }
+
+ /* Connect to notifications from our settings object that font hints have
+@@ -7627,8 +7619,8 @@ vte_terminal_unrealize(GtkWidget *widget
+ terminal->pvt->contents_changed_pending = FALSE;
+ terminal->pvt->cursor_moved_pending = FALSE;
+ terminal->pvt->text_modified_flag = FALSE;
+- terminal->pvt->text_inserted_count = 0;
+- terminal->pvt->text_deleted_count = 0;
++ terminal->pvt->text_inserted_flag = FALSE;
++ terminal->pvt->text_deleted_flag = FALSE;
+
+ /* Clear modifiers. */
+ terminal->pvt->modifiers = 0;
+@@ -7950,27 +7942,27 @@ vte_terminal_determine_colors(VteTermina
+ * reverse colors, else use the defaults. This means that many callers
+ * who specify highlight or cursor should also specify reverse. */
+ if (cursor && !highlight && terminal->pvt->cursor_color_set) {
+- *fore = cell ? cell->back : VTE_DEF_BG;
++ *fore = cell ? cell->attr.back : VTE_DEF_BG;
+ *back = VTE_CUR_BG;
+ } else
+ if (highlight && !cursor && terminal->pvt->highlight_color_set) {
+- *fore = cell ? cell->fore : VTE_DEF_FG;
++ *fore = cell ? cell->attr.fore : VTE_DEF_FG;
+ *back = VTE_DEF_HL;
+ } else
+- if (reverse ^ ((cell != NULL) && (cell->reverse))) {
+- *fore = cell ? cell->back : VTE_DEF_BG;
+- *back = cell ? cell->fore : VTE_DEF_FG;
++ if (reverse ^ ((cell != NULL) && (cell->attr.reverse))) {
++ *fore = cell ? cell->attr.back : VTE_DEF_BG;
++ *back = cell ? cell->attr.fore : VTE_DEF_FG;
+ } else {
+- *fore = cell ? cell->fore : VTE_DEF_FG;
+- *back = cell ? cell->back : VTE_DEF_BG;
++ *fore = cell ? cell->attr.fore : VTE_DEF_FG;
++ *back = cell ? cell->attr.back : VTE_DEF_BG;
+ }
+
+ /* Handle invisible, bold, and standout text by adjusting colors. */
+ if (cell) {
+- if (cell->invisible) {
++ if (cell->attr.invisible) {
+ *fore = *back;
+ }
+- if (cell->bold) {
++ if (cell->attr.bold) {
+ if (*fore == VTE_DEF_FG) {
+ *fore = VTE_BOLD_FG;
+ } else
+@@ -7978,7 +7970,7 @@ vte_terminal_determine_colors(VteTermina
+ *fore += VTE_COLOR_BRIGHT_OFFSET;
+ }
+ }
+- if (cell->half) {
++ if (cell->attr.half) {
+ if (*fore == VTE_DEF_FG) {
+ *fore = VTE_DIM_FG;
+ } else
+@@ -7986,7 +7978,7 @@ vte_terminal_determine_colors(VteTermina
+ *fore = corresponding_dim_index[*fore];;
+ }
+ }
+- if (cell->standout) {
++ if (cell->attr.standout) {
+ if (*back < VTE_LEGACY_COLOR_SET_SIZE) {
+ *back += VTE_COLOR_BRIGHT_OFFSET;
+ }
+@@ -9117,9 +9109,9 @@ _vte_terminal_fudge_pango_colors(VteTerm
+ (props[i].bg.red == 0) &&
+ (props[i].bg.green == 0) &&
+ (props[i].bg.blue == 0)) {
+- cells[i].fore = terminal->pvt->screen->color_defaults.fore;
+- cells[i].back = terminal->pvt->screen->color_defaults.back;
+- cells[i].reverse = TRUE;
++ cells[i].attr.fore = terminal->pvt->screen->color_defaults.attr.fore;
++ cells[i].attr.back = terminal->pvt->screen->color_defaults.attr.back;
++ cells[i].attr.reverse = TRUE;
+ }
+ }
+ }
+@@ -9143,10 +9135,10 @@ _vte_terminal_apply_pango_attr(VteTermin
+ i < attr->end_index && i < n_cells;
+ i++) {
+ if (attr->klass->type == PANGO_ATTR_FOREGROUND) {
+- cells[i].fore = ival;
++ cells[i].attr.fore = ival;
+ }
+ if (attr->klass->type == PANGO_ATTR_BACKGROUND) {
+- cells[i].back = ival;
++ cells[i].attr.back = ival;
+ }
+ }
+ break;
+@@ -9156,7 +9148,7 @@ _vte_terminal_apply_pango_attr(VteTermin
+ for (i = attr->start_index;
+ (i < attr->end_index) && (i < n_cells);
+ i++) {
+- cells[i].strikethrough = (ival != FALSE);
++ cells[i].attr.strikethrough = (ival != FALSE);
+ }
+ break;
+ case PANGO_ATTR_UNDERLINE:
+@@ -9165,7 +9157,7 @@ _vte_terminal_apply_pango_attr(VteTermin
+ for (i = attr->start_index;
+ (i < attr->end_index) && (i < n_cells);
+ i++) {
+- cells[i].underline = (ival != PANGO_UNDERLINE_NONE);
++ cells[i].attr.underline = (ival != PANGO_UNDERLINE_NONE);
+ }
+ break;
+ case PANGO_ATTR_WEIGHT:
+@@ -9174,7 +9166,7 @@ _vte_terminal_apply_pango_attr(VteTermin
+ for (i = attr->start_index;
+ (i < attr->end_index) && (i < n_cells);
+ i++) {
+- cells[i].bold = (ival >= PANGO_WEIGHT_BOLD);
++ cells[i].attr.bold = (ival >= PANGO_WEIGHT_BOLD);
+ }
+ break;
+ default:
+@@ -9267,9 +9259,9 @@ vte_terminal_draw_cells_with_attributes(
+ fore,
+ back,
+ TRUE, draw_default_bg,
+- cells[j].bold,
+- cells[j].underline,
+- cells[j].strikethrough,
++ cells[j].attr.bold,
++ cells[j].attr.underline,
++ cells[j].attr.strikethrough,
+ FALSE, FALSE, column_width, height);
+ j += g_unichar_to_utf8(items[i].c, scratch_buf);
+ }
+@@ -9332,7 +9324,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ if (row_data != NULL) {
+ cell = _vte_row_data_find_charcell(row_data, i);
+ if (cell != NULL) {
+- while (cell->fragment && i > 0) {
++ while (cell->attr.fragment && i > 0) {
+ cell = _vte_row_data_find_charcell(row_data, --i);
+ }
+ }
+@@ -9348,14 +9340,14 @@ vte_terminal_draw_rows(VteTerminal *term
+ FALSE,
+ &fore, &back);
+
+- bold = cell && cell->bold;
+- j = i + (cell ? cell->columns : 1);
++ bold = cell && cell->attr.bold;
++ j = i + (cell ? cell->attr.columns : 1);
+
+ while (j < end_column){
+ /* Don't render fragments of multicolumn characters
+ * which have the same attributes as the initial
+ * portions. */
+- if (cell != NULL && cell->fragment) {
++ if (cell != NULL && cell->attr.fragment) {
+ j++;
+ continue;
+ }
+@@ -9373,8 +9365,8 @@ vte_terminal_draw_rows(VteTerminal *term
+ if (nback != back) {
+ break;
+ }
+- bold = cell && cell->bold;
+- j += cell ? cell->columns : 1;
++ bold = cell && cell->attr.bold;
++ j += cell ? cell->attr.columns : 1;
+ }
+ if (back != VTE_DEF_BG) {
+ GdkColor color;
+@@ -9467,7 +9459,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ if (cell == NULL) {
+ goto fg_next_row;
+ }
+- while (cell->fragment && i > 0) {
++ while (cell->attr.fragment && i > 0) {
+ cell = _vte_row_data_find_charcell(row_data, --i);
+ }
+
+@@ -9480,7 +9472,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ }
+ while (cell->c == 0 ||
+ cell->c == ' ' ||
+- cell->fragment) {
++ cell->attr.fragment) {
+ if (++i >= end_column) {
+ goto fg_next_row;
+ }
+@@ -9496,9 +9488,9 @@ vte_terminal_draw_rows(VteTerminal *term
+ selected,
+ FALSE,
+ &fore, &back);
+- underline = cell->underline;
+- strikethrough = cell->strikethrough;
+- bold = cell->bold;
++ underline = cell->attr.underline;
++ strikethrough = cell->attr.strikethrough;
++ bold = cell->attr.bold;
+ if (terminal->pvt->show_match) {
+ hilite = vte_cell_is_between(i, row,
+ terminal->pvt->match_start.column,
+@@ -9511,7 +9503,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ }
+
+ items[0].c = cell->c;
+- items[0].columns = cell->columns;
++ items[0].columns = cell->attr.columns;
+ items[0].x = start_x + i * column_width;
+ items[0].y = y;
+ j = i + items[0].columns;
+@@ -9541,8 +9533,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ if (cell == NULL) {
+ break;
+ }
+- if (cell->c == 0 ||
+- cell->c == ' '){
++ if (cell->c == 0 || cell->c == ' '){
+ /* only break the run if we
+ * are drawing attributes
+ */
+@@ -9558,7 +9549,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ /* Don't render blank cells or fragments of multicolumn characters
+ * which have the same attributes as the initial
+ * portions. */
+- if (cell->fragment) {
++ if (cell->attr.fragment) {
+ j++;
+ continue;
+ }
+@@ -9580,26 +9571,26 @@ vte_terminal_draw_rows(VteTerminal *term
+ start_x + j * column_width,
+ y,
+ column_width,
+- cell->columns,
++ cell->attr.columns,
+ row_height)) {
+
+- j += cell->columns;
++ j += cell->attr.columns;
+ continue;
+ }
+ }
+ if (nfore != fore) {
+ break;
+ }
+- nbold = cell->bold;
++ nbold = cell->attr.bold;
+ if (nbold != bold) {
+ break;
+ }
+ /* Break up underlined/not-underlined text. */
+- nunderline = cell->underline;
++ nunderline = cell->attr.underline;
+ if (nunderline != underline) {
+ break;
+ }
+- nstrikethrough = cell->strikethrough;
++ nstrikethrough = cell->attr.strikethrough;
+ if (nstrikethrough != strikethrough) {
+ break;
+ }
+@@ -9618,7 +9609,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ }
+ /* Add this cell to the draw list. */
+ items[item_count].c = cell->c;
+- items[item_count].columns = cell->columns;
++ items[item_count].columns = cell->attr.columns;
+ items[item_count].x = start_x + j * column_width;
+ items[item_count].y = y;
+ j += items[item_count].columns;
+@@ -9647,7 +9638,7 @@ vte_terminal_draw_rows(VteTerminal *term
+ j = start_column;
+ cell = _vte_row_data_find_charcell(row_data, j);
+ } while (cell == NULL);
+- while (cell->fragment && j > 0) {
++ while (cell->attr.fragment && j > 0) {
+ cell = _vte_row_data_find_charcell(row_data, --j);
+ }
+ } while (TRUE);
+@@ -9712,7 +9703,7 @@ vte_terminal_expand_region (VteTerminal
+ if (col_stop == terminal->column_count)
+ rect.width = terminal->widget.allocation.width;
+ else
+- rect.width = col_stop*width;
++ rect.width = (col_stop + 1)*width;
+ rect.width -= rect.x;
+ if (row == 0)
+ rect.y = 0;
+@@ -9721,7 +9712,7 @@ vte_terminal_expand_region (VteTerminal
+ if (row_stop == terminal->row_count)
+ rect.height = terminal->widget.allocation.height;
+ else
+- rect.height = row_stop*height;
++ rect.height = (row_stop + 1)*height;
+ rect.height -= rect.y;
+ gdk_region_union_with_rect(region, &rect);
+
+@@ -9748,16 +9739,14 @@ vte_terminal_paint_area (VteTerminal *te
+ height = terminal->char_height;
+ delta = screen->scroll_delta;
+
+- /* increase the paint by one pixel on all sides to force the
+- * inclusion of neighbouring cells */
+ row = MAX(0, (area->y - VTE_PAD_WIDTH) / height);
+- row_stop = MIN(howmany(area->height + area->y - VTE_PAD_WIDTH, height),
++ row_stop = MIN((area->height + area->y - VTE_PAD_WIDTH) / height,
+ terminal->row_count);
+ if (row_stop <= row) {
+ return;
+ }
+ col = MAX(0, (area->x - VTE_PAD_WIDTH) / width);
+- col_stop = MIN(howmany(area->width + area->x - VTE_PAD_WIDTH, width),
++ col_stop = MIN((area->width + area->x - VTE_PAD_WIDTH) / width,
+ terminal->column_count);
+ if (col_stop <= col) {
+ return;
+@@ -9774,7 +9763,7 @@ vte_terminal_paint_area (VteTerminal *te
+ (col_stop - col) * width,
+ (row_stop - row) * height);
+ if (!GTK_WIDGET_DOUBLE_BUFFERED (terminal) ||
+- _vte_draw_has_background_image (terminal->pvt->draw)) {
++ _vte_draw_requires_clear (terminal->pvt->draw)) {
+ _vte_draw_clear (terminal->pvt->draw,
+ area->x, area->y,
+ area->width, area->height);
+@@ -9905,28 +9894,23 @@ vte_terminal_paint(GtkWidget *widget, Gd
+
+ /* Find the character "under" the cursor. */
+ cell = vte_terminal_find_charcell(terminal, col, drow);
+- while ((cell != NULL) && (cell->fragment) && (col > 0)) {
++ while ((cell != NULL) && (cell->attr.fragment) && (col > 0)) {
+ col--;
+ cell = vte_terminal_find_charcell(terminal, col, drow);
+ }
+
+ /* Draw the cursor. */
+ item.c = cell ? (cell->c ? cell->c : ' ') : ' ';
+- item.columns = cell ? cell->columns : 1;
++ item.columns = cell ? cell->attr.columns : 1;
+ item.x = col * width;
+ item.y = row * height;
+ cursor_width = item.columns * width;
+ if (cell) {
+- cursor_width = MAX(cursor_width,
+- _vte_draw_get_char_width(terminal->pvt->draw,
+- cell->c,
+- cell->columns));
+- cursor_width += cell->bold; /* pseudo-bolding */
+- }
+- _vte_draw_clear(terminal->pvt->draw,
+- col * width + VTE_PAD_WIDTH,
+- row * height + VTE_PAD_WIDTH,
+- cursor_width, height);
++ gint cw = _vte_draw_get_char_width (terminal->pvt->draw,
++ cell->c, cell->attr.columns);
++ cursor_width = MAX(cursor_width, cw);
++ cursor_width += cell->attr.bold; /* pseudo-bolding */
++ }
+ selected = vte_cell_is_selected(terminal, col, drow, NULL);
+ if (GTK_WIDGET_HAS_FOCUS(terminal)) {
+ blink = terminal->pvt->cursor_blink_state ^
+@@ -9951,42 +9935,46 @@ vte_terminal_paint(GtkWidget *widget, Gd
+ height,
+ &color,
+ VTE_DRAW_OPAQUE);
+- }
+- if (!vte_terminal_unichar_is_local_graphic(terminal, item.c) ||
+- !vte_terminal_draw_graphic(terminal,
+- item.c,
+- fore, back,
+- TRUE,
+- item.x,
+- item.y,
+- width,
+- item.columns,
+- height)) {
+- gboolean hilite = FALSE;
+- if (cell && terminal->pvt->show_match) {
+- hilite = vte_cell_is_between(col, row,
+- terminal->pvt->match_start.column,
+- terminal->pvt->match_start.row,
+- terminal->pvt->match_end.column,
+- terminal->pvt->match_end.row,
+- TRUE);
+- }
+- if (cell && cell->c != 0 && cell->c != ' ') {
+- vte_terminal_draw_cells(terminal,
+- &item, 1,
+- fore, back, TRUE, FALSE,
+- cell->bold,
+- cell->underline,
+- cell->strikethrough,
+- hilite,
+- FALSE,
+- width,
+- height);
++ if (!vte_terminal_unichar_is_local_graphic(terminal, item.c) ||
++ !vte_terminal_draw_graphic(terminal,
++ item.c,
++ fore, back,
++ TRUE,
++ item.x,
++ item.y,
++ width,
++ item.columns,
++ height)) {
++ gboolean hilite = FALSE;
++ if (cell && terminal->pvt->show_match) {
++ hilite = vte_cell_is_between(col, row,
++ terminal->pvt->match_start.column,
++ terminal->pvt->match_start.row,
++ terminal->pvt->match_end.column,
++ terminal->pvt->match_end.row,
++ TRUE);
++ }
++ if (cell && cell->c != 0 && cell->c != ' ') {
++ vte_terminal_draw_cells(terminal,
++ &item, 1,
++ fore, back, TRUE, FALSE,
++ cell->attr.bold,
++ cell->attr.underline,
++ cell->attr.strikethrough,
++ hilite,
++ FALSE,
++ width,
++ height);
++ }
+ }
+ }
+ } else {
+ GdkColor color;
+ draw_cursor_outline:
++ _vte_draw_clear(terminal->pvt->draw,
++ col * width + VTE_PAD_WIDTH,
++ row * height + VTE_PAD_WIDTH,
++ cursor_width, height);
+ vte_terminal_determine_colors(terminal, cell,
+ terminal->pvt->screen->reverse_mode,
+ selected,
+@@ -10016,9 +10004,9 @@ draw_cursor_outline:
+ vte_terminal_draw_cells(terminal,
+ &item, 1,
+ fore, back, TRUE, FALSE,
+- cell->bold,
+- cell->underline,
+- cell->strikethrough,
++ cell->attr.bold,
++ cell->attr.underline,
++ cell->attr.strikethrough,
+ hilite,
+ FALSE,
+ width,
+@@ -10086,8 +10074,8 @@ draw_cursor_outline:
+ row * height + VTE_PAD_WIDTH,
+ width * columns,
+ height);
+- fore = screen->defaults.fore;
+- back = screen->defaults.back;
++ fore = screen->defaults.attr.fore;
++ back = screen->defaults.attr.back;
+ vte_terminal_draw_cells_with_attributes(terminal,
+ items, len,
+ terminal->pvt->im_preedit_attrs,
+@@ -10104,18 +10092,6 @@ draw_cursor_outline:
+ FALSE,
+ TRUE,
+ width, height);
+- } else
+- if (preedit_cursor == len) {
+- /* Empty cursor at the end. */
+- vte_terminal_draw_cells(terminal,
+- &items[len], 1,
+- back, fore, TRUE, TRUE,
+- FALSE,
+- FALSE,
+- FALSE,
+- FALSE,
+- FALSE,
+- width, height);
+ }
+ g_free(items);
+ }
+@@ -10130,14 +10106,21 @@ static gint
+ vte_terminal_expose(GtkWidget *widget, GdkEventExpose *event)
+ {
+ VteTerminal *terminal = VTE_TERMINAL (widget);
++ /* Beware the out of order events -
++ * do not even think about skipping exposes! */
+ _vte_debug_print (VTE_DEBUG_WORK, "+");
+- if (terminal->pvt->visibility_state == GDK_VISIBILITY_FULLY_OBSCURED) {
+- return FALSE;
+- }
+ _vte_debug_print (VTE_DEBUG_EVENTS, "Expose (%d,%d)x(%d,%d)\n",
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+- if (terminal->pvt->active != NULL && !in_update_timeout) {
++ if (terminal->pvt->active != NULL &&
++ update_timeout_tag != VTE_INVALID_SOURCE &&
++ !in_update_timeout) {
++ /* fix up a race condition where we schedule a delayed update
++ * after an 'immediate' invalidate all */
++ if (terminal->pvt->invalidated_all &&
++ terminal->pvt->update_regions == NULL) {
++ terminal->pvt->invalidated_all = FALSE;
++ }
+ /* if we expect to redraw the widget soon,
+ * just add this event to the list */
+ if (!terminal->pvt->invalidated_all) {
+@@ -10163,6 +10146,7 @@ vte_terminal_scroll(GtkWidget *widget, G
+ {
+ GtkAdjustment *adj;
+ VteTerminal *terminal;
++ gdouble v;
+ glong new_value;
+ GdkModifierType modifiers;
+ int button;
+@@ -10216,21 +10200,19 @@ vte_terminal_scroll(GtkWidget *widget, G
+
+ /* Perform a history scroll. */
+ adj = terminal->adjustment;
+- new_value = terminal->pvt->screen->scroll_delta;
+-
++ v = MAX (1., ceil (adj->page_increment / 10.));
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+- new_value -= MAX(1, adj->page_increment / 10);
++ v = -v;
+ break;
+ case GDK_SCROLL_DOWN:
+- new_value += MAX(1, adj->page_increment / 10);
+ break;
+ default:
+ return FALSE;
+ }
+-
+- new_value = CLAMP(new_value, adj->lower,
+- MAX (adj->lower, adj->upper - adj->page_size));
++ v += terminal->pvt->screen->scroll_delta;
++ new_value = floor (CLAMP (v, adj->lower,
++ MAX (adj->lower, adj->upper - adj->page_size)));
+ vte_terminal_queue_adjustment_value_changed (terminal, new_value);
+
+ return TRUE;
+@@ -11530,10 +11512,10 @@ vte_terminal_reset(VteTerminal *terminal
+ * it's not a real attribute, but we need to treat it as one here. */
+ terminal->pvt->screen = &terminal->pvt->alternate_screen;
+ _vte_terminal_set_default_attributes(terminal);
+- terminal->pvt->screen->defaults.alternate = FALSE;
++ terminal->pvt->screen->defaults.attr.alternate = FALSE;
+ terminal->pvt->screen = &terminal->pvt->normal_screen;
+ _vte_terminal_set_default_attributes(terminal);
+- terminal->pvt->screen->defaults.alternate = FALSE;
++ terminal->pvt->screen->defaults.attr.alternate = FALSE;
+ /* Clear the scrollback buffers and reset the cursors. */
+ if (clear_history) {
+ _vte_ring_free(terminal->pvt->normal_screen.row_data, TRUE);
+@@ -12120,11 +12102,8 @@ static void time_process_incoming (VteTe
+ {
+ gdouble elapsed;
+ glong target;
+- gboolean again;
+ g_timer_reset (process_timer);
+- do {
+- again = vte_terminal_process_incoming (terminal);
+- } while (again);
++ vte_terminal_process_incoming (terminal);
+ elapsed = g_timer_elapsed (process_timer, NULL) * 1000;
+ target = VTE_MAX_PROCESS_TIME / elapsed * terminal->pvt->input_bytes;
+ terminal->pvt->max_input_bytes =
+@@ -12174,12 +12153,11 @@ process_timeout (gpointer data)
+ active = TRUE;
+ if (VTE_MAX_PROCESS_TIME && !multiple_active) {
+ time_process_incoming (terminal);
+- } else do {
+- again = vte_terminal_process_incoming(terminal);
+- } while (again);
++ } else {
++ vte_terminal_process_incoming(terminal);
++ }
+ terminal->pvt->input_bytes = 0;
+ }
+- vte_terminal_emit_pending_signals (terminal);
+ if (!active && terminal->pvt->update_regions == NULL) {
+ if (terminal->pvt->active != NULL) {
+ _vte_debug_print(VTE_DEBUG_TIMEOUT,
+@@ -12292,18 +12270,18 @@ update_repeat_timeout (gpointer data)
+ }
+ _vte_terminal_enable_input_source (terminal);
+ }
++ if (terminal->pvt->bg_update_pending) {
++ vte_terminal_background_update (terminal);
++ }
++ vte_terminal_emit_adjustment_changed (terminal);
+ if (need_processing (terminal)) {
+ if (VTE_MAX_PROCESS_TIME && !multiple_active) {
+ time_process_incoming (terminal);
+- } else do {
+- again = vte_terminal_process_incoming (terminal);
+- } while (again);
++ } else {
++ vte_terminal_process_incoming (terminal);
++ }
+ terminal->pvt->input_bytes = 0;
+ }
+- if (terminal->pvt->bg_update_pending) {
+- vte_terminal_background_update (terminal);
+- }
+- vte_terminal_emit_pending_signals (terminal);
+
+ again = update_regions (terminal);
+ if (!again) {
+@@ -12376,7 +12354,6 @@ update_timeout (gpointer data)
+ multiple_active = active_terminals->next != NULL;
+ for (l = active_terminals; l != NULL; l = next) {
+ VteTerminal *terminal = l->data;
+- gboolean again;
+
+ next = g_list_next (l);
+
+@@ -12392,18 +12369,18 @@ update_timeout (gpointer data)
+ }
+ _vte_terminal_enable_input_source (terminal);
+ }
++ if (terminal->pvt->bg_update_pending) {
++ vte_terminal_background_update (terminal);
++ }
++ vte_terminal_emit_adjustment_changed (terminal);
+ if (need_processing (terminal)) {
+ if (VTE_MAX_PROCESS_TIME && !multiple_active) {
+ time_process_incoming (terminal);
+- } else do {
+- again = vte_terminal_process_incoming (terminal);
+- } while (again);
++ } else {
++ vte_terminal_process_incoming (terminal);
++ }
+ terminal->pvt->input_bytes = 0;
+ }
+- if (terminal->pvt->bg_update_pending) {
+- vte_terminal_background_update (terminal);
+- }
+- vte_terminal_emit_pending_signals (terminal);
+
+ redraw |= update_regions (terminal);
+ }
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtedraw.c src/vtedraw.c
+--- ../vte-0.16.0/src/vtedraw.c Thu Mar 8 11:47:15 2007
++++ src/vtedraw.c Fri Mar 23 12:53:52 2007
+@@ -226,9 +226,9 @@ _vte_draw_set_background_image (struct _
+ }
+
+ gboolean
+-_vte_draw_has_background_image (struct _vte_draw *draw)
++_vte_draw_requires_clear (struct _vte_draw *draw)
+ {
+- return draw->has_background_image;
++ return draw->requires_clear;
+ }
+
+ gboolean
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtedraw.h src/vtedraw.h
+--- ../vte-0.16.0/src/vtedraw.h Thu Mar 8 11:47:15 2007
++++ src/vtedraw.h Fri Mar 23 12:53:52 2007
+@@ -100,7 +100,7 @@ struct _vte_draw {
+ GtkWidget *widget;
+ gboolean started;
+ gint width, height, ascent;
+- gboolean has_background_image;
++ gboolean requires_clear;
+ const struct _vte_draw_impl *impl;
+ gpointer impl_data;
+ };
+@@ -132,7 +132,7 @@ void _vte_draw_set_background_image(stru
+ const char *file,
+ const GdkColor *color,
+ double saturation);
+-gboolean _vte_draw_has_background_image (struct _vte_draw *draw);
++gboolean _vte_draw_requires_clear (struct _vte_draw *draw);
+ gboolean _vte_draw_requires_repaint(struct _vte_draw *draw);
+ gboolean _vte_draw_clip(struct _vte_draw *draw, GdkRegion *region);
+ void _vte_draw_clear(struct _vte_draw *draw,
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vteft2.c src/vteft2.c
+--- ../vte-0.16.0/src/vteft2.c Thu Mar 8 11:47:15 2007
++++ src/vteft2.c Fri Mar 23 12:53:52 2007
+@@ -164,7 +164,7 @@ _vte_ft2_set_background_image(struct _vt
+ g_object_unref(data->pixbuf);
+ }
+ data->pixbuf = bgpixbuf;
+- draw->has_background_image = bgpixbuf != NULL;
++ draw->requires_clear = bgpixbuf != NULL;
+ }
+
+ static void
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtegl.c src/vtegl.c
+--- ../vte-0.16.0/src/vtegl.c Thu Mar 8 11:47:15 2007
++++ src/vtegl.c Fri Mar 23 12:53:52 2007
+@@ -119,7 +119,6 @@ _vte_gl_create(struct _vte_draw *draw, G
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+- gboolean direct;
+
+ draw->impl_data = g_slice_new(struct _vte_gl_data);
+ data = (struct _vte_gl_data*) draw->impl_data;
+@@ -152,6 +151,7 @@ _vte_gl_create(struct _vte_draw *draw, G
+ data->buffer = _vte_buffer_new();
+
+ gtk_widget_set_double_buffered(widget, FALSE);
++ draw->requires_clear = TRUE;
+ }
+
+ static void
+@@ -263,7 +263,6 @@ _vte_gl_set_background_image(struct _vte
+ g_object_unref(data->bgpixbuf);
+ }
+ data->bgpixbuf = bgpixbuf;
+- draw->has_background_image = bgpixbuf != NULL;
+ }
+
+ static void
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtepango.c src/vtepango.c
+--- ../vte-0.16.0/src/vtepango.c Thu Mar 8 11:47:15 2007
++++ src/vtepango.c Fri Mar 23 12:53:52 2007
+@@ -175,13 +175,13 @@ _vte_pango_set_background_image(struct _
+ if (data->pixmap != NULL) {
+ g_object_unref(data->pixmap);
+ }
+- draw->has_background_image = FALSE;
++ draw->requires_clear = FALSE;
+ data->pixmap = NULL;
+ data->pixmapw = data->pixmaph = 0;
+ if (pixmap) {
+ data->pixmap = pixmap;
+ gdk_drawable_get_size(pixmap, &data->pixmapw, &data->pixmaph);
+- draw->has_background_image =
++ draw->requires_clear =
+ data->pixmapw > 0 && data->pixmaph > 0;
+ }
+ }
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtepangox.c src/vtepangox.c
+--- ../vte-0.16.0/src/vtepangox.c Thu Mar 8 11:47:15 2007
++++ src/vtepangox.c Fri Mar 23 12:53:52 2007
+@@ -208,13 +208,13 @@ _vte_pango_x_set_background_image(struct
+ if (data->pixmap != NULL) {
+ g_object_unref(data->pixmap);
+ }
+- draw->has_background_image = FALSE;
++ draw->requires_clear = FALSE;
+ data->pixmap = NULL;
+ data->pixmapw = data->pixmaph = 0;
+ if (pixmap != NULL) {
+ data->pixmap = pixmap;
+ gdk_drawable_get_size(pixmap, &data->pixmapw, &data->pixmaph);
+- draw->has_background_image =
++ draw->requires_clear =
+ data->pixmapw > 0 && data->pixmaph > 0;
+ }
+ }
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vteseq.c src/vteseq.c
+--- ../vte-0.16.0/src/vteseq.c Fri Mar 9 13:19:10 2007
++++ src/vteseq.c Fri Mar 23 12:53:53 2007
+@@ -341,8 +341,8 @@ vte_sequence_handler_scroll_up_or_down(V
+ _vte_terminal_adjust_adjustments(terminal);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_inserted_count++;
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_inserted_flag = TRUE;
++ terminal->pvt->text_deleted_flag = TRUE;
+
+ return FALSE;
+ }
+@@ -719,7 +719,6 @@ vte_sequence_handler_decset_internal(Vte
+ /* Reset scrollbars and repaint everything. */
+ terminal->adjustment->value =
+ terminal->pvt->screen->scroll_delta;
+- terminal->pvt->adjustment_value_changed_pending = TRUE;
+ vte_terminal_set_scrollback_lines(terminal,
+ terminal->pvt->scrollback_lines);
+ _vte_terminal_queue_contents_changed(terminal);
+@@ -862,7 +861,7 @@ vte_sequence_handler_ae(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.alternate = 0;
++ terminal->pvt->screen->defaults.attr.alternate = 0;
+ return FALSE;
+ }
+
+@@ -917,7 +916,7 @@ vte_sequence_handler_al(VteTerminal *ter
+ _vte_terminal_scroll_region(terminal, start, end - start + 1, param);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -938,7 +937,7 @@ vte_sequence_handler_as(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.alternate = 1;
++ terminal->pvt->screen->defaults.attr.alternate = 1;
+ return FALSE;
+ }
+
+@@ -1042,7 +1041,7 @@ vte_sequence_handler_cb(VteTerminal *ter
+ screen->cursor_current.row, 1);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1114,7 +1113,7 @@ vte_sequence_handler_cd(VteTerminal *ter
+ }
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1149,7 +1148,7 @@ vte_sequence_handler_ce(VteTerminal *ter
+ screen->cursor_current.row, 1);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1190,7 +1189,7 @@ vte_sequence_handler_cl(VteTerminal *ter
+ vte_sequence_handler_ho(terminal, NULL, 0, NULL);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1271,7 +1270,7 @@ vte_sequence_handler_clear_current_line(
+ }
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1314,10 +1313,10 @@ vte_sequence_handler_cs(VteTerminal *ter
+ }
+ /* Catch garbage. */
+ rows = terminal->row_count;
+- if ((start <= 0) || (start >= rows)) {
++ if (start <= 0 || start >= rows) {
+ start = 0;
+ }
+- if ((end <= 0) || (end >= rows)) {
++ if (end <= 0 || end >= rows) {
+ end = rows - 1;
+ }
+ /* Set the right values. */
+@@ -1325,12 +1324,13 @@ vte_sequence_handler_cs(VteTerminal *ter
+ screen->scrolling_region.end = end;
+ screen->scrolling_restricted = TRUE;
+ /* Special case -- run wild, run free. */
+- if ((screen->scrolling_region.start == 0) &&
+- (screen->scrolling_region.end == rows - 1)) {
++ if (screen->scrolling_region.start == 0 &&
++ screen->scrolling_region.end == rows - 1) {
+ screen->scrolling_restricted = FALSE;
+ }
+ screen->cursor_current.row = screen->insert_delta + start;
+ screen->cursor_current.col = 0;
++
+ return FALSE;
+ }
+
+@@ -1486,7 +1486,7 @@ vte_sequence_handler_dc(VteTerminal *ter
+ /* Remove the column. */
+ if (col < len) {
+ g_array_remove_index(rowdata->cells, col);
+- if (screen->fill_defaults.back != VTE_DEF_BG) {
++ if (screen->fill_defaults.attr.back != VTE_DEF_BG) {
+ vte_g_array_fill (rowdata->cells,
+ &screen->fill_defaults,
+ terminal->column_count);
+@@ -1500,7 +1500,7 @@ vte_sequence_handler_dc(VteTerminal *ter
+ }
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1558,7 +1558,7 @@ vte_sequence_handler_dl(VteTerminal *ter
+ _vte_terminal_scroll_region(terminal, start, end - start + 1, -param);
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1674,7 +1674,7 @@ vte_sequence_handler_ec(VteTerminal *ter
+ }
+
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -1749,7 +1749,7 @@ vte_sequence_handler_ic(VteTerminal *ter
+
+ save = screen->cursor_current;
+
+- _vte_terminal_insert_char(terminal, ' ', TRUE, TRUE, TRUE, 0);
++ _vte_terminal_insert_char(terminal, ' ', TRUE, TRUE);
+
+ screen->cursor_current = save;
+
+@@ -1887,7 +1887,7 @@ vte_sequence_handler_mb(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.blink = 1;
++ terminal->pvt->screen->defaults.attr.blink = 1;
+ return FALSE;
+ }
+
+@@ -1898,8 +1898,8 @@ vte_sequence_handler_md(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.bold = 1;
+- terminal->pvt->screen->defaults.half = 0;
++ terminal->pvt->screen->defaults.attr.bold = 1;
++ terminal->pvt->screen->defaults.attr.half = 0;
+ return FALSE;
+ }
+
+@@ -1921,8 +1921,8 @@ vte_sequence_handler_mh(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.half = 1;
+- terminal->pvt->screen->defaults.bold = 0;
++ terminal->pvt->screen->defaults.attr.half = 1;
++ terminal->pvt->screen->defaults.attr.bold = 0;
+ return FALSE;
+ }
+
+@@ -1933,7 +1933,7 @@ vte_sequence_handler_mk(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.invisible = 1;
++ terminal->pvt->screen->defaults.attr.invisible = 1;
+ return FALSE;
+ }
+
+@@ -1944,7 +1944,7 @@ vte_sequence_handler_mp(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.protect = 1;
++ terminal->pvt->screen->defaults.attr.protect = 1;
+ return FALSE;
+ }
+
+@@ -1955,7 +1955,7 @@ vte_sequence_handler_mr(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.reverse = 1;
++ terminal->pvt->screen->defaults.attr.reverse = 1;
+ return FALSE;
+ }
+
+@@ -2152,7 +2152,7 @@ vte_sequence_handler_se(VteTerminal *ter
+ vte_sequence_handler_ue(terminal, match, match_quark, params);
+ } else {
+ /* Otherwise just set standout mode. */
+- terminal->pvt->screen->defaults.standout = 0;
++ terminal->pvt->screen->defaults.attr.standout = 0;
+ }
+
+ g_free(blink);
+@@ -2184,10 +2184,9 @@ vte_sequence_handler_sf(VteTerminal *ter
+ start = screen->insert_delta;
+ end = start + terminal->row_count - 1;
+ }
+-
+ if (screen->cursor_current.row == end) {
+ /* Match xterm and fill to the end of row when scrolling. */
+- if (screen->fill_defaults.back != VTE_DEF_BG) {
++ if (screen->fill_defaults.attr.back != VTE_DEF_BG) {
+ VteRowData *rowdata;
+ rowdata = _vte_terminal_ensure_row (terminal);
+ vte_g_array_fill (rowdata->cells,
+@@ -2243,7 +2242,7 @@ vte_sequence_handler_sf(VteTerminal *ter
+ }
+
+ /* Match xterm and fill the new row when scrolling. */
+- if (screen->fill_defaults.back != VTE_DEF_BG) {
++ if (screen->fill_defaults.attr.back != VTE_DEF_BG) {
+ VteRowData *rowdata;
+ rowdata = _vte_terminal_ensure_row (terminal);
+ vte_g_array_fill (rowdata->cells,
+@@ -2317,7 +2316,7 @@ vte_sequence_handler_so(VteTerminal *ter
+ vte_sequence_handler_us(terminal, match, match_quark, params);
+ } else {
+ /* Otherwise just set standout mode. */
+- terminal->pvt->screen->defaults.standout = 1;
++ terminal->pvt->screen->defaults.attr.standout = 1;
+ }
+
+ g_free(blink);
+@@ -2499,7 +2498,7 @@ vte_sequence_handler_uc(VteTerminal *ter
+ cell = vte_terminal_find_charcell(terminal,
+ column,
+ screen->cursor_current.row);
+- while ((cell != NULL) && (cell->fragment) && (column > 0)) {
++ while ((cell != NULL) && (cell->attr.fragment) && (column > 0)) {
+ column--;
+ cell = vte_terminal_find_charcell(terminal,
+ column,
+@@ -2507,10 +2506,10 @@ vte_sequence_handler_uc(VteTerminal *ter
+ }
+ if (cell != NULL) {
+ /* Set this character to be underlined. */
+- cell->underline = 1;
++ cell->attr.underline = 1;
+ /* Cause the character to be repainted. */
+ _vte_invalidate_cells(terminal,
+- column, cell->columns,
++ column, cell->attr.columns,
+ screen->cursor_current.row, 1);
+ /* Move the cursor right. */
+ vte_sequence_handler_nd(terminal, match, match_quark, params);
+@@ -2529,7 +2528,7 @@ vte_sequence_handler_ue(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.underline = 0;
++ terminal->pvt->screen->defaults.attr.underline = 0;
+ return FALSE;
+ }
+
+@@ -2575,7 +2574,7 @@ vte_sequence_handler_us(VteTerminal *ter
+ GQuark match_quark,
+ GValueArray *params)
+ {
+- terminal->pvt->screen->defaults.underline = 1;
++ terminal->pvt->screen->defaults.attr.underline = 1;
+ return FALSE;
+ }
+
+@@ -2673,47 +2672,47 @@ vte_sequence_handler_character_attribute
+ _vte_terminal_set_default_attributes(terminal);
+ break;
+ case 1:
+- terminal->pvt->screen->defaults.bold = 1;
+- terminal->pvt->screen->defaults.half = 0;
++ terminal->pvt->screen->defaults.attr.bold = 1;
++ terminal->pvt->screen->defaults.attr.half = 0;
+ break;
+ case 2:
+- terminal->pvt->screen->defaults.half = 1;
+- terminal->pvt->screen->defaults.bold = 0;
++ terminal->pvt->screen->defaults.attr.half = 1;
++ terminal->pvt->screen->defaults.attr.bold = 0;
+ break;
+ case 4:
+- terminal->pvt->screen->defaults.underline = 1;
++ terminal->pvt->screen->defaults.attr.underline = 1;
+ break;
+ case 5:
+- terminal->pvt->screen->defaults.blink = 1;
++ terminal->pvt->screen->defaults.attr.blink = 1;
+ break;
+ case 7:
+- terminal->pvt->screen->defaults.reverse = 1;
++ terminal->pvt->screen->defaults.attr.reverse = 1;
+ break;
+ case 8:
+- terminal->pvt->screen->defaults.invisible = 1;
++ terminal->pvt->screen->defaults.attr.invisible = 1;
+ break;
+ case 9:
+- terminal->pvt->screen->defaults.strikethrough = 1;
++ terminal->pvt->screen->defaults.attr.strikethrough = 1;
+ break;
+ case 21: /* Error in old versions of linux console. */
+ case 22: /* ECMA 48. */
+- terminal->pvt->screen->defaults.bold = 0;
+- terminal->pvt->screen->defaults.half = 0;
++ terminal->pvt->screen->defaults.attr.bold = 0;
++ terminal->pvt->screen->defaults.attr.half = 0;
+ break;
+ case 24:
+- terminal->pvt->screen->defaults.underline = 0;
++ terminal->pvt->screen->defaults.attr.underline = 0;
+ break;
+ case 25:
+- terminal->pvt->screen->defaults.blink = 0;
++ terminal->pvt->screen->defaults.attr.blink = 0;
+ break;
+ case 27:
+- terminal->pvt->screen->defaults.reverse = 0;
++ terminal->pvt->screen->defaults.attr.reverse = 0;
+ break;
+ case 28:
+- terminal->pvt->screen->defaults.invisible = 0;
++ terminal->pvt->screen->defaults.attr.invisible = 0;
+ break;
+ case 29:
+- terminal->pvt->screen->defaults.strikethrough = 0;
++ terminal->pvt->screen->defaults.attr.strikethrough = 0;
+ break;
+ case 30:
+ case 31:
+@@ -2723,7 +2722,7 @@ vte_sequence_handler_character_attribute
+ case 35:
+ case 36:
+ case 37:
+- terminal->pvt->screen->defaults.fore = param - 30;
++ terminal->pvt->screen->defaults.attr.fore = param - 30;
+ break;
+ case 38:
+ {
+@@ -2737,17 +2736,17 @@ vte_sequence_handler_character_attribute
+ break;
+ }
+ param1 = g_value_get_long(value1);
+- terminal->pvt->screen->defaults.fore = param1;
++ terminal->pvt->screen->defaults.attr.fore = param1;
+ i += 2;
+ }
+ break;
+ }
+ case 39:
+ /* default foreground, no underscore */
+- terminal->pvt->screen->defaults.fore = VTE_DEF_FG;
++ terminal->pvt->screen->defaults.attr.fore = VTE_DEF_FG;
+ /* By ECMA 48, this underline off has no business
+ being here, but the Linux console specifies it. */
+- terminal->pvt->screen->defaults.underline = 0;
++ terminal->pvt->screen->defaults.attr.underline = 0;
+ break;
+ case 40:
+ case 41:
+@@ -2757,7 +2756,7 @@ vte_sequence_handler_character_attribute
+ case 45:
+ case 46:
+ case 47:
+- terminal->pvt->screen->defaults.back = param - 40;
++ terminal->pvt->screen->defaults.attr.back = param - 40;
+ break;
+ case 48:
+ {
+@@ -2771,14 +2770,14 @@ vte_sequence_handler_character_attribute
+ break;
+ }
+ param1 = g_value_get_long(value1);
+- terminal->pvt->screen->defaults.back = param1;
++ terminal->pvt->screen->defaults.attr.back = param1;
+ i += 2;
+ }
+ break;
+ }
+ case 49:
+ /* default background */
+- terminal->pvt->screen->defaults.back = VTE_DEF_BG;
++ terminal->pvt->screen->defaults.attr.back = VTE_DEF_BG;
+ break;
+ case 90:
+ case 91:
+@@ -2788,7 +2787,7 @@ vte_sequence_handler_character_attribute
+ case 95:
+ case 96:
+ case 97:
+- terminal->pvt->screen->defaults.fore = param - 90 + VTE_COLOR_BRIGHT_OFFSET;
++ terminal->pvt->screen->defaults.attr.fore = param - 90 + VTE_COLOR_BRIGHT_OFFSET;
+ break;
+ case 100:
+ case 101:
+@@ -2798,7 +2797,7 @@ vte_sequence_handler_character_attribute
+ case 105:
+ case 106:
+ case 107:
+- terminal->pvt->screen->defaults.back = param - 100 + VTE_COLOR_BRIGHT_OFFSET;
++ terminal->pvt->screen->defaults.attr.back = param - 100 + VTE_COLOR_BRIGHT_OFFSET;
+ break;
+ }
+ }
+@@ -2807,14 +2806,14 @@ vte_sequence_handler_character_attribute
+ _vte_terminal_set_default_attributes(terminal);
+ }
+ /* Save the new colors. */
+- terminal->pvt->screen->color_defaults.fore =
+- terminal->pvt->screen->defaults.fore;
+- terminal->pvt->screen->color_defaults.back =
+- terminal->pvt->screen->defaults.back;
+- terminal->pvt->screen->fill_defaults.fore =
+- terminal->pvt->screen->defaults.fore;
+- terminal->pvt->screen->fill_defaults.back =
+- terminal->pvt->screen->defaults.back;
++ terminal->pvt->screen->color_defaults.attr.fore =
++ terminal->pvt->screen->defaults.attr.fore;
++ terminal->pvt->screen->color_defaults.attr.back =
++ terminal->pvt->screen->defaults.attr.back;
++ terminal->pvt->screen->fill_defaults.attr.fore =
++ terminal->pvt->screen->defaults.attr.fore;
++ terminal->pvt->screen->fill_defaults.attr.back =
++ terminal->pvt->screen->defaults.attr.back;
+ return FALSE;
+ }
+
+@@ -2854,7 +2853,7 @@ vte_sequence_handler_clear_above_current
+ }
+ }
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -2894,7 +2893,7 @@ vte_sequence_handler_clear_screen(VteTer
+ /* Redraw everything. */
+ _vte_invalidate_all(terminal);
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -2911,15 +2910,6 @@ vte_sequence_handler_cursor_character_ab
+
+ screen = terminal->pvt->screen;
+
+- /* Match xterm and fill to the end of row when moving. */
+- if (screen->fill_defaults.back != VTE_DEF_BG) {
+- VteRowData *rowdata;
+- rowdata = _vte_terminal_ensure_row (terminal);
+- vte_g_array_fill (rowdata->cells,
+- &screen->fill_defaults,
+- terminal->column_count);
+- }
+-
+ val = 0;
+ if ((params != NULL) && (params->n_values > 0)) {
+ value = g_value_array_get_nth(params, 0);
+@@ -3292,7 +3282,7 @@ vte_sequence_handler_erase_in_display(Vt
+ break;
+ }
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return again;
+ }
+
+@@ -3337,7 +3327,7 @@ vte_sequence_handler_erase_in_line(VteTe
+ break;
+ }
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return again;
+ }
+
+@@ -3410,7 +3400,7 @@ vte_sequence_handler_insert_lines(VteTer
+ /* Adjust the scrollbars if necessary. */
+ _vte_terminal_adjust_adjustments(terminal);
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_inserted_count++;
++ terminal->pvt->text_inserted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -3463,7 +3453,7 @@ vte_sequence_handler_delete_lines(VteTer
+ /* Adjust the scrollbars if necessary. */
+ _vte_terminal_adjust_adjustments(terminal);
+ /* We've modified the display. Make a note of it. */
+- terminal->pvt->text_deleted_count++;
++ terminal->pvt->text_deleted_flag = TRUE;
+ return FALSE;
+ }
+
+@@ -3688,10 +3678,9 @@ vte_sequence_handler_screen_alignment_te
+ }
+ _vte_terminal_emit_text_deleted(terminal);
+ /* Fill this row. */
+- cell = screen->basic_defaults;
+ cell.c = 'E';
+- cell.columns = 1;
+- cell.empty = 0;
++ memcpy (&cell.attr, &screen->basic_defaults.attr, sizeof (cell.attr));
++ cell.attr.columns = 1;
+ vte_g_array_fill(rowdata->cells, &cell, terminal->column_count);
+ _vte_terminal_emit_text_inserted(terminal);
+ }
+diff --exclude Makefile.in --exclude *.svn* -rupN ../vte-0.16.0/src/vtexft.c src/vtexft.c
+--- ../vte-0.16.0/src/vtexft.c Thu Mar 8 11:47:15 2007
++++ src/vtexft.c Fri Mar 23 12:53:52 2007
+@@ -39,8 +39,6 @@
+ #define FONT_INDEX_FUDGE 1
+ #define CHAR_WIDTH_FUDGE 1
+
+-#define DPY_FUDGE 1
+-
+ /* libXft will accept runs up to 1024 glyphs before allocating a temporary
+ * array. However, setting this to a large value can cause dramatic slow-downs
+ * for some xservers (notably fglrx), see bug 410534.
+@@ -70,7 +68,6 @@ struct _vte_xft_data {
+ Visual *visual;
+ Colormap colormap;
+ XftDraw *draw;
+- GC gc;
+ GdkColor color;
+ guint16 opacity;
+ GdkPixmap *pixmap;
+@@ -344,13 +341,16 @@ static void
+ _vte_xft_create (struct _vte_draw *draw, GtkWidget *widget)
+ {
+ struct _vte_xft_data *data;
++
+ data = g_slice_new0 (struct _vte_xft_data);
+ draw->impl_data = data;
+- data->drawable = -1;
+- data->colormap = -1;
++
+ data->opacity = 0xffff;
++
+ data->xpixmap = -1;
+ data->pixmapw = data->pixmaph = -1;
++
++ data->drawable = -1;
+ }
+
+ static void
+@@ -381,9 +381,6 @@ _vte_xft_destroy (struct _vte_draw *draw
+ if (data->draw != NULL) {
+ XftDrawDestroy (data->draw);
+ }
+- if (data->gc != NULL) {
+- XFreeGC (data->display, data->gc);
+- }
+ g_slice_free (struct _vte_xft_data, data);
+ }
+
+@@ -402,8 +399,6 @@ _vte_xft_get_colormap (struct _vte_draw
+ static void
+ _vte_xft_start (struct _vte_draw *draw)
+ {
+- GdkVisual *gvisual;
+- GdkColormap *gcolormap;
+ GdkDrawable *drawable;
+ GPtrArray *locked_fonts;
+ guint i;
+@@ -411,33 +406,31 @@ _vte_xft_start (struct _vte_draw *draw)
+ struct _vte_xft_data *data;
+ data = (struct _vte_xft_data*) draw->impl_data;
+
++ gdk_error_trap_push ();
++
+ gdk_window_get_internal_paint_info (draw->widget->window,
+ &drawable,
+ &data->x_offs,
+ &data->y_offs);
+-
+- data->display = gdk_x11_drawable_get_xdisplay (drawable);
+- data->drawable = gdk_x11_drawable_get_xid (drawable);
+- gvisual = gdk_drawable_get_visual (drawable);
+- data->visual = gdk_x11_visual_get_xvisual (gvisual);
+- gcolormap = gdk_drawable_get_colormap (drawable);
+- data->colormap = gdk_x11_colormap_get_xcolormap (gcolormap);
+-
+- g_assert (data->display == data->font->display);
+-
+- gdk_error_trap_push ();
+-
+- if (data->draw != NULL) {
+- XftDrawDestroy (data->draw);
+- }
+- data->draw = XftDrawCreate (data->display, data->drawable,
+- data->visual, data->colormap);
+- if (data->gc != NULL) {
+- XFreeGC (data->display, data->gc);
++ if (data->drawable != gdk_x11_drawable_get_xid (drawable)) {
++ GdkVisual *gvisual;
++ GdkColormap *gcolormap;
++
++ if (data->draw != NULL) {
++ XftDrawDestroy (data->draw);
++ }
++ data->display = gdk_x11_drawable_get_xdisplay (drawable);
++ data->drawable = gdk_x11_drawable_get_xid (drawable);
++ gvisual = gdk_drawable_get_visual (drawable);
++ data->visual = gdk_x11_visual_get_xvisual (gvisual);
++ gcolormap = gdk_drawable_get_colormap (drawable);
++ data->colormap = gdk_x11_colormap_get_xcolormap (gcolormap);
++ data->draw = XftDrawCreate (data->display, data->drawable,
++ data->visual, data->colormap);
+ }
+- data->gc = XCreateGC (data->display, data->drawable, 0, NULL);
++ g_assert (data->display == data->font->display);
+
+- locked_fonts = data->locked_fonts [(++data->cur_locked_fonts)&1];
++ locked_fonts = data->locked_fonts [++data->cur_locked_fonts&1];
+ if (locked_fonts != NULL) {
+ guint cnt=0;
+ for (i = 1; i < locked_fonts->len; i++) {
+@@ -457,16 +450,6 @@ _vte_xft_end (struct _vte_draw *draw)
+ struct _vte_xft_data *data;
+
+ data = (struct _vte_xft_data*) draw->impl_data;
+- if (data->draw != NULL) {
+- XftDrawDestroy (data->draw);
+- data->draw = NULL;
+- }
+- if (data->gc != NULL) {
+- XFreeGC (data->display, data->gc);
+- data->gc = NULL;
+- }
+- data->drawable = -1;
+- data->x_offs = data->y_offs = 0;
+
+ gdk_error_trap_pop ();
+ }
+@@ -479,6 +462,9 @@ _vte_xft_set_background_color (struct _v
+ data = (struct _vte_xft_data*) draw->impl_data;
+ data->color = *color;
+ data->opacity = opacity;
++
++ draw->requires_clear = opacity != 0xffff
++ || (data->pixmapw > 0 && data->pixmaph > 0);
+ }
+
+ static void
+@@ -505,13 +491,13 @@ _vte_xft_set_background_image (struct _v
+ if (data->pixmap != NULL) {
+ g_object_unref (data->pixmap);
+ }
+- draw->has_background_image = FALSE;
++ draw->requires_clear = data->opacity != 0xffff;
+ data->pixmap = NULL;
+ if (pixmap != NULL) {
+ data->pixmap = pixmap;
+ data->xpixmap = gdk_x11_drawable_get_xid (pixmap);
+ gdk_drawable_get_size (pixmap, &data->pixmapw, &data->pixmaph);
+- draw->has_background_image =
++ draw->requires_clear |=
+ data->pixmapw > 0 && data->pixmaph > 0;
+ }
+ }
+@@ -521,25 +507,24 @@ _vte_xft_clip (struct _vte_draw *draw,
+ GdkRegion *region)
+ {
+ struct _vte_xft_data *data = draw->impl_data;
++ XRectangle stack_rect[16];
++ XRectangle *xrect;
+ GdkRectangle *rect;
+ gint i, n;
+
+ gdk_region_get_rectangles (region, &rect, &n);
+- if (n>0) {
+- XRectangle *xrect = g_new (XRectangle, n);
+- for (i = 0; i < n; i++) {
+- /* we include the offset here as XftDrawSetClipRectangles () has a
+- * byte-sex bug in its offset parameters. Bug 403159.
+- */
+- xrect[i].x = rect[i].x - data->x_offs;
+- xrect[i].y = rect[i].y - data->y_offs;
+- xrect[i].width = rect[i].width;
+- xrect[i].height = rect[i].height;
+- }
+- XftDrawSetClipRectangles (data->draw,
+- 0, 0, xrect, n);
+- g_free (xrect);
++ xrect = n > (gint) G_N_ELEMENTS (stack_rect) ?
++ g_new (XRectangle, n) :
++ stack_rect;
++ for (i = 0; i < n; i++) {
++ xrect[i].x = rect[i].x - data->x_offs;
++ xrect[i].y = rect[i].y - data->y_offs;
++ xrect[i].width = rect[i].width;
++ xrect[i].height = rect[i].height;
+ }
++ XftDrawSetClipRectangles (data->draw, 0, 0, xrect, n);
++ if (xrect != stack_rect)
++ g_free (xrect);
+ g_free (rect);
+ }
+
+@@ -551,6 +536,7 @@ _vte_xft_clear (struct _vte_draw *draw,
+ XRenderColor rcolor;
+ XftColor ftcolor;
+ gint h, w, txstop, tystop, sx, sy, tx, ty;
++ GC gc;
+
+ data = (struct _vte_xft_data*) draw->impl_data;
+
+@@ -580,6 +566,7 @@ _vte_xft_clear (struct _vte_draw *draw,
+ tystop = y + height;
+
+ /* Flood fill. */
++ gc = XCreateGC (data->display, data->drawable, 0, NULL);
+ sy = (data->scrolly + y) % data->pixmaph;
+ while (ty < tystop) {
+ h = MIN (data->pixmaph - sy, tystop - ty);
+@@ -590,7 +577,7 @@ _vte_xft_clear (struct _vte_draw *draw,
+ XCopyArea (data->display,
+ data->xpixmap,
+ data->drawable,
+- data->gc,
++ gc,
+ sx, sy,
+ w, h,
+ tx - data->x_offs, ty - data->y_offs);
+@@ -600,6 +587,7 @@ _vte_xft_clear (struct _vte_draw *draw,
+ ty += h;
+ sy = 0;
+ }
++ XFreeGC (data->display, gc);
+ }
+
+ static GPtrArray *
+@@ -791,7 +779,7 @@ _vte_xft_draw_text (struct _vte_draw *dr
+ XftColor ftcolor;
+ struct _vte_xft_data *data;
+ gsize i, j;
+- gint width, y_off, x_off;
++ gint width, y_off, x_off, char_width;
+ XftFont *font, *ft;
+ GPtrArray *locked_fonts;
+
+@@ -831,17 +819,21 @@ _vte_xft_draw_text (struct _vte_draw *dr
+ * haven't pinned down yet." */
+ x_off = -data->x_offs;
+ y_off = draw->ascent - data->y_offs;
++ char_width = draw->width;
+ do {
+ j = 0;
+ do {
++ gint next_x;
++
+ glyphs[j].glyph = XftCharIndex (data->display,
+ font, requests[i].c);
+ glyphs[j].x = requests[i].x + x_off;
++ next_x = requests[i].x + requests[i].columns*char_width;
+ width = _vte_xft_char_width (data->font,
+ font, requests[i].c, requests[i].columns);
+ if (G_UNLIKELY (width != 0)) {
+- width = requests[i].columns * draw->width - width;
+- width = CLAMP (width / 2, 0, draw->width);
++ width = requests[i].columns*char_width - width;
++ width = CLAMP (width / 2, 0, char_width);
+ glyphs[j].x += width;
+ }
+ glyphs[j].y = requests[i].y + y_off;
+@@ -857,7 +849,31 @@ _vte_xft_draw_text (struct _vte_draw *dr
+ }
+ break;
+ }
+- } while (j < MAX_RUN_LENGTH && ft == font);
++ if (j == MAX_RUN_LENGTH || ft != font) {
++ break;
++ }
++
++ /* check to see if we've skipped over any spaces...
++ * and reinsert them so as not to break the stream
++ * unnecessarily - the blank space is less overhead
++ * than starting a new sequence.
++ */
++ if (requests[i].y + y_off == glyphs[j-1].y) {
++ while (next_x < requests[i].x) {
++ glyphs[j].glyph = XftCharIndex (
++ data->display,
++ font,
++ ' ');
++ glyphs[j].x = next_x + x_off;
++ glyphs[j].y = glyphs[j-1].y;
++ if (++j == MAX_RUN_LENGTH) {
++ goto draw;
++ }
++ next_x += char_width;
++ }
++ }
++ } while (TRUE);
++draw:
+ XftDrawGlyphSpec (data->draw, &ftcolor, font, glyphs, j);
+ font = ft;
+ } while (i < n_requests);