Class StreamBasedTerminal

java.lang.Object
com.googlecode.lanterna.terminal.AbstractTerminal
com.googlecode.lanterna.terminal.ansi.StreamBasedTerminal
All Implemented Interfaces:
InputProvider, Terminal, Closeable, AutoCloseable
Direct Known Subclasses:
ANSITerminal

public abstract class StreamBasedTerminal extends AbstractTerminal
An abstract terminal implementing functionality for terminals using OutputStream/InputStream. You can extend from this class if your terminal implementation is using standard input and standard output but not ANSI escape codes (in which case you should extend ANSITerminal). This class also contains some automatic UTF-8 to VT100 character conversion when the terminal is not set to read UTF-8.
  • Field Details

    • UTF8_REFERENCE

      private static final Charset UTF8_REFERENCE
    • terminalInput

      private final InputStream terminalInput
    • terminalOutput

      private final OutputStream terminalOutput
    • terminalCharset

      private final Charset terminalCharset
    • inputDecoder

      private final InputDecoder inputDecoder
    • keyQueue

      private final Queue<KeyStroke> keyQueue
    • readLock

      private final Lock readLock
    • lastReportedCursorPosition

      private volatile TerminalPosition lastReportedCursorPosition
  • Constructor Details

  • Method Details

    • putCharacter

      public void putCharacter(char c) throws IOException
      Prints one character to the terminal at the current cursor location. Please note that the cursor will then move one column to the right, so multiple calls to putCharacter will print out a text string without the need to reposition the text cursor. If you reach the end of the line while putting characters using this method, you can expect the text cursor to move to the beginning of the next line.

      You can output CJK (Chinese, Japanese, Korean) characters (as well as other regional scripts) but remember that the terminal that the user is using might not have the required font to render it. Also worth noticing is that CJK (and some others) characters tend to take up 2 columns per character, simply because they are a square in their construction as opposed to the somewhat rectangular shape we fit latin characters in. As it's very difficult to create a monospace font for CJK with a 2:1 height-width proportion, it seems like the implementers back in the days simply gave up and made each character take 2 column. It causes issues for the random terminal programmer because you can't really trust 1 character = 1 column, but I suppose it's "しょうがない". If you try to print non-printable control characters, the terminal is likely to ignore them (all Terminal implementations bundled with Lanterna will). The StreamBasedTerminal class will attempt to translate some unicode characters to VT100 if the encoding attached to this Terminal isn't UTF-8.

      Parameters:
      c - Character to place on the terminal
      Throws:
      IOException - If there was an underlying I/O error
    • putString

      public void putString(String string) throws IOException
      Prints a string to the terminal at the current cursor location. Please note that the cursor will then move one column to the right, so multiple calls to putString will print out a text string without the need to reposition the text cursor. If you reach the end of the line while putting characters using this method, you can expect the text cursor to move to the beginning of the next line.

      You can output CJK (Chinese, Japanese, Korean) characters (as well as other regional scripts) but remember that the terminal that the user is using might not have the required font to render it. Also worth noticing is that CJK (and some others) characters tend to take up 2 columns per character, simply because they are a square in their construction as opposed to the somewhat rectangular shape we fit latin characters in. As it's very difficult to create a monospace font for CJK with a 2:1 height-width proportion, it seems like the implementers back in the days simply gave up and made each character take 2 column. It causes issues for the random terminal programmer because you can't really trust 1 character = 1 column, but I suppose it's "しょうがない".

      If you try to print non-printable control characters, the terminal is likely to ignore them (all Terminal implementations bundled with Lanterna will).

      You can use this method to place emoji characters on the terminal, since they take up more than one char with Java's built-in UTF16 encoding. The StreamBasedTerminal class will attempt to translate some unicode characters to VT100 if the encoding attached to this Terminal isn't UTF-8.

      Parameters:
      string - String to place on the terminal
      Throws:
      IOException - If there was an underlying I/O error
    • writeToTerminal

      protected void writeToTerminal(byte... bytes) throws IOException
      This method will write a list of bytes directly to the output stream of the terminal.
      Parameters:
      bytes - Bytes to write to the terminal (synchronized)
      Throws:
      IOException - If there was an underlying I/O error
    • enquireTerminal

      public byte[] enquireTerminal(int timeout, TimeUnit timeoutTimeUnit) throws IOException
      Description copied from interface: Terminal
      Retrieves optional information from the terminal by printing the ENQ (\u005) character. Terminals and terminal emulators may or may not respond to this command, sometimes it's configurable.
      Parameters:
      timeout - How long to wait for the talk-back message, if there's nothing immediately available on the input stream, you should probably set this to a somewhat small value to prevent unnecessary blockage on the input stream but large enough to accommodate a round-trip to the user's terminal (~300 ms if you are connection across the globe).
      timeoutTimeUnit - What unit to use when interpreting the timeout parameter
      Returns:
      Answer-back message from the terminal or empty if there was nothing
      Throws:
      IOException - If there was an I/O error while trying to read the enquiry reply
    • bell

      public void bell() throws IOException
      Description copied from interface: Terminal
      Prints 0x7 to the terminal, which will make the terminal (emulator) ring a bell (or more likely beep). Not all terminals implements this. Wikipedia has more details.
      Throws:
      IOException - If there was an underlying I/O error
    • getInputDecoder

      public InputDecoder getInputDecoder()
      Returns the InputDecoder attached to this StreamBasedTerminal. Can be used to add additional character patterns to recognize and tune the way input is turned in KeyStroke:s.
      Returns:
      InputDecoder attached to this StreamBasedTerminal
    • resetMemorizedCursorPosition

      void resetMemorizedCursorPosition()
      Used by the cursor reporting methods to reset any previous position memorized, so we're guaranteed to return the next reported position
    • waitForCursorPositionReport

      TerminalPosition waitForCursorPositionReport() throws IOException
      Waits for up to 5 seconds for a terminal cursor position report to appear in the input stream. If the timeout expires, it will return null. You should have sent the cursor position query already before calling this method.
      Returns:
      Current position of the cursor, or null if the terminal didn't report it in time.
      Throws:
      IOException - If there was an I/O error
    • pollInput

      public KeyStroke pollInput() throws IOException
      Description copied from interface: InputProvider
      Returns the next Key off the input queue or null if there is no more input events available. Note, this method call is not blocking, it returns null immediately if there is nothing on the input stream.
      Returns:
      Key object which represents a keystroke coming in through the input stream
      Throws:
      IOException - Propagated error if the underlying stream gave errors
    • readInput

      public KeyStroke readInput() throws IOException
      Description copied from interface: InputProvider
      Returns the next Key off the input queue or blocks until one is available. NOTE: In previous versions of Lanterna, this method was not blocking. From lanterna 3, it is blocking and you can call pollInput() for the non-blocking version.
      Returns:
      Key object which represents a keystroke coming in through the input stream
      Throws:
      IOException - Propagated error if the underlying stream gave errors
    • readInput

      private KeyStroke readInput(boolean blocking, boolean useKeyQueue) throws IOException
      Throws:
      IOException
    • flush

      public void flush() throws IOException
      Description copied from interface: Terminal
      Calls flush() on the underlying OutputStream object, or whatever other implementation this terminal is built around. Some implementing classes of this interface (like SwingTerminal) doesn't do anything as it doesn't really apply to them.
      Throws:
      IOException - If there was an underlying I/O error
    • close

      public void close() throws IOException
      Description copied from interface: Terminal
      Closes the terminal, if applicable. If the implementation doesn't support closing the terminal, this will do nothing. The Swing/AWT emulator implementations will translate this into a dispose() call on the UI resources, the telnet implementation will hang out the connection.
      Throws:
      IOException - If there was an underlying I/O error
    • getCharset

      protected Charset getCharset()
    • translateCharacter

      protected byte[] translateCharacter(char input)
    • convertToVT100

      private byte[] convertToVT100(char code)
    • convertToCharset

      private byte[] convertToCharset(char input)