   updateScreen: ->
     @dirtyLines[n] = n for n in [0...@lines]
 
-  setCursorLine: (line) ->
-    oldLine = @cursorY
-    @cursorY = line - 1
-    @updateLine oldLine
-    @updateLine()
-
-  setCursorColumn: (col) ->
-    @cursorX = col - 1
-    @updateLine()
-
-  setCursorPos: (line, col) ->
-    @setCursorLine(line)
-    @setCursorColumn(col)
-
-  saveCursor: ->
-    @savedCol = @cursorX
-    @savedLine = @cursorY
-
-  restoreCursor: ->
-    oldLine = @cursorY
-
-    @cursorY = @savedLine
-    @cursorX = @savedCol
-
-    @updateLine oldLine
-    @updateLine()
-
-  cursorLeft: ->
-    if @cursorX > 0
-      @cursorX -= 1
-      @updateLine()
-
-  cursorRight: ->
-    if @cursorX < @cols
+  carriageReturn: ->
+    @goToFirstColumn()
+
+  backspace: ->
+    @priorColumn()
+
+  print: (text) ->
+    text = Utf8.decode(text)
+
+    i = 0
+    while i < text.length
+      if @cursorX >= @cols
+        @cursorY += 1
+        @cursorX = 0
+
+      @fill @cursorY, @cursorX, 1, text[i]
       @cursorX += 1
-      @updateLine()
-
-  cursorUp: (n = 1) ->
+      i++
+
+    @updateLine()
+
+  clearLineData: (n) ->
+    @fill n, 0, @cols, " "
+
+  fill: (line, col, n, char) ->
+    lineArr = @getLine(line)
+
+    i = 0
+    while i < n
+      lineArr[col + i] = [char, @brush]
+      i++
+
+  inScrollRegion: ->
+    @cursorY >= @topMargin and @cursorY <= @bottomMargin
+
+  changes: ->
+    c = {}
+    for _, n of @dirtyLines
+      c[n] = @lineData[n]
+
+    c
+
+  clearChanges: ->
+    @dirtyLines = {}
+
+  # === ANSI handlers
+
+  # ------ Cursor control
+
+  # ----- Scroll control
+
+  reverseIndex: ->
+    @goToPriorRow()
+
+  lineFeed: ->
+    @goToNextRow()
+
+  verticalTab: ->
+    @goToNextRow()
+
+  formFeed: ->
+    @goToNextRow()
+
+  index: ->
+    @goToNextRow()
+
+  newLine: ->
+    @goToNextRowFirstColumn()
+
+
+  # === Commands
+
+  # ----- Cursor control
+
+  priorRow: (n = 1) ->
     for i in [0...n]
       if @cursorY > 0
         @cursorY -= 1
         @updateLine @cursorY
         @updateLine @cursorY + 1
 
-  cursorDown: (n = 1) ->
+  nextRow: (n = 1) ->
     for i in [0...n]
       if @cursorY + 1 < @lines
         @cursorY += 1
         @updateLine @cursorY - 1
         @updateLine @cursorY
 
-  cursorForward: (n) ->
-    @cursorRight() for i in [0...n]
-
-  cursorBack: (n) ->
-    @cursorLeft() for i in [0...n]
-
-  cr: ->
+  nextColumn: (n = 1) ->
+    @_cursorRight() for i in [0...n]
+
+  priorColumn: (n = 1) ->
+    @_cursorLeft() for i in [0...n]
+
+  _cursorLeft: ->
+    if @cursorX > 0
+      @cursorX -= 1
+      @updateLine()
+
+  _cursorRight: ->
+    if @cursorX < @cols
+      @cursorX += 1
+      @updateLine()
+
+  priorRowFirstColumn: (n = 1) ->
+    @carriageReturn()
+    @priorRow n
+
+  nextRowFirstColumn: (n = 1) ->
+    @carriageReturn()
+    @nextRow n
+
+  goToColumn: (col = 1) ->
+    @cursorX = col - 1
+    @updateLine()
+
+  goToRow: (line = 1) ->
+    oldLine = @cursorY
+    @cursorY = line - 1
+    @updateLine oldLine
+    @updateLine()
+
+  goToRowAndColumn: (line = 1, col = 1) ->
+    @goToRow line
+    @goToColumn col
+
+  setHorizontalTabStop: ->
+    # @tabStops << @cursorX
+
+  goToNextHorizontalTabStop: ->
+
+  goToPriorHorizontalTabStop: ->
+
+  clearHorizontalTabStop: ->
+
+  clearAllHorizontalTabStops: ->
+
+  saveCursor: ->
+    @savedCol = @cursorX
+    @savedLine = @cursorY
+
+  restoreCursor: ->
+    oldLine = @cursorY
+
+    @cursorY = @savedLine
+    @cursorX = @savedCol
+
+    @updateLine oldLine
+    @updateLine()
+
+  showCursor: ->
+    @renderer.showCursor true
+
+  hideCursor: ->
+    @renderer.showCursor false
+
+  goToFirstColumn: ->
     @cursorX = 0
     @updateLine()
 
-  backspace: ->
-    if @cursorX > 0
-      @cursorLeft()
-      @updateLine()
-
-  print: (text) ->
-    text = Utf8.decode(text)
-
-    i = 0
-    while i < text.length
-      if @cursorX >= @cols
-        @cursorY += 1
-        @cursorX = 0
-
-      @fill @cursorY, @cursorX, 1, text[i]
-      @cursorX += 1
-      i++
-
-    @updateLine()
-
-  eraseData: (n) ->
-    if n is 0
-      @eraseInLine 0
-
-      l = @cursorY + 1
-      while l < @lines
-        @clearLineData l
-        @updateLine l
-        l++
-
-    else if n is 1
-      l = 0
-      while l < @cursorY
-        @clearLineData l
-        @updateLine l
-        l++
-
-      @eraseInLine n
-
-    else if n is 2
-      l = 0
-      while l < @lines
-        @clearLineData l
-        @updateLine l
-        l++
-
-  eraseInLine: (n) ->
-    if n is 0
-      @fill @cursorY, @cursorX, @cols - @cursorX, " "
-    else if n is 1
-      @fill @cursorY, 0, @cursorX, " "
-    else if n is 2
-      @fill @cursorY, 0, @cols, " "
-
-    @updateLine()
-
-  clearLineData: (n) ->
-    @fill n, 0, @cols, " "
-
-  deleteCharacter: (n) ->
-    @getLine().splice(@cursorX, n)
-    @updateLine()
-
-  reserveCharacters: (n) ->
-    line = @getLine()
-    @lineData[@cursorY] = line.slice(0, @cursorX).concat(" ".times(n).split(""), line.slice(@cursorX, @cols - n))
-    @updateLine()
-
-  lineFeed: ->
-    @index()
-
-  index: ->
-    if @cursorY + 1 < @lines
-      @cursorDown()
-    else
-      @lineData.splice 0, 1
-      @updateScreen()
-
-  reverseIndex: ->
-    if @cursorY is 0
-      @insertLines 1, 0
-    else
-      @cursorUp()
-
-  insertLines: (n, l = @cursorY) ->
+  # ----- Scroll control
+
+  setScrollRegion: (top, bottom) ->
+    @topMargin = top - 1
+    @bottomMargin = bottom - 1
+
+  setLineWrap: (linewrap) ->
+
+  scrollUp: ->
+    # @lineData.splice l, 0, []
+    # @clearLineData l
+    @insertLine 1, 0
+    @updateScreen()
+
+  scrollDown: ->
+    @lineData.splice 0, 1
+    @updateScreen()
+
+  insertLine: (n, l = @cursorY) ->
+    return unless @inScrollRegion()
+
     i = 0
     while i < n
       @lineData.splice l, 0, []


  # ==== Screen buffer operations

  setBrush: (brush) ->
    @brush = brush

  clearScreen: ->
    @lineData.length = 0


class AsciiIo.VT

  constructor: (@cols, @lines, @renderer) ->
    @data = ''
    @resetTerminal()
    @compilePatterns()

  noop: ->
