19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 29f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * ConnectBot: simple, powerful, open-source SSH client for Android 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Copyright 2007 Kenny Root, Jeffrey Sharkey 49f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 59f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Licensed under the Apache License, Version 2.0 (the "License"); 69f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * you may not use this file except in compliance with the License. 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * You may obtain a copy of the License at 89f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * http://www.apache.org/licenses/LICENSE-2.0 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * distributed under the License is distributed on an "AS IS" BASIS, 139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * See the License for the specific language governing permissions and 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * limitations under the License. 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage org.connectbot.service; 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Context; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.SharedPreferences; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.SharedPreferences.OnSharedPreferenceChangeListener; 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Bitmap; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Canvas; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Color; 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Paint; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Typeface; 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Bitmap.Config; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.graphics.Paint.FontMetrics; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.text.ClipboardManager; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.view.ContextMenu; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.view.Menu; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.view.View; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.view.ContextMenu.ContextMenuInfo; 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.Log; 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.R; 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.facade.ui.UiFacade; 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.interpreter.InterpreterProcess; 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.jsonrpc.RpcReceiverManager; 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.jsonrpc.RpcReceiverManagerFactory; 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport de.mud.terminal.VDUBuffer; 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport de.mud.terminal.VDUDisplay; 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport de.mud.terminal.vt320; 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.IOException; 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.nio.charset.Charset; 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.LinkedList; 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.List; 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.TerminalView; 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.transport.AbsTransport; 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.util.Colors; 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.util.PreferenceConstants; 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.util.SelectionArea; 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Provides a bridge between a MUD terminal buffer and a possible TerminalView. This separation 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * allows us to keep the TerminalBridge running in a background service. A TerminalView shares down 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * a bitmap that we can use for rendering when available. 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class TerminalBridge implements VDUDisplay, OnSharedPreferenceChangeListener { 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final static int FONT_SIZE_STEP = 2; 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final int[] color = new int[Colors.defaults.length]; 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final TerminalManager manager; 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final InterpreterProcess mProcess; 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int mDefaultFgColor; 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int mDefaultBgColor; 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int scrollback; 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private String delKey; 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private String encoding; 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private AbsTransport transport; 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Paint defaultPaint; 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Relay relay; 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Bitmap bitmap = null; 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final VDUBuffer buffer; 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private TerminalView parent = null; 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Canvas canvas = new Canvas(); 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean forcedSize = false; 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int columns; 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int rows; 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final TerminalKeyListener keyListener; 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean selectingForCopy = false; 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final SelectionArea selectionArea; 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private ClipboardManager clipboard; 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int charWidth = -1; 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int charHeight = -1; 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int charTop = -1; 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private float fontSize = -1; 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final List<FontSizeChangedListener> fontSizeChangedListeners; 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Flag indicating if we should perform a full-screen redraw during our next rendering pass. 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean fullRedraw = false; 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final PromptHelper promptHelper; 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Create a new terminal bridge suitable for unit testing. 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalBridge() { 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer = new vt320() { 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void write(byte[] b) { 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void write(int b) { 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void sendTelnetCommand(byte cmd) { 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setWindowSize(int c, int r) { 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void debug(String s) { 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }; 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager = null; 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint = new Paint(); 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li selectionArea = new SelectionArea(); 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li scrollback = 1; 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport = null; 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li keyListener = new TerminalKeyListener(manager, this, buffer, null); 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mProcess = null; 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultFgColor = 0; 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultBgColor = 0; 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li promptHelper = null; 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li updateCharset(); 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Create new terminal bridge with following parameters. 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalBridge(final TerminalManager manager, InterpreterProcess process, AbsTransport t) 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throws IOException { 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.manager = manager; 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport = t; 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mProcess = process; 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String string = manager.getStringParameter(PreferenceConstants.SCROLLBACK, null); 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (string != null) { 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li scrollback = Integer.parseInt(string); 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li scrollback = PreferenceConstants.DEFAULT_SCROLLBACK; 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li string = manager.getStringParameter(PreferenceConstants.FONTSIZE, null); 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (string != null) { 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSize = Float.parseFloat(string); 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSize = PreferenceConstants.DEFAULT_FONT_SIZE; 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultFgColor = 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getIntParameter(PreferenceConstants.COLOR_FG, PreferenceConstants.DEFAULT_FG_COLOR); 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultBgColor = 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getIntParameter(PreferenceConstants.COLOR_BG, PreferenceConstants.DEFAULT_BG_COLOR); 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li delKey = manager.getStringParameter(PreferenceConstants.DELKEY, PreferenceConstants.DELKEY_DEL); 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // create prompt helper to relay password and hostkey requests up to gui 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li promptHelper = new PromptHelper(this); 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // create our default paint 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint = new Paint(); 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setAntiAlias(true); 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setTypeface(Typeface.MONOSPACE); 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setFakeBoldText(true); // more readable? 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(fontSize); 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // create terminal buffer and handle outgoing data 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // this is probably status reply information 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer = new vt320() { 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void debug(String s) { 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d(s); 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void write(byte[] b) { 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (b != null && transport != null) { 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.write(b); 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (IOException e) { 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Problem writing outgoing data in vt320() thread", e); 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void write(int b) { 2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (transport != null) { 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.write(b); 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (IOException e) { 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Problem writing outgoing data in vt320() thread", e); 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // We don't use telnet sequences. 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void sendTelnetCommand(byte cmd) { 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // We don't want remote to resize our window. 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setWindowSize(int c, int r) { 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void beep() { 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (parent.isShown()) { 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.playBeep(); 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }; 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Don't keep any scrollback if a session is not being opened. 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.setBufferSize(scrollback); 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li resetColors(); 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.setDisplay(this); 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li selectionArea = new SelectionArea(); 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li keyListener = new TerminalKeyListener(manager, this, buffer, encoding); 2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li updateCharset(); 2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.registerOnSharedPreferenceChangeListener(this); 2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Spawn thread to open connection and start login process. 2789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected void connect() { 2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.setBridge(this); 2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.setManager(manager); 2829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.connect(); 2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).reset(); 2859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // previously tried vt100 and xterm for emulation modes 2879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // "screen" works the best for color and escape codes 2889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).setAnswerBack("screen"); 2899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (PreferenceConstants.DELKEY_BACKSPACE.equals(delKey)) { 2919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).setBackspace(vt320.DELETE_IS_BACKSPACE); 2929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 2939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).setBackspace(vt320.DELETE_IS_DEL); 2949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // create thread to relay incoming connection data to buffer 2979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li relay = new Relay(this, transport, (vt320) buffer, encoding); 2989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Thread relayThread = new Thread(relay); 2999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li relayThread.setDaemon(true); 3009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li relayThread.setName("Relay"); 3019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li relayThread.start(); 3029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // force font-size to make sure we resizePTY as needed 3049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(fontSize); 3059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void updateCharset() { 3099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li encoding = 3109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getStringParameter(PreferenceConstants.ENCODING, Charset.defaultCharset().name()); 3119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (relay != null) { 3129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li relay.setCharset(encoding); 3139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li keyListener.setCharset(encoding); 3159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 3189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Inject a specific string into this terminal. Used for post-login strings and pasting clipboard. 3199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 3209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void injectString(final String string) { 3219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (string == null || string.length() == 0) { 3229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 3239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Thread injectStringThread = new Thread(new Runnable() { 3269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 3279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 3289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.write(string.getBytes(encoding)); 3299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (Exception e) { 3309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Couldn't inject string to remote host: ", e); 3319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 3349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li injectStringThread.setName("InjectString"); 3359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li injectStringThread.start(); 3369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 3399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @return whether a session is open or not 3409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 3419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isSessionOpen() { 3429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (transport != null) { 3439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return transport.isSessionOpen(); 3449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 3469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 3499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Force disconnection of this terminal bridge. 3509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 3519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void dispatchDisconnect(boolean immediate) { 3529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Cancel any pending prompts. 3549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li promptHelper.cancelPrompt(); 3559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (immediate) { 3579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.closeConnection(TerminalBridge.this, true); 3589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 3599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Thread disconnectPromptThread = new Thread(new Runnable() { 3609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 3619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String prompt = null; 3629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (transport != null && transport.isConnected()) { 3639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li prompt = manager.getResources().getString(R.string.prompt_confirm_exit); 3649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 3659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li prompt = manager.getResources().getString(R.string.prompt_process_exited); 3669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Boolean result = promptHelper.requestBooleanPrompt(null, prompt); 3689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (transport != null && transport.isConnected()) { 3709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.closeConnection(TerminalBridge.this, result != null && result.booleanValue()); 3719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (result != null && result.booleanValue()) { 3729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.closeConnection(TerminalBridge.this, false); 3739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 3769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disconnectPromptThread.setName("DisconnectPrompt"); 3779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disconnectPromptThread.setDaemon(true); 3789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disconnectPromptThread.start(); 3799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setSelectingForCopy(boolean selectingForCopy) { 3839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.selectingForCopy = selectingForCopy; 3849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isSelectingForCopy() { 3879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return selectingForCopy; 3889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public SelectionArea getSelectionArea() { 3919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return selectionArea; 3929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void tryKeyVibrate() { 3959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.tryKeyVibrate(); 3969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 3999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Request a different font size. Will make call to parentChanged() to make sure we resize PTY if 4009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * needed. 4019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 4029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /* package */final void setFontSize(float size) { 4039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (size <= 0.0) { 4049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 4059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setTextSize(size); 4089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSize = size; 4099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // read new metrics to get exact pixel dimensions 4119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li FontMetrics fm = defaultPaint.getFontMetrics(); 4129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li charTop = (int) Math.ceil(fm.top); 4139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float[] widths = new float[1]; 4159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.getTextWidths("X", widths); 4169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li charWidth = (int) Math.ceil(widths[0]); 4179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li charHeight = (int) Math.ceil(fm.descent - fm.top); 4189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // refresh any bitmap with new font size 4209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (parent != null) { 4219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li parentChanged(parent); 4229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (FontSizeChangedListener ofscl : fontSizeChangedListeners) { 4259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ofscl.onFontSizeChanged(size); 4269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li forcedSize = false; 4289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 4319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Add an {@link FontSizeChangedListener} to the list of listeners for this bridge. 4329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param listener 4349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * listener to add 4359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 4369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void addFontSizeChangedListener(FontSizeChangedListener listener) { 4379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSizeChangedListeners.add(listener); 4389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 4419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Remove an {@link FontSizeChangedListener} from the list of listeners for this bridge. 4429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param listener 4449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 4459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void removeFontSizeChangedListener(FontSizeChangedListener listener) { 4469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSizeChangedListeners.remove(listener); 4479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 4509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Something changed in our parent {@link TerminalView}, maybe it's a new parent, or maybe it's an 4519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * updated font size. We should recalculate terminal size information and request a PTY resize. 4529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 4539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public final synchronized void parentChanged(TerminalView parent) { 4549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (manager != null && !manager.isResizeAllowed()) { 4559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Resize is not allowed now"); 4569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 4579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.parent = parent; 4609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li final int width = parent.getWidth(); 4619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li final int height = parent.getHeight(); 4629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Something has gone wrong with our layout; we're 0 width or height! 4649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (width <= 0 || height <= 0) { 4659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 4669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE); 4699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li keyListener.setClipboardManager(clipboard); 4709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!forcedSize) { 4729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // recalculate buffer size 4739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int newColumns, newRows; 4749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li newColumns = width / charWidth; 4769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li newRows = height / charHeight; 4779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // If nothing has changed in the terminal dimensions and not an intial 4799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // draw then don't blow away scroll regions and such. 4809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (newColumns == columns && newRows == rows) { 4819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 4829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li columns = newColumns; 4859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li rows = newRows; 4869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // reallocate new bitmap if needed 4899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean newBitmap = (bitmap == null); 4909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (bitmap != null) { 4919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height); 4929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 4949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (newBitmap) { 4959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li discardBitmap(); 4969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); 4979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.setBitmap(bitmap); 4989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // clear out any old buffer information 5019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setColor(Color.BLACK); 5029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.drawPaint(defaultPaint); 5039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Stroke the border of the terminal if the size is being forced; 5059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (forcedSize) { 5069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int borderX = (columns * charWidth) + 1; 5079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int borderY = (rows * charHeight) + 1; 5089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setColor(Color.GRAY); 5109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setStrokeWidth(0.0f); 5119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (width >= borderX) { 5129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.drawLine(borderX, 0, borderX, borderY + 1, defaultPaint); 5139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (height >= borderY) { 5159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint); 5169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 5209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // request a terminal pty resize 5219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li synchronized (buffer) { 5229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.setScreenSize(columns, rows, true); 5239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (transport != null) { 5269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li transport.setDimensions(columns, rows, width, height); 5279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (Exception e) { 5299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Problem while trying to resize screen or PTY", e); 5309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // force full redraw with new buffer size 5339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fullRedraw = true; 5349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li redraw(); 5359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li parent.notifyUser(String.format("%d x %d", columns, rows)); 5379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.i(String.format("parentChanged() now width=%d, height=%d", columns, rows)); 5399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 5429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Somehow our parent {@link TerminalView} was destroyed. Now we don't need to redraw anywhere, 5439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * and we can recycle our internal bitmap. 5449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 5459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void parentDestroyed() { 5469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li parent = null; 5479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li discardBitmap(); 5489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void discardBitmap() { 5519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (bitmap != null) { 5529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bitmap.recycle(); 5539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bitmap = null; 5559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onDraw() { 5589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int fg, bg; 5599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li synchronized (buffer) { 5609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean entireDirty = buffer.update[0] || fullRedraw; 5619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean isWideCharacter = false; 5629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // walk through all lines in the buffer 5649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (int l = 0; l < buffer.height; l++) { 5659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // check if this line is dirty and needs to be repainted 5679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // also check for entire-buffer dirty flags 5689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!entireDirty && !buffer.update[l + 1]) { 5699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li continue; 5709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // reset dirty flag for this line 5739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.update[l + 1] = false; 5749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // walk through all characters in this line 5769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (int c = 0; c < buffer.width; c++) { 5779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int addr = 0; 5789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int currAttr = buffer.charAttributes[buffer.windowBase + l][c]; 5799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // check if foreground color attribute is set 5809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if ((currAttr & VDUBuffer.COLOR_FG) != 0) { 5819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int fgcolor = ((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1; 5829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (fgcolor < 8 && (currAttr & VDUBuffer.BOLD) != 0) { 5839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fg = color[fgcolor + 8]; 5849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 5859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fg = color[fgcolor]; 5869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 5889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fg = mDefaultFgColor; 5899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // check if background color attribute is set 5929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if ((currAttr & VDUBuffer.COLOR_BG) != 0) { 5939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bg = color[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1]; 5949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 5959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bg = mDefaultBgColor; 5969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 5979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 5989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // support character inversion by swapping background and foreground color 5999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if ((currAttr & VDUBuffer.INVERT) != 0) { 6009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int swapc = bg; 6019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bg = fg; 6029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fg = swapc; 6039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // set underlined attributes if requested 6069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0); 6079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li isWideCharacter = (currAttr & VDUBuffer.FULLWIDTH) != 0; 6099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (isWideCharacter) { 6119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li addr++; 6129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 6139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // determine the amount of continuous characters with the same settings and print them 6149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // all at once 6159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li while (c + addr < buffer.width 6169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) { 6179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li addr++; 6189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Save the current clip region 6229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.save(Canvas.CLIP_SAVE_FLAG); 6239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // clear this dirty area with background color 6259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setColor(bg); 6269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (isWideCharacter) { 6279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.clipRect(c * charWidth, l * charHeight, (c + 2) * charWidth, (l + 1) 6289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * charHeight); 6299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 6309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.clipRect(c * charWidth, l * charHeight, (c + addr) * charWidth, (l + 1) 6319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * charHeight); 6329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.drawPaint(defaultPaint); 6349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // write the text string starting at 'c' for 'addr' number of characters 6369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setColor(fg); 6379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if ((currAttr & VDUBuffer.INVISIBLE) == 0) { 6389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.drawText(buffer.charArray[buffer.windowBase + l], c, addr, c * charWidth, 6399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li (l * charHeight) - charTop, defaultPaint); 6409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Restore the previous clip region 6439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li canvas.restore(); 6449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // advance to the next text block with different characteristics 6469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li c += addr - 1; 6479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (isWideCharacter) { 6489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li c++; 6499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // reset entire-buffer flags 6549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.update[0] = false; 6559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fullRedraw = false; 6579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void redraw() { 6609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (parent != null) { 6619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li parent.postInvalidate(); 6629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // We don't have a scroll bar. 6669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void updateScrollBar() { 6679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 6709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Resize terminal to fit [rows]x[cols] in screen of size [width]x[height] 6719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 6729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param rows 6739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param cols 6749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param width 6759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param height 6769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 6779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void resizeComputed(int cols, int rows, int width, int height) { 6789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float size = 8.0f; 6799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float step = 8.0f; 6809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float limit = 0.125f; 6819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int direction; 6839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li while ((direction = fontSizeCompare(size, cols, rows, width, height)) < 0) { 6859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li size += step; 6869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (direction == 0) { 6899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d(String.format("Fontsize: found match at %f", size)); 6909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 6919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li step /= 2.0f; 6949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li size -= step; 6959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li while ((direction = fontSizeCompare(size, cols, rows, width, height)) != 0 && step >= limit) { 6979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li step /= 2.0f; 6989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (direction > 0) { 6999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li size -= step; 7009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 7019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li size += step; 7029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (direction > 0) { 7069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li size -= step; 7079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li columns = cols; 7109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.rows = rows; 7119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(size); 7129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li forcedSize = true; 7139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int fontSizeCompare(float size, int cols, int rows, int width, int height) { 7169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // read new metrics to get exact pixel dimensions 7179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.setTextSize(size); 7189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li FontMetrics fm = defaultPaint.getFontMetrics(); 7199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float[] widths = new float[1]; 7219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li defaultPaint.getTextWidths("X", widths); 7229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int termWidth = (int) widths[0] * cols; 7239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int termHeight = (int) Math.ceil(fm.descent - fm.top) * rows; 7249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d(String.format("Fontsize: font size %f resulted in %d x %d", size, termWidth, termHeight)); 7269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Check to see if it fits in resolution specified. 7289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (termWidth > width || termHeight > height) { 7299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return 1; 7309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (termWidth == width || termHeight == height) { 7339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return 0; 7349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return -1; 7379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /* 7409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * (non-Javadoc) 7419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 7429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @see de.mud.terminal.VDUDisplay#setVDUBuffer(de.mud.terminal.VDUBuffer) 7439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 7449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 7459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setVDUBuffer(VDUBuffer buffer) { 7469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /* 7499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * (non-Javadoc) 7509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 7519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @see de.mud.terminal.VDUDisplay#setColor(byte, byte, byte, byte) 7529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 7539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setColor(int index, int red, int green, int blue) { 7549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Don't allow the system colors to be overwritten for now. May violate specs. 7559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (index < color.length && index >= 16) { 7569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li color[index] = 0xff000000 | red << 16 | green << 8 | blue; 7579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public final void resetColors() { 7619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li System.arraycopy(Colors.defaults, 0, color, 0, Colors.defaults.length); 7629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalKeyListener getKeyHandler() { 7659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return keyListener; 7669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void resetScrollPosition() { 7699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // if we're in scrollback, scroll to bottom of window on input 7709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (buffer.windowBase != buffer.screenBase) { 7719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.setWindowBase(buffer.screenBase); 7729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void increaseFontSize() { 7769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(fontSize + FONT_SIZE_STEP); 7779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void decreaseFontSize() { 7809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(fontSize - FONT_SIZE_STEP); 7819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getId() { 7849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mProcess.getPort(); 7859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public String getName() { 7889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mProcess.getName(); 7899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public InterpreterProcess getProcess() { 7929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mProcess; 7939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getForegroundColor() { 7969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mDefaultFgColor; 7979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getBackgroundColor() { 8009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mDefaultBgColor; 8019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public VDUBuffer getVDUBuffer() { 8049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return buffer; 8059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public PromptHelper getPromptHelper() { 8089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return promptHelper; 8099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Bitmap getBitmap() { 8129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return bitmap; 8139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public AbsTransport getTransport() { 8169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return transport; 8179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Paint getPaint() { 8209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return defaultPaint; 8219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 8249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mProcess.isAlive()) { 8259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li RpcReceiverManagerFactory rpcReceiverManagerFactory = mProcess.getRpcReceiverManagerFactory(); 8269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (RpcReceiverManager manager : rpcReceiverManagerFactory.getRpcReceiverManagers().values()) { 8279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li UiFacade facade = manager.getReceiver(UiFacade.class); 8289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li facade.onCreateContextMenu(menu, v, menuInfo); 8299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean onPrepareOptionsMenu(Menu menu) { 8349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean returnValue = false; 8359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mProcess.isAlive()) { 8369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li RpcReceiverManagerFactory rpcReceiverManagerFactory = mProcess.getRpcReceiverManagerFactory(); 8379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (RpcReceiverManager manager : rpcReceiverManagerFactory.getRpcReceiverManagers().values()) { 8389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li UiFacade facade = manager.getReceiver(UiFacade.class); 8399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li returnValue = returnValue || facade.onPrepareOptionsMenu(menu); 8409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return returnValue; 8429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 8449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 8469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 8479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (PreferenceConstants.ENCODING.equals(key)) { 8489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li updateCharset(); 8499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.FONTSIZE.equals(key)) { 8509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String string = manager.getStringParameter(PreferenceConstants.FONTSIZE, null); 8519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (string != null) { 8529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSize = Float.parseFloat(string); 8539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 8549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fontSize = PreferenceConstants.DEFAULT_FONT_SIZE; 8559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li setFontSize(fontSize); 8579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fullRedraw = true; 8589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.SCROLLBACK.equals(key)) { 8599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String string = manager.getStringParameter(PreferenceConstants.SCROLLBACK, null); 8609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (string != null) { 8619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li scrollback = Integer.parseInt(string); 8629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 8639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li scrollback = PreferenceConstants.DEFAULT_SCROLLBACK; 8649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li buffer.setBufferSize(scrollback); 8669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.COLOR_FG.equals(key)) { 8679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultFgColor = 8689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getIntParameter(PreferenceConstants.COLOR_FG, 8699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li PreferenceConstants.DEFAULT_FG_COLOR); 8709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fullRedraw = true; 8719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.COLOR_BG.equals(key)) { 8729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDefaultBgColor = 8739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getIntParameter(PreferenceConstants.COLOR_BG, 8749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li PreferenceConstants.DEFAULT_BG_COLOR); 8759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li fullRedraw = true; 8769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (PreferenceConstants.DELKEY.equals(key)) { 8789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li delKey = 8799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li manager.getStringParameter(PreferenceConstants.DELKEY, PreferenceConstants.DELKEY_DEL); 8809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (PreferenceConstants.DELKEY_BACKSPACE.equals(delKey)) { 8819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).setBackspace(vt320.DELETE_IS_BACKSPACE); 8829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 8839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ((vt320) buffer).setBackspace(vt320.DELETE_IS_DEL); 8849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 8879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 888