Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/vte/ChangeLog,v
retrieving revision 1.693
diff -u -p -r1.693 ChangeLog
--- ChangeLog	13 Sep 2006 21:58:26 -0000	1.693
+++ ChangeLog	18 Sep 2006 16:57:08 -0000
@@ -1,3 +1,20 @@
+2006-09-18  Ryan Lortie  <desrt@desrt.ca>
+
+	Bug 356552.
+
+	* src/matcher.h: Use const char * where appropriate.
+	* src/matcher.c: Use const char * where appropriate.  Cast g_strdup
+	to (GCacheDupFunc) to avoid a warning.
+
+	* src/vtetc.h: Use const char * where appropriate.
+	* src/vtetc.c: Use const char * where appropriate.  Cast g_strdup
+	to (GCacheDupFunc) to avoid a warning.
+
+	* src/vte-private.h: Rework how cursor blinking works.
+	* src/vte.c: Rework how cursor blinking works.  Only register the
+	cursor blink callback when cursor blink is enabled and the window
+	is focused.
+
 2006-09-13  Behdad Esfahbod  <behdad@gnome.org>
 
 	Bug 354024 – Suppress multiple warnings for missing control sequence
Index: src/matcher.c
===================================================================
RCS file: /cvs/gnome/vte/src/matcher.c,v
retrieving revision 1.10
diff -u -p -r1.10 matcher.c
--- src/matcher.c	18 Apr 2006 22:50:29 -0000	1.10
+++ src/matcher.c	18 Sep 2006 16:57:09 -0000
@@ -59,7 +59,7 @@ _vte_matcher_add(struct _vte_matcher *ma
 
 /* Loads all sequences into matcher */
 static void
-_vte_matcher_init(struct _vte_matcher *matcher, char *emulation,
+_vte_matcher_init(struct _vte_matcher *matcher, const char *emulation,
 		  struct _vte_termcap *termcap)
 {
 	const char *code, *value;
@@ -194,7 +194,7 @@ _vte_matcher_destroy(gpointer value)
 
 /* Create and init matcher. */
 struct _vte_matcher *
-_vte_matcher_new(char *emulation, struct _vte_termcap *termcap)
+_vte_matcher_new(const char *emulation, struct _vte_termcap *termcap)
 {
 	struct _vte_matcher *ret = NULL;
 	g_static_mutex_lock(&_vte_matcher_mutex);
@@ -205,11 +205,12 @@ _vte_matcher_new(char *emulation, struct
 
 	if (_vte_matcher_cache == NULL) {
 		_vte_matcher_cache = g_cache_new(_vte_matcher_create,
-				_vte_matcher_destroy, g_strdup, g_free,
+				_vte_matcher_destroy,
+			       	(GCacheDupFunc) g_strdup, g_free,
 				g_str_hash, g_direct_hash, g_str_equal);
 	}
 
-	ret = g_cache_insert(_vte_matcher_cache, emulation);
+	ret = g_cache_insert(_vte_matcher_cache, (gpointer) emulation);
 
 	if (!ret->initialized) {
 		_vte_matcher_init(ret, emulation, termcap);
Index: src/matcher.h
===================================================================
RCS file: /cvs/gnome/vte/src/matcher.h,v
retrieving revision 1.7
diff -u -p -r1.7 matcher.h
--- src/matcher.h	18 Apr 2006 22:50:29 -0000	1.7
+++ src/matcher.h	18 Sep 2006 16:57:09 -0000
@@ -30,7 +30,7 @@ G_BEGIN_DECLS
 struct _vte_matcher;
 
 /* Create and init matcher. */
-struct _vte_matcher *_vte_matcher_new(char *emulation,
+struct _vte_matcher *_vte_matcher_new(const char *emulation,
 				      struct _vte_termcap *termcap);
 
 /* Free a matcher. */
Index: src/vte-private.h
===================================================================
RCS file: /cvs/gnome/vte/src/vte-private.h,v
retrieving revision 1.13
diff -u -p -r1.13 vte-private.h
--- src/vte-private.h	24 Jul 2006 21:59:23 -0000	1.13
+++ src/vte-private.h	18 Sep 2006 16:57:09 -0000
@@ -275,14 +275,13 @@ struct _VteTerminalPrivate {
 	long scrollback_lines;
 
 	/* Cursor blinking. */
-	int cursor_force_fg;
+	gboolean cursor_blink_state;
 	gboolean cursor_blinks;
 	gint cursor_blink_tag;
 	gint cursor_blink_timeout;
 	gboolean cursor_visible;
 
 	/* Input device options. */
-	time_t last_keypress_time;
 	gboolean mouse_send_xy_on_click;
 	gboolean mouse_send_xy_on_button;
 	gboolean mouse_hilite_tracking;
Index: src/vte.c
===================================================================
RCS file: /cvs/gnome/vte/src/vte.c,v
retrieving revision 1.486
diff -u -p -r1.486 vte.c
--- src/vte.c	13 Sep 2006 21:58:26 -0000	1.486
+++ src/vte.c	18 Sep 2006 16:57:17 -0000
@@ -509,9 +509,9 @@ vte_invalidate_cursor_periodic(gpointer 
 	}
 
 	terminal = VTE_TERMINAL(widget);
-	if (terminal->pvt->cursor_blinks) {
-		_vte_invalidate_cursor_once(terminal, TRUE);
-	}
+
+	terminal->pvt->cursor_blink_state = !terminal->pvt->cursor_blink_state;
+	_vte_invalidate_cursor_once(terminal, TRUE);
 
 	settings = gtk_widget_get_settings(GTK_WIDGET(data));
 	if (G_IS_OBJECT(settings)) {
@@ -546,8 +546,9 @@ vte_terminal_emit_selection_changed(VteT
 
 /* Emit a "commit" signal. */
 static void
-vte_terminal_emit_commit(VteTerminal *terminal, gchar *text, guint length)
+vte_terminal_emit_commit(VteTerminal *terminal, const gchar *text, guint length)
 {
+	const char *result = NULL;
 	char *wrapped = NULL;
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_SIGNALS)) {
@@ -556,15 +557,16 @@ vte_terminal_emit_commit(VteTerminal *te
 #endif
 	if (length == -1) {
 		length = strlen(text);
-		wrapped = text;
+		result = text;
 	} else {
-		wrapped = g_malloc0(length + 1);
+		result = wrapped = g_malloc0(length + 1);
 		memcpy(wrapped, text, length);
 	}
-	g_signal_emit_by_name(terminal, "commit", wrapped, length);
-	if (wrapped != text) {
+
+	g_signal_emit_by_name(terminal, "commit", result, length);
+
+	if (wrapped)
 		g_free(wrapped);
-	}
 }
 
 /* Emit an "emulation-changed" signal. */
@@ -3755,6 +3757,34 @@ vte_terminal_style_changed(GtkWidget *wi
 	}
 }
 
+static void
+add_cursor_timeout (VteTerminal *terminal)
+{
+	GtkSettings *settings;
+	gint blink_cycle = 1000;
+
+	/* Setup cursor blink */
+	settings = gtk_widget_get_settings(GTK_WIDGET(terminal));
+	if (G_IS_OBJECT(settings)) {
+		g_object_get(G_OBJECT(settings), "gtk-cursor-blink-time",
+			     &blink_cycle, NULL);
+	}
+
+	terminal->pvt->cursor_blink_tag = g_timeout_add_full(G_PRIORITY_LOW,
+							     blink_cycle / 2,
+							     vte_invalidate_cursor_periodic,
+							     terminal,
+							     NULL);
+}
+
+static void
+remove_cursor_timeout (VteTerminal *terminal)
+{
+	g_source_remove (terminal->pvt->cursor_blink_tag);
+	terminal->pvt->cursor_blink_tag = VTE_INVALID_SOURCE;
+}
+
+
 /* Read and handle a keypress event. */
 static gint
 vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
@@ -3815,10 +3845,11 @@ vte_terminal_key_press(GtkWidget *widget
 			}
 		}
 
-		/* Log the time of the last keypress. */
-		if (gettimeofday(&tv, &tz) == 0) {
-			terminal->pvt->last_keypress_time =
-				(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+		if (terminal->pvt->cursor_blink_tag != VTE_INVALID_SOURCE)
+		{
+			remove_cursor_timeout (terminal);
+			terminal->pvt->cursor_blink_state = TRUE;
+			add_cursor_timeout (terminal);
 		}
 
 		/* Determine if this is just a modifier key. */
@@ -6057,16 +6088,20 @@ vte_terminal_focus_in(GtkWidget *widget,
 	if (gdk_event_get_state((GdkEvent*)event, &modifiers)) {
 		terminal->pvt->modifiers = modifiers;
 	}
+
 	/* We only have an IM context when we're realized, and there's not much
 	 * point to painting the cursor if we don't have a window. */
 	if (GTK_WIDGET_REALIZED(widget)) {
+		terminal->pvt->cursor_blink_state = TRUE;
+
+		if (terminal->pvt->cursor_blinks &&
+		    terminal->pvt->cursor_blink_tag == VTE_INVALID_SOURCE)
+			add_cursor_timeout (terminal);
+
 		gtk_im_context_focus_in(terminal->pvt->im_context);
-		/* Force the cursor to be the foreground color twice, in case
-		   we're in blinking mode and the next scheduled redraw occurs
-		   just after the one we're about to perform. */
-		terminal->pvt->cursor_force_fg = 2;
 		_vte_invalidate_cursor_once(terminal, FALSE);
 	}
+
 	return FALSE;
 }
 
@@ -6094,6 +6129,10 @@ vte_terminal_focus_out(GtkWidget *widget
 		gtk_im_context_focus_out(terminal->pvt->im_context);
 		_vte_invalidate_cursor_once(terminal, FALSE);
 	}
+
+	if (terminal->pvt->cursor_blink_tag != VTE_INVALID_SOURCE)
+		remove_cursor_timeout (terminal);
+
 	return FALSE;
 }
 
@@ -6770,6 +6809,7 @@ vte_terminal_init(VteTerminal *terminal,
 					      (gpointer)terminal);
 	pvt->incoming = _vte_buffer_new();
 	pvt->pending = g_array_new(TRUE, TRUE, sizeof(gunichar));
+	pvt->cursor_blink_tag = VTE_INVALID_SOURCE;
 	pvt->coalesce_timeout = VTE_INVALID_SOURCE;
 	pvt->display_timeout = VTE_INVALID_SOURCE;
 	pvt->update_timeout = VTE_INVALID_SOURCE;
@@ -6817,13 +6857,6 @@ vte_terminal_init(VteTerminal *terminal,
 	pvt->cursor_visible = TRUE;
 	pvt->cursor_blink_timeout = 1000;
 
-	/* Input options. */
-	if (gettimeofday(&tv, &tz) == 0) {
-		pvt->last_keypress_time = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-	} else {
-		pvt->last_keypress_time = 0;
-	}
-
 	/* Matching data. */
 	pvt->match_regexes = g_array_new(FALSE, TRUE,
 					 sizeof(struct vte_match_regex));
@@ -7108,11 +7141,11 @@ vte_terminal_unrealize(GtkWidget *widget
 	}
 
 	/* Remove the blink timeout function. */
-	if (terminal->pvt->cursor_blink_tag != 0) {
+	if (terminal->pvt->cursor_blink_tag != VTE_INVALID_SOURCE) {
 		g_source_remove(terminal->pvt->cursor_blink_tag);
-		terminal->pvt->cursor_blink_tag = 0;
+		terminal->pvt->cursor_blink_tag = VTE_INVALID_SOURCE;
 	}
-	terminal->pvt->cursor_force_fg = 0;
+	terminal->pvt->cursor_blink_state = FALSE;
 
 	/* Cancel any pending background updates. */
 	if (terminal->pvt->bg_update_tag != VTE_INVALID_SOURCE) {
@@ -7378,9 +7411,7 @@ vte_terminal_realize(GtkWidget *widget)
 	GdkWindowAttr attributes;
 	GdkPixmap *bitmap;
 	GdkColor black = {0,0,0}, color;
-	GtkSettings *settings;
 	int attributes_mask = 0, i;
-	gint blink_cycle = 1000;
 	VteBg *bg;
 
 #ifdef VTE_DEBUG
@@ -7474,18 +7505,6 @@ vte_terminal_realize(GtkWidget *widget)
 		vte_terminal_set_color_internal(terminal, i, &color);
 	}
 
-	/* Setup cursor blink */
-	settings = gtk_widget_get_settings(GTK_WIDGET(terminal));
-	if (G_IS_OBJECT(settings)) {
-		g_object_get(G_OBJECT(settings), "gtk-cursor-blink-time",
-			     &blink_cycle, NULL);
-	}
-	terminal->pvt->cursor_blink_tag = g_timeout_add_full(G_PRIORITY_LOW,
-							     blink_cycle / 2,
-							     vte_invalidate_cursor_periodic,
-							     terminal,
-							     NULL);
-
 	/* Set up input method support.  FIXME: do we need to handle the
 	 * "retrieve-surrounding" and "delete-surrounding" events? */
 	if (terminal->pvt->im_context != NULL) {
@@ -8839,46 +8858,6 @@ vte_terminal_draw_cells_with_attributes(
 	g_free(cells);
 }
 
-static gboolean
-vte_terminal_get_blink_state(VteTerminal *terminal)
-{
-	struct timezone tz;
-	struct timeval tv;
-	gint blink_cycle = 1000;
-	GtkSettings *settings;
-	time_t daytime;
-	gboolean blink;
-	GtkWidget *widget;
-
-	/* Determine if blinking text should be shown. */
-	if (terminal->pvt->cursor_blinks) {
-		if (gettimeofday(&tv, &tz) == 0) {
-			widget = GTK_WIDGET(terminal);
-			settings = gtk_widget_get_settings(widget);
-			if (G_IS_OBJECT(settings)) {
-				g_object_get(G_OBJECT(settings),
-					     "gtk-cursor-blink-time",
-					     &blink_cycle, NULL);
-			}
-			daytime = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-			if (daytime >= terminal->pvt->last_keypress_time) {
-				daytime -= terminal->pvt->last_keypress_time;
-			}
-			daytime = daytime % blink_cycle;
-			blink = daytime < (blink_cycle / 2);
-		} else {
-			blink = TRUE;
-		}
-	} else {
-		blink = TRUE;
-	}
-	if (terminal->pvt->cursor_force_fg > 0) {
-		terminal->pvt->cursor_force_fg--;
-		blink = TRUE;
-	}
-	return blink;
-}
-
 /* Paint the contents of a given row at the given location.  Take advantage
  * of multiple-draw APIs by finding runs of characters with identical
  * attributes and bundling them together. */
@@ -9190,7 +9169,7 @@ vte_terminal_paint(GtkWidget *widget, Gd
 		if (GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(terminal))) {
 			selected = vte_cell_is_selected(terminal, col, drow,
 							NULL);
-			blink = vte_terminal_get_blink_state(terminal) ^
+			blink = terminal->pvt->cursor_blink_state ^
 				terminal->pvt->screen->reverse_mode;
 			vte_terminal_determine_colors(terminal, cell,
 						      blink,
@@ -10514,7 +10493,20 @@ void
 vte_terminal_set_cursor_blinks(VteTerminal *terminal, gboolean blink)
 {
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+	if (terminal->pvt->cursor_blinks == blink)
+		return;
+
 	terminal->pvt->cursor_blinks = blink;
+
+	if (!GTK_WIDGET_REALIZED (terminal) ||
+	    !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (terminal)))
+		return;
+
+	if (blink)
+		add_cursor_timeout (terminal);
+	else
+		remove_cursor_timeout (terminal);
 }
 
 /**
Index: src/vtetc.c
===================================================================
RCS file: /cvs/gnome/vte/src/vtetc.c,v
retrieving revision 1.10
diff -u -p -r1.10 vtetc.c
--- src/vtetc.c	31 Aug 2006 20:03:12 -0000	1.10
+++ src/vtetc.c	18 Sep 2006 16:57:17 -0000
@@ -431,17 +431,18 @@ _vte_termcap_destroy(gpointer key)
 }
 
 TERMCAP_MAYBE_STATIC struct _vte_termcap *
-_vte_termcap_new(char *filename)
+_vte_termcap_new(const char *filename)
 {
 	struct _vte_termcap *ret = NULL;
 	g_static_mutex_lock(&_vte_termcap_mutex);
 
 	if (_vte_termcap_cache == NULL) {
 		_vte_termcap_cache = g_cache_new(_vte_termcap_create,
-				_vte_termcap_destroy, g_strdup, g_free,
+				_vte_termcap_destroy,
+                                (GCacheDupFunc) g_strdup, g_free,
 				g_str_hash, g_direct_hash, g_str_equal);
 	}
-	ret = g_cache_insert(_vte_termcap_cache, filename);
+	ret = g_cache_insert(_vte_termcap_cache, (gpointer) filename);
 
 	g_static_mutex_unlock(&_vte_termcap_mutex);
 	return ret;
Index: src/vtetc.h
===================================================================
RCS file: /cvs/gnome/vte/src/vtetc.h,v
retrieving revision 1.3
diff -u -p -r1.3 vtetc.h
--- src/vtetc.h	18 Apr 2006 22:50:30 -0000	1.3
+++ src/vtetc.h	18 Sep 2006 16:57:17 -0000
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
 struct _vte_termcap;
 
 /* Create a new termcap structure. */
-struct _vte_termcap *_vte_termcap_new(char *filename);
+struct _vte_termcap *_vte_termcap_new(const char *filename);
 
 /* Free a termcap structure. */
 void _vte_termcap_free(struct _vte_termcap *termcap);
