// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Klipspringer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.
package net.avadeaux.klipspringer;
import java.io.IOException;
import net.avadeaux.klipspringer.codec.Library;
/** Unix terminal stuff. */
public class Terminal {
static {
Library.init();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try { cancelNonCanonical(); } catch (IOException ex) { }
}
});
}
private static boolean nonCanonical = false, interruptEnabled = false;
/** Checks if input is a terminal that can be used for interaction. */
public static native boolean inTty();
/** Checks if output is a terminal that can be used for interaction. */
public static native boolean outTty();
/** Checks if error output is a terminal that can be used for interaction. */
public static native boolean errTty();
/** Prepares for using {@link #getChar()} for getting keypresses interactively, by disabling
* canonical mode and echoing. Terminal input will not function normally again until {@link
* #stopKeyListen()} called. Does nothing if already in key listening mode.
*/
public static synchronized void startKeyListen() throws IOException {
if (nonCanonical) { return; }
setupNonCanonical();
nonCanonical = true;
}
/** Reset terminal input to normal operation after invoking {@link #startKeyListen()}. Does
* nothing if terminal is not in key listening mode.
*/
public static synchronized void stopKeyListen() throws IOException {
if (!nonCanonical) { return; }
cancelNonCanonical();
nonCanonical = false;
}
/** Prepares for prematurely interrupting {@link #getChar()} by setting up a signal
* handler. Does nothing if already in interruptable mode.
*/
public static synchronized void enableInterruptGetChar() throws IOException {
if (interruptEnabled) { return; }
setupSigaction();
interruptEnabled = true;
}
/** Restores signal handler to normal, disabling the possibility to interrupt {@link
* #getChar()}. Does nothing if not in interruptable mode.
*/
public static synchronized void disableInterruptGetChar() throws IOException {
if (!interruptEnabled) { return; }
cancelSigaction();
interruptEnabled = false;
}
/** Gets a single character from terminal input. If canonical mode has been disabled by calling
* {@link #startKeyListen()}, this can be used for interactively getting a keypress, without
* waiting for newline. Returns {@code -1} if interrupted.
*/
public static native int getChar() throws IOException;
/** If there is a {@link #getChar()} in progress, and {@link #enableInterruptGetChar} has been
* enable, make it terminate early and return {@code -1}, by sending a signal to its
* thread. Throws {@link IllegalStateExe
*/
public static synchronized void interruptGetChar() throws IOException {
if (!interruptEnabled) { throw new IllegalStateException("Not in interruptable state"); }
sigThread();
}
private static native void setupNonCanonical() throws IOException;
private static native void cancelNonCanonical() throws IOException;
private static native void setupSigaction() throws IOException;
private static native void cancelSigaction() throws IOException;
private static native void sigThread() throws IOException;
}
Version: v4.3.2.2 (2026-05-16T17:03:34+02:00)
Raw file
Source code overview
Klipspringer home