? vte-0.11.14
? vte-0.11.14.tar.gz
? vte-0.11.15.tar.gz
? doc/reference/vte-overrides.txt
? doc/reference/tmpl/internals.sgml
? gnome-pty-helper/.in
? src/vteapp
Index: src/vte.c
===================================================================
RCS file: /cvs/gnome/vte/src/vte.c,v
retrieving revision 1.425
diff -u -p -r1.425 vte.c
--- src/vte.c	10 Aug 2005 13:29:12 -0000	1.425
+++ src/vte.c	29 Aug 2005 11:19:41 -0000
@@ -357,7 +357,9 @@ struct _VteTerminalPrivate {
 
 	/* Adjustment updates pending. */
 	gboolean adjustment_changed_tag;
-
+	glong adjustment_freeze_value;
+	glong adjustment_freeze_scroll_delta;
+ 
 	/* Background images/"transparency". */
 	gboolean bg_update_pending;
 	gboolean bg_transparent;
@@ -490,6 +492,7 @@ static char *vte_terminal_get_text_maybe
 						 gboolean include_trailing_spaces);
 static void _vte_terminal_disconnect_pty_read(VteTerminal *terminal);
 static void _vte_terminal_disconnect_pty_write(VteTerminal *terminal);
+static void vte_terminal_handle_scroll(VteTerminal *terminal);
 static void vte_terminal_stop_processing (VteTerminal *terminal);
 static void vte_terminal_start_processing (VteTerminal *terminal);
 static gboolean vte_terminal_is_processing (VteTerminal *terminal);
@@ -658,9 +661,7 @@ vte_invalidate_cells(VteTerminal *termin
 static void
 vte_invalidate_all(VteTerminal *terminal)
 {
-	GdkRectangle rect;
 	GtkWidget *widget;
-	int width, height;
 
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	if (!GTK_IS_WIDGET(terminal)) {
@@ -675,13 +676,7 @@ vte_invalidate_all(VteTerminal *terminal
 	}
 
 	/* Expose the entire widget area. */
-	width = height = 0;
-	gdk_drawable_get_size(widget->window, &width, &height);
-	rect.x = 0;
-	rect.y = 0;
-	rect.width = width;
-	rect.height = height;
-	gdk_window_invalidate_rect(widget->window, &rect, FALSE);
+	gdk_window_invalidate_rect(widget->window, NULL, FALSE);
 }
 
 /* Scroll a rectangular region up or down by a fixed number of lines,
@@ -1808,6 +1803,54 @@ vte_terminal_queue_adjustment_changed(Vt
 	}
 }
 
+/* simple freeze/thaw implementation to stop the scrollbar from scrolling immediately
+ * note that this functions do not work cumulative */
+#define VTE_TERMINAL_ADJUSTMENT_IS_FROZEN(terminal) ((terminal)->pvt->adjustment_freeze_value >= 0)
+static void
+vte_terminal_freeze_adjustment (VteTerminal *terminal)
+{
+	g_return_if_fail (!VTE_TERMINAL_ADJUSTMENT_IS_FROZEN (terminal));
+	terminal->pvt->adjustment_freeze_value = terminal->pvt->screen->scroll_delta;
+	terminal->pvt->adjustment_freeze_scroll_delta = terminal->pvt->screen->scroll_delta;
+}
+
+static void
+vte_terminal_thaw_adjustment (VteTerminal *terminal)
+{
+	g_return_if_fail (VTE_TERMINAL_ADJUSTMENT_IS_FROZEN (terminal));
+	if (floor (terminal->adjustment->value) != terminal->pvt->adjustment_freeze_value) {
+		terminal->pvt->screen->scroll_delta = terminal->pvt->adjustment_freeze_scroll_delta;
+		terminal->pvt->adjustment_freeze_value = -1;
+		gtk_adjustment_value_changed (terminal->adjustment);
+	} else {
+		terminal->pvt->adjustment_freeze_value = -1;
+		if (terminal->pvt->screen->scroll_delta != terminal->pvt->adjustment_freeze_scroll_delta) {
+			terminal->pvt->screen->scroll_delta = terminal->pvt->adjustment_freeze_scroll_delta;
+			vte_terminal_handle_scroll (terminal);
+		}
+	}
+}
+
+static void
+vte_terminal_set_adjustment_value (VteTerminal *terminal, glong value)
+{
+	GtkAdjustment *adjustment = terminal->adjustment;
+	value = CLAMP (value, adjustment->lower, adjustment->upper);
+
+	if (value != floor (adjustment->value)) {
+		adjustment->value = value;
+		if (!VTE_TERMINAL_ADJUSTMENT_IS_FROZEN (terminal)) {
+			gtk_adjustment_value_changed (adjustment);
+		} else {
+			terminal->pvt->screen->scroll_delta = value + 
+				_vte_ring_delta (terminal->pvt->screen->row_data);
+		}
+	} else {
+		terminal->pvt->screen->scroll_delta = value + 
+				_vte_ring_delta (terminal->pvt->screen->row_data);
+	}
+}
+
 /* Update the adjustment field of the widget.  This function should be called
  * whenever we add rows to or remove rows from the history or switch screens. */
 static void
@@ -1834,19 +1877,6 @@ vte_terminal_adjust_adjustments(VteTermi
 			delta, screen->scroll_delta);
 	}
 #endif
-	if (terminal->adjustment->lower != delta) {
-#ifdef VTE_DEBUG
-		if (_vte_debug_on(VTE_DEBUG_IO)) {
-			fprintf(stderr, "Changing lower bound from %lf to %ld\n",
-				terminal->adjustment->lower,
-				delta);
-
-		}
-#endif 
-
-		terminal->adjustment->lower = delta;
-		changed = TRUE;
-	}
 
 	/* Snap the insert delta and the cursor position to be in the visible
 	 * area.  Leave the scrolling delta alone because it will be updated
@@ -1857,8 +1887,10 @@ vte_terminal_adjust_adjustments(VteTermi
 
 	/* The upper value is the number of rows which might be visible.  (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 = MAX(0,
+		   MAX(_vte_ring_next(terminal->pvt->screen->row_data),
+		   terminal->pvt->screen->cursor_current.row + 1)
+		   - delta);
 	if (terminal->adjustment->upper != rows) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_IO)) {
@@ -1922,19 +1954,12 @@ vte_terminal_adjust_adjustments(VteTermi
 	}
 
 	/* Set the scrollbar adjustment to where the screen wants it to be. */
-	if (floor(terminal->adjustment->value) !=
-	    screen->scroll_delta) {
-#ifdef VTE_DEBUG
-	      if (_vte_debug_on(VTE_DEBUG_IO)) {
-		    fprintf(stderr, "Changing adjustment scroll position: "
-			    "%ld\n", screen->scroll_delta);
-	      }
-#endif 
-		/* This emits a "value-changed" signal, so no need to screw
-		 * with anything else for just this. */
-		gtk_adjustment_set_value(terminal->adjustment,
-				       screen->scroll_delta);
-
+	if (terminal->pvt->screen->scroll_delta < delta)
+		vte_terminal_set_adjustment_value(terminal, 0);
+	if (terminal->pvt->screen->scroll_delta - delta > MAX (0, terminal->adjustment->upper - terminal->row_count))
+		vte_terminal_set_adjustment_value(terminal, terminal->adjustment->upper - terminal->row_count);
+	if (floor(gtk_adjustment_get_value(terminal->adjustment)) + delta != terminal->pvt->screen->scroll_delta)
+		vte_terminal_set_adjustment_value(terminal, terminal->pvt->screen->scroll_delta - delta);
 #ifdef VTE_DEBUG
 	      if (_vte_debug_on(VTE_DEBUG_IO)) {
 		    fprintf(stderr, "Changed adjustment scroll position: "
@@ -1942,15 +1967,15 @@ vte_terminal_adjust_adjustments(VteTermi
 	      }
 #endif 
 
-	}
-
 	/* If anything changed, signal that there was a change. */
 	if (changed == TRUE) {
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_IO)) {
-			fprintf(stderr, "Changed adjustment values "
-				"(delta = %ld, scroll = %ld).\n",
-				delta, terminal->pvt->screen->scroll_delta);
+			fprintf (stderr, "adjustment: [%ld, %ld, %ld] scroll_delta: %ld ring: [%ld, %ld]\n", 
+				(long) terminal->adjustment->lower, (long) terminal->adjustment->value, 
+				(long) terminal->adjustment->upper, terminal->pvt->screen->scroll_delta, 
+				_vte_ring_delta(terminal->pvt->screen->row_data),
+				_vte_ring_next(terminal->pvt->screen->row_data));
 		}
 #endif
 		if (immediate) {
@@ -1980,7 +2005,7 @@ vte_terminal_scroll_pages(VteTerminal *t
 			    terminal->adjustment->lower,
 			    terminal->adjustment->upper - terminal->row_count);
 	/* Tell the scrollbar to adjust itself. */
-	gtk_adjustment_set_value(terminal->adjustment, destination);
+	vte_terminal_set_adjustment_value(terminal, destination);
 	/* Clear dingus match set. */
 	vte_terminal_match_contents_clear(terminal);
 	/* Notify viewers that the contents have changed. */
@@ -1991,12 +2016,9 @@ vte_terminal_scroll_pages(VteTerminal *t
 static void
 vte_terminal_maybe_scroll_to_top(VteTerminal *terminal)
 {
-	long delta;
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
-	if (floor(gtk_adjustment_get_value(terminal->adjustment)) !=
-	    _vte_ring_delta(terminal->pvt->screen->row_data)) {
-		delta = _vte_ring_delta(terminal->pvt->screen->row_data);
-		gtk_adjustment_set_value(terminal->adjustment, delta);
+	if (floor(gtk_adjustment_get_value(terminal->adjustment)) != 0) {
+		vte_terminal_set_adjustment_value(terminal, 0);
 	}
 }
 
@@ -2005,11 +2027,10 @@ vte_terminal_maybe_scroll_to_bottom(VteT
 {
 	glong delta;
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
-	if ((terminal->pvt->screen->scroll_delta !=
-	    terminal->pvt->screen->insert_delta)) {
-		delta = terminal->pvt->screen->insert_delta;
-		gtk_adjustment_set_value(terminal->adjustment, delta);
 
+	delta = terminal->pvt->screen->insert_delta - _vte_ring_delta (terminal->pvt->screen->row_data);
+	if (floor(gtk_adjustment_get_value(terminal->adjustment)) != delta) {
+		vte_terminal_set_adjustment_value(terminal, delta);
 #ifdef VTE_DEBUG
 		if (_vte_debug_on(VTE_DEBUG_IO)) {
 		      fprintf (stderr, "Snapping to bottom of screen\n");
@@ -4806,6 +4827,7 @@ vte_sequence_handler_decset_internal(Vte
 		 NULL, NULL},
 	};
 
+	vte_terminal_thaw_adjustment (terminal);
 	/* Handle the setting. */
 	for (i = 0; i < G_N_ELEMENTS(settings); i++)
 	if (settings[i].setting == setting) {
@@ -5051,6 +5073,7 @@ vte_sequence_handler_decset_internal(Vte
 			  setting);
 	}
 #endif
+	vte_terminal_freeze_adjustment(terminal);
 	return again;
 }
 
@@ -7535,6 +7558,7 @@ vte_terminal_process_incoming(VteTermina
 	g_return_val_if_fail(GTK_IS_WIDGET(terminal), FALSE);
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
 	widget = GTK_WIDGET(terminal);
+	vte_terminal_freeze_adjustment(terminal);
 
 	bottom = (terminal->pvt->screen->insert_delta ==
 		  terminal->pvt->screen->scroll_delta);
@@ -7831,6 +7855,7 @@ vte_terminal_process_incoming(VteTermina
 		gtk_im_context_set_cursor_location(terminal->pvt->im_context,
 						   &rect);
 	}
+	vte_terminal_thaw_adjustment(terminal);
 
 #ifdef VTE_DEBUG
 	if (_vte_debug_on(VTE_DEBUG_IO)) {
@@ -10128,7 +10153,7 @@ vte_terminal_autoscroll(gpointer data)
 				    terminal->adjustment->lower,
 				    terminal->adjustment->upper -
 				    terminal->row_count);
-			gtk_adjustment_set_value(terminal->adjustment, adj);
+			vte_terminal_set_adjustment_value(terminal, adj);
 			extend = TRUE;
 		}
 #ifdef VTE_DEBUG
@@ -10145,7 +10170,7 @@ vte_terminal_autoscroll(gpointer data)
 				    terminal->adjustment->lower,
 				    terminal->adjustment->upper -
 				    terminal->row_count);
-			gtk_adjustment_set_value(terminal->adjustment, adj);
+			vte_terminal_set_adjustment_value(terminal, adj);
 			extend = TRUE;
 		}
 #ifdef VTE_DEBUG
@@ -10905,7 +10930,7 @@ vte_terminal_set_size(VteTerminal *termi
 static void
 vte_terminal_handle_scroll(VteTerminal *terminal)
 {
-	long dy, adj;
+	long dy, adj, delta;
 	GtkWidget *widget;
 	VteScreen *screen;
 
@@ -10917,33 +10942,35 @@ vte_terminal_handle_scroll(VteTerminal *
 		return;
 	}
 
-	/* This may generate multiple redraws, so freeze it while we do them. */
-	gdk_window_freeze_updates(widget->window);
 
 	/* Read the new adjustment value and save the difference. */
-	adj = floor(gtk_adjustment_get_value(terminal->adjustment));
+	delta = _vte_ring_delta (terminal->pvt->screen->row_data);
+	adj = floor(gtk_adjustment_get_value(terminal->adjustment) + delta);
 	dy = adj - screen->scroll_delta;
-	screen->scroll_delta = adj;
+	screen->scroll_delta = CLAMP (adj, delta, delta + terminal->adjustment->upper -1);
 	if (dy != 0) {
 #ifdef VTE_DEBUG
 	      if (_vte_debug_on(VTE_DEBUG_IO)) {
 		    fprintf(stderr, "Scrolling by %ld\n", dy);
 	      }
 #endif
+		/* This may generate multiple redraws, so freeze it while we do them. */
+		gdk_window_freeze_updates(widget->window);
+
 		vte_terminal_match_contents_clear(terminal);
 		vte_terminal_scroll_region(terminal, screen->scroll_delta,
 					   terminal->row_count, -dy);
 		vte_terminal_emit_text_scrolled(terminal, dy);
 		vte_terminal_emit_contents_changed(terminal);
+
+		/* Let the refreshing begin. */
+		gdk_window_thaw_updates(widget->window);
 	}
 #ifdef VTE_DEBUG
 	else if (_vte_debug_on(VTE_DEBUG_IO)) {
 	      fprintf(stderr, "Not scrolling\n");
 	}
 #endif
-
-	/* Let the refreshing begin. */
-	gdk_window_thaw_updates(widget->window);
 }
 
 /* Set the adjustment objects used by the terminal widget. */
@@ -11310,6 +11337,7 @@ vte_terminal_init(VteTerminal *terminal,
 	pvt->dec_saved = g_hash_table_new(g_direct_hash, g_direct_equal);
 	pvt->default_column_count = 80;
 	pvt->default_row_count = 24;
+	pvt->adjustment_freeze_value = -1;
 
 	/* Setting the terminal type and size requires the PTY master to
 	 * be set up properly first. */
@@ -14169,7 +14197,7 @@ vte_terminal_scroll(GtkWidget *widget, G
 	}
 
 	new_value = CLAMP(new_value, adj->lower, adj->upper - adj->page_size);
-	gtk_adjustment_set_value(adj, new_value);
+	vte_terminal_set_adjustment_value(terminal, new_value);
 
 	return TRUE;
 }
