+ @a = ((@a & ~mask) | value)
+
+ # we're supposed to ignore leeding zeros, and while we're at it, lets swap
+ # in the default for blank or missing values
+ fix_esc_arg: (value, deef_alt) ->
+ if value? and value != ''
+ while value[0] is '0' and value.length > 1
+ value = value.substr 1
+ return value
+ else
+ return deef_alt
+
+ # csi_@: rxvt does nothing I can detect
+
+ # "The auxiliary keypad keys will send ASCII codes corresponding to the
+ # characters engraved on their keys." (numlock?)
+ "esc_>": ->
+
+ # move cursor up
+ csi_A: (lines) ->
+ lines = parseInt @fix_esc_arg lines, '1'
+ @y -= lines
+ if @y < 0
+ @y = 0
+ return
+
+ # move cursor down
+ csi_B: (lines) ->
+ lines = parseInt @fix_esc_arg lines, '1'
+ @y += lines
+ if @y >= @height
+ @y = @height - 1
+ return
+
+ # move cursor right
+ csi_C: (cols) ->
+ cols = parseInt @fix_esc_arg cols, '1'
+ @x += cols
+ if @x >= @width
+ @x = @width - 1
+ return
+
+ # move cursor left
+ csi_D: (cols) ->
+ cols = parseInt @fix_esc_arg cols, '1'
+ @x -= cols
+ if @x < 0
+ @x = 0
+ return
+
+ # cursor set_row (y)
+ csi_d: (row) ->
+ row = parseInt @fix_esc_arg row, '1'
+ @set_row_clamped row
+ return
+
+ # cursor column (x)
+ csi_G: (col) ->
+ row = parseInt @fix_esc_arg col, '1'
+ @set_row_clamped col
+ return
+
+ # set cursor row (zero based)
+ set_row_clamped: (row) ->
+ if row < 0
+ row = 0
+ if row >= @height
+ row = @height - 1
+ @y = row
+ return
+ # set cursor column (zero based)
+ set_column_clamped: (column) ->
+ if column < 0
+ column = 0
+ if column >= @width
+ column = @width - 1
+ @x = column
+ return
+ # set cursor position (one based)
+ csi_H: (row, column) ->
+ # handle blank/missing args and convert to 0 base
+ row = -1 + parseInt @fix_esc_arg row, '1'
+ column = -1 + parseInt @fix_esc_arg column, '1'
+ @set_row_clamped row
+ @set_column_clamped column
+ return
+
+ # clear to screen edge(es)
+ csi_J: (direction) ->
+ switch @fix_esc_arg direction, '0'
+ when '0' # erase down
+ # rest of current line
+ @csi_K direction
+ # rest of lines
+ for row in [@y...@height]
+ for i in [0...@width]
+ @text[row][i] = ' '
+ @attributes[row][i] = @a
+ when '1' # erase up
+ # beginning of current line
+ @csi_K direction
+ # all previous lines
+ for row in [0..@y]
+ for i in [0...@width]
+ @text[row][i] = ' '
+ @attributes[row][i] = @a
+ when '2' # erase everything
+ for row in [0...@height]
+ for i in [0...@width]
+ @text[row][i] = ' '
+ @attributes[row][i] = @a
+ else
+ log "confusing arg for csi_J: #{direction}"
+ return
+
+ # clear (some or all of) current line
+ csi_K: (direction) ->
+ switch @fix_esc_arg direction, '0'
+ when '0' # erase to right
+ for i in [@x...@width]
+ @text[@y][i] = ' '
+ @attributes[@y][i] = @a
+ when '1' # erase to left
+ # @x can equal @width (after printing to right-most column)
+ if @x < @width
+ max = @x
+ else
+ max = @width - 1
+ for i in [0..max]
+ @text[@y][i] = ' '
+ @attributes[@y][i] = @a
+ when '2' # erase whole line
+ for i in [0...@width]
+ @text[@y][i] = ' '
+ @attributes[@y][i] = @a
+ else
+ log "confusing arg for csi_K: #{direction}"
+ return