     @view.visualBell()
     # @trigger('bell')
 
-  compilePatterns: ->
-    @COMPILED_PATTERNS = ([new RegExp("^" + re), f] for re, f of @PATTERNS)
+  # compilePatterns: ->
+  #   @COMPILED_PATTERNS = ([new RegExp("^" + re), f] for re, f of @PATTERNS)
 
   feed: (data) ->
     @data += data
 
     while @data.length > 0
-      match = null
-
-      for pattern in @COMPILED_PATTERNS
-        match = pattern[0].exec(@data)
-
-        if match
-          handler = pattern[1]
-          handler.call(this, @data, match)
-          @data = @data.slice(match[0].length)
-          break
-
-      break unless match
+      processed = @handleData(@data)
+
+      if processed is 0
+        # console.log "no kurwa: #{@formattedData(@data)}"
+        break
+        # throw 'up'
+
+      @data = @data.slice(processed)
+
+      # match = null
+
+      # for pattern in @COMPILED_PATTERNS
+      #   match = pattern[0].exec(@data)
+
+      #   if match
+      #     handler = pattern[1]
+      #     handler.call(this, @data, match)
+      #     @data = @data.slice(match[0].length)
+      #     break
+
+      # break unless match
 
     @render()
 
-    if @data.length > 500
-      head = @data.slice(0, 100)
-      hex = ("0x#{c.charCodeAt(0).toString(16)}" for c in head)
-      console.log "failed matching: '" + Utf8.decode(head) + "' (" + hex.join() + ")" # [pos: " + (@dataIndex - count) + "]"
-
     @data.length is 0
+
+  # aaa: ->
+  #   if @data.length > 500
+  #     head = @data.slice(0, 100)
+  #     hex = ("0x#{c.charCodeAt(0).toString(16)}" for c in head)
+  #     console.log "failed matching: '" + Utf8.decode(head) + "' (" + hex.join() + ")" # [pos: " + (@dataIndex - count) + "]"
+
+  formattedData: (data) ->
+    head = data.slice(0, 100)
+    hex = ("0x#{c.charCodeAt(0).toString(16)}" for c in head)
+    Utf8.decode(head) + " (" + hex.join() + ")"
 
   render: ->
     @view.render(@buffer.changes(), @buffer.cursorX, @buffer.cursorY)

    @data = ''
    @resetTerminal()
    @render()
    @compilePatterns()

  noop: ->

  # handleC0ControlSet: (data) ->
  #   console.log 'handling C0'

  handlePrintableCharacters: (text) ->

  # handleC1ControlSet: (data) ->

  # handleControlSequence: (data) ->

  _C0_PATTERNS:
    # C0 set of 7-bit control characters
    "[\x00-\x1f]":
      # bell
      "\x07": (data) -> @bell()

      # backspace
      "\x08": (data) -> @backspace()

      # Move the cursor to the next tab stop
      "\x09": (data) ->

      "\x0a": (data) -> @lineFeed()

      "\x0d": (data) -> @carriageReturn()

      "\x0e": (data) ->

      "\x0f": (data) ->

      # Reserved (?)
      "\x82": (data) ->

      # Cancel Character, ignore previous character
      "\x94": (data) ->

      # Escape sequence
      "\x1b": _.extend({}, @_C0_PATTERNS, {

        # Control sequence
        "\x1b\\[": @_CS_PATTERNS
      })

  _CS_PATTERNS:
    "sth": 1

  _PATTERNS: _.extend({}, @_C0_PATTERNS, {
    # Printable characters
    "([\x20-\x7e])+": @handlePrintableCharacters

    # "Delete", always and everywhere ignored
    "[\x7f\xff]": @noop

    # C1 control set
    "[\x80-\x9f]":

      # Control sequence
      "\x9b": @_CS_PATTERNS

    # G1 Displayable, 94 additional displayable characters
    "[\xa1-\xfe]": @handlePrintableCharacters

    # Always and everywhere a blank space
    "\xa0": -> @handlePrintableCharacters(' ')

  })

  PATTERNS:
    "\x00": (data) ->
    "\x07": (data) -> @bell()
    "\x08": (data) -> @backspace()
    "\x09": (data) -> @buffer.goToNextHorizontalTabStop()
    "\x0a": (data) -> @lineFeed()
    "\x0b": (data) -> @verticalTab()
    "\x0c": (data) -> @formFeed()
    "\x0d": (data) -> @carriageReturn()
    "\x0e": (data) ->
    "\x0f": (data) ->
    "\x82": (data) -> # Reserved (?)
    "\x85": (data) -> @setHorizontalTabStop()
    "\x94": (data) -> # Cancel Character, ignore previous character

    # 20 - 7e
    "([\x20-\x7e]|\xe2..|[\xc2\xc4\xc5].)+": (data, match) ->
      @buffer.print match[0]

    "\x1b\\(B": (data) -> # SCS (Set G0 Character SET)

    "\x1b\\[([0-9;]*)([\x40-\x7e])": (data, match) ->
      if match[1].length == 0
        @params = []
      else
        @params = _(match[1].split(';')).map (n) -> if n is '' then undefined else parseInt(n)

      @n = @params[0]
      @m = @params[1]
      @handleCS match[2]

    # private standards
    "\x1b\\[\\?([\x30-\x3f]+)([hlsr])": (data, match) ->
      # h = Sets DEC/xterm specific mode (http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html#decmode)
      # l = Resets mode (http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html#mode)
      # 1001 + s = ?
      # 1001 + r = ?
      modes = match[1].split(";")
      action = match[2]
      mode = undefined

      for mode in modes
        if mode is "1"
          # 1 + h / l = cursor keys stuff
        else if mode is "5"
          # Reverse/normal video - ignoring
        else if mode is "7"
          # Enables/disables autowrap mode
        else if mode is "12"
          if action is "h"
            # blinking cursor
          else action is "l"
            # steady cursor
        else if mode is "25"
          if action is "h"
            @showCursor()
          else if action is "l"
            @hideCursor()
        else if mode is "47"
          if action is "h"
            @switchToAlternateBuffer()
          else if action is "l"
            @switchToNormalBuffer()
        else if mode is "1000"
          # Enables/disables normal mouse tracking
        else if mode is "1001"
          # pbly sth with mouse/keys...
        else if mode is "1002"
          # 2002 + h / l = mouse tracking stuff
        else if mode is "1049"
          if action is "h"
            # Save cursor position, switch to alternate screen buffer, and clear screen.
            @switchToAlternateBuffer()
            @clearScreen()
          else if action is "l"
            # Clear screen, switch to normal screen buffer, and restore cursor position.
            @clearScreen()
            @switchToNormalBuffer()
        else
          throw "unknown mode: " + mode + action

    "\x1b\x3d": (data) -> # DECKPAM - Set keypad to applications mode (ESCape instead of digits)

    "\x1b\x3e": (data) -> # DECKPNM - Set keypad to numeric mode (digits intead of ESCape seq)

    "\x1b\\\\": -> # String Terminator (VT125 exits graphics)

    "\x1b\x5d[012]\x3b.*?\x07": (data, match) -> # OSC - Operating System Command (terminal title)

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

    "\x1bc": -> @resetTerminal()
    "\x1bP([^\\\\])*?\\\\": (data) -> # DCS, Device Control String
    "\x1bD": -> @index()
    "\x1bE": -> @newLine()
    "\x1bH": -> @setHorizontalTabStop()
    "\x1bM": -> @reverseIndex()
    "\x1bk": -> # NAPLPS lock-shift G1 to GR

    "\x1b7": (data) -> # save cursor pos and char attrs
      @saveTerminalState()

    "\x1b8": (data) -> # restore cursor pos and char attrs
      @restoreTerminalState()

  handleCS: (term) ->
    switch term
      when "@"
        @buffer.insertCharacters @n
      when "A"
        @buffer.priorRow @n
      when "B"
        @buffer.nextRow @n
      when "C"
        @buffer.nextColumn @n
      when "D"
        @buffer.priorColumn @n
      when "E"
        @buffer.nextRowFirstColumn @n
      when "F"
        @buffer.priorRowFirstColumn @n
      when "G"
        @buffer.goToColumn @n
      when "H"
        @buffer.goToRowAndColumn @n, @m
      when "I"
        @buffer.goToNextHorizontalTabStop @n
      when "J"
        if @n is 2
          @buffer.eraseScreen()
        else if @n is 1
          @buffer.eraseFromScreenStart()
        else
          @buffer.eraseToScreenEnd()
      when "K"
        if @n is 2
          @buffer.eraseRow()
        else if @n is 1
          @buffer.eraseFromRowStart()
        else
          @buffer.eraseToRowEnd()
      when "L"
        @buffer.insertLine @n or 1
      when "M"
        @buffer.deleteLine @n or 1
      when "P" # DCH - Delete Character, from current position to end of field
        @buffer.deleteCharacters @n or 1
      when "S"
        @buffer.scrollUp @n
      when "T"
        @buffer.scrollDown @n
      when "X"
        @buffer.eraseCharacters @n
      when "Z"
        @buffer.goToPriorHorizontalTabStop @n
      when "b"
        @buffer.repeatLastCharacter @n
      when "d" # VPA - Vertical Position Absolute
        @buffer.goToRow @n
      when "f"
        @buffer.goToRowAndColumn @n, @m
      when "g"
        if !@n or @n is 0
          @buffer.clearHorizontalTabStop()
        else if @n is 3
          @buffer.clearAllHorizontalTabStops()
      when "l" # l, Reset mode
        console.log "(TODO) reset: " + @n
      when "m"
        @handleSGR @params
      when "n"
        @reportRowAndColumn()
      when "r" # Set top and bottom margins (scroll region on VT100)
        @setScrollRegion @n or 0, @m or @lines - 1
      when "^"
        # reserved
        # Privacy Message (password verification), terminated by ST
        # TODO
      else
        throw "no handler for CSI term: " + term

  handleSGR: (numbers) ->
    @buffer.setBrush @sgrInterpreter.buildBrush(@buffer.brush, numbers)

  reportRowAndColumn: ->

# http://www.shaels.net/index.php/propterm/documents
# http://manpages.ubuntu.com/manpages/lucid/man7/urxvt.7.html
