com_android_terminal_Terminal.cpp revision 410e0da343fd581f3112037deb475db9fb0da850
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> 20ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include "jni.h" 21ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include "JNIHelp.h" 228c040334130cea6e44dda03516d86e774d18d376Kenny Root#include <ScopedLocalRef.h> 23ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 245d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <termios.h> 255d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <util.h> 265d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey//#include <pty.h> 275d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <utmp.h> 285d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey#include <unistd.h> 295d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey//#include <stdlib.h> 305d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 31ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include <vterm.h> 32ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 33ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey#include <string.h> 34ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 35ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeynamespace android { 36ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 378c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 388c040334130cea6e44dda03516d86e774d18d376Kenny Root * JavaVM reference 398c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 408c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic JavaVM* gJavaVM; 418c040334130cea6e44dda03516d86e774d18d376Kenny Root 428c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 438c040334130cea6e44dda03516d86e774d18d376Kenny Root * Callback class reference 448c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 458c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jclass terminalCallbacksClass; 468c040334130cea6e44dda03516d86e774d18d376Kenny Root 478c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 488c040334130cea6e44dda03516d86e774d18d376Kenny Root * Callback methods 498c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 508c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID damageMethod; 518c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID prescrollMethod; 528c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID moveRectMethod; 538c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID moveCursorMethod; 548c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropBooleanMethod; 558c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropIntMethod; 568c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropStringMethod; 578c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID setTermPropColorMethod; 588c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID bellMethod; 598c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jmethodID resizeMethod; 608c040334130cea6e44dda03516d86e774d18d376Kenny Root 61410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey/* 62410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey * Cell class 63410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey */ 64410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jclass cellClass; 65410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jfieldID cellCharsField; 66410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 678c040334130cea6e44dda03516d86e774d18d376Kenny Root 688c040334130cea6e44dda03516d86e774d18d376Kenny Root/* 698c040334130cea6e44dda03516d86e774d18d376Kenny Root * Terminal session 708c040334130cea6e44dda03516d86e774d18d376Kenny Root */ 718c040334130cea6e44dda03516d86e774d18d376Kenny Root 728c040334130cea6e44dda03516d86e774d18d376Kenny Rootclass Terminal { 738c040334130cea6e44dda03516d86e774d18d376Kenny Rootpublic: 748c040334130cea6e44dda03516d86e774d18d376Kenny Root Terminal(jobject callbacks, int rows, int cols); 758c040334130cea6e44dda03516d86e774d18d376Kenny Root ~Terminal(); 768c040334130cea6e44dda03516d86e774d18d376Kenny Root 775d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey size_t write(const char *bytes, size_t len); 78410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 79410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey int resize(short unsigned int rows, short unsigned int cols); 80410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey int getCell(VTermPos pos, VTermScreenCell* cell); 815d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 828c040334130cea6e44dda03516d86e774d18d376Kenny Root int getRows() const; 83410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey int getCols() const; 848c040334130cea6e44dda03516d86e774d18d376Kenny Root 858c040334130cea6e44dda03516d86e774d18d376Kenny Root jobject getCallbacks() const; 868c040334130cea6e44dda03516d86e774d18d376Kenny Root 878c040334130cea6e44dda03516d86e774d18d376Kenny Rootprivate: 885d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey int mMasterFd; 898c040334130cea6e44dda03516d86e774d18d376Kenny Root VTerm *mVt; 908c040334130cea6e44dda03516d86e774d18d376Kenny Root VTermScreen *mVts; 918c040334130cea6e44dda03516d86e774d18d376Kenny Root 92410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey jobject mCallbacks; 935d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey short unsigned int mRows; 945d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey short unsigned int mCols; 958c040334130cea6e44dda03516d86e774d18d376Kenny Root}; 968c040334130cea6e44dda03516d86e774d18d376Kenny Root 978c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic JNIEnv* getEnv() { 988c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env; 998c040334130cea6e44dda03516d86e774d18d376Kenny Root 1008c040334130cea6e44dda03516d86e774d18d376Kenny Root if (gJavaVM->AttachCurrentThread(&env, NULL) < 0) { 1018c040334130cea6e44dda03516d86e774d18d376Kenny Root return NULL; 1028c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1038c040334130cea6e44dda03516d86e774d18d376Kenny Root 1048c040334130cea6e44dda03516d86e774d18d376Kenny Root return env; 1058c040334130cea6e44dda03516d86e774d18d376Kenny Root} 106ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 107ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey/* 108ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * VTerm event handlers 109ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey */ 110ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 111ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_damage(VTermRect rect, void *user) { 112ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 113ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_damage"); 1148c040334130cea6e44dda03516d86e774d18d376Kenny Root 1158c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 1168c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 1178c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_damage: couldn't get JNIEnv"); 1188c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1198c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1208c040334130cea6e44dda03516d86e774d18d376Kenny Root 1218c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), damageMethod, rect.start_row, rect.end_row, 1228c040334130cea6e44dda03516d86e774d18d376Kenny Root rect.start_col, rect.end_col); 123ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 124ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 125ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_prescroll(VTermRect rect, void *user) { 126ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 127ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_prescroll"); 1288c040334130cea6e44dda03516d86e774d18d376Kenny Root 1298c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 1308c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 1318c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_prescroll: couldn't get JNIEnv"); 1328c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1338c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1348c040334130cea6e44dda03516d86e774d18d376Kenny Root 1358c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), prescrollMethod); 136ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 137ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 138ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_moverect(VTermRect dest, VTermRect src, void *user) { 139ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 140ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_moverect"); 1418c040334130cea6e44dda03516d86e774d18d376Kenny Root 1428c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 1438c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 1448c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_moverect: couldn't get JNIEnv"); 1458c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1468c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1478c040334130cea6e44dda03516d86e774d18d376Kenny Root 1488c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), moveRectMethod); 149ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 150ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 151ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user) { 152ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 153ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_movecursor"); 1548c040334130cea6e44dda03516d86e774d18d376Kenny Root 1558c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 1568c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 1578c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_movecursor: couldn't get JNIEnv"); 1588c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1598c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1608c040334130cea6e44dda03516d86e774d18d376Kenny Root 1618c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), moveCursorMethod); 162ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 163ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 164ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_settermprop(VTermProp prop, VTermValue *val, void *user) { 165ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 166ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_settermprop"); 1678c040334130cea6e44dda03516d86e774d18d376Kenny Root 1688c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 1698c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 1708c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_settermprop: couldn't get JNIEnv"); 1718c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1728c040334130cea6e44dda03516d86e774d18d376Kenny Root } 1738c040334130cea6e44dda03516d86e774d18d376Kenny Root 1748c040334130cea6e44dda03516d86e774d18d376Kenny Root switch (vterm_get_prop_type(prop)) { 1758c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_BOOL: 1768c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropBooleanMethod, 1778c040334130cea6e44dda03516d86e774d18d376Kenny Root static_cast<jboolean>(val->boolean)); 1788c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_INT: 1798c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropIntMethod, prop, val->number); 1808c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_STRING: 1818c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropStringMethod, prop, 1828c040334130cea6e44dda03516d86e774d18d376Kenny Root env->NewStringUTF(val->string)); 1838c040334130cea6e44dda03516d86e774d18d376Kenny Root case VTERM_VALUETYPE_COLOR: 1848c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), setTermPropIntMethod, prop, val->color.red, 1858c040334130cea6e44dda03516d86e774d18d376Kenny Root val->color.green, val->color.blue); 1868c040334130cea6e44dda03516d86e774d18d376Kenny Root default: 1878c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("unknown callback type"); 1888c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 1898c040334130cea6e44dda03516d86e774d18d376Kenny Root } 190ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 191ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 192ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_setmousefunc(VTermMouseFunc func, void *data, void *user) { 193ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 194ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_setmousefunc"); 195ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return 1; 196ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 197ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 198ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_bell(void *user) { 199ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 200ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_bell"); 2018c040334130cea6e44dda03516d86e774d18d376Kenny Root 2028c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 2038c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 2048c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_bell: couldn't get JNIEnv"); 2058c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 2068c040334130cea6e44dda03516d86e774d18d376Kenny Root } 2078c040334130cea6e44dda03516d86e774d18d376Kenny Root 2088c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), bellMethod); 209ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 210ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 211ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic int term_resize(int rows, int cols, void *user) { 212ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(user); 213ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey ALOGW("term_resize"); 2148c040334130cea6e44dda03516d86e774d18d376Kenny Root 2158c040334130cea6e44dda03516d86e774d18d376Kenny Root JNIEnv* env = getEnv(); 2168c040334130cea6e44dda03516d86e774d18d376Kenny Root if (env == NULL) { 2178c040334130cea6e44dda03516d86e774d18d376Kenny Root ALOGE("term_bell: couldn't get JNIEnv"); 2188c040334130cea6e44dda03516d86e774d18d376Kenny Root return 0; 2198c040334130cea6e44dda03516d86e774d18d376Kenny Root } 2208c040334130cea6e44dda03516d86e774d18d376Kenny Root 2218c040334130cea6e44dda03516d86e774d18d376Kenny Root return env->CallIntMethod(term->getCallbacks(), resizeMethod); 222ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 223ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 224ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic VTermScreenCallbacks cb = { 225ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .damage = term_damage, 226ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .prescroll = term_prescroll, 227ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .moverect = term_moverect, 228ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .movecursor = term_movecursor, 229ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .settermprop = term_settermprop, 230ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .setmousefunc = term_setmousefunc, 231ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .bell = term_bell, 232ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey .resize = term_resize, 233ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey}; 234ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 2358c040334130cea6e44dda03516d86e774d18d376Kenny RootTerminal::Terminal(jobject callbacks, int rows, int cols) : 2368c040334130cea6e44dda03516d86e774d18d376Kenny Root mCallbacks(callbacks), mRows(rows), mCols(cols) { 237ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey /* Create VTerm */ 238ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey mVt = vterm_new(rows, cols); 239ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_parser_set_utf8(mVt, 1); 240ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 241ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey /* Set up screen */ 242ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey mVts = vterm_obtain_screen(mVt); 243ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_screen_enable_altscreen(mVts, 1); 244ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_screen_set_callbacks(mVts, &cb, this); 245ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_screen_set_damage_merge(mVts, VTERM_DAMAGE_SCROLL); 246ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 2475d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey /* None of the docs about termios explain how to construct a new one of 2485d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey * these, so this is largely a guess */ 2495d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey struct termios termios = { 2505d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey .c_iflag = ICRNL|IXON|IUTF8, 2515d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey .c_oflag = OPOST|ONLCR|NL0|CR0|TAB0|BS0|VT0|FF0, 2525d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey .c_cflag = CS8|CREAD, 2535d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey .c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK, 2545d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey /* c_cc later */ 2555d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey }; 2565d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 2575d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// cfsetspeed(&termios, 38400); 2585d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2595d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VINTR] = 0x1f & 'C'; 2605d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VQUIT] = 0x1f & '\\'; 2615d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VERASE] = 0x7f; 2625d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VKILL] = 0x1f & 'U'; 2635d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VEOF] = 0x1f & 'D'; 2645d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VEOL] = _POSIX_VDISABLE; 2655d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VEOL2] = _POSIX_VDISABLE; 2665d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VSTART] = 0x1f & 'Q'; 2675d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VSTOP] = 0x1f & 'S'; 2685d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VSUSP] = 0x1f & 'Z'; 2695d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VREPRINT] = 0x1f & 'R'; 2705d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VWERASE] = 0x1f & 'W'; 2715d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VLNEXT] = 0x1f & 'V'; 2725d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VMIN] = 1; 2735d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// termios.c_cc[VTIME] = 0; 2745d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2755d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// struct winsize size = { mRows, mCols, 0, 0 }; 2765d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2775d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// pid_t kid = forkpty(&mMasterFd, NULL, &termios, &size); 2785d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// if(kid == 0) { 2795d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// /* Restore the ISIG signals back to defaults */ 2805d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// signal(SIGINT, SIG_DFL); 2815d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// signal(SIGQUIT, SIG_DFL); 2825d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// signal(SIGSTOP, SIG_DFL); 2835d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// signal(SIGCONT, SIG_DFL); 2845d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2855d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// gchar *term = g_strdup_printf("TERM=%s", CONF_term); 2865d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// putenv(term); 2875d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// /* Do not free 'term', it is part of the environment */ 2885d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2895d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// char *shell = getenv("SHELL"); 2905d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// char *args[2] = {shell, NULL}; 2915d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// execvp(shell, args); 2925d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// fprintf(stderr_save, "Cannot exec(%s) - %s\n", shell, strerror(errno)); 2935d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// _exit(1); 2945d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// } 2955d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// 2965d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey// fcntl(mMasterFd, F_SETFL, fcntl(mMasterFd, F_GETFL) | O_NONBLOCK); 297ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 298ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 299ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff SharkeyTerminal::~Terminal() { 3005d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey close(mMasterFd); 301ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey vterm_free(mVt); 302ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 303ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 3045d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkeysize_t Terminal::write(const char *bytes, size_t len) { 3055d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey return ::write(mMasterFd, bytes, len); 3065d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 3075d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 308410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeyint Terminal::resize(short unsigned int rows, short unsigned int cols) { 309410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey ALOGD("resize(%d, %d)", rows, cols); 3105d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey mRows = rows; 3115d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey mCols = cols; 3125d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey struct winsize size = { rows, cols, 0, 0 }; 3135d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey ioctl(mMasterFd, TIOCSWINSZ, &size); 314410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return 0; 315410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 316410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 317410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeyint Terminal::getCell(VTermPos pos, VTermScreenCell* cell) { 318410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return vterm_screen_get_cell(mVts, pos, cell); 3195d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 3205d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 3218c040334130cea6e44dda03516d86e774d18d376Kenny Rootint Terminal::getRows() const { 322ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return mRows; 323ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 324ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 325410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeyint Terminal::getCols() const { 326410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return mCols; 327410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 328410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 3298c040334130cea6e44dda03516d86e774d18d376Kenny Rootjobject Terminal::getCallbacks() const { 3308c040334130cea6e44dda03516d86e774d18d376Kenny Root return mCallbacks; 3318c040334130cea6e44dda03516d86e774d18d376Kenny Root} 3328c040334130cea6e44dda03516d86e774d18d376Kenny Root 333ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey/* 334ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey * JNI glue 335ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey */ 336ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 3378c040334130cea6e44dda03516d86e774d18d376Kenny Rootstatic jint com_android_terminal_Terminal_nativeInit(JNIEnv* env, jclass clazz, jobject callbacks, 338ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey jint rows, jint cols) { 3398c040334130cea6e44dda03516d86e774d18d376Kenny Root return reinterpret_cast<jint>(new Terminal(env->NewGlobalRef(callbacks), rows, cols)); 340ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 341ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 3425d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkeystatic void com_android_terminal_Terminal_nativeWrite(JNIEnv* env, 3435d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey jclass clazz, jint ptr) { 3445d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 3455d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey // const char *bytes, size_t len 3465d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey term->write(NULL, 0); 3475d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 3485d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 349410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeResize(JNIEnv* env, 3505d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey jclass clazz, jint ptr, jint rows, jint cols) { 3515d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 352410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return term->resize(rows, cols); 353410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 354410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 355410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeGetCell(JNIEnv* env, 356410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey jclass clazz, jint ptr, jint row, jint col, jobject cell) { 357410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey //ALOGD("getCell(%d, %d)", row, col); 358410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 359410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 360410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey VTermPos pos = { 361410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey .row = row, 362410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey .col = col, 363410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey }; 364410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 365410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey VTermScreenCell termCell; 366410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey memset(&termCell, 0, sizeof(VTermScreenCell)); 367410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey int res = term->getCell(pos, &termCell); 368410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 369410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey // TODO: support full UTF-32 characters 370410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey // for testing, 0x00020000 should become 0xD840 0xDC00 371410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 372410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey jintArray charsArray = (jintArray)env->GetObjectField(cell, cellCharsField); 373410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey jint *chars = env->GetIntArrayElements(charsArray, 0); 374410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey chars[0] = '$'; 375410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey chars[1] = 0x00; 376410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey env->ReleaseIntArrayElements(charsArray, chars, 0); 377410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 378410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return 0; 3795d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey} 3805d4b3955da5952d8ec2cb45e3aa5406294560798Jeff Sharkey 381ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeGetRows(JNIEnv* env, jclass clazz, jint ptr) { 382ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 383ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return term->getRows(); 384ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 385ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 386410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkeystatic jint com_android_terminal_Terminal_nativeGetCols(JNIEnv* env, jclass clazz, jint ptr) { 387410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey Terminal* term = reinterpret_cast<Terminal*>(ptr); 388410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey return term->getCols(); 389410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey} 390410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 391ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeystatic JNINativeMethod gMethods[] = { 3928c040334130cea6e44dda03516d86e774d18d376Kenny Root { "nativeInit", "(Lcom/android/terminal/TerminalCallbacks;II)I", (void*)com_android_terminal_Terminal_nativeInit }, 393410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey { "nativeResize", "(III)I", (void*)com_android_terminal_Terminal_nativeResize }, 394410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey { "nativeGetCell", "(IIILcom/android/terminal/Terminal$Cell;)I", (void*)com_android_terminal_Terminal_nativeGetCell }, 395ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey { "nativeGetRows", "(I)I", (void*)com_android_terminal_Terminal_nativeGetRows }, 396410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey { "nativeGetCols", "(I)I", (void*)com_android_terminal_Terminal_nativeGetCols }, 397ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey}; 398ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 399ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkeyint register_com_android_terminal_Terminal(JNIEnv* env) { 4008c040334130cea6e44dda03516d86e774d18d376Kenny Root ScopedLocalRef<jclass> localClass(env, 4018c040334130cea6e44dda03516d86e774d18d376Kenny Root env->FindClass("com/android/terminal/TerminalCallbacks")); 4028c040334130cea6e44dda03516d86e774d18d376Kenny Root 4038c040334130cea6e44dda03516d86e774d18d376Kenny Root android::terminalCallbacksClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get())); 4048c040334130cea6e44dda03516d86e774d18d376Kenny Root 4058c040334130cea6e44dda03516d86e774d18d376Kenny Root android::damageMethod = env->GetMethodID(terminalCallbacksClass, "damage", "(IIII)I"); 4068c040334130cea6e44dda03516d86e774d18d376Kenny Root android::prescrollMethod = env->GetMethodID(terminalCallbacksClass, "prescroll", "(IIII)I"); 4078c040334130cea6e44dda03516d86e774d18d376Kenny Root android::moveRectMethod = env->GetMethodID(terminalCallbacksClass, "moveRect", "(IIIIIIII)I"); 4088c040334130cea6e44dda03516d86e774d18d376Kenny Root android::moveCursorMethod = env->GetMethodID(terminalCallbacksClass, "moveCursor", 4098c040334130cea6e44dda03516d86e774d18d376Kenny Root "(IIIIIIIII)I"); 4108c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropBooleanMethod = env->GetMethodID(terminalCallbacksClass, 4118c040334130cea6e44dda03516d86e774d18d376Kenny Root "setTermPropBoolean", "(IZ)I"); 4128c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropIntMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropInt", 4138c040334130cea6e44dda03516d86e774d18d376Kenny Root "(II)I"); 4148c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropStringMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropString", 4158c040334130cea6e44dda03516d86e774d18d376Kenny Root "(ILjava/lang/String;)I"); 4168c040334130cea6e44dda03516d86e774d18d376Kenny Root android::setTermPropColorMethod = env->GetMethodID(terminalCallbacksClass, "setTermPropColor", 4178c040334130cea6e44dda03516d86e774d18d376Kenny Root "(IIII)I"); 4188c040334130cea6e44dda03516d86e774d18d376Kenny Root android::bellMethod = env->GetMethodID(terminalCallbacksClass, "bell", "()I"); 4198c040334130cea6e44dda03516d86e774d18d376Kenny Root android::resizeMethod = env->GetMethodID(terminalCallbacksClass, "resize", "(II)I"); 4208c040334130cea6e44dda03516d86e774d18d376Kenny Root 421410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey ScopedLocalRef<jclass> cellLocal(env, 422410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey env->FindClass("com/android/terminal/Terminal$Cell")); 423410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey cellClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellLocal.get())); 424410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey cellCharsField = env->GetFieldID(cellClass, "chars", "[C"); 425410e0da343fd581f3112037deb475db9fb0da850Jeff Sharkey 4268c040334130cea6e44dda03516d86e774d18d376Kenny Root env->GetJavaVM(&gJavaVM); 4278c040334130cea6e44dda03516d86e774d18d376Kenny Root 428ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey return jniRegisterNativeMethods(env, "com/android/terminal/Terminal", 429ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey gMethods, NELEM(gMethods)); 430ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} 431ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey 432ef946f3ae80556ab221265c0bf1c560683ea27f6Jeff Sharkey} /* namespace android */ 433