Commit 611f12e2 authored by apvrille's avatar apvrille

Adding terminal facility

parent e6277c04
......@@ -26,6 +26,7 @@
<root url="jar://$PROJECT_DIR$/libs/batik-xml.jar!/" />
<root url="jar://$PROJECT_DIR$/libs/jautomata-core.jar!/" />
<root url="jar://$PROJECT_DIR$/libs/com.microsoft.z3.jar!/" />
<root url="jar://$PROJECT_DIR$/libs/jna-3.3.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/libs/commons-io-2.5-javadoc.jar!/" />
......
......@@ -26,6 +26,7 @@ dependencies {
compileOnly name: 'commons-codec-1.10'
compileOnly name: 'jsoup-1.8.1'
compile name: 'jautomata-core'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -21,6 +21,7 @@ dependencies {
compileOnly name: 'commons-codec-1.10'
compileOnly name: 'jsoup-1.8.1'
compile name: 'jautomata-core'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -15,6 +15,7 @@ dependencies {
compile name: 'commons-codec-1.10'
compileOnly name: 'commons-io-2.5'
compileOnly name: 'jsoup-1.8.1'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -25,6 +25,7 @@ dependencies {
compileOnly name:'batik-util'
compile name:'jautomata-core'
compile name:'com.microsoft.z3'
compileOnly name: 'jna-3.3.0'
}
jar {
......
// Copyright 2015 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms of any of the following licenses:
//
// LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html
// EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
//
// Home page: http://www.source-code.biz/snippets/java/RawConsoleInput
package myutil;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
/**
* A JNA based driver for reading single characters from the console.
*
* <p>This class is used for console mode programs.
* It supports non-blocking reads of single key strokes without echo.
*/
public class RawConsoleInput {
private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
private static final int invalidKey = 0xFFFE;
private static final String invalidKeyStr = String.valueOf((char)invalidKey);
private static boolean initDone;
private static boolean stdinIsConsole;
private static boolean consoleModeAltered;
/**
* Reads a character from the console without echo.
*
* @param wait
* <code>true</code> to wait until an input character is available,
* <code>false</code> to return immediately if no character is available.
* @return
* -2 if <code>wait</code> is <code>false</code> and no character is available.
* -1 on EOF.
* Otherwise an Unicode character code within the range 0 to 0xFFFF.
*/
public static int read (boolean wait) throws IOException {
if (isWindows) {
return readWindows(wait); }
else {
return readUnix(wait); }}
/**
* Resets console mode to normal line mode with echo.
*
* <p>On Windows this method re-enables Ctrl-C processing.
*
* <p>On Unix this method switches the console back to echo mode.
* read() leaves the console in non-echo mode.
*/
public static void resetConsoleMode() throws IOException {
if (isWindows) {
resetConsoleModeWindows(); }
else {
resetConsoleModeUnix(); }}
private static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook( new Thread() {
public void run() {
shutdownHook(); }}); }
private static void shutdownHook() {
try {
resetConsoleMode(); }
catch (Exception e) {}}
//--- Windows ------------------------------------------------------------------
// The Windows version uses _kbhit() and _getwch() from msvcrt.dll.
private static Msvcrt msvcrt;
private static Kernel32 kernel32;
private static Pointer consoleHandle;
private static int originalConsoleMode;
private static int readWindows (boolean wait) throws IOException {
initWindows();
if (!stdinIsConsole) {
int c = msvcrt.getwchar();
if (c == 0xFFFF) {
c = -1; }
return c; }
consoleModeAltered = true;
setConsoleMode(consoleHandle, originalConsoleMode & ~Kernel32Defs.ENABLE_PROCESSED_INPUT);
// ENABLE_PROCESSED_INPUT must remain off to prevent Ctrl-C from beeing processed by the system
// while the program is not within getwch().
if (!wait && msvcrt._kbhit() == 0) {
return -2; } // no key available
return getwch(); }
private static int getwch() {
int c = msvcrt._getwch();
if (c == 0 || c == 0xE0) { // Function key or arrow key
c = msvcrt._getwch();
if (c >= 0 && c <= 0x18FF) {
return 0xE000 + c; } // construct key code in private Unicode range
return invalidKey; }
if (c < 0 || c > 0xFFFF) {
return invalidKey; }
return c; } // normal key
private static synchronized void initWindows() throws IOException {
if (initDone) {
return; }
msvcrt = (Msvcrt)Native.loadLibrary("msvcrt", Msvcrt.class);
kernel32 = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
try {
consoleHandle = getStdInputHandle();
originalConsoleMode = getConsoleMode(consoleHandle);
stdinIsConsole = true; }
catch (IOException e) {
stdinIsConsole = false; }
if (stdinIsConsole) {
registerShutdownHook(); }
initDone = true; }
private static Pointer getStdInputHandle() throws IOException {
Pointer handle = kernel32.GetStdHandle(Kernel32Defs.STD_INPUT_HANDLE);
if (Pointer.nativeValue(handle) == 0 || Pointer.nativeValue(handle) == Kernel32Defs.INVALID_HANDLE_VALUE) {
throw new IOException("GetStdHandle(STD_INPUT_HANDLE) failed."); }
return handle; }
private static int getConsoleMode (Pointer handle) throws IOException {
IntByReference mode = new IntByReference();
int rc = kernel32.GetConsoleMode(handle, mode);
if (rc == 0) {
throw new IOException("GetConsoleMode() failed."); }
return mode.getValue(); }
private static void setConsoleMode (Pointer handle, int mode) throws IOException {
int rc = kernel32.SetConsoleMode(handle, mode);
if (rc == 0) {
throw new IOException("SetConsoleMode() failed."); }}
private static void resetConsoleModeWindows() throws IOException {
if (!initDone || !stdinIsConsole || !consoleModeAltered) {
return; }
setConsoleMode(consoleHandle, originalConsoleMode);
consoleModeAltered = false; }
private static interface Msvcrt extends Library {
int _kbhit();
int _getwch();
int getwchar(); }
private static class Kernel32Defs {
static final int STD_INPUT_HANDLE = -10;
static final long INVALID_HANDLE_VALUE = (Pointer.SIZE == 8) ? -1 : 0xFFFFFFFFL;
static final int ENABLE_PROCESSED_INPUT = 0x0001;
static final int ENABLE_LINE_INPUT = 0x0002;
static final int ENABLE_ECHO_INPUT = 0x0004;
static final int ENABLE_WINDOW_INPUT = 0x0008; }
private static interface Kernel32 extends Library {
int GetConsoleMode (Pointer hConsoleHandle, IntByReference lpMode);
int SetConsoleMode (Pointer hConsoleHandle, int dwMode);
Pointer GetStdHandle (int nStdHandle); }
//--- Unix ---------------------------------------------------------------------
// The Unix version uses tcsetattr() to switch the console to non-canonical mode,
// System.in.available() to check whether data is available and System.in.read()
// to read bytes from the console.
// A CharsetDecoder is used to convert bytes to characters.
private static final int stdinFd = 0;
private static Libc libc;
private static CharsetDecoder charsetDecoder;
private static Termios originalTermios;
private static Termios rawTermios;
private static Termios intermediateTermios;
private static int readUnix (boolean wait) throws IOException {
initUnix();
if (!stdinIsConsole) { // STDIN is not a console
return readSingleCharFromByteStream(System.in); }
consoleModeAltered = true;
setTerminalAttrs(stdinFd, rawTermios); // switch off canonical mode, echo and signals
try {
if (!wait && System.in.available() == 0) {
return -2; } // no input available
return readSingleCharFromByteStream(System.in); }
finally {
setTerminalAttrs(stdinFd, intermediateTermios); }} // reset some console attributes
private static Termios getTerminalAttrs (int fd) throws IOException {
Termios termios = new Termios();
try {
int rc = libc.tcgetattr(fd, termios);
if (rc != 0) {
throw new RuntimeException("tcgetattr() failed."); }}
catch (LastErrorException e) {
throw new IOException("tcgetattr() failed.", e); }
return termios; }
private static void setTerminalAttrs (int fd, Termios termios) throws IOException {
try {
int rc = libc.tcsetattr(fd, LibcDefs.TCSANOW, termios);
if (rc != 0) {
throw new RuntimeException("tcsetattr() failed."); }}
catch (LastErrorException e) {
throw new IOException("tcsetattr() failed.", e); }}
private static int readSingleCharFromByteStream (InputStream inputStream) throws IOException {
byte[] inBuf = new byte[4];
int inLen = 0;
while (true) {
if (inLen >= inBuf.length) { // input buffer overflow
return invalidKey; }
int b = inputStream.read(); // read next byte
if (b == -1) { // EOF
return -1; }
inBuf[inLen++] = (byte)b;
int c = decodeCharFromBytes(inBuf, inLen);
if (c != -1) {
return c; }}}
// (This method is synchronized because the charsetDecoder must only be used by a single thread at once.)
private static synchronized int decodeCharFromBytes (byte[] inBytes, int inLen) {
charsetDecoder.reset();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE);
charsetDecoder.replaceWith(invalidKeyStr);
ByteBuffer in = ByteBuffer.wrap(inBytes, 0, inLen);
CharBuffer out = CharBuffer.allocate(1);
charsetDecoder.decode(in, out, false);
if (out.position() == 0) {
return -1; }
return out.get(0); }
private static synchronized void initUnix() throws IOException {
if (initDone) {
return; }
libc = (Libc)Native.loadLibrary("c", Libc.class);
stdinIsConsole = libc.isatty(stdinFd) == 1;
charsetDecoder = Charset.defaultCharset().newDecoder();
if (stdinIsConsole) {
originalTermios = getTerminalAttrs(stdinFd);
rawTermios = new Termios(originalTermios);
rawTermios.c_lflag &= ~(LibcDefs.ICANON | LibcDefs.ECHO | LibcDefs.ECHONL | LibcDefs.ISIG);
intermediateTermios = new Termios(rawTermios);
intermediateTermios.c_lflag |= LibcDefs.ICANON;
// Canonical mode can be switched off between the read() calls, but echo must remain disabled.
registerShutdownHook(); }
initDone = true; }
private static void resetConsoleModeUnix() throws IOException {
if (!initDone || !stdinIsConsole || !consoleModeAltered) {
return; }
setTerminalAttrs(stdinFd, originalTermios);
consoleModeAltered = false; }
protected static class Termios extends Structure { // termios.h
public int c_iflag;
public int c_oflag;
public int c_cflag;
public int c_lflag;
public byte c_line;
public byte[] filler = new byte[64]; // actual length is platform dependent
@Override protected List<String> getFieldOrder() {
return Arrays.asList("c_iflag", "c_oflag", "c_cflag", "c_lflag", "c_line", "filler"); }
Termios() {}
Termios (Termios t) {
c_iflag = t.c_iflag;
c_oflag = t.c_oflag;
c_cflag = t.c_cflag;
c_lflag = t.c_lflag;
c_line = t.c_line;
filler = t.filler.clone(); }}
private static class LibcDefs {
// termios.h
static final int ISIG = 0000001;
static final int ICANON = 0000002;
static final int ECHO = 0000010;
static final int ECHONL = 0000100;
static final int TCSANOW = 0; }
private static interface Libc extends Library {
// termios.h
int tcgetattr (int fd, Termios termios) throws LastErrorException;
int tcsetattr (int fd, int opt, Termios termios) throws LastErrorException;
// unistd.h
int isatty (int fd); }
}
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
*
* ludovic.apvrille AT enst.fr
*
* This software is a computer program whose purpose is to allow the
* edition of TURTLE analysis, design and deployment diagrams, to
* allow the generation of RT-LOTOS or Java code from this diagram,
* and at last to allow the analysis of formal validation traces
* obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
* from INRIA Rhone-Alpes.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
package myutil;
import java.util.Vector;
/**
* Class GenericTree
* Creation: 13/03/2003
* Version 2.0 25/10/2007
* @author Ludovic APVRILLE
*/
public class Terminal {
private final static int MAX_BUFFER_SIZE = 5000;
private Vector<String> buffer;
int maxbufferSize = MAX_BUFFER_SIZE;
public Terminal() {
buffer = new Vector<>();
}
public String getNextString() {
char x = 110;
int val = 0;
int cpt = 0;
printPrompt(cpt);
String currentBuf = "";
try {
while(val != 3) {
val = (RawConsoleInput.read(true));
x = (char) val;
if (val >= 32) {
//System.out.print("" + x + "(val=" + val + ");");
myPrint(""+x);
currentBuf += x;
}
if (val == 10) {
cpt ++;
myPrint("\n");
printPrompt(cpt);
return currentBuf;
}
}
} catch (Exception e) {
return null;
}
return "";
}
public void myPrint(String s) {
System.out.print(s);
}
public void printHistory() {
int cpt = 1;
for(String s: buffer) {
System.out.println("" + cpt+ ":" + s);
cpt ++;
}
}
public void printPrompt(int cpt) {
System.out.print("" + cpt + "> ");
}
}
......@@ -20,6 +20,7 @@ dependencies {
compileOnly name: 'commons-io-2.5'
compileOnly name: 'jsoup-1.8.1'
compileOnly name: 'commons-codec-1.10'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -26,6 +26,7 @@ dependencies {
compile name: 'commons-math3-3.6.1'
compile name: 'jautomata-core'
compile name: 'com.microsoft.z3'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -34,6 +34,7 @@ dependencies {
compile name: 'batik-awt-util'
compile name: 'jautomata-core'
compile name: 'com.microsoft.z3'
compile name: 'jna-3.3.0'
// Use JUnit test framework
testCompile 'junit:junit:4.12'
......
Main-Class: TToolCLI
Class-Path: jsoup-1.8.1.jar commons-codec-1.10.jar gs-core-1.3.jar gs-ui-1.3.jar commons-io-2.5.jar commons-math3-3.6.1.jar batik-awt-util.jar batik-dom.jar batik-svggen.jar batik-util.jar batik-xml.jar jautomata-core.jar com.microsoft.z3.jar
Class-Path: jsoup-1.8.1.jar commons-codec-1.10.jar gs-core-1.3.jar gs-ui-1.3.jar commons-io-2.5.jar commons-math3-3.6.1.jar batik-awt-util.jar batik-dom.jar batik-svggen.jar batik-util.jar batik-xml.jar jautomata-core.jar com.microsoft.z3.jar jna-3.3.0.jar
Manifest-Version: 1.0
Class-Path: jsoup-1.8.1.jar commons-codec-1.10.jar gs-core-1.3.jar gs-ui-1.3.jar commons-io-2.5.jar commons-math3-3.6.1.jar batik-awt-util.jar batik-dom.jar batik-svggen.jar batik-util.jar batik-xml.jar jautomata-core.jar com.microsoft.z3.jar
Class-Path: jsoup-1.8.1.jar commons-codec-1.10.jar gs-core-1.3.jar gs-ui-1.3.jar commons-io-2.5.jar commons-math3-3.6.1.jar batik-awt-util.jar batik-dom.jar batik-svggen.jar batik-util.jar batik-xml.jar jautomata-core.jar com.microsoft.z3.jar jna-3.3.0.jar
Main-Class: Main
......@@ -38,6 +38,8 @@ dependencies {
compile name: 'assertj/assertj-swing/3.8.0/assertj-swing-3.8.0-sources'
compile name: 'assertj/assertj-swing-junit/3.8.0/assertj-swing-junit-3.8.0'
compile name: 'assertj/assertj-swing-junit/3.8.0/assertj-swing-junit-3.8.0-sources'
compile name: 'jna-3.3.0'
// Use JUnit test framework
testCompile 'junit:junit:4.12'
......
......@@ -22,6 +22,7 @@ dependencies {
compileOnly name: 'JavaPlot'
compileOnly name: 'jaxen-1.1.6'
compileOnly name: 'opencloud'
compileOnly name: 'jna-3.3.0'
}
jar {
......
......@@ -22,6 +22,7 @@ dependencies {
compile name: 'JavaPlot'
compile name: 'jaxen-1.1.6'
compile name: 'opencloud'
compileOnly name: 'jna-3.3.0'
}
jar {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment