Change build scripts
[jvcard.git] / src / com / googlecode / lanterna / terminal / ansi / UnixTerminal.java
1 /*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
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.
8 *
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.
13 *
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/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19 package com.googlecode.lanterna.terminal.ansi;
20
21
22 import java.io.*;
23 import java.nio.charset.Charset;
24
25 import com.googlecode.lanterna.TerminalSize;
26
27 /**
28 * This class extends UnixLikeTerminal and implements the Unix-specific parts.
29 * <p>
30 * If you need to have Lanterna to call stty at a different location, you'll need to
31 * subclass this and override {@code getSTTYCommand()}.
32 *
33 * @author Martin
34 */
35 @SuppressWarnings("WeakerAccess")
36 public class UnixTerminal extends UnixLikeTerminal {
37
38 protected final UnixTerminalSizeQuerier terminalSizeQuerier;
39 private final boolean catchSpecialCharacters;
40
41 /**
42 * Creates a UnixTerminal with default settings, using System.in and System.out for input/output, using the default
43 * character set on the system as the encoding and trap ctrl+c signal instead of killing the application.
44 * @throws IOException If there was an I/O error initializing the terminal
45 */
46 public UnixTerminal() throws IOException {
47 this(System.in, System.out, Charset.defaultCharset());
48 }
49
50 /**
51 * Creates a UnixTerminal using a specified input stream, output stream and character set. Ctrl+c signal will be
52 * trapped instead of killing the application.
53 *
54 * @param terminalInput Input stream to read terminal input from
55 * @param terminalOutput Output stream to write terminal output to
56 * @param terminalCharset Character set to use when converting characters to bytes
57 * @throws java.io.IOException If there was an I/O error initializing the terminal
58 */
59 public UnixTerminal(
60 InputStream terminalInput,
61 OutputStream terminalOutput,
62 Charset terminalCharset) throws IOException {
63 this(terminalInput, terminalOutput, terminalCharset, null);
64 }
65
66 /**
67 * Creates a UnixTerminal using a specified input stream, output stream and character set, with a custom size
68 * querier instead of using the default one. This way you can override size detection (if you want to force the
69 * terminal to a fixed size, for example). Ctrl+c signal will be trapped instead of killing the application.
70 *
71 * @param terminalInput Input stream to read terminal input from
72 * @param terminalOutput Output stream to write terminal output to
73 * @param terminalCharset Character set to use when converting characters to bytes
74 * @param customSizeQuerier Object to use for looking up the size of the terminal, or null to use the built-in
75 * method
76 * @throws java.io.IOException If there was an I/O error initializing the terminal
77 */
78 @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
79 public UnixTerminal(
80 InputStream terminalInput,
81 OutputStream terminalOutput,
82 Charset terminalCharset,
83 UnixTerminalSizeQuerier customSizeQuerier) throws IOException {
84 this(terminalInput, terminalOutput, terminalCharset, customSizeQuerier, CtrlCBehaviour.CTRL_C_KILLS_APPLICATION);
85 }
86
87 /**
88 * Creates a UnixTerminal using a specified input stream, output stream and character set, with a custom size
89 * querier instead of using the default one. This way you can override size detection (if you want to force the
90 * terminal to a fixed size, for example). You also choose how you want ctrl+c key strokes to be handled.
91 *
92 * @param terminalInput Input stream to read terminal input from
93 * @param terminalOutput Output stream to write terminal output to
94 * @param terminalCharset Character set to use when converting characters to bytes
95 * @param customSizeQuerier Object to use for looking up the size of the terminal, or null to use the built-in
96 * method
97 * @param terminalCtrlCBehaviour Special settings on how the terminal will behave, see {@code UnixTerminalMode} for more
98 * details
99 * @throws java.io.IOException If there was an I/O error initializing the terminal
100 */
101 @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
102 public UnixTerminal(
103 InputStream terminalInput,
104 OutputStream terminalOutput,
105 Charset terminalCharset,
106 UnixTerminalSizeQuerier customSizeQuerier,
107 CtrlCBehaviour terminalCtrlCBehaviour) throws IOException {
108 super(terminalInput,
109 terminalOutput,
110 terminalCharset,
111 terminalCtrlCBehaviour,
112 new File("/dev/tty"));
113
114 this.terminalSizeQuerier = customSizeQuerier;
115
116 //Make sure to set an initial size
117 onResized(80, 24);
118
119 setupWinResizeHandler();
120 saveSTTY();
121 setCBreak(true);
122 setEcho(false);
123 sttyMinimum1CharacterForRead();
124 if("false".equals(System.getProperty("com.googlecode.lanterna.terminal.UnixTerminal.catchSpecialCharacters", "").trim().toLowerCase())) {
125 catchSpecialCharacters = false;
126 }
127 else {
128 catchSpecialCharacters = true;
129 disableSpecialCharacters();
130 }
131 setupShutdownHook();
132 }
133
134 @Override
135 public TerminalSize getTerminalSize() throws IOException {
136 if(terminalSizeQuerier != null) {
137 return terminalSizeQuerier.queryTerminalSize();
138 }
139
140 return super.getTerminalSize();
141 }
142
143 @Override
144 protected void sttyKeyEcho(final boolean enable) throws IOException {
145 exec(getSTTYCommand(), enable ? "echo" : "-echo");
146 }
147
148 @Override
149 protected void sttyMinimum1CharacterForRead() throws IOException {
150 exec(getSTTYCommand(), "min", "1");
151 }
152
153 @Override
154 protected void sttyICanon(final boolean enable) throws IOException {
155 exec(getSTTYCommand(), enable ? "icanon" : "-icanon");
156 }
157
158 @Override
159 protected String sttySave() throws IOException {
160 return exec(getSTTYCommand(), "-g").trim();
161 }
162
163 @Override
164 protected void sttyRestore(String tok) throws IOException {
165 exec(getSTTYCommand(), tok);
166 }
167
168 /*
169 //What was the problem with this one? I don't remember... Restoring ctrl+c for now (see below)
170 private void restoreEOFCtrlD() throws IOException {
171 exec(getShellCommand(), "-c", getSTTYCommand() + " eof ^d < /dev/tty");
172 }
173
174 private void disableSpecialCharacters() throws IOException {
175 exec(getShellCommand(), "-c", getSTTYCommand() + " intr undef < /dev/tty");
176 exec(getShellCommand(), "-c", getSTTYCommand() + " start undef < /dev/tty");
177 exec(getShellCommand(), "-c", getSTTYCommand() + " stop undef < /dev/tty");
178 exec(getShellCommand(), "-c", getSTTYCommand() + " susp undef < /dev/tty");
179 }
180
181 private void restoreSpecialCharacters() throws IOException {
182 exec(getShellCommand(), "-c", getSTTYCommand() + " intr ^C < /dev/tty");
183 exec(getShellCommand(), "-c", getSTTYCommand() + " start ^Q < /dev/tty");
184 exec(getShellCommand(), "-c", getSTTYCommand() + " stop ^S < /dev/tty");
185 exec(getShellCommand(), "-c", getSTTYCommand() + " susp ^Z < /dev/tty");
186 }
187 */
188
189
190 /**
191 * This method causes certain keystrokes (at the moment only ctrl+c) to be passed in to the program instead of
192 * interpreted by the shell and affect the program. For example, ctrl+c will send an interrupt that causes the
193 * JVM to shut down, but this method will make it pass in ctrl+c as a normal KeyStroke instead (you can still make
194 * ctrl+c kill the application, but Lanterna can do this for you after having restored the terminal).
195 * <p>
196 * Please note that this method is generally called automatically (i.e. it's turned on by default), unless you
197 * define a system property "com.googlecode.lanterna.terminal.UnixTerminal.catchSpecialCharacters" and set it to
198 * the string "false".
199 * @throws IOException If there was an I/O error when attempting to disable special characters
200 * @see com.googlecode.lanterna.terminal.ansi.UnixLikeTerminal.CtrlCBehaviour
201 */
202 public void disableSpecialCharacters() throws IOException {
203 exec(getSTTYCommand(), "intr", "undef");
204 }
205
206 /**
207 * This method restores the special characters disabled by {@code disableSpecialCharacters()}, if it has been
208 * called.
209 * @throws IOException If there was an I/O error when attempting to restore special characters
210 */
211 public void restoreSpecialCharacters() throws IOException {
212 exec(getSTTYCommand(), "intr", "^C");
213 }
214
215 @Override
216 protected synchronized void restoreSTTY() throws IOException {
217 super.restoreSTTY();
218 if(catchSpecialCharacters) {
219 restoreSpecialCharacters();
220 }
221 }
222
223 protected String getSTTYCommand() {
224 return "/bin/stty";
225 }
226
227 }