diff --git a/src/caps.c b/src/caps.c
index edeb97d..b51882f 100644
--- a/src/caps.c
+++ b/src/caps.c
@@ -136,13 +136,13 @@ const char _vte_xterm_capability_strings[] =
         ENTRY(CSI "I", "cursor-forward-tabulation")
         ENTRY(CSI "%dI", "cursor-forward-tabulation")
         ENTRY(CSI "J", "erase-in-display")
-        ENTRY(CSI "%dJ", "erase-in-display")
+        ENTRY(CSI "%mJ", "erase-in-display")
         ENTRY(CSI "?J", "selective-erase-in-display")
-        ENTRY(CSI "?%dJ", "selective-erase-in-display")
+        ENTRY(CSI "?%mJ", "selective-erase-in-display")
         ENTRY(CSI "K", "erase-in-line")
-        ENTRY(CSI "%dK", "erase-in-line")
+        ENTRY(CSI "%mK", "erase-in-line")
         ENTRY(CSI "?K", "selective-erase-in-line")
-        ENTRY(CSI "?%dK", "selective-erase-in-line")
+        ENTRY(CSI "?%mK", "selective-erase-in-line")
         ENTRY(CSI "L", "insert-lines")
         ENTRY(CSI "%dL", "insert-lines")
         ENTRY(CSI "M", "delete-lines")
diff --git a/src/ring.c b/src/ring.c
index 2451871..f6d49fe 100644
--- a/src/ring.c
+++ b/src/ring.c
@@ -78,7 +78,7 @@ _vte_ring_init (VteRing *ring, gulong max_rows, gboolean has_streams)
 	_vte_row_data_init (&ring->cached_row);
 	ring->cached_row_num = (gulong) -1;
 
-	ring->visible_rows_hint = 0;
+	ring->visible_rows = 0;
 
 	_vte_ring_validate(ring);
 }
@@ -422,7 +422,7 @@ _vte_ring_discard_one_row (VteRing *ring)
 static void
 _vte_ring_maybe_freeze_one_row (VteRing *ring)
 {
-	if (G_LIKELY (ring->mask >= ring->visible_rows_hint && ring->writable + ring->mask + 1 == ring->end))
+	if (G_LIKELY (ring->mask >= ring->visible_rows && ring->writable + ring->mask + 1 == ring->end))
 		_vte_ring_freeze_one_row (ring);
 	else
 		_vte_ring_ensure_writable_room (ring);
@@ -441,7 +441,7 @@ _vte_ring_ensure_writable_room (VteRing *ring)
 	gulong new_mask, old_mask, i, end;
 	VteRowData *old_array, *new_array;;
 
-	if (G_LIKELY (ring->mask >= ring->visible_rows_hint && ring->writable + ring->mask + 1 > ring->end))
+	if (G_LIKELY (ring->mask >= ring->visible_rows && ring->writable + ring->mask + 1 > ring->end))
 		return;
 
 	old_mask = ring->mask;
@@ -449,7 +449,7 @@ _vte_ring_ensure_writable_room (VteRing *ring)
 
 	do {
 		ring->mask = (ring->mask << 1) + 1;
-	} while (ring->mask < ring->visible_rows_hint || ring->writable + ring->mask + 1 <= ring->end);
+	} while (ring->mask < ring->visible_rows || ring->writable + ring->mask + 1 <= ring->end);
 
 	_vte_debug_print(VTE_DEBUG_RING, "Enlarging writable array from %lu to %lu\n", old_mask, ring->mask);
 
@@ -616,17 +616,36 @@ _vte_ring_append (VteRing * ring)
 
 
 /**
- * _vte_ring_set_visible_rows_hint:
+ * _vte_ring_drop_scrollback:
  * @ring: a #VteRing
+ * @position: drop contents up to this point, which must be in the writable region.
  *
- * Set the number of visible rows, a hint for better performance.
- * It's no longer a hint only; it's required to be set correctly
- * for the alternate screen so that it never hits the streams.
+ * Drop the scrollback (offscreen contents).
+ *
+ * TODOegmont: We wouldn't need the position argument after addressing 708213#c29.
+ */
+void
+_vte_ring_drop_scrollback (VteRing * ring, gulong position)
+{
+        g_assert(ring->writable <= position);
+
+        ring->start = ring->writable = position;
+        _vte_ring_reset_streams (ring, position);
+}
+
+
+/**
+ * _vte_ring_set_visible_rows:
+ * @ring: a #VteRing
+ *
+ * Set the number of visible rows.
+ * It's required to be set correctly for the alternate screen so that it
+ * never hits the streams. It's also required for clearing the scrollback.
  */
 void
-_vte_ring_set_visible_rows_hint (VteRing *ring, gulong rows)
+_vte_ring_set_visible_rows (VteRing *ring, gulong rows)
 {
-	ring->visible_rows_hint = rows;
+	ring->visible_rows = rows;
 }
 
 
diff --git a/src/ring.h b/src/ring.h
index 1490ed5..8f51821 100644
--- a/src/ring.h
+++ b/src/ring.h
@@ -66,7 +66,7 @@ struct _VteRing {
 	gulong cached_row_num;
 
 	gboolean has_streams;
-	gulong visible_rows_hint;  /* to keep at least a screenful of lines in memory, bug 646098 comment 12 */
+	gulong visible_rows;  /* to keep at least a screenful of lines in memory, bug 646098 comment 12 */
 };
 
 #define _vte_ring_contains(__ring, __position) \
@@ -87,7 +87,8 @@ void _vte_ring_shrink (VteRing *ring, gulong max_len);
 VteRowData *_vte_ring_insert (VteRing *ring, gulong position);
 VteRowData *_vte_ring_append (VteRing *ring);
 void _vte_ring_remove (VteRing *ring, gulong position);
-void _vte_ring_set_visible_rows_hint (VteRing *ring, gulong rows);
+void _vte_ring_drop_scrollback (VteRing *ring, gulong position);
+void _vte_ring_set_visible_rows (VteRing *ring, gulong rows);
 void _vte_ring_rewrap (VteRing *ring, glong columns, VteVisualPosition **markers);
 gboolean _vte_ring_write_contents (VteRing *ring,
 				   GOutputStream *stream,
diff --git a/src/vte-private.h b/src/vte-private.h
index dded036..3a40131 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -474,6 +474,7 @@ 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_cursor_down (VteTerminal *terminal);
+void _vte_terminal_drop_scrollback (VteTerminal *terminal);
 void _vte_terminal_restore_cursor (VteTerminal *terminal, VteScreen *screen);
 void _vte_terminal_save_cursor (VteTerminal *terminal, VteScreen *screen);
 gboolean _vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
diff --git a/src/vte.c b/src/vte.c
index bcd4b21..5fd9977 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -3025,6 +3025,20 @@ _vte_terminal_cursor_down (VteTerminal *terminal)
 	}
 }
 
+/* Drop the scrollback. */
+void
+_vte_terminal_drop_scrollback (VteTerminal *terminal)
+{
+        /* Only for normal screen; alternate screen doesn't have a scrollback. */
+        _vte_ring_drop_scrollback (terminal->pvt->normal_screen.row_data,
+                                   terminal->pvt->normal_screen.insert_delta);
+
+        if (terminal->pvt->screen == &terminal->pvt->normal_screen) {
+                vte_terminal_queue_adjustment_value_changed (terminal, terminal->pvt->normal_screen.insert_delta);
+                _vte_terminal_adjust_adjustments_full (terminal);
+        }
+}
+
 /* Restore cursor on a screen. */
 void
 _vte_terminal_restore_cursor (VteTerminal *terminal, VteScreen *screen)
@@ -7855,8 +7869,8 @@ vte_terminal_set_size(VteTerminal *terminal, glong columns, glong rows)
 	if (old_rows != terminal->pvt->row_count || old_columns != terminal->pvt->column_count) {
                 terminal->pvt->scrolling_restricted = FALSE;
 
-		_vte_ring_set_visible_rows_hint(terminal->pvt->normal_screen.row_data, terminal->pvt->row_count);
-		_vte_ring_set_visible_rows_hint(terminal->pvt->alternate_screen.row_data, terminal->pvt->row_count);
+		_vte_ring_set_visible_rows(terminal->pvt->normal_screen.row_data, terminal->pvt->row_count);
+		_vte_ring_set_visible_rows(terminal->pvt->alternate_screen.row_data, terminal->pvt->row_count);
 
 		/* Resize the normal screen and (if rewrapping is enabled) rewrap it even if the alternate screen is visible: bug 415277 */
 		vte_terminal_screen_set_size(terminal, &terminal->pvt->normal_screen, old_columns, old_rows, terminal->pvt->rewrap_on_resize);
diff --git a/src/vteseq.c b/src/vteseq.c
index 4d2b461..47fbd17 100644
--- a/src/vteseq.c
+++ b/src/vteseq.c
@@ -2470,13 +2470,14 @@ vte_sequence_handler_erase_in_display (VteTerminal *terminal, GValueArray *param
 	guint i;
 	/* The default parameter is 0. */
 	param = 0;
-	/* Pull out a parameter. */
+	/* Pull out the first parameter. */
 	for (i = 0; (params != NULL) && (i < params->n_values); i++) {
 		value = g_value_array_get_nth(params, i);
 		if (!G_VALUE_HOLDS_LONG(value)) {
 			continue;
 		}
 		param = g_value_get_long(value);
+                break;
 	}
 	/* Clear the right area. */
 	switch (param) {
@@ -2495,6 +2496,10 @@ vte_sequence_handler_erase_in_display (VteTerminal *terminal, GValueArray *param
 		/* Clear the entire screen. */
 		_vte_terminal_clear_screen (terminal);
 		break;
+        case 3:
+                /* Drop the scrollback. */
+                _vte_terminal_drop_scrollback (terminal);
+                break;
 	default:
 		break;
 	}
@@ -2511,13 +2516,14 @@ vte_sequence_handler_erase_in_line (VteTerminal *terminal, GValueArray *params)
 	guint i;
 	/* The default parameter is 0. */
 	param = 0;
-	/* Pull out a parameter. */
+	/* Pull out the first parameter. */
 	for (i = 0; (params != NULL) && (i < params->n_values); i++) {
 		value = g_value_array_get_nth(params, i);
 		if (!G_VALUE_HOLDS_LONG(value)) {
 			continue;
 		}
 		param = g_value_get_long(value);
+                break;
 	}
 	/* Clear the right area. */
 	switch (param) {
