     @lineData = @alternateBuffer
     @updateScreen()
 
-  setScrollRegion: (top, bottom) ->
-    @topMargin = top - 1
-    @bottomMargin = bottom - 1
-
   updateLine: (n) ->
     n = (if typeof n isnt "undefined" then n else @cursorY)
     @dirtyLines[n] = n


    "\x1b\\[>c": (data) -> # Secondary Device Attribute request (?)

    "\x1bP([^\\\\])*?\\\\": (data) -> # DCS, Device Control String

    "\x1bD": ->
      console.log 'ya yebie'

    "\x1bM": ->
      @reverseIndex()

    "\x1b\x37": (data) -> # save cursor pos and char attrs
      @saveCursor()

    "\x1b\x38": (data) -> # restore cursor pos and char attrs
      @restoreCursor()

  handleCSI: (term) ->
    switch term
      when "@"
        @reserveCharacters @n
      when "A"
        @cursorUp @n or 1
      when "B"
        @cursorDown @n or 1
      when "C"
        @cursorForward @n or 1
      when "D"
        @cursorBack @n or 1
      when "G"
        @setCursorColumn @n
      when "H"
        @setCursorPos @n or 1, @m or 1
      when "J"
        @eraseData @n or 0
      when "K"
        @eraseInLine @n or 0
      when "L"
        @insertLines @n or 1
      when "M"
        @deleteLines @n or 1
      when "d" # VPA - Vertical Position Absolute
        @setCursorLine(@n)
      when "l" # l, Reset mode
        console.log "(TODO) reset: " + @n
      when "m"
        @handleSGR @params
      when "P" # DCH - Delete Character, from current position to end of field
        @deleteCharacter @n or 1
      when "r" # Set top and bottom margins (scroll region on VT100)
        @setScrollRegion(@n, @m)
      else
        throw "no handler for CSI term: " + term


  updateScreen: ->
    @dirtyLines[n] = n for n in [0...@lines]

  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
      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

  nextRow: (n = 1) ->
    for i in [0...n]
      if @cursorY + 1 < @lines
        @cursorY += 1
        @updateLine @cursorY - 1
        @updateLine @cursorY

  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()

  # ----- 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, []
