diff --git a/ANSI.c b/ANSI.c
index 5b04cb6..3b08d5d 100644
--- a/ANSI.c
+++ b/ANSI.c
@@ -152,7 +152,7 @@
     remove wcstok, avoiding potential interference with the host;
     similarly, use a private heap instead of malloc.
 
-  v1.80, 26 October to 19 November, 2017:
+  v1.80, 26 October to 23 November, 2017:
     fix unloading;
     revert back to (re)storing buffer cursor position;
     increase cache to five handles;
@@ -161,7 +161,8 @@
     preserve escape that isn't part of a sequence;
     fix escape followed by CRM in control mode;
     use the system default sound for the bell;
-    add DECPS Play Sound.
+    add DECPS Play Sound;
+    use intermediate byte '+' to use buffer, not window.
 */
 
 #include "ansicon.h"
@@ -668,12 +669,15 @@ void InterpretEscSeq( void )
   SMALL_RECT Rect;
   CHAR_INFO  CharInfo;
   DWORD      mode;
+  SHORT      top, bottom;
 
 #define WIDTH  Info.dwSize.X
+#define HEIGHT Info.dwSize.Y
 #define CUR    Info.dwCursorPosition
 #define WIN    Info.srWindow
 #define TOP    WIN.Top
 #define BOTTOM WIN.Bottom
+#define LAST   (HEIGHT - 1)
 #define LEFT   0
 #define RIGHT  (WIDTH - 1)
 
@@ -707,6 +711,16 @@ void InterpretEscSeq( void )
       return;
 
     GetConsoleScreenBufferInfo( hConOut, &Info );
+    if (suffix2 == '+')
+    {
+      top    = 0;
+      bottom = LAST;
+    }
+    else
+    {
+      top    = TOP;
+      bottom = BOTTOM;
+    }
     switch (suffix)
     {
       case 'm':
@@ -829,32 +843,32 @@ void InterpretEscSeq( void )
 	switch (es_argv[0])
 	{
 	  case 0: // ESC[0J erase from cursor to end of display
-	    len = (BOTTOM - CUR.Y) * WIDTH + WIDTH - CUR.X;
+	    len = (bottom - CUR.Y) * WIDTH + WIDTH - CUR.X;
 	    FillBlank( len, CUR );
 	  return;
 
 	  case 1: // ESC[1J erase from start to cursor.
-	    Pos.X = 0;
-	    Pos.Y = TOP;
-	    len   = (CUR.Y - TOP) * WIDTH + CUR.X + 1;
+	    Pos.X = LEFT;
+	    Pos.Y = top;
+	    len   = (CUR.Y - top) * WIDTH + CUR.X + 1;
 	    FillBlank( len, Pos );
 	  return;
 
 	  case 2: // ESC[2J Clear screen and home cursor
-	    if (TOP != screen_top || BOTTOM == Info.dwSize.Y - 1)
+	    if (suffix2 != '+' && (TOP != screen_top || CUR.Y == LAST))
 	    {
 	      // Rather than clearing the existing window, make the current
 	      // line the new top of the window (assuming this is the first
 	      // thing a program does).
 	      int range = BOTTOM - TOP;
-	      if (CUR.Y + range < Info.dwSize.Y)
+	      if (CUR.Y + range < HEIGHT)
 	      {
 		TOP = CUR.Y;
 		BOTTOM = TOP + range;
 	      }
 	      else
 	      {
-		BOTTOM = Info.dwSize.Y - 1;
+		BOTTOM = LAST;
 		TOP = BOTTOM - range;
 		Rect.Left = LEFT;
 		Rect.Right = RIGHT;
@@ -867,10 +881,12 @@ void InterpretEscSeq( void )
 	      }
 	      SetConsoleWindowInfo( hConOut, TRUE, &WIN );
 	      screen_top = TOP;
+	      top = TOP;
+	      bottom = BOTTOM;
 	    }
 	    Pos.X = LEFT;
-	    Pos.Y = TOP;
-	    len   = (BOTTOM - TOP + 1) * WIDTH;
+	    Pos.Y = top;
+	    len   = (bottom - top + 1) * WIDTH;
 	    FillBlank( len, Pos );
 	    // Not technically correct, but perhaps expected.
 	    SetConsoleCursorPosition( hConOut, Pos );
@@ -918,7 +934,7 @@ void InterpretEscSeq( void )
 	Rect.Left   = WIN.Left	= LEFT;
 	Rect.Right  = WIN.Right = RIGHT;
 	Rect.Top    = CUR.Y;
-	Rect.Bottom = BOTTOM;
+	Rect.Bottom = bottom;
 	Pos.X = LEFT;
 	Pos.Y = CUR.Y + es_argv[0];
 	CharInfo.Char.UnicodeChar = ' ';
@@ -932,7 +948,7 @@ void InterpretEscSeq( void )
 	if (es_argc != 1) return;
 	Rect.Left   = WIN.Left	= LEFT;
 	Rect.Right  = WIN.Right = RIGHT;
-	Rect.Bottom = BOTTOM;
+	Rect.Bottom = bottom;
 	Rect.Top    = CUR.Y - es_argv[0];
 	Pos.X = LEFT;
 	Pos.Y = TOP = CUR.Y;
@@ -975,7 +991,7 @@ void InterpretEscSeq( void )
 	if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A
 	if (es_argc != 1) return;
 	Pos.Y = CUR.Y - es_argv[0];
-	if (Pos.Y < TOP) Pos.Y = TOP;
+	if (Pos.Y < top) Pos.Y = top;
 	Pos.X = CUR.X;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
@@ -985,7 +1001,7 @@ void InterpretEscSeq( void )
 	if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B
 	if (es_argc != 1) return;
 	Pos.Y = CUR.Y + es_argv[0];
-	if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
+	if (Pos.Y > bottom) Pos.Y = bottom;
 	Pos.X = CUR.X;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
@@ -1014,7 +1030,7 @@ void InterpretEscSeq( void )
 	if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E
 	if (es_argc != 1) return;
 	Pos.Y = CUR.Y + es_argv[0];
-	if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
+	if (Pos.Y > bottom) Pos.Y = bottom;
 	Pos.X = LEFT;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
@@ -1023,7 +1039,7 @@ void InterpretEscSeq( void )
 	if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F
 	if (es_argc != 1) return;
 	Pos.Y = CUR.Y - es_argv[0];
-	if (Pos.Y < TOP) Pos.Y = TOP;
+	if (Pos.Y < top) Pos.Y = top;
 	Pos.X = LEFT;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
@@ -1042,9 +1058,9 @@ void InterpretEscSeq( void )
       case 'd': // ESC[#d Moves cursor row #, current column.
 	if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d
 	if (es_argc != 1) return;
-	Pos.Y = es_argv[0] - 1;
-	if (Pos.Y < TOP) Pos.Y = TOP;
-	if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
+	Pos.Y = top + es_argv[0] - 1;
+	if (Pos.Y < top) Pos.Y = top;
+	if (Pos.Y > bottom) Pos.Y = bottom;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
 
@@ -1058,9 +1074,9 @@ void InterpretEscSeq( void )
 	Pos.X = es_argv[1] - 1;
 	if (Pos.X < LEFT) Pos.X = LEFT;
 	if (Pos.X > RIGHT) Pos.X = RIGHT;
-	Pos.Y = es_argv[0] - 1;
-	if (Pos.Y < TOP) Pos.Y = TOP;
-	if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
+	Pos.Y = top + es_argv[0] - 1;
+	if (Pos.Y < top) Pos.Y = top;
+	if (Pos.Y > bottom) Pos.Y = bottom;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
 
@@ -1101,7 +1117,7 @@ void InterpretEscSeq( void )
 	if (es_argc != 0) return;
 	Pos = pState->SavePos;
 	if (Pos.X > RIGHT) Pos.X = RIGHT;
-	if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
+	if (Pos.Y > bottom) Pos.Y = bottom;
 	SetConsoleCursorPosition( hConOut, Pos );
       return;
 
@@ -1116,7 +1132,9 @@ void InterpretEscSeq( void )
 	  case 6: // ESC[6n Report cursor position
 	  {
 	    TCHAR buf[32];
-	    wsprintf( buf, L"\33[%d;%dR", CUR.Y - TOP + 1, CUR.X + 1 );
+	    wsprintf( buf, L"\33[%d;%d%sR",
+		      CUR.Y - top + 1, CUR.X + 1,
+		      (suffix2 == '+') ? L"+" : L"" );
 	    SendSequence( buf );
 	  }
 	  return;
@@ -1320,7 +1338,7 @@ ParseAndPrintString( HANDLE hDev,
       {
 	suffix2 = c;
       }
-      else if (suffix2 != 0 && suffix2 != ',')
+      else if (suffix2 != 0 && suffix2 != ',' && suffix2 != '+')
       {
 	state = 1;
       }
@@ -1353,7 +1371,7 @@ ParseAndPrintString( HANDLE hDev,
       {
 	suffix2 = c;
       }
-      else if (suffix2 != 0 && suffix2 != ',')
+      else if (suffix2 != 0 && suffix2 != ',' && suffix2 != '+')
       {
 	state = 1;
       }
diff --git a/ansicon.c b/ansicon.c
index a34725c..ff2b1ac 100644
--- a/ansicon.c
+++ b/ansicon.c
@@ -90,7 +90,7 @@
     write newline with _putws, not putwchar (fixes redirecting to CON).
 */
 
-#define PDATE L"19 November, 2017"
+#define PDATE L"23 November, 2017"
 
 #include "ansicon.h"
 #include "version.h"
diff --git a/readme.txt b/readme.txt
index a1a82f8..00b4741 100644
--- a/readme.txt
+++ b/readme.txt
@@ -278,7 +278,6 @@ DEC Special Graphics Character Set
 Limitations
 ===========
 
-    Line sequences use the window; column sequences use the buffer.
     Tabs are fixed at eight columns.
     The saved position will not be restored correctly if the buffer scrolls.
 
@@ -296,7 +295,7 @@ Version History
 
     Legend: + added, - bug-fixed, * changed.
 
-    1.80 - 17 November, 2017:
+    1.80 - 23 November, 2017:
     - fix unloading;
     - fix -e et al when redirecting to CON;
     - hook CreateFile and CreateConsoleScreenBuffer to force read/write access
@@ -306,7 +305,8 @@ Version History
     * go back to saving the buffer cursor position;
     * preserve escape that isn't part of a sequence;
     + use the system default sound for the bell;
-    + added Play Sound DECPS.
+    + added Play Sound DECPS;
+    + added '+' intermediate byte to use the buffer, rather than the window.
 
     1.72 - 24 December, 2015:
     - handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile;
@@ -535,4 +535,4 @@ Distribution
 
 
 =============================
-Jason Hood, 19 November, 2017.
+Jason Hood, 23 November, 2017.
diff --git a/sequences.txt b/sequences.txt
index 04e5a7e..66b53d4 100644
--- a/sequences.txt
+++ b/sequences.txt
@@ -3,7 +3,10 @@
 				  Version 1.80
 
 This is a complete list of the ANSI escape sequences recognised by ANSICON,
-roughly ordered by function.  The initial escape character is assumed.
+roughly ordered by function.  The initial escape character is assumed.	The
+display consists of the buffer width and window height; add '+' before the
+final character to use the buffer height (e.g. "[2J" will erase the window,
+whilst "[2+J" will erase the buffer).
 
 
 [m	restore default color (and intensity)