1ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey/* 2ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * 4ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * you may not use this file except in compliance with the License. 6ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * You may obtain a copy of the License at 7ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * 8ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * 10ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * See the License for the specific language governing permissions and 14ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * limitations under the License. 15ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey */ 16ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 17ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#define LOG_TAG "Terminal" 18ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 19ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include <utils/Log.h> 2000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#include <utils/Mutex.h> 2100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#include "android_runtime/AndroidRuntime.h" 2200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 23ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include "jni.h" 24ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include "JNIHelp.h" 25479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey#include "ScopedLocalRef.h" 26479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey#include "ScopedPrimitiveArray.h" 27ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 289a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright#include <fcntl.h> 29ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes#include <pty.h> 309a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright#include <stdio.h> 315d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <termios.h> 329a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright#include <unistd.h> 335d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <util.h> 345d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <utmp.h> 355d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 36ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include <vterm.h> 37ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 38ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include <string.h> 39ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 40c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright#define USE_TEST_SHELL 0 41de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#define DEBUG_CALLBACKS 0 42de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#define DEBUG_IO 0 4300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#define DEBUG_SCROLLBACK 0 44a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey 45ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeynamespace android { 46ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 478c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 488c040334130cea6e44dda03516d86e774d18d376Kenny Root * Callback class reference 498c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 508c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jclass terminalCallbacksClass; 518c040334130cea6e44dda03516d86e774d18d376Kenny Root 528c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 538c040334130cea6e44dda03516d86e774d18d376Kenny Root * Callback methods 548c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 558c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID damageMethod; 568c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID moveRectMethod; 578c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID moveCursorMethod; 588c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropBooleanMethod; 598c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropIntMethod; 608c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropStringMethod; 618c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropColorMethod; 628c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID bellMethod; 638c040334130cea6e44dda03516d86e774d18d376Kenny Root 64410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey/* 659cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey * CellRun class 66410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey */ 679cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkeystatic jclass cellRunClass; 689cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkeystatic jfieldID cellRunDataField; 699cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkeystatic jfieldID cellRunDataSizeField; 709cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkeystatic jfieldID cellRunColSizeField; 71cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkeystatic jfieldID cellRunFgField; 72cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkeystatic jfieldID cellRunBgField; 73cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 7400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeytypedef short unsigned int dimen_t; 7500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 7600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeyclass ScrollbackLine { 7700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeypublic: 7800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey inline ScrollbackLine(dimen_t _cols) : cols(_cols) { 7900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mCells = new VTermScreenCell[cols]; 8000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey }; 8100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey inline ~ScrollbackLine() { 8200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey delete mCells; 8300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 8400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 8500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey inline dimen_t copyFrom(dimen_t cols, const VTermScreenCell* cells) { 8600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t n = this->cols > cols ? cols : this->cols; 8700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memcpy(mCells, cells, sizeof(VTermScreenCell) * n); 8800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return n; 8900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 9000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 9100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey inline dimen_t copyTo(dimen_t cols, VTermScreenCell* cells) { 9200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t n = cols > this->cols ? this->cols : cols; 9300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memcpy(cells, mCells, sizeof(VTermScreenCell) * n); 9400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return n; 9500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 9600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 9700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey inline void getCell(dimen_t col, VTermScreenCell* cell) { 9800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey *cell = mCells[col]; 9900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 10000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 10100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey const dimen_t cols; 10200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 10300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeyprivate: 10400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey VTermScreenCell* mCells; 10500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey}; 10600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 1078c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 1088c040334130cea6e44dda03516d86e774d18d376Kenny Root * Terminal session 1098c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 1108c040334130cea6e44dda03516d86e774d18d376Kenny Rootclass Terminal { 1118c040334130cea6e44dda03516d86e774d18d376Kenny Rootpublic: 112d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshall Terminal(jobject callbacks); 1138c040334130cea6e44dda03516d86e774d18d376Kenny Root ~Terminal(); 1148c040334130cea6e44dda03516d86e774d18d376Kenny Root 11500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey status_t run(); 116479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey 1175d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey size_t write(const char *bytes, size_t len); 118410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 119c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright bool dispatchCharacter(int mod, int character); 120c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright bool dispatchKey(int mod, int key); 121c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright bool flushInput(); 122007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 12300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey status_t resize(dimen_t rows, dimen_t cols, dimen_t scrollRows); 12400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 12500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey status_t onPushline(dimen_t cols, const VTermScreenCell* cells); 12600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey status_t onPopline(dimen_t cols, VTermScreenCell* cells); 127a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey 12800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey void getCellLocked(VTermPos pos, VTermScreenCell* cell); 1295d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 13000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t getRows() const; 13100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t getCols() const; 13200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t getScrollRows() const; 1338c040334130cea6e44dda03516d86e774d18d376Kenny Root 1348c040334130cea6e44dda03516d86e774d18d376Kenny Root jobject getCallbacks() const; 1358c040334130cea6e44dda03516d86e774d18d376Kenny Root 13600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Lock protecting mutations of internal libvterm state 13700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex mLock; 13800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 1398c040334130cea6e44dda03516d86e774d18d376Kenny Rootprivate: 1405d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey int mMasterFd; 14100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey pid_t mChildPid; 1428c040334130cea6e44dda03516d86e774d18d376Kenny Root VTerm *mVt; 1438c040334130cea6e44dda03516d86e774d18d376Kenny Root VTermScreen *mVts; 1448c040334130cea6e44dda03516d86e774d18d376Kenny Root 145410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey jobject mCallbacks; 1468c040334130cea6e44dda03516d86e774d18d376Kenny Root 14700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t mRows; 14800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t mCols; 14900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey bool mKilled; 1508c040334130cea6e44dda03516d86e774d18d376Kenny Root 15100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ScrollbackLine **mScroll; 15200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t mScrollCur; 15300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t mScrollSize; 1548c040334130cea6e44dda03516d86e774d18d376Kenny Root 15500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey}; 156ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 157ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey/* 158ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * VTerm event handlers 159ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey */ 160ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 161ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_damage(VTermRect rect, void *user) { 162ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 163de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 164ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_damage"); 165de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 1668c040334130cea6e44dda03516d86e774d18d376Kenny Root 16700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 1688c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), damageMethod, rect.start_row, rect.end_row, 1698c040334130cea6e44dda03516d86e774d18d376Kenny Root rect.start_col, rect.end_col); 170ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 171ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 172ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_moverect(VTermRect dest, VTermRect src, void *user) { 173ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 174de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 175ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_moverect"); 176de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 1778c040334130cea6e44dda03516d86e774d18d376Kenny Root 17800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 1796a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey return env->CallIntMethod(term->getCallbacks(), moveRectMethod, 1806a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey dest.start_row, dest.end_row, dest.start_col, dest.end_col, 1816a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey src.start_row, src.end_row, src.start_col, src.end_col); 182ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 183ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 184ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user) { 185ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 186de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 187ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_movecursor"); 188de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 1898c040334130cea6e44dda03516d86e774d18d376Kenny Root 19000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 1916a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey return env->CallIntMethod(term->getCallbacks(), moveCursorMethod, pos.row, 1926a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey pos.col, oldpos.row, oldpos.col, visible); 193ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 194ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 195ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_settermprop(VTermProp prop, VTermValue *val, void *user) { 196ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 197de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 198ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_settermprop"); 199de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 2008c040334130cea6e44dda03516d86e774d18d376Kenny Root 20100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 2028c040334130cea6e44dda03516d86e774d18d376Kenny Root switch (vterm_get_prop_type(prop)) { 2038c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_BOOL: 204ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes return env->CallIntMethod(term->getCallbacks(), setTermPropBooleanMethod, prop, 205ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes val->boolean ? JNI_TRUE : JNI_FALSE); 2068c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_INT: 2078c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropIntMethod, prop, val->number); 2088c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_STRING: 2098c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropStringMethod, prop, 2108c040334130cea6e44dda03516d86e774d18d376Kenny Root env->NewStringUTF(val->string)); 2118c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_COLOR: 2128c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropIntMethod, prop, val->color.red, 2138c040334130cea6e44dda03516d86e774d18d376Kenny Root val->color.green, val->color.blue); 2148c040334130cea6e44dda03516d86e774d18d376Kenny Root default: 2158c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("unknown callback type"); 2168c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 2178c040334130cea6e44dda03516d86e774d18d376Kenny Root } 218ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 219ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 220ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_setmousefunc(VTermMouseFunc func, void *data, void *user) { 221ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 222de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 223ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_setmousefunc"); 224de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 225ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return 1; 226ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 227ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 228ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_bell(void *user) { 229ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 230de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 231ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_bell"); 232de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 2338c040334130cea6e44dda03516d86e774d18d376Kenny Root 23400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 2358c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), bellMethod); 236ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 237ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 23800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatic int term_sb_pushline(int cols, const VTermScreenCell *cells, void *user) { 239ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 240de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_CALLBACKS 24100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ALOGW("term_sb_pushline"); 242de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 2438c040334130cea6e44dda03516d86e774d18d376Kenny Root 24400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return term->onPushline(cols, cells); 24500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey} 2468c040334130cea6e44dda03516d86e774d18d376Kenny Root 24700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatic int term_sb_popline(int cols, VTermScreenCell *cells, void *user) { 24800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 24900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#if DEBUG_CALLBACKS 25000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ALOGW("term_sb_popline"); 25100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#endif 25200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 25300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return term->onPopline(cols, cells); 254ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 255ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 256ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic VTermScreenCallbacks cb = { 257ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .damage = term_damage, 258ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .moverect = term_moverect, 259ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .movecursor = term_movecursor, 260ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .settermprop = term_settermprop, 261ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .setmousefunc = term_setmousefunc, 262ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .bell = term_bell, 26300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Resize requests are applied immediately, so callback is ignored 26400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey .resize = NULL, 26500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey .sb_pushline = term_sb_pushline, 26600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey .sb_popline = term_sb_popline, 267ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey}; 268ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 269d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom MarshallTerminal::Terminal(jobject callbacks) : 270d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshall mCallbacks(callbacks), mRows(25), mCols(80), mKilled(false), 27100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mScrollCur(0), mScrollSize(100) { 27200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv* env = AndroidRuntime::getJNIEnv(); 27300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mCallbacks = env->NewGlobalRef(callbacks); 27400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 27500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mScroll = new ScrollbackLine*[mScrollSize]; 27600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memset(mScroll, 0, sizeof(ScrollbackLine*) * mScrollSize); 27700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 278ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey /* Create VTerm */ 279d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshall mVt = vterm_new(mRows, mCols); 280ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_parser_set_utf8(mVt, 1); 281ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 282ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey /* Set up screen */ 283ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey mVts = vterm_obtain_screen(mVt); 284ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_screen_enable_altscreen(mVts, 1); 285ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_screen_set_callbacks(mVts, &cb, this); 2866a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey vterm_screen_set_damage_merge(mVts, VTERM_DAMAGE_SCROLL); 287479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey vterm_screen_reset(mVts, 1); 288479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey} 289ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 290479bd643981271fb0edf756ae5915e44a7352c4dJeff SharkeyTerminal::~Terminal() { 291479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey close(mMasterFd); 29200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ::kill(mChildPid, SIGHUP); 29300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 294479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey vterm_free(mVt); 29500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 29600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey delete mScroll; 29700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 29800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey JNIEnv *env = AndroidRuntime::getJNIEnv(); 29900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey env->DeleteGlobalRef(mCallbacks); 300479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey} 301479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey 30200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatus_t Terminal::run() { 303ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes struct termios termios; 304ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes memset(&termios, 0, sizeof(termios)); 305ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes termios.c_iflag = ICRNL|IXON|IUTF8; 306ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes termios.c_oflag = OPOST|ONLCR|NL0|CR0|TAB0|BS0|VT0|FF0; 307ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes termios.c_cflag = CS8|CREAD; 308ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes termios.c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK; 3095d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 3109a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright cfsetispeed(&termios, B38400); 3119a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright cfsetospeed(&termios, B38400); 3129a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 3139a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VINTR] = 0x1f & 'C'; 3149a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VQUIT] = 0x1f & '\\'; 3159a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VERASE] = 0x7f; 3169a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VKILL] = 0x1f & 'U'; 3179a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VEOF] = 0x1f & 'D'; 3189a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VSTART] = 0x1f & 'Q'; 3199a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VSTOP] = 0x1f & 'S'; 3209a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VSUSP] = 0x1f & 'Z'; 3219a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VREPRINT] = 0x1f & 'R'; 3229a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VWERASE] = 0x1f & 'W'; 3239a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VLNEXT] = 0x1f & 'V'; 3249a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VMIN] = 1; 3259a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright termios.c_cc[VTIME] = 0; 3269a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 3279a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright struct winsize size = { mRows, mCols, 0, 0 }; 3289a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 3299a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright int stderr_save_fd = dup(2); 3309a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright if (stderr_save_fd < 0) { 3319a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright ALOGE("failed to dup stderr - %s", strerror(errno)); 3329a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright } 3339a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 33400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mChildPid = forkpty(&mMasterFd, NULL, &termios, &size); 33500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mChildPid == 0) { 3369a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright /* Restore the ISIG signals back to defaults */ 3379a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright signal(SIGINT, SIG_DFL); 3389a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright signal(SIGQUIT, SIG_DFL); 3399a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright signal(SIGSTOP, SIG_DFL); 3409a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright signal(SIGCONT, SIG_DFL); 3419a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 3429a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright FILE *stderr_save = fdopen(stderr_save_fd, "a"); 3439a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 3449a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright if (!stderr_save) { 3459a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright ALOGE("failed to open stderr - %s", strerror(errno)); 3469a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright } 3479a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 348ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes // We know execvp(2) won't actually try to modify this. 349ffbad51da16422bab578c6616a714ad05ae20d73Elliott Hughes char *shell = const_cast<char*>("/system/bin/sh"); 350de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if USE_TEST_SHELL 35100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey char *args[4] = {shell, "-c", "x=1; c=0; while true; do echo -e \"stop \e[00;3${c}mechoing\e[00m yourself! ($x)\"; x=$(( $x + 1 )); c=$((($c+1)%7)); if [ $x -gt 110 ]; then sleep 0.5; fi; done", NULL}; 352a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey#else 3539a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright char *args[2] = {shell, NULL}; 354a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey#endif 355a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey 3569a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright execvp(shell, args); 3579a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright fprintf(stderr_save, "Cannot exec(%s) - %s\n", shell, strerror(errno)); 3589a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright _exit(1); 3599a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright } 3609a0032b22232e66c29d49091dbdc6c8ea87a3785Michael Wright 361cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey ALOGD("entering read() loop"); 362d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey while (1) { 363d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey char buffer[4096]; 364d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey ssize_t bytes = ::read(mMasterFd, buffer, sizeof buffer); 365de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#if DEBUG_IO 366de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey ALOGD("read() returned %d bytes", bytes); 367de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey#endif 368d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey 36900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mKilled) { 37000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ALOGD("kill() requested"); 371de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey break; 372de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey } 373479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey if (bytes == 0) { 374479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey ALOGD("read() found EOF"); 375479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey break; 376d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey } 377479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey if (bytes == -1) { 378479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey ALOGE("read() failed: %s", strerror(errno)); 379d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey return 1; 380d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey } 381d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey 38200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey { 38300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex::Autolock lock(mLock); 38400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey vterm_push_bytes(mVt, buffer, bytes); 38500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey vterm_screen_flush_damage(mVts); 38600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 387d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey } 388479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey 389de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey return 0; 390de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey} 391de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey 392479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkeysize_t Terminal::write(const char *bytes, size_t len) { 393479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey return ::write(mMasterFd, bytes, len); 394479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey} 395479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey 396c8be1790590605603a8dca8f9ee93327c916de3fMichael Wrightbool Terminal::dispatchCharacter(int mod, int character) { 39700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex::Autolock lock(mLock); 398303dab01fa211d0da20136049196e3321241cad8Michael Wright vterm_input_push_char(mVt, static_cast<VTermModifier>(mod), character); 399c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright return flushInput(); 400007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright} 401007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 402c8be1790590605603a8dca8f9ee93327c916de3fMichael Wrightbool Terminal::dispatchKey(int mod, int key) { 40300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex::Autolock lock(mLock); 404007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright vterm_input_push_key(mVt, static_cast<VTermModifier>(mod), static_cast<VTermKey>(key)); 405c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright return flushInput(); 406007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright} 407007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 408c8be1790590605603a8dca8f9ee93327c916de3fMichael Wrightbool Terminal::flushInput() { 409007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright size_t len = vterm_output_get_buffer_current(mVt); 410007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright if (len) { 411007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright char buf[len]; 412007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright len = vterm_output_bufferread(mVt, buf, len); 413c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright return len == write(buf, len); 414007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright } 415c8be1790590605603a8dca8f9ee93327c916de3fMichael Wright return true; 416007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright} 417007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 41800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatus_t Terminal::resize(dimen_t rows, dimen_t cols, dimen_t scrollRows) { 41900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex::Autolock lock(mLock); 420a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey 42100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ALOGD("resize(%d, %d, %d)", rows, cols, scrollRows); 422cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 4235d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey mRows = rows; 4245d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey mCols = cols; 42500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // TODO: resize scrollback 426cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 4275d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey struct winsize size = { rows, cols, 0, 0 }; 4285d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey ioctl(mMasterFd, TIOCSWINSZ, &size); 429cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 430cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey vterm_set_size(mVt, rows, cols); 431cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey vterm_screen_flush_damage(mVts); 432cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 433410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return 0; 434410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 435410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 43600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatus_t Terminal::onPushline(dimen_t cols, const VTermScreenCell* cells) { 43700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ScrollbackLine* line = NULL; 43800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mScrollCur == mScrollSize) { 43900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey /* Recycle old row if it's the right size */ 44000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mScroll[mScrollCur - 1]->cols == cols) { 44100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey line = mScroll[mScrollCur - 1]; 44200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } else { 44300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey delete mScroll[mScrollCur - 1]; 44400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 44500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 44600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memmove(mScroll + 1, mScroll, sizeof(ScrollbackLine*) * (mScrollCur - 1)); 44700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } else if (mScrollCur > 0) { 44800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memmove(mScroll + 1, mScroll, sizeof(ScrollbackLine*) * mScrollCur); 44900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 45000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 45100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (line == NULL) { 45200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey line = new ScrollbackLine(cols); 45300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 45400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 45500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mScroll[0] = line; 45600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 45700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mScrollCur < mScrollSize) { 45800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mScrollCur++; 45900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 46000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 46100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey line->copyFrom(cols, cells); 46200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return 1; 4635d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 4645d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 46500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatus_t Terminal::onPopline(dimen_t cols, VTermScreenCell* cells) { 46600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (mScrollCur == 0) { 46700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return 0; 46800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 46900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 47000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ScrollbackLine* line = mScroll[0]; 47100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey mScrollCur--; 47200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memmove(mScroll, mScroll + 1, sizeof(ScrollbackLine*) * mScrollCur); 47300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 47400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey dimen_t n = line->copyTo(cols, cells); 47500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey for (dimen_t col = n; col < cols; col++) { 47600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cells[col].chars[0] = 0; 47700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cells[col].width = 1; 47800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 47900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 48000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey delete line; 48100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return 1; 48200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey} 48300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 48400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeyvoid Terminal::getCellLocked(VTermPos pos, VTermScreenCell* cell) { 48500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // The UI may be asking for cell data while the model is changing 48600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // underneath it, so we always fill with meaningful data. 48700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 48800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (pos.row < 0) { 48900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey size_t scrollRow = -pos.row; 49000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (scrollRow > mScrollCur) { 49100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Invalid region above current scrollback 49200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->width = 1; 49300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#if DEBUG_SCROLLBACK 49400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->bg.red = 255; 49500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#endif 49600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return; 49700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 49800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 49900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey ScrollbackLine* line = mScroll[scrollRow - 1]; 50000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if ((size_t) pos.col < line->cols) { 50100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Valid scrollback cell 50200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey line->getCell(pos.col, cell); 50300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->width = 1; 50400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#if DEBUG_SCROLLBACK 50500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->bg.blue = 255; 50600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#endif 50700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return; 50800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } else { 50900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Extend last scrollback cell into invalid region 51000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey line->getCell(line->cols - 1, cell); 51100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->width = 1; 51200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->chars[0] = ' '; 51300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#if DEBUG_SCROLLBACK 51400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->bg.green = 255; 51500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#endif 51600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return; 51700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 51800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 51900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 52000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if ((size_t) pos.row >= mRows) { 52100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Invalid region below screen 52200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->width = 1; 52300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#if DEBUG_SCROLLBACK 52400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey cell->bg.red = 128; 52500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey#endif 52600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return; 52700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey } 52800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 52900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey // Valid screen cell 53000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey vterm_screen_get_cell(mVts, pos, cell); 53100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey} 53200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 53300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeydimen_t Terminal::getRows() const { 534ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return mRows; 535ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 536ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 53700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeydimen_t Terminal::getCols() const { 538410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return mCols; 539410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 540410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 54100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeydimen_t Terminal::getScrollRows() const { 54200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return mScrollSize; 54300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey} 54400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 5458c040334130cea6e44dda03516d86e774d18d376Kenny Rootjobject Terminal::getCallbacks() const { 5468c040334130cea6e44dda03516d86e774d18d376Kenny Root return mCallbacks; 5478c040334130cea6e44dda03516d86e774d18d376Kenny Root} 5488c040334130cea6e44dda03516d86e774d18d376Kenny Root 549ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey/* 550ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * JNI glue 551ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey */ 552ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 553d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshallstatic jlong com_android_terminal_Terminal_nativeInit(JNIEnv* env, jclass clazz, jobject callbacks) { 554d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshall return reinterpret_cast<jlong>(new Terminal(callbacks)); 555d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey} 556d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey 55796403af9b78d4852f1ac86857a319e078e8fc93fColin Crossstatic jint com_android_terminal_Terminal_nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) { 558de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 55900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey delete term; 56000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return 0; 561de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey} 562de15e79aadde33fd8c880c19bd4fc6caca0bf795Jeff Sharkey 56396403af9b78d4852f1ac86857a319e078e8fc93fColin Crossstatic jint com_android_terminal_Terminal_nativeRun(JNIEnv* env, jclass clazz, jlong ptr) { 564a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 56500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return term->run(); 566a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey} 567a76e33884c55bbd5db7e512b7687210cc3f635cfJeff Sharkey 568410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeResize(JNIEnv* env, 56996403af9b78d4852f1ac86857a319e078e8fc93fColin Cross jclass clazz, jlong ptr, jint rows, jint cols, jint scrollRows) { 5705d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 57100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return term->resize(rows, cols, scrollRows); 572410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 573410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 57400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatic inline int toArgb(const VTermColor& color) { 57500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return (0xff << 24 | color.red << 16 | color.green << 8 | color.blue); 576cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey} 577cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 57800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkeystatic inline bool isCellStyleEqual(const VTermScreenCell& a, const VTermScreenCell& b) { 57900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (toArgb(a.fg) != toArgb(b.fg)) return false; 58000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (toArgb(a.bg) != toArgb(b.bg)) return false; 58100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 58200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.bold != b.attrs.bold) return false; 58300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.underline != b.attrs.underline) return false; 58400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.italic != b.attrs.italic) return false; 58500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.blink != b.attrs.blink) return false; 58600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.reverse != b.attrs.reverse) return false; 58700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.strike != b.attrs.strike) return false; 58800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (a.attrs.font != b.attrs.font) return false; 58900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 590cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey return true; 591cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey} 592cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey 5939cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeGetCellRun(JNIEnv* env, 59496403af9b78d4852f1ac86857a319e078e8fc93fColin Cross jclass clazz, jlong ptr, jint row, jint col, jobject run) { 595410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 59600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Mutex::Autolock lock(term->mLock); 597410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 5989cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey jcharArray dataArray = (jcharArray) env->GetObjectField(run, cellRunDataField); 599479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey ScopedCharArrayRW data(env, dataArray); 600479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey if (data.get() == NULL) { 601479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey return -1; 602479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey } 6039cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey 60400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey VTermScreenCell firstCell, cell; 6059cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey 606410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey VTermPos pos = { 607410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey .row = row, 608410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey .col = col, 609410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey }; 610410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 61100b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey size_t dataSize = 0; 61200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey size_t colSize = 0; 61300b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey while ((size_t) pos.col < term->getCols()) { 61400b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memset(&cell, 0, sizeof(VTermScreenCell)); 61500b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey term->getCellLocked(pos, &cell); 616410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 617cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey if (colSize == 0) { 61800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey env->SetIntField(run, cellRunFgField, toArgb(cell.fg)); 61900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey env->SetIntField(run, cellRunBgField, toArgb(cell.bg)); 62000b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey memcpy(&firstCell, &cell, sizeof(VTermScreenCell)); 621cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey } else { 62200b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey if (!isCellStyleEqual(cell, firstCell)) { 623cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey break; 624cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey } 625cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey } 626d439bacee510759728accb29ba93687a4e380eb6Jeff Sharkey 6279cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey // Only include cell chars if they fit into run 628fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey uint32_t rawCell = cell.chars[0]; 62900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey size_t size = (rawCell < 0x10000) ? 1 : 2; 630479bd643981271fb0edf756ae5915e44a7352c4dJeff Sharkey if (dataSize + size <= data.size()) { 631fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey if (rawCell < 0x10000) { 632fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey data[dataSize++] = rawCell; 633fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey } else { 634fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey data[dataSize++] = (((rawCell - 0x10000) >> 10) & 0x3ff) + 0xd800; 635fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey data[dataSize++] = ((rawCell - 0x10000) & 0x3ff) + 0xdc00; 636fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey } 637fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey 638fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey for (int i = 1; i < cell.width; i++) { 639fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey data[dataSize++] = ' '; 640fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey } 641fd6f0973405ce609964fc35b66ee355be596795dJeff Sharkey 6429cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey colSize += cell.width; 6439cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey pos.col += cell.width; 6449cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey } else { 6459cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey break; 6469cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey } 6479cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey } 648410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 6499cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey env->SetIntField(run, cellRunDataSizeField, dataSize); 6509cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey env->SetIntField(run, cellRunColSizeField, colSize); 651410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 652410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return 0; 6535d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 6545d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 65596403af9b78d4852f1ac86857a319e078e8fc93fColin Crossstatic jint com_android_terminal_Terminal_nativeGetRows(JNIEnv* env, jclass clazz, jlong ptr) { 656ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 657ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return term->getRows(); 658ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 659ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 66096403af9b78d4852f1ac86857a319e078e8fc93fColin Crossstatic jint com_android_terminal_Terminal_nativeGetCols(JNIEnv* env, jclass clazz, jlong ptr) { 661410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 662410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return term->getCols(); 663410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 664410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 66596403af9b78d4852f1ac86857a319e078e8fc93fColin Crossstatic jint com_android_terminal_Terminal_nativeGetScrollRows(JNIEnv* env, jclass clazz, jlong ptr) { 66600b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 66700b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey return term->getScrollRows(); 66800b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey} 66900b00812cd0c883c2380065d7fda29512d5477f0Jeff Sharkey 670c8be1790590605603a8dca8f9ee93327c916de3fMichael Wrightstatic jboolean com_android_terminal_Terminal_nativeDispatchCharacter(JNIEnv *env, jclass clazz, 67196403af9b78d4852f1ac86857a319e078e8fc93fColin Cross jlong ptr, jint mod, jint c) { 672007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright Terminal* term = reinterpret_cast<Terminal*>(ptr); 673007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright return term->dispatchCharacter(mod, c); 674007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright} 675007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 676c8be1790590605603a8dca8f9ee93327c916de3fMichael Wrightstatic jboolean com_android_terminal_Terminal_nativeDispatchKey(JNIEnv *env, jclass clazz, 67796403af9b78d4852f1ac86857a319e078e8fc93fColin Cross jlong ptr, jint mod, jint c) { 678007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright Terminal* term = reinterpret_cast<Terminal*>(ptr); 679007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright return term->dispatchKey(mod, c); 680007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright} 681007efde8867b52cd5f3648173adb1a12069b6e0dMichael Wright 682ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic JNINativeMethod gMethods[] = { 683d3090cb2c2ca1d6a2441c3bd1413da129ceadc38Tom Marshall { "nativeInit", "(Lcom/android/terminal/TerminalCallbacks;)J", (void*)com_android_terminal_Terminal_nativeInit }, 68496403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeDestroy", "(J)I", (void*)com_android_terminal_Terminal_nativeDestroy }, 68596403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeRun", "(J)I", (void*)com_android_terminal_Terminal_nativeRun }, 68696403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeResize", "(JIII)I", (void*)com_android_terminal_Terminal_nativeResize }, 68796403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeGetCellRun", "(JIILcom/android/terminal/Terminal$CellRun;)I", (void*)com_android_terminal_Terminal_nativeGetCellRun }, 68896403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeGetRows", "(J)I", (void*)com_android_terminal_Terminal_nativeGetRows }, 68996403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeGetCols", "(J)I", (void*)com_android_terminal_Terminal_nativeGetCols }, 69096403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeGetScrollRows", "(J)I", (void*)com_android_terminal_Terminal_nativeGetScrollRows }, 69196403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeDispatchCharacter", "(JII)Z", (void*)com_android_terminal_Terminal_nativeDispatchCharacter}, 69296403af9b78d4852f1ac86857a319e078e8fc93fColin Cross { "nativeDispatchKey", "(JII)Z", (void*)com_android_terminal_Terminal_nativeDispatchKey }, 693ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey}; 694ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 695ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeyint register_com_android_terminal_Terminal(JNIEnv* env) { 6968c040334130cea6e44dda03516d86e774d18d376Kenny Root ScopedLocalRef<jclass> localClass(env, 6978c040334130cea6e44dda03516d86e774d18d376Kenny Root env->FindClass("com/android/terminal/TerminalCallbacks")); 6988c040334130cea6e44dda03516d86e774d18d376Kenny Root 6998c040334130cea6e44dda03516d86e774d18d376Kenny Root android::terminalCallbacksClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get())); 7008c040334130cea6e44dda03516d86e774d18d376Kenny Root 7018c040334130cea6e44dda03516d86e774d18d376Kenny Root android::damageMethod = env->GetMethodID(terminalCallbacksClass, "damage", "(IIII)I"); 7028c040334130cea6e44dda03516d86e774d18d376Kenny Root android::moveRectMethod = env->GetMethodID(terminalCallbacksClass, "moveRect", "(IIIIIIII)I"); 7038c040334130cea6e44dda03516d86e774d18d376Kenny Root android::moveCursorMethod = env->GetMethodID(terminalCallbacksClass, "moveCursor", 7046a142b6d4831c3841b6be1705fc97c9b75a7c9d1Jeff Sharkey "(IIIII)I"); 7058c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropBooleanMethod = env->GetMethodID(terminalCallbacksClass, 7068c040334130cea6e44dda03516d86e774d18d376Kenny Root "setTermPropBoolean", "(IZ)I"); 7078c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropIntMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropInt", 7088c040334130cea6e44dda03516d86e774d18d376Kenny Root "(II)I"); 7098c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropStringMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropString", 7108c040334130cea6e44dda03516d86e774d18d376Kenny Root "(ILjava/lang/String;)I"); 7118c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropColorMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropColor", 7128c040334130cea6e44dda03516d86e774d18d376Kenny Root "(IIII)I"); 7138c040334130cea6e44dda03516d86e774d18d376Kenny Root android::bellMethod = env->GetMethodID(terminalCallbacksClass, "bell", "()I"); 7148c040334130cea6e44dda03516d86e774d18d376Kenny Root 7159cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey ScopedLocalRef<jclass> cellRunLocal(env, 7169cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey env->FindClass("com/android/terminal/Terminal$CellRun")); 7179cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey cellRunClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellRunLocal.get())); 7189cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey cellRunDataField = env->GetFieldID(cellRunClass, "data", "[C"); 7199cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey cellRunDataSizeField = env->GetFieldID(cellRunClass, "dataSize", "I"); 7209cae0a9616b1b71eac7e762d198fe1da47fea901Jeff Sharkey cellRunColSizeField = env->GetFieldID(cellRunClass, "colSize", "I"); 721cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey cellRunFgField = env->GetFieldID(cellRunClass, "fg", "I"); 722cedf158c17dc147163734ad1070032ff934d1b2eJeff Sharkey cellRunBgField = env->GetFieldID(cellRunClass, "bg", "I"); 723410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 724ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return jniRegisterNativeMethods(env, "com/android/terminal/Terminal", 725ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey gMethods, NELEM(gMethods)); 726ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 727ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 728ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} /* namespace android */ 729