2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * Copyright (C) 2010-2015 Martin
19 package com
.googlecode
.lanterna
.terminal
.ansi
;
21 import com
.googlecode
.lanterna
.TerminalSize
;
24 import java
.nio
.charset
.Charset
;
25 import java
.util
.ArrayList
;
26 import java
.util
.Arrays
;
27 import java
.util
.List
;
28 import java
.util
.regex
.Matcher
;
29 import java
.util
.regex
.Pattern
;
32 * This class extends UnixLikeTerminal and implements the Cygwin-specific implementations. This means, running a Java
33 * application using Lanterna inside the Cygwin Terminal application. The standard Windows command prompt (cmd.exe) is
34 * not supported by this class.<p>
36 * <b>NOTE:</b> This class is experimental and does not fully work! Some of the operations, like disabling echo and
37 * changing cbreak seems to be impossible to do without resorting to native code. Running "stty raw" before starting the
38 * JVM will improve compatibility.
43 public class CygwinTerminal
extends UnixLikeTerminal
{
45 private static final Pattern STTY_SIZE_PATTERN
= Pattern
.compile(".*rows ([0-9]+);.*columns ([0-9]+);.*");
46 private static final String STTY_LOCATION
= findProgram("stty.exe");
49 * Creates a new CygwinTerminal based off input and output streams and a character set to use
50 * @param terminalInput Input stream to read input from
51 * @param terminalOutput Output stream to write output to
52 * @param terminalCharset Character set to use when writing to the output stream
53 * @throws IOException If there was an I/O error when trying to initialize the class and setup the terminal
55 public CygwinTerminal(
56 InputStream terminalInput
,
57 OutputStream terminalOutput
,
58 Charset terminalCharset
) throws IOException
{
59 super(terminalInput
, terminalOutput
, terminalCharset
,
60 CtrlCBehaviour
.TRAP
, null);
62 //Make sure to set an initial size
68 sttyMinimum1CharacterForRead();
73 public TerminalSize
getTerminalSize() {
75 String stty
= exec(findSTTY(), "-F", getPseudoTerminalDevice(), "-a");
76 Matcher matcher
= STTY_SIZE_PATTERN
.matcher(stty
);
77 if(matcher
.matches()) {
78 return new TerminalSize(Integer
.parseInt(matcher
.group(2)), Integer
.parseInt(matcher
.group(1)));
81 return new TerminalSize(80, 24);
85 return new TerminalSize(80, 24);
90 protected void sttyKeyEcho(final boolean enable
) throws IOException
{
91 runSTTYCommand(enable ?
"echo" : "-echo");
95 protected void sttyMinimum1CharacterForRead() throws IOException
{
96 runSTTYCommand("min", "1");
100 protected void sttyICanon(final boolean enable
) throws IOException
{
101 runSTTYCommand(enable ?
"icanon" : "cbreak");
105 protected String
sttySave() throws IOException
{
106 return runSTTYCommand("-g").trim();
110 protected void sttyRestore(String tok
) throws IOException
{
114 protected String
findSTTY() {
115 return STTY_LOCATION
;
118 private String
runSTTYCommand(String
... parameters
) throws IOException
{
119 List
<String
> commandLine
= new ArrayList
<String
>(Arrays
.asList(
122 getPseudoTerminalDevice()));
123 commandLine
.addAll(Arrays
.asList(parameters
));
124 return exec(commandLine
.toArray(new String
[commandLine
.size()]));
127 private String
getPseudoTerminalDevice() {
128 //This will only work if you only have one terminal window open, otherwise we'll need to figure out somehow
129 //which pty to use, which could be very tricky...
133 private static String
findProgram(String programName
) {
134 String
[] paths
= System
.getProperty("java.library.path").split(";");
135 for(String path
: paths
) {
136 File shBin
= new File(path
, programName
);
138 return shBin
.getAbsolutePath();