public void run() {
      rawMode(true);

      try {
         InputStream in = con.tif.getInput();
         while (eloop.running()) {
            // Blocks until a character is available, then reads all
            // available (to make sure we get the whole stream for a
            // multi-byte key, e.g. F1 or Up)
            try {
               int ch = in.read();
               if (ch == -1) break;
               buf_len = 0;
               buf[buf_len++] = (byte) ch;
               int avail = in.available();
               for (int a = avail; a>0; a--) {
                  if (buf_len == buf.length) break;
                  ch = in.read();
                  if (ch == -1) break;
                  buf[buf_len++] = (byte) ch;
               }
               buf_index = 0;
            } catch (IOException e) {
               // Abort application on I/O error
               con.debug("I/O error on keyboard input: " + e.getMessage());
               break;
            }
            
            // Convert to key events
            try {
               while (more())
                  eloop.add(convertKey());
            } catch (IOException e) {
               // Throw away the rest of the buffer as it could be broken
               // sequences following this stuff we didn't understand
               con.beep();
            }
         }
      } finally {
         // May crash out in case of scramjet C front-end being killed
         // off.  Need to make sure that event loop thread also
         // terminates.
         eloop.reqAbort();
      }
   }