01: package gnu.mapping;
02:
03: import java.io.*;
04:
05: /** A class to compensate from System.in blocking other threads. */
06:
07: public class SysInPort extends TtyInPort {
08: InputStream inStream;
09:
10: public SysInPort(InputStream inStream, String name, OutPort tie) {
11: super (inStream, name, tie);
12: this .inStream = inStream;
13: }
14:
15: public int fill(int len) throws java.io.IOException {
16: int off = pos;
17: /* This explanation and work-around comes from jacl 1.0's Shell.java:
18: *
19: * On Unix platforms, System.in.read() will block the delivery of
20: * of AWT events. We must make sure System.in.available() is larger
21: * than zero before attempting to read from System.in. Since
22: * there is no asynchronous IO in Java, we must poll the System.in
23: * every 100 milliseconds.
24: */
25:
26: if (!in.ready()) {
27: try {
28: while (inStream.available() == 0)
29: Thread.currentThread().sleep(100);
30: } catch (java.lang.InterruptedException ex) {
31: } catch (java.io.IOException ex) {
32: // available or ready does not seem to be supported or working.
33: }
34: }
35:
36: // It would be more efficient to just do super.fill(buffer, off, len).
37: // Unfortunately, that may hang. One reported problem is when running
38: // Kawa inside a shell or inferior-lisp window in ntemacs on Windows NT.
39: // Ntemacs uses pipes to communicate with the inferior shell (because
40: // pseudo-ttys are not available). This causes too much input to be
41: // buffered. (The problem seems to be in java.io.InputStreamReader.)
42:
43: int count;
44: for (count = 0; count < len;) {
45: int ch = in.read();
46: if (ch < 0) {
47: if (count == 0)
48: return -1;
49: break;
50: }
51: buffer[off++] = (char) (0xff & ch);
52: count++;
53: if (ch == '\n' || ch == '\r')
54: break;
55: }
56: if (tie != null)
57: tie.echo(buffer, off - count, count);
58: return count;
59: }
60: }
|