1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.terminal; 18 19 import android.graphics.Color; 20 21 /** 22 * Single terminal session backed by a pseudo terminal on the local device. 23 */ 24 public class Terminal { 25 public static final String TAG = "Terminal"; 26 27 public final int key; 28 29 private static int sNumber = 0; 30 31 static { 32 System.loadLibrary("jni_terminal"); 33 } 34 35 /** 36 * Represents a run of one or more {@code VTermScreenCell} which all have 37 * the same formatting. 38 */ 39 public static class CellRun { 40 char[] data; 41 int dataSize; 42 int colSize; 43 44 boolean bold; 45 int underline; 46 boolean blink; 47 boolean reverse; 48 boolean strike; 49 int font; 50 51 int fg = Color.CYAN; 52 int bg = Color.DKGRAY; 53 } 54 55 // NOTE: clients must not call back into terminal while handling a callback, 56 // since native mutex isn't reentrant. 57 public interface TerminalClient { 58 public void onDamage(int startRow, int endRow, int startCol, int endCol); 59 public void onMoveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, 60 int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol); 61 public void onMoveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible); 62 public void onBell(); 63 } 64 65 private final long mNativePtr; 66 private final Thread mThread; 67 68 private String mTitle; 69 70 private TerminalClient mClient; 71 72 private boolean mCursorVisible; 73 private int mCursorRow; 74 private int mCursorCol; 75 76 private final TerminalCallbacks mCallbacks = new TerminalCallbacks() { 77 @Override 78 public int damage(int startRow, int endRow, int startCol, int endCol) { 79 if (mClient != null) { 80 mClient.onDamage(startRow, endRow, startCol, endCol); 81 } 82 return 1; 83 } 84 85 @Override 86 public int moveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, 87 int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol) { 88 if (mClient != null) { 89 mClient.onMoveRect(destStartRow, destEndRow, destStartCol, destEndCol, srcStartRow, 90 srcEndRow, srcStartCol, srcEndCol); 91 } 92 return 1; 93 } 94 95 @Override 96 public int moveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible) { 97 mCursorVisible = (visible != 0); 98 mCursorRow = posRow; 99 mCursorCol = posCol; 100 if (mClient != null) { 101 mClient.onMoveCursor(posRow, posCol, oldPosRow, oldPosCol, visible); 102 } 103 return 1; 104 } 105 106 @Override 107 public int bell() { 108 if (mClient != null) { 109 mClient.onBell(); 110 } 111 return 1; 112 } 113 }; 114 115 public Terminal() { 116 mNativePtr = nativeInit(mCallbacks); 117 key = sNumber++; 118 mTitle = TAG + " " + key; 119 mThread = new Thread(mTitle) { 120 @Override 121 public void run() { 122 nativeRun(mNativePtr); 123 } 124 }; 125 } 126 127 /** 128 * Start thread which internally forks and manages the pseudo terminal. 129 */ 130 public void start() { 131 mThread.start(); 132 } 133 134 public void destroy() { 135 if (nativeDestroy(mNativePtr) != 0) { 136 throw new IllegalStateException("destroy failed"); 137 } 138 } 139 140 public void setClient(TerminalClient client) { 141 mClient = client; 142 } 143 144 public void resize(int rows, int cols, int scrollRows) { 145 if (nativeResize(mNativePtr, rows, cols, scrollRows) != 0) { 146 throw new IllegalStateException("resize failed"); 147 } 148 } 149 150 public int getRows() { 151 return nativeGetRows(mNativePtr); 152 } 153 154 public int getCols() { 155 return nativeGetCols(mNativePtr); 156 } 157 158 public int getScrollRows() { 159 return nativeGetScrollRows(mNativePtr); 160 } 161 162 public void getCellRun(int row, int col, CellRun run) { 163 if (nativeGetCellRun(mNativePtr, row, col, run) != 0) { 164 throw new IllegalStateException("getCell failed"); 165 } 166 } 167 168 public boolean getCursorVisible() { 169 return mCursorVisible; 170 } 171 172 public int getCursorRow() { 173 return mCursorRow; 174 } 175 176 public int getCursorCol() { 177 return mCursorCol; 178 } 179 180 public String getTitle() { 181 // TODO: hook up to title passed through termprop 182 return mTitle; 183 } 184 185 public boolean dispatchKey(int modifiers, int key) { 186 return nativeDispatchKey(mNativePtr, modifiers, key); 187 } 188 189 public boolean dispatchCharacter(int modifiers, int character) { 190 return nativeDispatchCharacter(mNativePtr, modifiers, character); 191 } 192 193 private static native long nativeInit(TerminalCallbacks callbacks); 194 private static native int nativeDestroy(long ptr); 195 196 private static native int nativeRun(long ptr); 197 private static native int nativeResize(long ptr, int rows, int cols, int scrollRows); 198 private static native int nativeGetCellRun(long ptr, int row, int col, CellRun run); 199 private static native int nativeGetRows(long ptr); 200 private static native int nativeGetCols(long ptr); 201 private static native int nativeGetScrollRows(long ptr); 202 203 private static native boolean nativeDispatchKey(long ptr, int modifiers, int key); 204 private static native boolean nativeDispatchCharacter(long ptr, int modifiers, int character); 205 } 206