def handle_stdin
    @escapes ||= 0
    @ebuff ||= ''
    
    $stdin.read_nonblock(1024).each_char do |chr|
    
      if @escapes == 0
        if chr == "\e"
          @escapes = 1
        elsif chr == "\t"
          cycle_controls
        elsif chr == "\177"
          route_key :backspace
        else
          route_key chr
        end
        
      elsif @escapes == 1 && chr == '['
        @escapes = 2
      elsif @escapes == 1 && chr == 'O'
        @escapes = 5
        
      elsif @escapes == 2
        if chr == 'A'
          route_key :up
        elsif chr == 'B'
          route_key :down
        elsif chr == 'C'
          route_key :right
        elsif chr == 'D'
          route_key :left
        elsif chr == 'E'
          route_key :center
        elsif chr == 'Z'
          cycle_controls_back
        else
          @ebuff = chr
          @escapes = 3
        end
        @escapes = 0 if @escapes == 2
        
      elsif @escapes == 3
        if chr == '~' && @ebuff.to_i.to_s == @ebuff
          route_key case @ebuff.to_i
            when 2; :insert
            when 3; :delete
            when 5; :pageup
            when 6; :pagedown
            when 15; :f5
            when 17; :f6
            when 18; :f7
            when 19; :f8
            when 20; :f9
            when 24; :f12
            else; raise @ebuff.inspect
          end
        elsif @ebuff[0,1] == 'M' && @ebuff.size == 3
          @ebuff += chr
          info, x, y = @ebuff.unpack('xCCC').map{|i| i - 32}
          modifiers = []
          modifiers << :shift if info & 4 == 4
          modifiers << :meta if info & 8 == 8
          modifiers << :control if info & 16 == 16
          pane = pane_at(x, y)
          
          unless modal && modal != pane
            pane.handle_click BUTTONS[info & 71], modifiers, x, y if pane
          end
        elsif @ebuff.size > 10
          raise "long ebuff #{@ebuff.inspect} - #{chr.inspect}"
        else
          @ebuff += chr
          @escapes = 4
        end
        @escapes = 0 if @escapes == 3
        @escapes = 3 if @escapes == 4
        @ebuff = '' if @escapes == 0
        
      elsif @escapes == 5
        if chr == 'H'
          route_key :home
        elsif chr == 'F'
          route_key :end
        elsif chr == 'Q'
          route_key :f2
        elsif chr == 'R'
          route_key :f3
        elsif chr == 'S'
          route_key :f4
        else
          raise "escape 5 #{chr.inspect}"
        end
        @escapes = 0
        
      else
        @escapes = 0
      end
    end
    
    @driver.flush
    
  rescue Errno::EAGAIN
  rescue EOFError
  end
def handle_stdin
    @escapes ||= 0
    @ebuff ||= ''
    
    $stdin.read_nonblock(1024).each_char do |chr|
    
      if @escapes == 0
        if chr == "\e"
          @escapes = 1
        elsif chr == "\t"
          cycle_controls
        elsif chr == "\177"
          route_key :backspace
        else
          route_key chr
        end
        
      elsif @escapes == 1 && chr == '['
        @escapes = 2
      elsif @escapes == 1 && chr == 'O'
        @escapes = 5
        
      elsif @escapes == 2
        if chr == 'A'
          route_key :up
        elsif chr == 'B'
          route_key :down
        elsif chr == 'C'
          route_key :right
        elsif chr == 'D'
          route_key :left
        elsif chr == 'E'
          route_key :center
        elsif chr == 'Z'
          cycle_controls_back
        else
          @ebuff = chr
          @escapes = 3
        end
        @escapes = 0 if @escapes == 2
        
      elsif @escapes == 3
        if chr == '~' && @ebuff.to_i.to_s == @ebuff
          route_key case @ebuff.to_i
            when 2; :insert
            when 3; :delete
            when 5; :pageup
            when 6; :pagedown
            when 15; :f5
            when 17; :f6
            when 18; :f7
            when 19; :f8
            when 20; :f9
            when 24; :f12
            else; raise @ebuff.inspect
          end
        elsif @ebuff[0,1] == 'M' && @ebuff.size == 3
          @ebuff += chr
          info, x, y = @ebuff.unpack('xCCC').map{|i| i - 32}
          modifiers = []
          modifiers << :shift if info & 4 == 4
          modifiers << :meta if info & 8 == 8
          modifiers << :control if info & 16 == 16
          pane = pane_at(x, y)
          
          unless modal && modal != pane
            pane.handle_click BUTTONS[info & 71], modifiers, x, y if pane
          end
        elsif @ebuff.size > 10
          raise "long ebuff #{@ebuff.inspect} - #{chr.inspect}"
        else
          @ebuff += chr
          @escapes = 4
        end
        @escapes = 0 if @escapes == 3
        @escapes = 3 if @escapes == 4
        @ebuff = '' if @escapes == 0
        
      elsif @escapes == 5
        if chr == 'H'
          route_key :home
        elsif chr == 'F'
          route_key :end
        elsif chr == 'Q'
          route_key :f2
        elsif chr == 'R'
          route_key :f3
        elsif chr == 'S'
          route_key :f4
        else
          raise "escape 5 #{chr.inspect}"
        end
        @escapes = 0
        
      else
        @escapes = 0
      end
    end
    
    @driver.flush
    
  rescue Errno::EAGAIN
  rescue EOFError
  end
alt-anything => \e*KEY* (same as Esc, key)
 alt-[ would become \e[ which is an ANSI escape

 ctrl-stuff becomes weird stuff, i.e. ctrl-space = \x00, ctrl-a = \x01, ctrl-b = \x02

 super is not sent?