Formatted code to GoogleCodeStyle. Fixed misc warnings

This commit is contained in:
nathan 2014-11-16 21:07:03 +01:00
parent d647d23829
commit 90ee355958
11 changed files with 1137 additions and 1162 deletions

View File

@ -14,9 +14,10 @@ package dorkbox.util.input;
import java.nio.charset.Charset; import java.nio.charset.Charset;
public class Encoding { public class Encoding {
/** /**
* Get the default encoding. Will first look at the LC_CTYPE environment variable, then the input.encoding * Get the default encoding. Will first look at the LC_CTYPE environment variable, then the input.encoding system
* system property, then the default charset according to the JVM. * property, then the default charset according to the JVM.
* *
* @return The default encoding to use when none is specified. * @return The default encoding to use when none is specified.
*/ */

View File

@ -15,6 +15,10 @@
*/ */
package dorkbox.util.input; package dorkbox.util.input;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.slf4j.Logger;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -25,10 +29,6 @@ import java.security.ProtectionDomain;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.slf4j.Logger;
import dorkbox.util.OS; import dorkbox.util.OS;
import dorkbox.util.bytes.ByteBuffer2; import dorkbox.util.bytes.ByteBuffer2;
import dorkbox.util.bytes.ByteBuffer2Poolable; import dorkbox.util.bytes.ByteBuffer2Poolable;
@ -40,18 +40,13 @@ import dorkbox.util.objectPool.ObjectPoolFactory;
import dorkbox.util.objectPool.ObjectPoolHolder; import dorkbox.util.objectPool.ObjectPoolHolder;
public class InputConsole { public class InputConsole {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(InputConsole.class); private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(InputConsole.class);
private static final InputConsole consoleProxyReader = new InputConsole(); private static final InputConsole consoleProxyReader = new InputConsole();
private static final char[] emptyLine = new char[0]; private static final char[] emptyLine = new char[0];
/**
* empty method to allow code to initialize the input console.
*/
public static void init() {
}
// this is run by our init... // this is run by our init...
{ static {
AnsiConsole.systemInstall(); AnsiConsole.systemInstall();
Thread consoleThread = new Thread(new Runnable() { Thread consoleThread = new Thread(new Runnable() {
@ -81,8 +76,21 @@ public class InputConsole {
Runtime.getRuntime().addShutdownHook(shutdownThread); Runtime.getRuntime().addShutdownHook(shutdownThread);
} }
/** return null if no data */ /**
public static final String readLine() { * Permit our InputConsole to be initialized
*/
public static void init() {
if (logger.isDebugEnabled()) {
logger.debug("Created Terminal: {} ({}w x {}h)", consoleProxyReader.terminal.getClass().getSimpleName(),
consoleProxyReader.terminal.getWidth(),
consoleProxyReader.terminal.getHeight());
}
}
/**
* return null if no data
*/
public static String readLine() {
char[] line = consoleProxyReader.readLine0(); char[] line = consoleProxyReader.readLine0();
return new String(line); return new String(line);
} }
@ -100,13 +108,17 @@ public class InputConsole {
}; };
/** return -1 if no data */ /**
public static final int read() { * return -1 if no data
*/
public static int read() {
return consoleProxyReader.read0(); return consoleProxyReader.read0();
} }
/** return null if no data */ /**
public static final char[] readLinePassword() { * return null if no data
*/
public static char[] readLinePassword() {
return consoleProxyReader.readLinePassword0(); return consoleProxyReader.readLinePassword0();
} }
@ -133,7 +145,9 @@ public class InputConsole {
private ThreadLocal<Integer> threadBufferCounter = new ThreadLocal<Integer>(); private ThreadLocal<Integer> threadBufferCounter = new ThreadLocal<Integer>();
private ThreadLocal<ObjectPoolHolder<ByteBuffer2>> readLineBuff = new ThreadLocal<ObjectPoolHolder<ByteBuffer2>>(); private ThreadLocal<ObjectPoolHolder<ByteBuffer2>> readLineBuff = new ThreadLocal<ObjectPoolHolder<ByteBuffer2>>();
private List<ObjectPoolHolder<ByteBuffer2>> readLineBuffers = new CopyOnWriteArrayList<ObjectPoolHolder<ByteBuffer2>>(); private List<ObjectPoolHolder<ByteBuffer2>>
readLineBuffers =
new CopyOnWriteArrayList<ObjectPoolHolder<ByteBuffer2>>();
private final Terminal terminal; private final Terminal terminal;
private final Boolean enableBackspace; private final Boolean enableBackspace;
@ -147,11 +161,11 @@ public class InputConsole {
try { try {
readers2 = Integer.parseInt(readers); readers2 = Integer.parseInt(readers);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
} }
} }
this.pool = ObjectPoolFactory.create(new ByteBuffer2Poolable(), readers2); this.pool = ObjectPoolFactory.create(new ByteBuffer2Poolable(), readers2);
String type = System.getProperty(TerminalType.TYPE, TerminalType.AUTO).toLowerCase(); String type = System.getProperty(TerminalType.TYPE, TerminalType.AUTO).toLowerCase();
if ("dumb".equals(System.getenv("TERM"))) { if ("dumb".equals(System.getenv("TERM"))) {
type = TerminalType.NONE; type = TerminalType.NONE;
@ -164,20 +178,18 @@ public class InputConsole {
} }
} }
Terminal t; Terminal t;
try { try {
if (type.equals(TerminalType.UNIX)) { if (type.equals(TerminalType.UNIX)) {
t = new UnixTerminal(); t = new UnixTerminal();
} } else if (type.equals(TerminalType.WIN) || type.equals(TerminalType.WINDOWS)) {
else if (type.equals(TerminalType.WIN) || type.equals(TerminalType.WINDOWS)) {
t = new WindowsTerminal(); t = new WindowsTerminal();
} } else if (type.equals(TerminalType.NONE) || type.equals(TerminalType.OFF) || type.equals(TerminalType.FALSE)) {
else if (type.equals(TerminalType.NONE) || type.equals(TerminalType.OFF) || type.equals(TerminalType.FALSE)) {
t = new UnsupportedTerminal(); t = new UnsupportedTerminal();
} else { } else {
if (isIDEAutoDetect()) { if (isIDEAutoDetect()) {
logger.debug("Terminal is in UNSUPPORTED (best guess). Unable to support single key input. Only line input available."); logger.debug(
"Terminal is in UNSUPPORTED (best guess). Unable to support single key input. Only line input available.");
t = new UnsupportedTerminal(); t = new UnsupportedTerminal();
} else { } else {
if (OS.isWindows()) { if (OS.isWindows()) {
@ -187,16 +199,14 @@ public class InputConsole {
} }
} }
} }
} } catch (Exception e) {
catch (Exception e) {
logger.error("Failed to construct terminal, falling back to unsupported"); logger.error("Failed to construct terminal, falling back to unsupported");
t = new UnsupportedTerminal(); t = new UnsupportedTerminal();
} }
try { try {
t.init(); t.init();
} } catch (Throwable e) {
catch (Throwable e) {
logger.error("Terminal initialization failed, falling back to unsupported"); logger.error("Terminal initialization failed, falling back to unsupported");
t = new UnsupportedTerminal(); t = new UnsupportedTerminal();
@ -211,7 +221,6 @@ public class InputConsole {
this.terminal = t; this.terminal = t;
this.enableBackspace = Boolean.parseBoolean(System.getProperty(TerminalType.ENABLE_BACKSPACE, "true")); this.enableBackspace = Boolean.parseBoolean(System.getProperty(TerminalType.ENABLE_BACKSPACE, "true"));
logger.debug("Created Terminal: {} ({}x{})", t.getClass().getSimpleName(), t.getWidth(), t.getHeight());
} }
// called when the JVM is shutting down. // called when the JVM is shutting down.
@ -243,11 +252,13 @@ public class InputConsole {
return this.terminal.isEchoEnabled(); return this.terminal.isEchoEnabled();
} }
/** return -1 if no data or bunged-up */ /**
private final int read0() { * return -1 if no data or bunged-up
*/
private int read0() {
Integer bufferCounter = this.threadBufferCounter.get(); Integer bufferCounter = this.threadBufferCounter.get();
ObjectPoolHolder<ByteBuffer2> objectPoolHolder = this.readBuff.get(); ObjectPoolHolder<ByteBuffer2> objectPoolHolder = this.readBuff.get();
ByteBuffer2 buffer = null; ByteBuffer2 buffer;
if (objectPoolHolder == null) { if (objectPoolHolder == null) {
bufferCounter = 0; bufferCounter = 0;
@ -283,8 +294,10 @@ public class InputConsole {
return c; return c;
} }
/** return empty char[] if no data */ /**
private final char[] readLinePassword0() { * return empty char[] if no data
*/
private char[] readLinePassword0() {
// don't bother in an IDE. it won't work. // don't bother in an IDE. it won't work.
boolean echoEnabled = this.terminal.isEchoEnabled(); boolean echoEnabled = this.terminal.isEchoEnabled();
this.terminal.setEchoEnabled(false); this.terminal.setEchoEnabled(false);
@ -294,8 +307,10 @@ public class InputConsole {
return readLine0; return readLine0;
} }
/** return empty char[] if no data */ /**
private final char[] readLine0() { * return empty char[] if no data
*/
private char[] readLine0() {
synchronized (this.inputLock) { synchronized (this.inputLock) {
// empty here, because we don't want to register a readLine WHILE we are still processing // empty here, because we don't want to register a readLine WHILE we are still processing
// the current line info. // the current line info.
@ -351,7 +366,7 @@ public class InputConsole {
} }
} }
private final void run() { private void run() {
Logger logger2 = logger; Logger logger2 = logger;
final boolean ansiEnabled = Ansi.isEnabled(); final boolean ansiEnabled = Ansi.isEnabled();
@ -383,7 +398,6 @@ public class InputConsole {
this.inputLockSingle.notifyAll(); this.inputLockSingle.notifyAll();
} }
// now to handle readLine stuff // now to handle readLine stuff
// if we type a backspace key, swallow it + previous in READLINE. READCHAR will have it passed. // if we type a backspace key, swallow it + previous in READLINE. READCHAR will have it passed.
@ -429,14 +443,12 @@ public class InputConsole {
out.flush(); out.flush();
} }
} }
} } else if (asChar == '\n') {
else if (asChar == '\n') {
// ignoring \r, because \n is ALWAYS the last character in a new line sequence. (even for windows) // ignoring \r, because \n is ALWAYS the last character in a new line sequence. (even for windows)
synchronized (this.inputLockLine) { synchronized (this.inputLockLine) {
this.inputLockLine.notifyAll(); this.inputLockLine.notifyAll();
} }
} } else {
else {
// only append if we are not a new line. // only append if we are not a new line.
// our windows console PREVENTS us from returning '\r' (it truncates '\r\n', and returns just '\n') // our windows console PREVENTS us from returning '\r' (it truncates '\r\n', and returns just '\n')
for (ObjectPoolHolder<ByteBuffer2> objectPoolHolder : this.readLineBuffers) { for (ObjectPoolHolder<ByteBuffer2> objectPoolHolder : this.readLineBuffers) {
@ -462,7 +474,7 @@ public class InputConsole {
File locFile = new File(loc.getFile()); File locFile = new File(loc.getFile());
return locFile.isDirectory(); return locFile.isDirectory();
} catch (Exception e) { } catch (Exception ignored) {
} }
// fall-back to unsupported // fall-back to unsupported
@ -471,25 +483,22 @@ public class InputConsole {
/** /**
* Return the number of characters that will be printed when the specified * Return the number of characters that will be printed when the specified character is echoed to the screen
* character is echoed to the screen
* *
* Adapted from cat by Torbjorn Granlund, as repeated in stty by David MacKenzie. * Adapted from cat by Torbjorn Granlund, as repeated in stty by David MacKenzie.
*/ */
public static int getPrintableCharacters(final int ch) { private static int getPrintableCharacters(final int ch) {
// StringBuilder sbuff = new StringBuilder(); // StringBuilder sbuff = new StringBuilder();
if (ch >= 32) { if (ch >= 32) {
if (ch < 127) { if (ch < 127) {
// sbuff.append((char) ch); // sbuff.append((char) ch);
return 1; return 1;
} } else if (ch == 127) {
else if (ch == 127) {
// sbuff.append('^'); // sbuff.append('^');
// sbuff.append('?'); // sbuff.append('?');
return 2; return 2;
} } else {
else {
// sbuff.append('M'); // sbuff.append('M');
// sbuff.append('-'); // sbuff.append('-');
int count = 2; int count = 2;
@ -498,22 +507,19 @@ public class InputConsole {
if (ch < 128 + 127) { if (ch < 128 + 127) {
// sbuff.append((char) (ch - 128)); // sbuff.append((char) (ch - 128));
count++; count++;
} } else {
else {
// sbuff.append('^'); // sbuff.append('^');
// sbuff.append('?'); // sbuff.append('?');
count += 2; count += 2;
} }
} } else {
else {
// sbuff.append('^'); // sbuff.append('^');
// sbuff.append((char) (ch - 128 + 64)); // sbuff.append((char) (ch - 128 + 64));
count += 2; count += 2;
} }
return count; return count;
} }
} } else {
else {
// sbuff.append('^'); // sbuff.append('^');
// sbuff.append((char) (ch + 64)); // sbuff.append((char) (ch + 64));
return 2; return 2;

View File

@ -18,15 +18,16 @@ package dorkbox.util.input;
import java.io.IOException; import java.io.IOException;
public abstract class Terminal { public abstract class Terminal {
protected final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass()); protected final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
public static final int DEFAULT_WIDTH = 80; protected static final int DEFAULT_WIDTH = 80;
public static final int DEFAULT_HEIGHT = 24; protected static final int DEFAULT_HEIGHT = 24;
private volatile boolean echoEnabled; private volatile boolean echoEnabled;
public Terminal() { protected Terminal() {
} }
public abstract void init() throws IOException; public abstract void init() throws IOException;
@ -42,6 +43,7 @@ public abstract class Terminal {
} }
public abstract int getWidth(); public abstract int getWidth();
public abstract int getHeight(); public abstract int getHeight();
/** /**

View File

@ -16,6 +16,7 @@
package dorkbox.util.input; package dorkbox.util.input;
public class TerminalType { public class TerminalType {
public static final String TYPE = "input.terminal"; public static final String TYPE = "input.terminal";
public static final String READERS = "input.terminal.readers"; public static final String READERS = "input.terminal.readers";
public static final String ENABLE_BACKSPACE = "input.enableBackspace"; public static final String ENABLE_BACKSPACE = "input.enableBackspace";

View File

@ -32,25 +32,22 @@ import java.nio.charset.UnmappableCharacterException;
/** /**
* * NOTE for JLine: the default InputStreamReader that comes from the JRE usually read more bytes than needed from the
* NOTE for JLine: the default InputStreamReader that comes from the JRE * input stream, which is not usable in a character per character model used in the console. We thus use the harmony
* usually read more bytes than needed from the input stream, which * code which only reads the minimal number of bytes, with a modification to ensure we can read larger characters
* is not usable in a character per character model used in the console. * (UTF-16 has up to 4 bytes, and UTF-32, rare as it is, may have up to 8).
* We thus use the harmony code which only reads the minimal number of bytes,
* with a modification to ensure we can read larger characters (UTF-16 has
* up to 4 bytes, and UTF-32, rare as it is, may have up to 8).
* *
* *
* A class for turning a byte stream into a character stream. Data read from the * A class for turning a byte stream into a character stream. Data read from the source input stream is converted into
* source input stream is converted into characters by either a default or a * characters by either a default or a provided character converter. The default encoding is taken from the
* provided character converter. The default encoding is taken from the * "file.encoding" system property. {@code InputStreamReader} contains a buffer of bytes read from the source stream and
* "file.encoding" system property. {@code InputStreamReader} contains a buffer * converts these into characters as needed. The buffer size is 8K.
* of bytes read from the source stream and converts these into characters as
* needed. The buffer size is 8K.
* *
* @see OutputStreamWriter * @see OutputStreamWriter
*/ */
public class InputStreamReader extends Reader { @SuppressWarnings("ALL")
class InputStreamReader extends Reader {
private InputStream in; private InputStream in;
private static final int BUFFER_SIZE = 8192; private static final int BUFFER_SIZE = 8192;
@ -64,13 +61,11 @@ public class InputStreamReader extends Reader {
ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE); ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE);
/** /**
* Constructs a new {@code InputStreamReader} on the {@link InputStream} * Constructs a new {@code InputStreamReader} on the {@link InputStream} {@code in}. This constructor sets the
* {@code in}. This constructor sets the character converter to the encoding * character converter to the encoding specified in the "file.encoding" property and falls back to ISO 8859_1
* specified in the "file.encoding" property and falls back to ISO 8859_1
* (ISO-Latin-1) if the property doesn't exist. * (ISO-Latin-1) if the property doesn't exist.
* *
* @param in * @param in the input stream from which to read characters.
* the input stream from which to read characters.
*/ */
public InputStreamReader(InputStream in) { public InputStreamReader(InputStream in) {
super(in); super(in);
@ -84,19 +79,14 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Constructs a new InputStreamReader on the InputStream {@code in}. The * Constructs a new InputStreamReader on the InputStream {@code in}. The character converter that is used to decode
* character converter that is used to decode bytes into characters is * bytes into characters is identified by name by {@code enc}. If the encoding cannot be found, an
* identified by name by {@code enc}. If the encoding cannot be found, an
* UnsupportedEncodingException error is thrown. * UnsupportedEncodingException error is thrown.
* *
* @param in * @param in the InputStream from which to read characters.
* the InputStream from which to read characters. * @param enc identifies the character converter to use.
* @param enc * @throws NullPointerException if {@code enc} is {@code null}.
* identifies the character converter to use. * @throws UnsupportedEncodingException if the encoding specified by {@code enc} cannot be found.
* @throws NullPointerException
* if {@code enc} is {@code null}.
* @throws UnsupportedEncodingException
* if the encoding specified by {@code enc} cannot be found.
*/ */
public InputStreamReader(InputStream in, final String enc) public InputStreamReader(InputStream in, final String enc)
// throws UnsupportedEncodingException // throws UnsupportedEncodingException
@ -121,13 +111,10 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Constructs a new InputStreamReader on the InputStream {@code in} and * Constructs a new InputStreamReader on the InputStream {@code in} and CharsetDecoder {@code dec}.
* CharsetDecoder {@code dec}.
* *
* @param in * @param in the source InputStream from which to read characters.
* the source InputStream from which to read characters. * @param dec the CharsetDecoder used by the character conversion.
* @param dec
* the CharsetDecoder used by the character conversion.
*/ */
public InputStreamReader(InputStream in, CharsetDecoder dec) { public InputStreamReader(InputStream in, CharsetDecoder dec) {
super(in); super(in);
@ -138,13 +125,10 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Constructs a new InputStreamReader on the InputStream {@code in} and * Constructs a new InputStreamReader on the InputStream {@code in} and Charset {@code charset}.
* Charset {@code charset}.
* *
* @param in * @param in the source InputStream from which to read characters.
* the source InputStream from which to read characters. * @param charset the Charset that defines the character converter
* @param charset
* the Charset that defines the character converter
*/ */
public InputStreamReader(InputStream in, Charset charset) { public InputStreamReader(InputStream in, Charset charset) {
super(in); super(in);
@ -156,11 +140,9 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Closes this reader. This implementation closes the source InputStream and * Closes this reader. This implementation closes the source InputStream and releases all local storage.
* releases all local storage.
* *
* @throws IOException * @throws IOException if an error occurs attempting to close this reader.
* if an error occurs attempting to close this reader.
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
@ -174,11 +156,10 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Returns the name of the encoding used to convert bytes into characters. * Returns the name of the encoding used to convert bytes into characters. The value {@code null} is returned if this
* The value {@code null} is returned if this reader has been closed. * reader has been closed.
* *
* @return the name of the character converter or {@code null} if this * @return the name of the character converter or {@code null} if this reader is closed.
* reader is closed.
*/ */
public String getEncoding() { public String getEncoding() {
if (!isOpen()) { if (!isOpen()) {
@ -188,16 +169,12 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Reads a single character from this reader and returns it as an integer * Reads a single character from this reader and returns it as an integer with the two higher-order bytes set to 0.
* with the two higher-order bytes set to 0. Returns -1 if the end of the * Returns -1 if the end of the reader has been reached. The byte value is either obtained from converting bytes in
* reader has been reached. The byte value is either obtained from * this reader's buffer or by first filling the buffer from the source InputStream and then reading from the buffer.
* converting bytes in this reader's buffer or by first filling the buffer
* from the source InputStream and then reading from the buffer.
* *
* @return the character read or -1 if the end of the reader has been * @return the character read or -1 if the end of the reader has been reached.
* reached. * @throws IOException if this reader is closed or some other I/O error occurs.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/ */
@Override @Override
public int read() throws IOException { public int read() throws IOException {
@ -212,28 +189,18 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Reads at most {@code length} characters from this reader and stores them * Reads at most {@code length} characters from this reader and stores them at position {@code offset} in the
* at position {@code offset} in the character array {@code buf}. Returns * character array {@code buf}. Returns the number of characters actually read or -1 if the end of the reader has been
* the number of characters actually read or -1 if the end of the reader has * reached. The bytes are either obtained from converting bytes in this reader's buffer or by first filling the buffer
* been reached. The bytes are either obtained from converting bytes in this * from the source InputStream and then reading from the buffer.
* reader's buffer or by first filling the buffer from the source
* InputStream and then reading from the buffer.
* *
* @param buf * @param buf the array to store the characters read.
* the array to store the characters read. * @param offset the initial position in {@code buf} to store the characters read from this reader.
* @param offset * @param length the maximum number of characters to read.
* the initial position in {@code buf} to store the characters * @return the number of characters read or -1 if the end of the reader has been reached.
* read from this reader. * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code length < 0}, or if {@code offset + length} is
* @param length * greater than the length of {@code buf}.
* the maximum number of characters to read. * @throws IOException if this reader is closed or some other I/O error occurs.
* @return the number of characters read or -1 if the end of the reader has
* been reached.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code length < 0}, or if
* {@code offset + length} is greater than the length of
* {@code buf}.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/ */
@Override @Override
public int read(char[] buf, int offset, int length) throws IOException { public int read(char[] buf, int offset, int length) throws IOException {
@ -322,17 +289,14 @@ public class InputStreamReader extends Reader {
} }
/** /**
* Indicates whether this reader is ready to be read without blocking. If * Indicates whether this reader is ready to be read without blocking. If the result is {@code true}, the next {@code
* the result is {@code true}, the next {@code read()} will not block. If * read()} will not block. If the result is {@code false} then this reader may or may not block when {@code read()} is
* the result is {@code false} then this reader may or may not block when * called. This implementation returns {@code true} if there are bytes available in the buffer or the source stream
* {@code read()} is called. This implementation returns {@code true} if * has bytes available.
* there are bytes available in the buffer or the source stream has bytes
* available.
* *
* @return {@code true} if the receiver will not block when {@code read()} * @return {@code true} if the receiver will not block when {@code read()} is called, {@code false} if unknown or
* is called, {@code false} if unknown or blocking will occur. * blocking will occur.
* @throws IOException * @throws IOException if this reader is closed or some other I/O error occurs.
* if this reader is closed or some other I/O error occurs.
*/ */
@Override @Override
public boolean ready() throws IOException { public boolean ready() throws IOException {

View File

@ -15,11 +15,13 @@
*/ */
package dorkbox.util.input.posix; package dorkbox.util.input.posix;
import java.nio.ByteBuffer;
import com.sun.jna.Library; import com.sun.jna.Library;
public interface PosixTerminalControl extends Library { import java.nio.ByteBuffer;
@SuppressWarnings("ALL")
interface PosixTerminalControl extends Library {
public static final int TCSANOW = 0; public static final int TCSANOW = 0;
public static final int TBUFLEN = 124; public static final int TBUFLEN = 124;

View File

@ -15,29 +15,47 @@
*/ */
package dorkbox.util.input.posix; package dorkbox.util.input.posix;
import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import com.sun.jna.Structure; @SuppressWarnings("ALL")
class TermiosStruct extends Structure {
public class TermiosStruct extends Structure { /**
/** input mode flags */ * input mode flags
*/
public int c_iflag; public int c_iflag;
/** output mode flags */ /**
* output mode flags
*/
public int c_oflag; public int c_oflag;
/** control mode flags */ /**
* control mode flags
*/
public int c_cflag; public int c_cflag;
/** local mode flags */ /**
* local mode flags
*/
public int c_lflag; public int c_lflag;
/** line discipline */ /**
* line discipline
*/
public byte c_line; public byte c_line;
/** control characters */ /**
* control characters
*/
public byte[] c_cc = new byte[32]; public byte[] c_cc = new byte[32];
/** input speed */ /**
* input speed
*/
public int c_ispeed; public int c_ispeed;
/** output speed */ /**
* output speed
*/
public int c_ospeed; public int c_ospeed;
public TermiosStruct() { public TermiosStruct() {

View File

@ -15,18 +15,18 @@
*/ */
package dorkbox.util.input.posix; package dorkbox.util.input.posix;
import com.sun.jna.Native;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.sun.jna.Native;
import dorkbox.util.input.Encoding; import dorkbox.util.input.Encoding;
import dorkbox.util.input.Terminal; import dorkbox.util.input.Terminal;
/** /**
* Terminal that is used for unix platforms. Terminal initialization * Terminal that is used for unix platforms. Terminal initialization is handled via JNA and
* is handled via JNA and ioctl/tcgetattr/tcsetattr/cfmakeraw. * ioctl/tcgetattr/tcsetattr/cfmakeraw.
* *
* This implementation should work for an reasonable POSIX system. * This implementation should work for an reasonable POSIX system.
*/ */
@ -35,9 +35,9 @@ public class UnixTerminal extends Terminal {
private volatile TermiosStruct termInfoDefault = new TermiosStruct(); private volatile TermiosStruct termInfoDefault = new TermiosStruct();
private volatile TermiosStruct termInfo = new TermiosStruct(); private volatile TermiosStruct termInfo = new TermiosStruct();
private Reader reader; private final Reader reader;
private PosixTerminalControl term; private final PosixTerminalControl term;
private ByteBuffer windowSizeBuffer = ByteBuffer.allocate(8); private ByteBuffer windowSizeBuffer = ByteBuffer.allocate(8);
@ -84,10 +84,10 @@ public class UnixTerminal extends Terminal {
this.termInfo.c_iflag &= ~PosixTerminalControl.IXON; // DISABLE - flow control mediated by ^S and ^Q this.termInfo.c_iflag &= ~PosixTerminalControl.IXON; // DISABLE - flow control mediated by ^S and ^Q
// struct.c_iflag |= PosixTerminalControl.IUTF8; // DISABLE - flow control mediated by ^S and ^Q // struct.c_iflag |= PosixTerminalControl.IUTF8; // DISABLE - flow control mediated by ^S and ^Q
this.termInfo.c_lflag &= ~PosixTerminalControl.ICANON; // DISABLE - canonical mode (pass chars straight through to terminal) this.termInfo.c_lflag &=
~PosixTerminalControl.ICANON; // DISABLE - canonical mode (pass chars straight through to terminal)
// struct.c_lflag &= ~PosixTerminalControl.ISIG; // DISABLE - When any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate the corresponding signal. // struct.c_lflag &= ~PosixTerminalControl.ISIG; // DISABLE - When any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate the corresponding signal.
// If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before the read is satisfied. As TIME is zero, the timer is not used. // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before the read is satisfied. As TIME is zero, the timer is not used.
this.termInfo.c_cc[PosixTerminalControl.VMIN] = 1; // Minimum number of characters for noncanonical read (MIN). this.termInfo.c_cc[PosixTerminalControl.VMIN] = 1; // Minimum number of characters for noncanonical read (MIN).
this.termInfo.c_cc[PosixTerminalControl.VTIME] = 0; // Timeout in deciseconds for noncanonical read (TIME). this.termInfo.c_cc[PosixTerminalControl.VTIME] = 0; // Timeout in deciseconds for noncanonical read (TIME).
@ -96,16 +96,14 @@ public class UnixTerminal extends Terminal {
this.termInfo.c_cc[PosixTerminalControl.VEOF] = 0; // eof disabled this.termInfo.c_cc[PosixTerminalControl.VEOF] = 0; // eof disabled
this.termInfo.c_cc[PosixTerminalControl.VEOL] = 0; // eol disabled this.termInfo.c_cc[PosixTerminalControl.VEOL] = 0; // eol disabled
if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) { if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) {
throw new IOException("Can not set terminal flags"); throw new IOException("Can not set terminal flags");
} }
} }
/** /**
* Restore the original terminal configuration, which can be used when * Restore the original terminal configuration, which can be used when shutting down the console reader. The
* shutting down the console reader. The ConsoleReader cannot be * ConsoleReader cannot be used after calling this method.
* used after calling this method.
*/ */
@Override @Override
public final void restore() throws IOException { public final void restore() throws IOException {
@ -123,8 +121,7 @@ public class UnixTerminal extends Terminal {
return DEFAULT_WIDTH; return DEFAULT_WIDTH;
} }
short columns = (short)(0x000000FF &this.windowSizeBuffer.get(2) + (0x000000FF & this.windowSizeBuffer.get(3)) * 256); return (short) (0x000000FF & this.windowSizeBuffer.get(2) + (0x000000FF & this.windowSizeBuffer.get(3)) * 256);
return columns;
} }
/** /**
@ -136,8 +133,8 @@ public class UnixTerminal extends Terminal {
return DEFAULT_HEIGHT; return DEFAULT_HEIGHT;
} }
short rows = (short)(0x000000FF &this.windowSizeBuffer.get(0) + (0x000000FF & this.windowSizeBuffer.get(1)) * 256); return
return rows; (short) (0x000000FF & this.windowSizeBuffer.get(0) + (0x000000FF & this.windowSizeBuffer.get(1)) * 256);
} }
@Override @Override
@ -149,8 +146,7 @@ public class UnixTerminal extends Terminal {
if (enabled) { if (enabled) {
this.termInfo.c_lflag |= PosixTerminalControl.ECHO; // ENABLE Echo input characters. this.termInfo.c_lflag |= PosixTerminalControl.ECHO; // ENABLE Echo input characters.
} } else {
else {
this.termInfo.c_lflag &= ~PosixTerminalControl.ECHO; // DISABLE Echo input characters. this.termInfo.c_lflag &= ~PosixTerminalControl.ECHO; // DISABLE Echo input characters.
} }

View File

@ -23,10 +23,10 @@ import dorkbox.util.input.Terminal;
public class UnsupportedTerminal extends Terminal { public class UnsupportedTerminal extends Terminal {
private ByteBuffer2 buffer = new ByteBuffer2(8, -1); private final ByteBuffer2 buffer = new ByteBuffer2(8, -1);
private int readerCount = -1; private int readerCount = -1;
private InputStream in; private final InputStream in;
public UnsupportedTerminal() { public UnsupportedTerminal() {
this.in = System.in; this.in = System.in;
@ -73,18 +73,16 @@ public class UnsupportedTerminal extends Terminal {
this.buffer.writeChar(asChar); this.buffer.writeChar(asChar);
} }
} }
} catch (IOException e1) { } catch (IOException ignored) {
} }
} }
// EACH thread will have it's own count! // EACH thread will have it's own count!
if (this.readerCount == this.buffer.position()) { if (this.readerCount == this.buffer.position()) {
this.readerCount = -1; this.readerCount = -1;
return '\n'; return '\n';
} else { } else {
char c = this.buffer.readChar(); return this.buffer.readChar();
return c;
} }
} }
} }

View File

@ -12,52 +12,42 @@
package dorkbox.util.input.windows; package dorkbox.util.input.windows;
/** /**
* Console mode * Console mode <p/> Constants copied <tt>wincon.h</tt>.
* <p/>
* Constants copied <tt>wincon.h</tt>.
*/ */
public enum ConsoleMode { public enum ConsoleMode {
/** /**
* The ReadFile or ReadConsole function returns only when a carriage return * The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is
* character is read. If this mode is disable, the functions return when one * disable, the functions return when one or more characters are available.
* or more characters are available.
*/ */
ENABLE_LINE_INPUT(2), ENABLE_LINE_INPUT(2),
/** /**
* Characters read by the ReadFile or ReadConsole function are written to * Characters read by the ReadFile or ReadConsole function are written to the active screen buffer as they are read.
* the active screen buffer as they are read. This mode can be used only if * This mode can be used only if the ENABLE_LINE_INPUT mode is also enabled.
* the ENABLE_LINE_INPUT mode is also enabled.
*/ */
ENABLE_ECHO_INPUT(4), ENABLE_ECHO_INPUT(4),
/** /**
* CTRL+C is processed by the system and is not placed in the input buffer. * CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer is being read by
* If the input buffer is being read by ReadFile or ReadConsole, other * ReadFile or ReadConsole, other control keys are processed by the system and are not returned in the ReadFile or
* control keys are processed by the system and are not returned in the * ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also enabled, backspace, carriage return, and linefeed
* ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also * characters are handled by the system.
* enabled, backspace, carriage return, and linefeed characters are handled
* by the system.
*/ */
ENABLE_PROCESSED_INPUT(1), ENABLE_PROCESSED_INPUT(1),
/** /**
* User interactions that change the size of the console screen buffer are * User interactions that change the size of the console screen buffer are reported in the console's input buffee.
* reported in the console's input buffee. Information about these events * Information about these events can be read from the input buffer by applications using theReadConsoleInput
* can be read from the input buffer by applications using * function, but not by those using ReadFile orReadConsole.
* theReadConsoleInput function, but not by those using ReadFile
* orReadConsole.
*/ */
ENABLE_WINDOW_INPUT(8), ENABLE_WINDOW_INPUT(8),
/** /**
* If the mouse pointer is within the borders of the console window and the * If the mouse pointer is within the borders of the console window and the window has the keyboard focus, mouse
* window has the keyboard focus, mouse events generated by mouse movement * events generated by mouse movement and button presses are placed in the input buffer. These events are discarded by
* and button presses are placed in the input buffer. These events are * ReadFile or ReadConsole, even when this mode is enabled.
* discarded by ReadFile or ReadConsole, even when this mode is enabled.
*/ */
ENABLE_MOUSE_INPUT(16), ENABLE_MOUSE_INPUT(16),;
;
public final int code; public final int code;

View File

@ -11,27 +11,25 @@
*/ */
package dorkbox.util.input.windows; package dorkbox.util.input.windows;
import java.io.IOException;
import java.io.PrintStream;
import org.fusesource.jansi.internal.Kernel32.INPUT_RECORD; import org.fusesource.jansi.internal.Kernel32.INPUT_RECORD;
import org.fusesource.jansi.internal.Kernel32.KEY_EVENT_RECORD; import org.fusesource.jansi.internal.Kernel32.KEY_EVENT_RECORD;
import org.fusesource.jansi.internal.WindowsSupport; import org.fusesource.jansi.internal.WindowsSupport;
import java.io.IOException;
import java.io.PrintStream;
import dorkbox.util.input.Terminal; import dorkbox.util.input.Terminal;
/** /**
* Terminal implementation for Microsoft Windows. Terminal initialization in * Terminal implementation for Microsoft Windows. Terminal initialization in {@link #init} is accomplished by calling
* {@link #init} is accomplished by calling the Win32 APIs <a * the Win32 APIs <a href="http://msdn.microsoft.com/library/default.asp? url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a>
* href="http://msdn.microsoft.com/library/default.asp? * and <a href="http://msdn.microsoft.com/library/default.asp? url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a>
* url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a> and * to disable character echoing. <p/>
* <a href="http://msdn.microsoft.com/library/default.asp? *
* url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a> to
* disable character echoing.
* <p/>
* @since 2.0 (customized) * @since 2.0 (customized)
*/ */
public class WindowsTerminal extends Terminal { public class WindowsTerminal extends Terminal {
private volatile int originalMode; private volatile int originalMode;
private final PrintStream out; private final PrintStream out;
@ -52,9 +50,8 @@ public class WindowsTerminal extends Terminal {
} }
/** /**
* Restore the original terminal configuration, which can be used when * Restore the original terminal configuration, which can be used when shutting down the console reader. The
* shutting down the console reader. The ConsoleReader cannot be * ConsoleReader cannot be used after calling this method.
* used after calling this method.
*/ */
@Override @Override
public final void restore() throws IOException { public final void restore() throws IOException {
@ -92,10 +89,10 @@ public class WindowsTerminal extends Terminal {
return input; return input;
} }
private final int readInput() { private int readInput() {
// this HOOKS the input event, and prevents it from going to the console "proper" // this HOOKS the input event, and prevents it from going to the console "proper"
try { try {
INPUT_RECORD[] events = null; INPUT_RECORD[] events;
while (true) { while (true) {
// we ALWAYS read until we have an event we care about! // we ALWAYS read until we have an event we care about!
events = WindowsSupport.readConsoleInput(1); events = WindowsSupport.readConsoleInput(1);