diff --git a/src/vte.cc b/src/vte.cc
index 8df3902..f0ccb5c 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -4502,8 +4502,33 @@ vte_terminal_send(VteTerminal *terminal, const char *encoding,
 		/* If there's a place for it to go, add the data to the
 		 * outgoing buffer. */
 		if ((cooked_length > 0) && (terminal->pvt->pty != NULL)) {
+			struct termios t;
+			tcgetattr(vte_pty_get_fd(terminal->pvt->pty), &t);
+
 			_vte_byte_array_append(terminal->pvt->outgoing,
 					   cooked, cooked_length);
+
+			for (i = 0; i < cooked_length; i++) {
+				if (terminal->pvt->scroll_locked) {
+					if (!(t.c_iflag & IXON) ||
+					    ((t.c_iflag & IXON) &&
+					            ((t.c_iflag & IXANY) ||
+					             cooked[i] == t.c_cc[VSTART] ||
+					             cooked[i] == t.c_cc[VINTR] ||
+					             cooked[i] == t.c_cc[VQUIT]))) {
+						_vte_debug_print(VTE_DEBUG_KEYBOARD, "Scroll lock released\n");
+						terminal->pvt->scroll_locked = FALSE;
+						_vte_invalidate_cursor_once(terminal, FALSE);
+					}
+				} else {
+					if ((t.c_iflag & IXON) && cooked[i] == t.c_cc[VSTOP]) {
+						_vte_debug_print(VTE_DEBUG_KEYBOARD, "Scroll locked\n");
+						terminal->pvt->scroll_locked = TRUE;
+						_vte_invalidate_cursor_once(terminal, FALSE);
+					}
+				}
+			}
+
 			_VTE_DEBUG_IF(VTE_DEBUG_KEYBOARD) {
 				for (i = 0; i < cooked_length; i++) {
 					if ((((guint8) cooked[i]) < 32) ||
@@ -9997,6 +10022,14 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
 	x = item.x;
 	y = item.y;
 
+	if (terminal->pvt->scroll_locked) {
+                vte_terminal_fill_rectangle(terminal, &bg,
+					    x, y, width / 3, height);
+                vte_terminal_fill_rectangle(terminal, &bg,
+					    x + width - width / 3, y, width / 3, height);
+		return;
+	}
+
         switch (_vte_terminal_decscusr_cursor_shape(terminal)) {
 
 		case VTE_CURSOR_SHAPE_IBEAM: {
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index d585365..41eb1a0 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -403,4 +403,6 @@ public:
         guint hscroll_policy : 1; /* unused */
 
         guint vscroll_policy : 1;
+
+        gboolean scroll_locked;
 };
