blob: b6e981eee577ccac742e0c740e20118c6e6136c9 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.terminal;
import android.graphics.Color;
/**
* Single terminal session backed by a pseudo terminal on the local device.
*/
public class Terminal {
public static final String TAG = "Terminal";
public final int key;
private static int sNumber = 0;
static {
System.loadLibrary("jni_terminal");
}
/**
* Represents a run of one or more {@code VTermScreenCell} which all have
* the same formatting.
*/
public static class CellRun {
char[] data;
int dataSize;
int colSize;
boolean bold;
int underline;
boolean blink;
boolean reverse;
boolean strike;
int font;
int fg = Color.CYAN;
int bg = Color.DKGRAY;
}
// NOTE: clients must not call back into terminal while handling a callback,
// since native mutex isn't reentrant.
public interface TerminalClient {
public void onDamage(int startRow, int endRow, int startCol, int endCol);
public void onMoveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol,
int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol);
public void onMoveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible);
public void onBell();
}
private final long mNativePtr;
private final Thread mThread;
private String mTitle;
private TerminalClient mClient;
private boolean mCursorVisible;
private int mCursorRow;
private int mCursorCol;
private final TerminalCallbacks mCallbacks = new TerminalCallbacks() {
@Override
public int damage(int startRow, int endRow, int startCol, int endCol) {
if (mClient != null) {
mClient.onDamage(startRow, endRow, startCol, endCol);
}
return 1;
}
@Override
public int moveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol,
int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol) {
if (mClient != null) {
mClient.onMoveRect(destStartRow, destEndRow, destStartCol, destEndCol, srcStartRow,
srcEndRow, srcStartCol, srcEndCol);
}
return 1;
}
@Override
public int moveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible) {
mCursorVisible = (visible != 0);
mCursorRow = posRow;
mCursorCol = posCol;
if (mClient != null) {
mClient.onMoveCursor(posRow, posCol, oldPosRow, oldPosCol, visible);
}
return 1;
}
@Override
public int bell() {
if (mClient != null) {
mClient.onBell();
}
return 1;
}
};
public Terminal() {
mNativePtr = nativeInit(mCallbacks);
key = sNumber++;
mTitle = TAG + " " + key;
mThread = new Thread(mTitle) {
@Override
public void run() {
nativeRun(mNativePtr);
}
};
}
/**
* Start thread which internally forks and manages the pseudo terminal.
*/
public void start() {
mThread.start();
}
public void destroy() {
if (nativeDestroy(mNativePtr) != 0) {
throw new IllegalStateException("destroy failed");
}
}
public void setClient(TerminalClient client) {
mClient = client;
}
public void resize(int rows, int cols, int scrollRows) {
if (nativeResize(mNativePtr, rows, cols, scrollRows) != 0) {
throw new IllegalStateException("resize failed");
}
}
public int getRows() {
return nativeGetRows(mNativePtr);
}
public int getCols() {
return nativeGetCols(mNativePtr);
}
public int getScrollRows() {
return nativeGetScrollRows(mNativePtr);
}
public void getCellRun(int row, int col, CellRun run) {
if (nativeGetCellRun(mNativePtr, row, col, run) != 0) {
throw new IllegalStateException("getCell failed");
}
}
public boolean getCursorVisible() {
return mCursorVisible;
}
public int getCursorRow() {
return mCursorRow;
}
public int getCursorCol() {
return mCursorCol;
}
public String getTitle() {
// TODO: hook up to title passed through termprop
return mTitle;
}
public boolean dispatchKey(int modifiers, int key) {
return nativeDispatchKey(mNativePtr, modifiers, key);
}
public boolean dispatchCharacter(int modifiers, int character) {
return nativeDispatchCharacter(mNativePtr, modifiers, character);
}
private static native long nativeInit(TerminalCallbacks callbacks);
private static native int nativeDestroy(long ptr);
private static native int nativeRun(long ptr);
private static native int nativeResize(long ptr, int rows, int cols, int scrollRows);
private static native int nativeGetCellRun(long ptr, int row, int col, CellRun run);
private static native int nativeGetRows(long ptr);
private static native int nativeGetCols(long ptr);
private static native int nativeGetScrollRows(long ptr);
private static native boolean nativeDispatchKey(long ptr, int modifiers, int key);
private static native boolean nativeDispatchCharacter(long ptr, int modifiers, int character);
}