diff options
author | Joe Marcus Clarke <marcus@FreeBSD.org> | 2007-03-23 17:07:05 +0000 |
---|---|---|
committer | Joe Marcus Clarke <marcus@FreeBSD.org> | 2007-03-23 17:07:05 +0000 |
commit | 4e6fc3a9fb8514caf52452b3801d57bba83b0dc5 (patch) | |
tree | b5ddd375aa623d91dfcc9ab34dc328e817a98d3f /x11-toolkits/vte | |
parent | dd93c747f868392b43a1396d2b6a8772f7a764dc (diff) | |
download | ports-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/Makefile | 2 | ||||
-rw-r--r-- | x11-toolkits/vte/files/patch-vte_svn | 2786 |
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); |