+ /**
+ * Set listener to a different Object.
+ *
+ * @param listener the new listening object that run() wakes up on new
+ * input
+ */
+ public void setListener(final Object listener) {
+ this.listener = listener;
+ }
+
+ // ------------------------------------------------------------------------
+ // Runnable ---------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Read function runs on a separate thread.
+ */
+ public void run() {
+ boolean done = false;
+ // available() will often return > 1, so we need to read in chunks to
+ // stay caught up.
+ char [] readBuffer = new char[128];
+ List<TInputEvent> events = new LinkedList<TInputEvent>();
+
+ while (!done && !stopReaderThread) {
+ try {
+ // We assume that if inputStream has bytes available, then
+ // input won't block on read().
+ int n = inputStream.available();
+
+ /*
+ System.err.printf("inputStream.available(): %d\n", n);
+ System.err.flush();
+ */
+
+ if (n > 0) {
+ if (readBuffer.length < n) {
+ // The buffer wasn't big enough, make it huger
+ readBuffer = new char[readBuffer.length * 2];
+ }
+
+ // System.err.printf("BEFORE read()\n"); System.err.flush();
+
+ int rc = input.read(readBuffer, 0, readBuffer.length);
+
+ /*
+ System.err.printf("AFTER read() %d\n", rc);
+ System.err.flush();
+ */
+
+ if (rc == -1) {
+ // This is EOF
+ done = true;
+ } else {
+ for (int i = 0; i < rc; i++) {
+ int ch = readBuffer[i];
+ processChar(events, (char)ch);
+ }
+ getIdleEvents(events);
+ if (events.size() > 0) {
+ // Add to the queue for the backend thread to
+ // be able to obtain.
+ synchronized (eventQueue) {
+ eventQueue.addAll(events);
+ }
+ if (listener != null) {
+ synchronized (listener) {
+ listener.notifyAll();
+ }
+ }
+ events.clear();
+ }
+ }
+ } else {
+ getIdleEvents(events);
+ if (events.size() > 0) {
+ synchronized (eventQueue) {
+ eventQueue.addAll(events);
+ }
+ if (listener != null) {
+ synchronized (listener) {
+ listener.notifyAll();
+ }
+ }
+ events.clear();
+ }
+
+ // Wait 20 millis for more data
+ Thread.sleep(20);
+ }
+ // System.err.println("end while loop"); System.err.flush();
+ } catch (InterruptedException e) {
+ // SQUASH
+ } catch (IOException e) {
+ e.printStackTrace();
+ done = true;
+ }
+ } // while ((done == false) && (stopReaderThread == false))
+ // System.err.println("*** run() exiting..."); System.err.flush();
+ }
+
+ // ------------------------------------------------------------------------
+ // ECMA48Terminal ---------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Getter for sessionInfo.
+ *
+ * @return the SessionInfo
+ */
+ public SessionInfo getSessionInfo() {
+ return sessionInfo;
+ }
+
+ /**
+ * Get the output writer.
+ *
+ * @return the Writer
+ */
+ public PrintWriter getOutput() {
+ return output;
+ }
+
+ /**
+ * Call 'stty' to set cooked mode.
+ *
+ * <p>Actually executes '/bin/sh -c stty sane cooked < /dev/tty'
+ */
+ private void sttyCooked() {
+ doStty(false);
+ }
+
+ /**
+ * Call 'stty' to set raw mode.
+ *
+ * <p>Actually executes '/bin/sh -c stty -ignbrk -brkint -parmrk -istrip
+ * -inlcr -igncr -icrnl -ixon -opost -echo -echonl -icanon -isig -iexten
+ * -parenb cs8 min 1 < /dev/tty'
+ */
+ private void sttyRaw() {
+ doStty(true);
+ }
+
+ /**
+ * Call 'stty' to set raw or cooked mode.
+ *
+ * @param mode if true, set raw mode, otherwise set cooked mode
+ */
+ private void doStty(final boolean mode) {
+ String [] cmdRaw = {
+ "/bin/sh", "-c", "stty -ignbrk -brkint -parmrk -istrip -inlcr -igncr -icrnl -ixon -opost -echo -echonl -icanon -isig -iexten -parenb cs8 min 1 < /dev/tty"
+ };
+ String [] cmdCooked = {
+ "/bin/sh", "-c", "stty sane cooked < /dev/tty"
+ };
+ try {
+ Process process;
+ if (mode) {
+ process = Runtime.getRuntime().exec(cmdRaw);
+ } else {
+ process = Runtime.getRuntime().exec(cmdCooked);
+ }
+ BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
+ String line = in.readLine();
+ if ((line != null) && (line.length() > 0)) {
+ System.err.println("WEIRD?! Normal output from stty: " + line);
+ }
+ while (true) {
+ BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
+ line = err.readLine();
+ if ((line != null) && (line.length() > 0)) {
+ System.err.println("Error output from stty: " + line);
+ }
+ try {
+ process.waitFor();
+ break;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ int rc = process.exitValue();
+ if (rc != 0) {
+ System.err.println("stty returned error code: " + rc);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+