line source
+ − /*
+ − * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform".
+ − *
+ − * (c) Matthias L. Jugel, Marcus Meiner 1996-2005. All Rights Reserved.
+ − *
+ − * Please visit http://javatelnet.org/ for updates and contact.
+ − *
+ − * --LICENSE NOTICE--
+ − * This program is free software; you can redistribute it and/or
+ − * modify it under the terms of the GNU General Public License
+ − * as published by the Free Software Foundation; either version 2
+ − * of the License, or (at your option) any later version.
+ − *
+ − * This program is distributed in the hope that it will be useful,
+ − * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ − * GNU General Public License for more details.
+ − *
+ − * You should have received a copy of the GNU General Public License
+ − * along with this program; if not, write to the Free Software
+ − * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ − * --LICENSE NOTICE--
+ − *
+ − */
+ −
+ − package de.mud.terminal;
+ −
+ − import android.text.AndroidCharacter;
+ −
+ − import java.util.Properties;
+ −
+ − /**
+ − * Implementation of a VT terminal emulation plus ANSI compatible.
+ − * <P>
+ − * <B>Maintainer:</B> Marcus Meißner
+ − *
+ − * @version $Id: vt320.java 507 2005-10-25 10:14:52Z marcus $
+ − * @author Matthias L. Jugel, Marcus Meißner
+ − */
+ − public abstract class vt320 extends VDUBuffer implements VDUInput {
+ −
+ − /** the debug level */
+ − private final static int debug = 0;
+ − private StringBuilder debugStr;
+ − public abstract void debug(String notice);
+ −
+ − /**
+ − * Write an answer back to the remote host. This is needed to be able to
+ − * send terminal answers requests like status and type information.
+ − * @param b the array of bytes to be sent
+ − */
+ − public abstract void write(byte[] b);
+ −
+ − /**
+ − * Write an answer back to the remote host. This is needed to be able to
+ − * send terminal answers requests like status and type information.
+ − * @param b the byte to be sent
+ − */
+ − public abstract void write(int b);
+ −
+ − /**
+ − * No more bytes to read from the transport, hook here to test screen changes
+ − */
+ − public void testChanged() {
+ − /* do nothing by default */
+ − }
+ −
+ − /**
+ − * inject field contents as if typed
+ − */
+ − public void setField(int l, int c, char [] d) {
+ − // ignore line and column, just send the bytes to the host.
+ − int n = d.length;
+ − byte [] b = new byte [n];
+ −
+ − for (int i = 0; i < n; i++) b[i] = (byte)(d[i] & 0x00ff);
+ −
+ − write(b);
+ − }
+ −
+ − public void monitorKey(boolean down) {
+ − // do nothing
+ − }
+ −
+ − public void keyDepressed(int keyCode, char keyChar, int modifiers) {
+ − keyPressed(keyCode, keyChar, modifiers);
+ − }
+ −
+ − /**
+ − * Play the beep sound ...
+ − */
+ − public void beep() {
+ − /* do nothing by default */
+ − }
+ −
+ − public void redrawPassthru() {
+ − redraw(); // VDUBuffer.redraw is protected
+ − }
+ −
+ − /**
+ − * Convenience function for putString(char[], int, int)
+ − */
+ − public void putString(String s) {
+ − int len = s.length();
+ − char[] tmp = new char[len];
+ − s.getChars(0, len, tmp, 0);
+ − putString(tmp, null, 0, len);
+ − }
+ −
+ − /**
+ − * Put string at current cursor position. Moves cursor
+ − * according to the String. Does NOT wrap.
+ − * @param s character array
+ − * @param start place to start in array
+ − * @param len number of characters to process
+ − */
+ − public void putString(char[] s, byte[] fullwidths, int start, int len) {
+ − if (len > 0) {
+ − //markLine(R, 1);
+ − int lastChar = -1;
+ − char c;
+ − boolean isWide = false;
+ −
+ − for (int i = 0; i < len; i++) {
+ − c = s[start + i];
+ −
+ − // Shortcut for my favorite ASCII
+ − if (c <= 0x7F) {
+ − if (lastChar != -1)
+ − putChar((char) lastChar, isWide, false);
+ −
+ − lastChar = c;
+ − isWide = false;
+ − }
+ − else if (!Character.isLowSurrogate(c) && !Character.isHighSurrogate(c)) {
+ − if (Character.getType(c) == Character.NON_SPACING_MARK) {
+ − if (lastChar != -1) {
+ − char nc = Precomposer.precompose((char) lastChar, c);
+ − putChar(nc, isWide, false);
+ − lastChar = -1;
+ − }
+ − }
+ − else {
+ − if (lastChar != -1)
+ − putChar((char) lastChar, isWide, false);
+ −
+ − lastChar = c;
+ −
+ − if (fullwidths != null) {
+ − final byte width = fullwidths[i];
+ − isWide = (width == AndroidCharacter.EAST_ASIAN_WIDTH_WIDE)
+ − || (width == AndroidCharacter.EAST_ASIAN_WIDTH_FULL_WIDTH);
+ − }
+ − }
+ − }
+ − }
+ −
+ − if (lastChar != -1)
+ − putChar((char) lastChar, isWide, false);
+ −
+ − setCursorPosition(C, R);
+ − redraw();
+ − }
+ − }
+ −
+ − protected void sendTelnetCommand(byte cmd) {
+ − /* do nothing by default */
+ − }
+ −
+ − /**
+ − * Sent the changed window size from the terminal to all listeners.
+ − */
+ − protected void setWindowSize(int c, int r) {
+ − /* To be overridden by Terminal.java */
+ − }
+ −
+ − @Override
+ − public void setScreenSize(int c, int r, boolean broadcast) {
+ − int oldrows = height;
+ −
+ − if (debug > 2) {
+ − if (debugStr == null)
+ − debugStr = new StringBuilder();
+ −
+ − debugStr.append("setscreensize (")
+ − .append(c)
+ − .append(',')
+ − .append(r)
+ − .append(',')
+ − .append(broadcast)
+ − .append(')');
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − super.setScreenSize(c, r, false);
+ − boolean cursorChanged = false;
+ −
+ − // Don't let the cursor go off the screen.
+ − if (C >= c) {
+ − C = c - 1;
+ − cursorChanged = true;
+ − }
+ −
+ − if (R >= r) {
+ − R = r - 1;
+ − cursorChanged = true;
+ − }
+ −
+ − if (cursorChanged) {
+ − setCursorPosition(C, R);
+ − redraw();
+ − }
+ −
+ − if (broadcast) {
+ − setWindowSize(c, r); /* broadcast up */
+ − }
+ − }
+ −
+ −
+ − /**
+ − * Create a new vt320 terminal and intialize it with useful settings.
+ − */
+ − public vt320(int width, int height) {
+ − super(width, height);
+ − debugStr = new StringBuilder();
+ − setVMS(false);
+ − setIBMCharset(false);
+ − setTerminalID("vt320");
+ − setBufferSize(100);
+ − //setBorder(2, false);
+ − gx = new char[4];
+ − reset();
+ − /* top row of numpad */
+ − PF1 = "\u001bOP";
+ − PF2 = "\u001bOQ";
+ − PF3 = "\u001bOR";
+ − PF4 = "\u001bOS";
+ − /* the 3x2 keyblock on PC keyboards */
+ − Insert = new String[4];
+ − Remove = new String[4];
+ − KeyHome = new String[4];
+ − KeyEnd = new String[4];
+ − NextScn = new String[4];
+ − PrevScn = new String[4];
+ − Escape = new String[4];
+ − BackSpace = new String[4];
+ − TabKey = new String[4];
+ − Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~";
+ − Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~";
+ − PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~";
+ − NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~";
+ − KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001b[H";
+ − KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001b[F";
+ − Escape[0] = Escape[1] = Escape[2] = Escape[3] = "\u001b";
+ −
+ − if (vms) {
+ − BackSpace[1] = "" + (char) 10; // VMS shift deletes word back
+ − BackSpace[2] = "\u0018"; // VMS control deletes line back
+ − BackSpace[0] = BackSpace[3] = "\u007f"; // VMS other is delete
+ − }
+ − else {
+ − //BackSpace[0] = BackSpace[1] = BackSpace[2] = BackSpace[3] = "\b";
+ − // ConnectBot modifications.
+ − BackSpace[0] = "\b";
+ − BackSpace[1] = "\u007f";
+ − BackSpace[2] = "\u001b[3~";
+ − BackSpace[3] = "\u001b[2~";
+ − }
+ −
+ − /* some more VT100 keys */
+ − Find = "\u001b[1~";
+ − Select = "\u001b[4~";
+ − Help = "\u001b[28~";
+ − Do = "\u001b[29~";
+ − FunctionKey = new String[21];
+ − FunctionKey[0] = "";
+ − FunctionKey[1] = PF1;
+ − FunctionKey[2] = PF2;
+ − FunctionKey[3] = PF3;
+ − FunctionKey[4] = PF4;
+ − /* following are defined differently for vt220 / vt132 ... */
+ − FunctionKey[5] = "\u001b[15~";
+ − FunctionKey[6] = "\u001b[17~";
+ − FunctionKey[7] = "\u001b[18~";
+ − FunctionKey[8] = "\u001b[19~";
+ − FunctionKey[9] = "\u001b[20~";
+ − FunctionKey[10] = "\u001b[21~";
+ − FunctionKey[11] = "\u001b[23~";
+ − FunctionKey[12] = "\u001b[24~";
+ − FunctionKey[13] = "\u001b[25~";
+ − FunctionKey[14] = "\u001b[26~";
+ − FunctionKey[15] = Help;
+ − FunctionKey[16] = Do;
+ − FunctionKey[17] = "\u001b[31~";
+ − FunctionKey[18] = "\u001b[32~";
+ − FunctionKey[19] = "\u001b[33~";
+ − FunctionKey[20] = "\u001b[34~";
+ − FunctionKeyShift = new String[21];
+ − FunctionKeyAlt = new String[21];
+ − FunctionKeyCtrl = new String[21];
+ −
+ − for (int i = 0; i < 20; i++) {
+ − FunctionKeyShift[i] = "";
+ − FunctionKeyAlt[i] = "";
+ − FunctionKeyCtrl[i] = "";
+ − }
+ −
+ − FunctionKeyShift[15] = Find;
+ − FunctionKeyShift[16] = Select;
+ − TabKey[0] = "\u0009";
+ − TabKey[1] = "\u001bOP\u0009";
+ − TabKey[2] = TabKey[3] = "";
+ − KeyUp = new String[4];
+ − KeyUp[0] = "\u001b[A";
+ − KeyDown = new String[4];
+ − KeyDown[0] = "\u001b[B";
+ − KeyRight = new String[4];
+ − KeyRight[0] = "\u001b[C";
+ − KeyLeft = new String[4];
+ − KeyLeft[0] = "\u001b[D";
+ − Numpad = new String[10];
+ − Numpad[0] = "\u001bOp";
+ − Numpad[1] = "\u001bOq";
+ − Numpad[2] = "\u001bOr";
+ − Numpad[3] = "\u001bOs";
+ − Numpad[4] = "\u001bOt";
+ − Numpad[5] = "\u001bOu";
+ − Numpad[6] = "\u001bOv";
+ − Numpad[7] = "\u001bOw";
+ − Numpad[8] = "\u001bOx";
+ − Numpad[9] = "\u001bOy";
+ − KPMinus = PF4;
+ − KPComma = "\u001bOl";
+ − KPPeriod = "\u001bOn";
+ − KPEnter = "\u001bOM";
+ − NUMPlus = new String[4];
+ − NUMPlus[0] = "+";
+ − NUMDot = new String[4];
+ − NUMDot[0] = ".";
+ − }
+ −
+ − public void setBackspace(int type) {
+ − switch (type) {
+ − case DELETE_IS_DEL:
+ − BackSpace[0] = "\u007f";
+ − BackSpace[1] = "\b";
+ − break;
+ −
+ − case DELETE_IS_BACKSPACE:
+ − BackSpace[0] = "\b";
+ − BackSpace[1] = "\u007f";
+ − break;
+ − }
+ − }
+ −
+ − /**
+ − * Create a default vt320 terminal with 80 columns and 24 lines.
+ − */
+ − public vt320() {
+ − this(80, 24);
+ − }
+ −
+ − /**
+ − * Terminal is mouse-aware and requires (x,y) coordinates of
+ − * on the terminal (character coordinates) and the button clicked.
+ − * @param x
+ − * @param y
+ − * @param modifiers
+ − */
+ − public void mousePressed(int x, int y, int modifiers) {
+ − if (mouserpt == 0)
+ − return;
+ −
+ − int mods = modifiers;
+ − mousebut = 3;
+ −
+ − if ((mods & 16) == 16) mousebut = 0;
+ −
+ − if ((mods & 8) == 8) mousebut = 1;
+ −
+ − if ((mods & 4) == 4) mousebut = 2;
+ −
+ − int mousecode;
+ −
+ − if (mouserpt == 9) /* X10 Mouse */
+ − mousecode = 0x20 | mousebut;
+ − else /* normal xterm mouse reporting */
+ − mousecode = mousebut | 0x20 | ((mods & 7) << 2);
+ −
+ − byte b[] = new byte[6];
+ − b[0] = 27;
+ − b[1] = (byte) '[';
+ − b[2] = (byte) 'M';
+ − b[3] = (byte) mousecode;
+ − b[4] = (byte)(0x20 + x + 1);
+ − b[5] = (byte)(0x20 + y + 1);
+ − write(b); // FIXME: writeSpecial here
+ − }
+ −
+ − /**
+ − * Terminal is mouse-aware and requires the coordinates and button
+ − * of the release.
+ − * @param x
+ − * @param y
+ − * @param modifiers
+ − */
+ − public void mouseReleased(int x, int y, int modifiers) {
+ − if (mouserpt == 0)
+ − return;
+ −
+ − /* problem is tht modifiers still have the released button set in them.
+ − int mods = modifiers;
+ − mousebut = 3;
+ − if ((mods & 16)==16) mousebut=0;
+ − if ((mods & 8)==8 ) mousebut=1;
+ − if ((mods & 4)==4 ) mousebut=2;
+ − */
+ − int mousecode;
+ −
+ − if (mouserpt == 9)
+ − mousecode = 0x20 + mousebut; /* same as press? appears so. */
+ − else
+ − mousecode = '#';
+ −
+ − byte b[] = new byte[6];
+ − b[0] = 27;
+ − b[1] = (byte) '[';
+ − b[2] = (byte) 'M';
+ − b[3] = (byte) mousecode;
+ − b[4] = (byte)(0x20 + x + 1);
+ − b[5] = (byte)(0x20 + y + 1);
+ − write(b); // FIXME: writeSpecial here
+ − mousebut = 0;
+ − }
+ −
+ −
+ − /** we should do localecho (passed from other modules). false is default */
+ − private boolean localecho = false;
+ −
+ − /**
+ − * Enable or disable the local echo property of the terminal.
+ − * @param echo true if the terminal should echo locally
+ − */
+ − public void setLocalEcho(boolean echo) {
+ − localecho = echo;
+ − }
+ −
+ − /**
+ − * Enable the VMS mode of the terminal to handle some things differently
+ − * for VMS hosts.
+ − * @param vms true for vms mode, false for normal mode
+ − */
+ − public void setVMS(boolean vms) {
+ − this.vms = vms;
+ − }
+ −
+ − /**
+ − * Enable the usage of the IBM character set used by some BBS's. Special
+ − * graphical character are available in this mode.
+ − * @param ibm true to use the ibm character set
+ − */
+ − public void setIBMCharset(boolean ibm) {
+ − useibmcharset = ibm;
+ − }
+ −
+ − /**
+ − * Override the standard key codes used by the terminal emulation.
+ − * @param codes a properties object containing key code definitions
+ − */
+ − public void setKeyCodes(Properties codes) {
+ − String res, prefixes[] = {"", "S", "C", "A"};
+ − int i;
+ −
+ − for (i = 0; i < 10; i++) {
+ − res = codes.getProperty("NUMPAD" + i);
+ −
+ − if (res != null) Numpad[i] = unEscape(res);
+ − }
+ −
+ − for (i = 1; i < 20; i++) {
+ − res = codes.getProperty("F" + i);
+ −
+ − if (res != null) FunctionKey[i] = unEscape(res);
+ −
+ − res = codes.getProperty("SF" + i);
+ −
+ − if (res != null) FunctionKeyShift[i] = unEscape(res);
+ −
+ − res = codes.getProperty("CF" + i);
+ −
+ − if (res != null) FunctionKeyCtrl[i] = unEscape(res);
+ −
+ − res = codes.getProperty("AF" + i);
+ −
+ − if (res != null) FunctionKeyAlt[i] = unEscape(res);
+ − }
+ −
+ − for (i = 0; i < 4; i++) {
+ − res = codes.getProperty(prefixes[i] + "PGUP");
+ −
+ − if (res != null) PrevScn[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "PGDOWN");
+ −
+ − if (res != null) NextScn[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "END");
+ −
+ − if (res != null) KeyEnd[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "HOME");
+ −
+ − if (res != null) KeyHome[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "INSERT");
+ −
+ − if (res != null) Insert[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "REMOVE");
+ −
+ − if (res != null) Remove[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "UP");
+ −
+ − if (res != null) KeyUp[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "DOWN");
+ −
+ − if (res != null) KeyDown[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "LEFT");
+ −
+ − if (res != null) KeyLeft[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "RIGHT");
+ −
+ − if (res != null) KeyRight[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "ESCAPE");
+ −
+ − if (res != null) Escape[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "BACKSPACE");
+ −
+ − if (res != null) BackSpace[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "TAB");
+ −
+ − if (res != null) TabKey[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "NUMPLUS");
+ −
+ − if (res != null) NUMPlus[i] = unEscape(res);
+ −
+ − res = codes.getProperty(prefixes[i] + "NUMDECIMAL");
+ −
+ − if (res != null) NUMDot[i] = unEscape(res);
+ − }
+ − }
+ −
+ − /**
+ − * Set the terminal id used to identify this terminal.
+ − * @param terminalID the id string
+ − */
+ − public void setTerminalID(String terminalID) {
+ − this.terminalID = terminalID;
+ −
+ − if (terminalID.equals("scoansi")) {
+ − FunctionKey[1] = "\u001b[M"; FunctionKey[2] = "\u001b[N";
+ − FunctionKey[3] = "\u001b[O"; FunctionKey[4] = "\u001b[P";
+ − FunctionKey[5] = "\u001b[Q"; FunctionKey[6] = "\u001b[R";
+ − FunctionKey[7] = "\u001b[S"; FunctionKey[8] = "\u001b[T";
+ − FunctionKey[9] = "\u001b[U"; FunctionKey[10] = "\u001b[V";
+ − FunctionKey[11] = "\u001b[W"; FunctionKey[12] = "\u001b[X";
+ − FunctionKey[13] = "\u001b[Y"; FunctionKey[14] = "?";
+ − FunctionKey[15] = "\u001b[a"; FunctionKey[16] = "\u001b[b";
+ − FunctionKey[17] = "\u001b[c"; FunctionKey[18] = "\u001b[d";
+ − FunctionKey[19] = "\u001b[e"; FunctionKey[20] = "\u001b[f";
+ − PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[I";
+ − NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[G";
+ − // more theoretically.
+ − }
+ − }
+ −
+ − public void setAnswerBack(String ab) {
+ − this.answerBack = unEscape(ab);
+ − }
+ −
+ − /**
+ − * Get the terminal id used to identify this terminal.
+ − */
+ − public String getTerminalID() {
+ − return terminalID;
+ − }
+ −
+ − /**
+ − * A small conveniance method thar converts the string to a byte array
+ − * for sending.
+ − * @param s the string to be sent
+ − */
+ − private boolean write(String s, boolean doecho) {
+ − if (debug > 2) {
+ − debugStr.append("write(|")
+ − .append(s)
+ − .append("|,")
+ − .append(doecho);
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − if (s == null) // aka the empty string.
+ − return true;
+ −
+ − /* NOTE: getBytes() honours some locale, it *CONVERTS* the string.
+ − * However, we output only 7bit stuff towards the target, and *some*
+ − * 8 bit control codes. We must not mess up the latter, so we do hand
+ − * by hand copy.
+ − */
+ − byte arr[] = new byte[s.length()];
+ −
+ − for (int i = 0; i < s.length(); i++) {
+ − arr[i] = (byte) s.charAt(i);
+ − }
+ −
+ − write(arr);
+ −
+ − if (doecho)
+ − putString(s);
+ −
+ − return true;
+ − }
+ −
+ − private boolean write(int s, boolean doecho) {
+ − if (debug > 2) {
+ − debugStr.append("write(|")
+ − .append(s)
+ − .append("|,")
+ − .append(doecho);
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − write(s);
+ −
+ − // TODO check if character is wide
+ − if (doecho)
+ − putChar((char)s, false, false);
+ −
+ − return true;
+ − }
+ −
+ − private boolean write(String s) {
+ − return write(s, localecho);
+ − }
+ −
+ − // ===================================================================
+ − // the actual terminal emulation code comes here:
+ − // ===================================================================
+ −
+ − private String terminalID = "vt320";
+ − private String answerBack = "Use Terminal.answerback to set ...\n";
+ −
+ − // X - COLUMNS, Y - ROWS
+ − int R, C;
+ − int attributes = 0;
+ −
+ − int Sc, Sr, Sa, Stm, Sbm;
+ − char Sgr, Sgl;
+ − char Sgx[];
+ −
+ − int insertmode = 0;
+ − int statusmode = 0;
+ − boolean vt52mode = false;
+ − boolean keypadmode = false; /* false - numeric, true - application */
+ − boolean output8bit = false;
+ − int normalcursor = 0;
+ − boolean moveoutsidemargins = true;
+ − boolean wraparound = true;
+ − boolean sendcrlf = true;
+ − boolean capslock = false;
+ − boolean numlock = false;
+ − int mouserpt = 0;
+ − byte mousebut = 0;
+ −
+ − boolean useibmcharset = false;
+ −
+ − int lastwaslf = 0;
+ − boolean usedcharsets = false;
+ −
+ − private final static char ESC = 27;
+ − private final static char IND = 132;
+ − private final static char NEL = 133;
+ − private final static char RI = 141;
+ − private final static char SS2 = 142;
+ − private final static char SS3 = 143;
+ − private final static char DCS = 144;
+ − private final static char HTS = 136;
+ − private final static char CSI = 155;
+ − private final static char OSC = 157;
+ − private final static int TSTATE_DATA = 0;
+ − private final static int TSTATE_ESC = 1; /* ESC */
+ − private final static int TSTATE_CSI = 2; /* ESC [ */
+ − private final static int TSTATE_DCS = 3; /* ESC P */
+ − private final static int TSTATE_DCEQ = 4; /* ESC [? */
+ − private final static int TSTATE_ESCSQUARE = 5; /* ESC # */
+ − private final static int TSTATE_OSC = 6; /* ESC ] */
+ − private final static int TSTATE_SETG0 = 7; /* ESC (? */
+ − private final static int TSTATE_SETG1 = 8; /* ESC )? */
+ − private final static int TSTATE_SETG2 = 9; /* ESC *? */
+ − private final static int TSTATE_SETG3 = 10; /* ESC +? */
+ − private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */
+ − private final static int TSTATE_CSI_EX = 12; /* ESC [ ! */
+ − private final static int TSTATE_ESCSPACE = 13; /* ESC <space> */
+ − private final static int TSTATE_VT52X = 14;
+ − private final static int TSTATE_VT52Y = 15;
+ − private final static int TSTATE_CSI_TICKS = 16;
+ − private final static int TSTATE_CSI_EQUAL = 17; /* ESC [ = */
+ − private final static int TSTATE_TITLE = 18; /* xterm title */
+ −
+ − /* Keys we support */
+ − public final static int KEY_PAUSE = 1;
+ − public final static int KEY_F1 = 2;
+ − public final static int KEY_F2 = 3;
+ − public final static int KEY_F3 = 4;
+ − public final static int KEY_F4 = 5;
+ − public final static int KEY_F5 = 6;
+ − public final static int KEY_F6 = 7;
+ − public final static int KEY_F7 = 8;
+ − public final static int KEY_F8 = 9;
+ − public final static int KEY_F9 = 10;
+ − public final static int KEY_F10 = 11;
+ − public final static int KEY_F11 = 12;
+ − public final static int KEY_F12 = 13;
+ − public final static int KEY_F13 = 14; // only used by tn5250
+ − public final static int KEY_F14 = 15; // only used by tn5250
+ − public final static int KEY_F15 = 16; // only used by tn5250
+ − public final static int KEY_F16 = 17; // only used by tn5250
+ − public final static int KEY_F17 = 18; // only used by tn5250
+ − public final static int KEY_F18 = 19; // only used by tn5250
+ − public final static int KEY_F19 = 20; // only used by tn5250
+ − public final static int KEY_F20 = 21; // only used by tn5250
+ − public final static int KEY_F21 = 22; // only used by tn5250
+ − public final static int KEY_F22 = 23; // only used by tn5250
+ − public final static int KEY_F23 = 24; // only used by tn5250
+ − public final static int KEY_F24 = 25; // only used by tn5250
+ − public final static int KEY_UP = 26;
+ − public final static int KEY_DOWN = 27;
+ − public final static int KEY_LEFT = 28;
+ − public final static int KEY_RIGHT = 29;
+ − public final static int KEY_PAGE_DOWN = 30;
+ − public final static int KEY_PAGE_UP = 31;
+ − public final static int KEY_INSERT = 32;
+ − public final static int KEY_DELETE = 33;
+ − public final static int KEY_BACK_SPACE = 34;
+ − public final static int KEY_HOME = 35;
+ − public final static int KEY_END = 36;
+ − public final static int KEY_NUM_LOCK = 37;
+ − public final static int KEY_CAPS_LOCK = 38;
+ − public final static int KEY_SHIFT = 39;
+ − public final static int KEY_CONTROL = 40;
+ − public final static int KEY_ALT = 41;
+ − public final static int KEY_ENTER = 42;
+ − public final static int KEY_NUMPAD0 = 43;
+ − public final static int KEY_NUMPAD1 = 44;
+ − public final static int KEY_NUMPAD2 = 45;
+ − public final static int KEY_NUMPAD3 = 46;
+ − public final static int KEY_NUMPAD4 = 47;
+ − public final static int KEY_NUMPAD5 = 48;
+ − public final static int KEY_NUMPAD6 = 49;
+ − public final static int KEY_NUMPAD7 = 50;
+ − public final static int KEY_NUMPAD8 = 51;
+ − public final static int KEY_NUMPAD9 = 52;
+ − public final static int KEY_DECIMAL = 53;
+ − public final static int KEY_ADD = 54;
+ − public final static int KEY_ESCAPE = 55;
+ − public final static int KEY_TAB = 56;
+ − public final static int KEY_SYSREQ = 57; // only used by tn5250
+ −
+ − public final static int DELETE_IS_DEL = 0;
+ − public final static int DELETE_IS_BACKSPACE = 1;
+ −
+ − /* The graphics charsets
+ − * B - default ASCII
+ − * A - ISO Latin 1
+ − * 0 - DEC SPECIAL
+ − * < - User defined
+ − * ....
+ − */
+ − char gx[];
+ − char gl; // GL (left charset)
+ − char gr; // GR (right charset)
+ − int onegl; // single shift override for GL.
+ −
+ − // Map from scoansi linedrawing to DEC _and_ unicode (for the stuff which
+ − // is not in linedrawing). Got from experimenting with scoadmin.
+ − private final static String scoansi_acs = "Tm7k3x4u?kZl@mYjEnB\u2566DqCtAvM\u2550:\u2551N\u2557I\u2554;\u2557H\u255a0a<\u255d";
+ − // array to store DEC Special -> Unicode mapping
+ − // Unicode DEC Unicode name (DEC name)
+ − private static char DECSPECIAL[] = {
+ − '\u0040', //5f blank
+ − '\u2666', //60 black diamond
+ − '\u2592', //61 grey square
+ − '\u2409', //62 Horizontal tab (ht) pict. for control
+ − '\u240c', //63 Form Feed (ff) pict. for control
+ − '\u240d', //64 Carriage Return (cr) pict. for control
+ − '\u240a', //65 Line Feed (lf) pict. for control
+ − '\u00ba', //66 Masculine ordinal indicator
+ − '\u00b1', //67 Plus or minus sign
+ − '\u2424', //68 New Line (nl) pict. for control
+ − '\u240b', //69 Vertical Tab (vt) pict. for control
+ − '\u2518', //6a Forms light up and left
+ − '\u2510', //6b Forms light down and left
+ − '\u250c', //6c Forms light down and right
+ − '\u2514', //6d Forms light up and right
+ − '\u253c', //6e Forms light vertical and horizontal
+ − '\u2594', //6f Upper 1/8 block (Scan 1)
+ − '\u2580', //70 Upper 1/2 block (Scan 3)
+ − '\u2500', //71 Forms light horizontal or ?em dash? (Scan 5)
+ − '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7)
+ − '\u005f', //73 \u005f underscore or \u2581 lower 1/8 (Scan 9)
+ − '\u251c', //74 Forms light vertical and right
+ − '\u2524', //75 Forms light vertical and left
+ − '\u2534', //76 Forms light up and horizontal
+ − '\u252c', //77 Forms light down and horizontal
+ − '\u2502', //78 vertical bar
+ − '\u2264', //79 less than or equal
+ − '\u2265', //7a greater than or equal
+ − '\u00b6', //7b paragraph
+ − '\u2260', //7c not equal
+ − '\u00a3', //7d Pound Sign (british)
+ − '\u00b7' //7e Middle Dot
+ − };
+ −
+ − /** Strings to send on function key pressing */
+ − private String Numpad[];
+ − private String FunctionKey[];
+ − private String FunctionKeyShift[];
+ − private String FunctionKeyCtrl[];
+ − private String FunctionKeyAlt[];
+ − private String TabKey[];
+ − private String KeyUp[], KeyDown[], KeyLeft[], KeyRight[];
+ − private String KPMinus, KPComma, KPPeriod, KPEnter;
+ − private String PF1, PF2, PF3, PF4;
+ − private String Help, Do, Find, Select;
+ −
+ − private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[];
+ − private String Escape[], BackSpace[], NUMDot[], NUMPlus[];
+ −
+ − private String osc, dcs; /* to memorize OSC & DCS control sequence */
+ −
+ − /** vt320 state variable (internal) */
+ − private int term_state = TSTATE_DATA;
+ − /** in vms mode, set by Terminal.VMS property */
+ − private boolean vms = false;
+ − /** Tabulators */
+ − private byte[] Tabs;
+ − /** The list of integers as used by CSI */
+ − private int[] DCEvars = new int[30];
+ − private int DCEvar;
+ −
+ − /**
+ − * Replace escape code characters (backslash + identifier) with their
+ − * respective codes.
+ − * @param tmp the string to be parsed
+ − * @return a unescaped string
+ − */
+ − static String unEscape(String tmp) {
+ − int idx = 0, oldidx = 0;
+ − String cmd;
+ − // f.println("unescape("+tmp+")");
+ − cmd = "";
+ −
+ − while ((idx = tmp.indexOf('\\', oldidx)) >= 0 &&
+ − ++idx <= tmp.length()) {
+ − cmd += tmp.substring(oldidx, idx - 1);
+ −
+ − if (idx == tmp.length()) return cmd;
+ −
+ − switch (tmp.charAt(idx)) {
+ − case 'b':
+ − cmd += "\b";
+ − break;
+ −
+ − case 'e':
+ − cmd += "\u001b";
+ − break;
+ −
+ − case 'n':
+ − cmd += "\n";
+ − break;
+ −
+ − case 'r':
+ − cmd += "\r";
+ − break;
+ −
+ − case 't':
+ − cmd += "\t";
+ − break;
+ −
+ − case 'v':
+ − cmd += "\u000b";
+ − break;
+ −
+ − case 'a':
+ − cmd += "\u0012";
+ − break;
+ −
+ − default :
+ − if ((tmp.charAt(idx) >= '0') && (tmp.charAt(idx) <= '9')) {
+ − int i;
+ −
+ − for (i = idx; i < tmp.length(); i++)
+ − if ((tmp.charAt(i) < '0') || (tmp.charAt(i) > '9'))
+ − break;
+ −
+ − cmd += (char) Integer.parseInt(tmp.substring(idx, i));
+ − idx = i - 1;
+ − }
+ − else
+ − cmd += tmp.substring(idx, ++idx);
+ −
+ − break;
+ − }
+ −
+ − oldidx = ++idx;
+ − }
+ −
+ − if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx);
+ −
+ − return cmd;
+ − }
+ −
+ − /**
+ − * A small conveniance method thar converts a 7bit string to the 8bit
+ − * version depending on VT52/Output8Bit mode.
+ − *
+ − * @param s the string to be sent
+ − */
+ − private boolean writeSpecial(String s) {
+ − if (s == null)
+ − return true;
+ −
+ − if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == 'O'))) {
+ − if (vt52mode) {
+ − if ((s.charAt(2) >= 'P') && (s.charAt(2) <= 'S')) {
+ − s = "\u001b" + s.substring(2); /* ESC x */
+ − }
+ − else {
+ − s = "\u001b?" + s.substring(2); /* ESC ? x */
+ − }
+ − }
+ − else {
+ − if (output8bit) {
+ − s = "\u008f" + s.substring(2); /* SS3 x */
+ − } /* else keep string as it is */
+ − }
+ − }
+ −
+ − if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == '['))) {
+ − if (output8bit) {
+ − s = "\u009b" + s.substring(2); /* CSI ... */
+ − } /* else keep */
+ − }
+ −
+ − return write(s, false);
+ − }
+ −
+ − /**
+ − * main keytyping event handler for all the special function and modifier keys
+ − * the normal keys are processed by write(byte b);
+ − */
+ − public void keyPressed(int keyCode, char keyChar, int modifiers) {
+ − boolean control = (modifiers & VDUInput.KEY_CONTROL) != 0;
+ − boolean shift = (modifiers & VDUInput.KEY_SHIFT) != 0;
+ − boolean alt = (modifiers & VDUInput.KEY_ALT) != 0;
+ −
+ − if (debug > 1) {
+ − debugStr.append("keyPressed(")
+ − .append(keyCode)
+ − .append(", ")
+ − .append((int)keyChar)
+ − .append(", ")
+ − .append(modifiers)
+ − .append(')');
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − int xind;
+ − String fmap[];
+ − xind = 0;
+ − fmap = FunctionKey;
+ −
+ − if (shift) {
+ − fmap = FunctionKeyShift;
+ − xind = 1;
+ − }
+ −
+ − if (control) {
+ − fmap = FunctionKeyCtrl;
+ − xind = 2;
+ − }
+ −
+ − if (alt) {
+ − fmap = FunctionKeyAlt;
+ − xind = 3;
+ − }
+ −
+ − switch (keyCode) {
+ − case KEY_PAUSE:
+ − if (shift || control)
+ − sendTelnetCommand((byte) 243); // BREAK
+ −
+ − break;
+ −
+ − case KEY_F1:
+ − writeSpecial(fmap[1]);
+ − break;
+ −
+ − case KEY_F2:
+ − writeSpecial(fmap[2]);
+ − break;
+ −
+ − case KEY_F3:
+ − writeSpecial(fmap[3]);
+ − break;
+ −
+ − case KEY_F4:
+ − writeSpecial(fmap[4]);
+ − break;
+ −
+ − case KEY_F5:
+ − writeSpecial(fmap[5]);
+ − break;
+ −
+ − case KEY_F6:
+ − writeSpecial(fmap[6]);
+ − break;
+ −
+ − case KEY_F7:
+ − writeSpecial(fmap[7]);
+ − break;
+ −
+ − case KEY_F8:
+ − writeSpecial(fmap[8]);
+ − break;
+ −
+ − case KEY_F9:
+ − writeSpecial(fmap[9]);
+ − break;
+ −
+ − case KEY_F10:
+ − writeSpecial(fmap[10]);
+ − break;
+ −
+ − case KEY_F11:
+ − writeSpecial(fmap[11]);
+ − break;
+ −
+ − case KEY_F12:
+ − writeSpecial(fmap[12]);
+ − break;
+ −
+ − case KEY_F13:
+ − case KEY_F14:
+ − case KEY_F15:
+ − case KEY_F16:
+ − case KEY_F17:
+ − case KEY_F18:
+ − case KEY_F19:
+ − case KEY_F20:
+ − case KEY_F21:
+ − case KEY_F22:
+ − case KEY_F23:
+ − case KEY_F24:
+ − break;
+ −
+ − case KEY_UP:
+ − writeSpecial(KeyUp[xind]);
+ − break;
+ −
+ − case KEY_DOWN:
+ − writeSpecial(KeyDown[xind]);
+ − break;
+ −
+ − case KEY_LEFT:
+ − writeSpecial(KeyLeft[xind]);
+ − break;
+ −
+ − case KEY_RIGHT:
+ − writeSpecial(KeyRight[xind]);
+ − break;
+ −
+ − case KEY_PAGE_DOWN:
+ − writeSpecial(NextScn[xind]);
+ − break;
+ −
+ − case KEY_PAGE_UP:
+ − writeSpecial(PrevScn[xind]);
+ − break;
+ −
+ − case KEY_INSERT:
+ − writeSpecial(Insert[xind]);
+ − break;
+ −
+ − case KEY_DELETE:
+ − writeSpecial(Remove[xind]);
+ − break;
+ −
+ − case KEY_BACK_SPACE:
+ − writeSpecial(BackSpace[xind]);
+ −
+ − if (localecho) {
+ − if (BackSpace[xind] == "\b") {
+ − putString("\b \b"); // make the last char 'deleted'
+ − }
+ − else {
+ − putString(BackSpace[xind]); // echo it
+ − }
+ − }
+ −
+ − break;
+ −
+ − case KEY_HOME:
+ − writeSpecial(KeyHome[xind]);
+ − break;
+ −
+ − case KEY_END:
+ − writeSpecial(KeyEnd[xind]);
+ − break;
+ −
+ − case KEY_NUM_LOCK:
+ − if (vms && control) {
+ − writeSpecial(PF1);
+ − }
+ −
+ − if (!control)
+ − numlock = !numlock;
+ −
+ − break;
+ −
+ − case KEY_CAPS_LOCK:
+ − capslock = !capslock;
+ − break;
+ −
+ − case KEY_SHIFT:
+ − case KEY_CONTROL:
+ − case KEY_ALT:
+ − break;
+ −
+ − case KEY_ESCAPE:
+ − writeSpecial(Escape[xind]);
+ − break;
+ −
+ − case KEY_ENTER:
+ − write(0x0d);
+ − break;
+ −
+ − case KEY_TAB:
+ − writeSpecial(TabKey[xind]);
+ − break;
+ −
+ − default:
+ − break;
+ − }
+ − }
+ −
+ − private void handle_dcs(String dcs) {
+ − debugStr.append("DCS: ")
+ − .append(dcs);
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − private void handle_osc(String osc) {
+ − if (osc.length() > 2 && osc.substring(0, 2).equals("4;")) {
+ − // Define color palette
+ − String[] colorData = osc.split(";");
+ −
+ − try {
+ − int colorIndex = Integer.parseInt(colorData[1]);
+ −
+ − if ("rgb:".equals(colorData[2].substring(0, 4))) {
+ − String[] rgb = colorData[2].substring(4).split("/");
+ − int red = Integer.parseInt(rgb[0].substring(0, 2), 16) & 0xFF;
+ − int green = Integer.parseInt(rgb[1].substring(0, 2), 16) & 0xFF;
+ − int blue = Integer.parseInt(rgb[2].substring(0, 2), 16) & 0xFF;
+ − display.setColor(colorIndex, red, green, blue);
+ − }
+ − }
+ − catch (Exception e) {
+ − debugStr.append("OSC: invalid color sequence encountered: ")
+ − .append(osc);
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ − }
+ − else
+ − debug("OSC: " + osc);
+ − }
+ −
+ − private final static char unimap[] = {
+ − //#
+ − //# Name: cp437_DOSLatinUS to Unicode table
+ − //# Unicode version: 1.1
+ − //# Table version: 1.1
+ − //# Table format: Format A
+ − //# Date: 03/31/95
+ − //# Authors: Michel Suignard <michelsu@microsoft.com>
+ − //# Lori Hoerth <lorih@microsoft.com>
+ − //# General notes: none
+ − //#
+ − //# Format: Three tab-separated columns
+ − //# Column #1 is the cp1255_WinHebrew code (in hex)
+ − //# Column #2 is the Unicode (in hex as 0xXXXX)
+ − //# Column #3 is the Unicode name (follows a comment sign, '#')
+ − //#
+ − //# The entries are in cp437_DOSLatinUS order
+ − //#
+ −
+ − 0x0000, // #NULL
+ − 0x0001, // #START OF HEADING
+ − 0x0002, // #START OF TEXT
+ − 0x0003, // #END OF TEXT
+ − 0x0004, // #END OF TRANSMISSION
+ − 0x0005, // #ENQUIRY
+ − 0x0006, // #ACKNOWLEDGE
+ − 0x0007, // #BELL
+ − 0x0008, // #BACKSPACE
+ − 0x0009, // #HORIZONTAL TABULATION
+ − 0x000a, // #LINE FEED
+ − 0x000b, // #VERTICAL TABULATION
+ − 0x000c, // #FORM FEED
+ − 0x000d, // #CARRIAGE RETURN
+ − 0x000e, // #SHIFT OUT
+ − 0x000f, // #SHIFT IN
+ − 0x0010, // #DATA LINK ESCAPE
+ − 0x0011, // #DEVICE CONTROL ONE
+ − 0x0012, // #DEVICE CONTROL TWO
+ − 0x0013, // #DEVICE CONTROL THREE
+ − 0x0014, // #DEVICE CONTROL FOUR
+ − 0x0015, // #NEGATIVE ACKNOWLEDGE
+ − 0x0016, // #SYNCHRONOUS IDLE
+ − 0x0017, // #END OF TRANSMISSION BLOCK
+ − 0x0018, // #CANCEL
+ − 0x0019, // #END OF MEDIUM
+ − 0x001a, // #SUBSTITUTE
+ − 0x001b, // #ESCAPE
+ − 0x001c, // #FILE SEPARATOR
+ − 0x001d, // #GROUP SEPARATOR
+ − 0x001e, // #RECORD SEPARATOR
+ − 0x001f, // #UNIT SEPARATOR
+ − 0x0020, // #SPACE
+ − 0x0021, // #EXCLAMATION MARK
+ − 0x0022, // #QUOTATION MARK
+ − 0x0023, // #NUMBER SIGN
+ − 0x0024, // #DOLLAR SIGN
+ − 0x0025, // #PERCENT SIGN
+ − 0x0026, // #AMPERSAND
+ − 0x0027, // #APOSTROPHE
+ − 0x0028, // #LEFT PARENTHESIS
+ − 0x0029, // #RIGHT PARENTHESIS
+ − 0x002a, // #ASTERISK
+ − 0x002b, // #PLUS SIGN
+ − 0x002c, // #COMMA
+ − 0x002d, // #HYPHEN-MINUS
+ − 0x002e, // #FULL STOP
+ − 0x002f, // #SOLIDUS
+ − 0x0030, // #DIGIT ZERO
+ − 0x0031, // #DIGIT ONE
+ − 0x0032, // #DIGIT TWO
+ − 0x0033, // #DIGIT THREE
+ − 0x0034, // #DIGIT FOUR
+ − 0x0035, // #DIGIT FIVE
+ − 0x0036, // #DIGIT SIX
+ − 0x0037, // #DIGIT SEVEN
+ − 0x0038, // #DIGIT EIGHT
+ − 0x0039, // #DIGIT NINE
+ − 0x003a, // #COLON
+ − 0x003b, // #SEMICOLON
+ − 0x003c, // #LESS-THAN SIGN
+ − 0x003d, // #EQUALS SIGN
+ − 0x003e, // #GREATER-THAN SIGN
+ − 0x003f, // #QUESTION MARK
+ − 0x0040, // #COMMERCIAL AT
+ − 0x0041, // #LATIN CAPITAL LETTER A
+ − 0x0042, // #LATIN CAPITAL LETTER B
+ − 0x0043, // #LATIN CAPITAL LETTER C
+ − 0x0044, // #LATIN CAPITAL LETTER D
+ − 0x0045, // #LATIN CAPITAL LETTER E
+ − 0x0046, // #LATIN CAPITAL LETTER F
+ − 0x0047, // #LATIN CAPITAL LETTER G
+ − 0x0048, // #LATIN CAPITAL LETTER H
+ − 0x0049, // #LATIN CAPITAL LETTER I
+ − 0x004a, // #LATIN CAPITAL LETTER J
+ − 0x004b, // #LATIN CAPITAL LETTER K
+ − 0x004c, // #LATIN CAPITAL LETTER L
+ − 0x004d, // #LATIN CAPITAL LETTER M
+ − 0x004e, // #LATIN CAPITAL LETTER N
+ − 0x004f, // #LATIN CAPITAL LETTER O
+ − 0x0050, // #LATIN CAPITAL LETTER P
+ − 0x0051, // #LATIN CAPITAL LETTER Q
+ − 0x0052, // #LATIN CAPITAL LETTER R
+ − 0x0053, // #LATIN CAPITAL LETTER S
+ − 0x0054, // #LATIN CAPITAL LETTER T
+ − 0x0055, // #LATIN CAPITAL LETTER U
+ − 0x0056, // #LATIN CAPITAL LETTER V
+ − 0x0057, // #LATIN CAPITAL LETTER W
+ − 0x0058, // #LATIN CAPITAL LETTER X
+ − 0x0059, // #LATIN CAPITAL LETTER Y
+ − 0x005a, // #LATIN CAPITAL LETTER Z
+ − 0x005b, // #LEFT SQUARE BRACKET
+ − 0x005c, // #REVERSE SOLIDUS
+ − 0x005d, // #RIGHT SQUARE BRACKET
+ − 0x005e, // #CIRCUMFLEX ACCENT
+ − 0x005f, // #LOW LINE
+ − 0x0060, // #GRAVE ACCENT
+ − 0x0061, // #LATIN SMALL LETTER A
+ − 0x0062, // #LATIN SMALL LETTER B
+ − 0x0063, // #LATIN SMALL LETTER C
+ − 0x0064, // #LATIN SMALL LETTER D
+ − 0x0065, // #LATIN SMALL LETTER E
+ − 0x0066, // #LATIN SMALL LETTER F
+ − 0x0067, // #LATIN SMALL LETTER G
+ − 0x0068, // #LATIN SMALL LETTER H
+ − 0x0069, // #LATIN SMALL LETTER I
+ − 0x006a, // #LATIN SMALL LETTER J
+ − 0x006b, // #LATIN SMALL LETTER K
+ − 0x006c, // #LATIN SMALL LETTER L
+ − 0x006d, // #LATIN SMALL LETTER M
+ − 0x006e, // #LATIN SMALL LETTER N
+ − 0x006f, // #LATIN SMALL LETTER O
+ − 0x0070, // #LATIN SMALL LETTER P
+ − 0x0071, // #LATIN SMALL LETTER Q
+ − 0x0072, // #LATIN SMALL LETTER R
+ − 0x0073, // #LATIN SMALL LETTER S
+ − 0x0074, // #LATIN SMALL LETTER T
+ − 0x0075, // #LATIN SMALL LETTER U
+ − 0x0076, // #LATIN SMALL LETTER V
+ − 0x0077, // #LATIN SMALL LETTER W
+ − 0x0078, // #LATIN SMALL LETTER X
+ − 0x0079, // #LATIN SMALL LETTER Y
+ − 0x007a, // #LATIN SMALL LETTER Z
+ − 0x007b, // #LEFT CURLY BRACKET
+ − 0x007c, // #VERTICAL LINE
+ − 0x007d, // #RIGHT CURLY BRACKET
+ − 0x007e, // #TILDE
+ − 0x007f, // #DELETE
+ − 0x00c7, // #LATIN CAPITAL LETTER C WITH CEDILLA
+ − 0x00fc, // #LATIN SMALL LETTER U WITH DIAERESIS
+ − 0x00e9, // #LATIN SMALL LETTER E WITH ACUTE
+ − 0x00e2, // #LATIN SMALL LETTER A WITH CIRCUMFLEX
+ − 0x00e4, // #LATIN SMALL LETTER A WITH DIAERESIS
+ − 0x00e0, // #LATIN SMALL LETTER A WITH GRAVE
+ − 0x00e5, // #LATIN SMALL LETTER A WITH RING ABOVE
+ − 0x00e7, // #LATIN SMALL LETTER C WITH CEDILLA
+ − 0x00ea, // #LATIN SMALL LETTER E WITH CIRCUMFLEX
+ − 0x00eb, // #LATIN SMALL LETTER E WITH DIAERESIS
+ − 0x00e8, // #LATIN SMALL LETTER E WITH GRAVE
+ − 0x00ef, // #LATIN SMALL LETTER I WITH DIAERESIS
+ − 0x00ee, // #LATIN SMALL LETTER I WITH CIRCUMFLEX
+ − 0x00ec, // #LATIN SMALL LETTER I WITH GRAVE
+ − 0x00c4, // #LATIN CAPITAL LETTER A WITH DIAERESIS
+ − 0x00c5, // #LATIN CAPITAL LETTER A WITH RING ABOVE
+ − 0x00c9, // #LATIN CAPITAL LETTER E WITH ACUTE
+ − 0x00e6, // #LATIN SMALL LIGATURE AE
+ − 0x00c6, // #LATIN CAPITAL LIGATURE AE
+ − 0x00f4, // #LATIN SMALL LETTER O WITH CIRCUMFLEX
+ − 0x00f6, // #LATIN SMALL LETTER O WITH DIAERESIS
+ − 0x00f2, // #LATIN SMALL LETTER O WITH GRAVE
+ − 0x00fb, // #LATIN SMALL LETTER U WITH CIRCUMFLEX
+ − 0x00f9, // #LATIN SMALL LETTER U WITH GRAVE
+ − 0x00ff, // #LATIN SMALL LETTER Y WITH DIAERESIS
+ − 0x00d6, // #LATIN CAPITAL LETTER O WITH DIAERESIS
+ − 0x00dc, // #LATIN CAPITAL LETTER U WITH DIAERESIS
+ − 0x00a2, // #CENT SIGN
+ − 0x00a3, // #POUND SIGN
+ − 0x00a5, // #YEN SIGN
+ − 0x20a7, // #PESETA SIGN
+ − 0x0192, // #LATIN SMALL LETTER F WITH HOOK
+ − 0x00e1, // #LATIN SMALL LETTER A WITH ACUTE
+ − 0x00ed, // #LATIN SMALL LETTER I WITH ACUTE
+ − 0x00f3, // #LATIN SMALL LETTER O WITH ACUTE
+ − 0x00fa, // #LATIN SMALL LETTER U WITH ACUTE
+ − 0x00f1, // #LATIN SMALL LETTER N WITH TILDE
+ − 0x00d1, // #LATIN CAPITAL LETTER N WITH TILDE
+ − 0x00aa, // #FEMININE ORDINAL INDICATOR
+ − 0x00ba, // #MASCULINE ORDINAL INDICATOR
+ − 0x00bf, // #INVERTED QUESTION MARK
+ − 0x2310, // #REVERSED NOT SIGN
+ − 0x00ac, // #NOT SIGN
+ − 0x00bd, // #VULGAR FRACTION ONE HALF
+ − 0x00bc, // #VULGAR FRACTION ONE QUARTER
+ − 0x00a1, // #INVERTED EXCLAMATION MARK
+ − 0x00ab, // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ − 0x00bb, // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ − 0x2591, // #LIGHT SHADE
+ − 0x2592, // #MEDIUM SHADE
+ − 0x2593, // #DARK SHADE
+ − 0x2502, // #BOX DRAWINGS LIGHT VERTICAL
+ − 0x2524, // #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+ − 0x2561, // #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+ − 0x2562, // #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+ − 0x2556, // #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+ − 0x2555, // #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+ − 0x2563, // #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+ − 0x2551, // #BOX DRAWINGS DOUBLE VERTICAL
+ − 0x2557, // #BOX DRAWINGS DOUBLE DOWN AND LEFT
+ − 0x255d, // #BOX DRAWINGS DOUBLE UP AND LEFT
+ − 0x255c, // #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+ − 0x255b, // #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+ − 0x2510, // #BOX DRAWINGS LIGHT DOWN AND LEFT
+ − 0x2514, // #BOX DRAWINGS LIGHT UP AND RIGHT
+ − 0x2534, // #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+ − 0x252c, // #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+ − 0x251c, // #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+ − 0x2500, // #BOX DRAWINGS LIGHT HORIZONTAL
+ − 0x253c, // #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+ − 0x255e, // #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+ − 0x255f, // #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+ − 0x255a, // #BOX DRAWINGS DOUBLE UP AND RIGHT
+ − 0x2554, // #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+ − 0x2569, // #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+ − 0x2566, // #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+ − 0x2560, // #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+ − 0x2550, // #BOX DRAWINGS DOUBLE HORIZONTAL
+ − 0x256c, // #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+ − 0x2567, // #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+ − 0x2568, // #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+ − 0x2564, // #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+ − 0x2565, // #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+ − 0x2559, // #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+ − 0x2558, // #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+ − 0x2552, // #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+ − 0x2553, // #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+ − 0x256b, // #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+ − 0x256a, // #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+ − 0x2518, // #BOX DRAWINGS LIGHT UP AND LEFT
+ − 0x250c, // #BOX DRAWINGS LIGHT DOWN AND RIGHT
+ − 0x2588, // #FULL BLOCK
+ − 0x2584, // #LOWER HALF BLOCK
+ − 0x258c, // #LEFT HALF BLOCK
+ − 0x2590, // #RIGHT HALF BLOCK
+ − 0x2580, // #UPPER HALF BLOCK
+ − 0x03b1, // #GREEK SMALL LETTER ALPHA
+ − 0x00df, // #LATIN SMALL LETTER SHARP S
+ − 0x0393, // #GREEK CAPITAL LETTER GAMMA
+ − 0x03c0, // #GREEK SMALL LETTER PI
+ − 0x03a3, // #GREEK CAPITAL LETTER SIGMA
+ − 0x03c3, // #GREEK SMALL LETTER SIGMA
+ − 0x00b5, // #MICRO SIGN
+ − 0x03c4, // #GREEK SMALL LETTER TAU
+ − 0x03a6, // #GREEK CAPITAL LETTER PHI
+ − 0x0398, // #GREEK CAPITAL LETTER THETA
+ − 0x03a9, // #GREEK CAPITAL LETTER OMEGA
+ − 0x03b4, // #GREEK SMALL LETTER DELTA
+ − 0x221e, // #INFINITY
+ − 0x03c6, // #GREEK SMALL LETTER PHI
+ − 0x03b5, // #GREEK SMALL LETTER EPSILON
+ − 0x2229, // #INTERSECTION
+ − 0x2261, // #IDENTICAL TO
+ − 0x00b1, // #PLUS-MINUS SIGN
+ − 0x2265, // #GREATER-THAN OR EQUAL TO
+ − 0x2264, // #LESS-THAN OR EQUAL TO
+ − 0x2320, // #TOP HALF INTEGRAL
+ − 0x2321, // #BOTTOM HALF INTEGRAL
+ − 0x00f7, // #DIVISION SIGN
+ − 0x2248, // #ALMOST EQUAL TO
+ − 0x00b0, // #DEGREE SIGN
+ − 0x2219, // #BULLET OPERATOR
+ − 0x00b7, // #MIDDLE DOT
+ − 0x221a, // #SQUARE ROOT
+ − 0x207f, // #SUPERSCRIPT LATIN SMALL LETTER N
+ − 0x00b2, // #SUPERSCRIPT TWO
+ − 0x25a0, // #BLACK SQUARE
+ − 0x00a0, // #NO-BREAK SPACE
+ − };
+ −
+ − public char map_cp850_unicode(char x) {
+ − if (x >= 0x100)
+ − return x;
+ −
+ − return unimap[x];
+ − }
+ −
+ − private void _SetCursor(int row, int col) {
+ − int maxr = height - 1;
+ − int tm = getTopMargin();
+ − R = (row < 0) ? 0 : row;
+ − C = (col < 0) ? 0 : (col >= width) ? width - 1 : col;
+ −
+ − if (!moveoutsidemargins) {
+ − R += tm;
+ − maxr = getBottomMargin();
+ − }
+ −
+ − if (R > maxr) R = maxr;
+ − }
+ −
+ − private void putChar(char c, boolean isWide, boolean doshowcursor) {
+ − int rows = this.height; //statusline
+ − int columns = this.width;
+ −
+ − // byte msg[];
+ − // if (debug > 4) {
+ − // debugStr.append("putChar(")
+ − // .append(c)
+ − // .append(" [")
+ − // .append((int) c)
+ − // .append("]) at R=")
+ − // .append(R)
+ − // .append(" , C=")
+ − // .append(C)
+ − // .append(", columns=")
+ − // .append(columns)
+ − // .append(", rows=")
+ − // .append(rows);
+ − // debug(debugStr.toString());
+ − // debugStr.setLength(0);
+ − // }
+ − // markLine(R, 1);
+ − // if (c > 255) {
+ − // if (debug > 0)
+ − // debug("char > 255:" + (int) c);
+ − // //return;
+ − // }
+ − switch (term_state) {
+ − case TSTATE_DATA:
+ −
+ − /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset.
+ − * probably... but some BBS do anyway...
+ − */
+ − if (!useibmcharset) {
+ − boolean doneflag = true;
+ −
+ − switch (c) {
+ − case OSC:
+ − osc = "";
+ − term_state = TSTATE_OSC;
+ − break;
+ −
+ − case RI:
+ − if (R > getTopMargin())
+ − R--;
+ − else
+ − insertLine(R, 1, SCROLL_DOWN);
+ −
+ − if (debug > 1)
+ − debug("RI");
+ −
+ − break;
+ −
+ − case IND:
+ − if (debug > 2) {
+ − debugStr.append("IND at ")
+ − .append(R)
+ − .append(", tm is ")
+ − .append(getTopMargin())
+ − .append(", bm is ")
+ − .append(getBottomMargin());
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − if (R == getBottomMargin() || R == rows - 1)
+ − insertLine(R, 1, SCROLL_UP);
+ − else
+ − R++;
+ −
+ − if (debug > 1)
+ − debug("IND (at " + R + " )");
+ −
+ − break;
+ −
+ − case NEL:
+ − if (R == getBottomMargin() || R == rows - 1)
+ − insertLine(R, 1, SCROLL_UP);
+ − else
+ − R++;
+ −
+ − C = 0;
+ −
+ − if (debug > 1)
+ − debug("NEL (at " + R + " )");
+ −
+ − break;
+ −
+ − case HTS:
+ − Tabs[C] = 1;
+ −
+ − if (debug > 1)
+ − debug("HTS");
+ −
+ − break;
+ −
+ − case DCS:
+ − dcs = "";
+ − term_state = TSTATE_DCS;
+ − break;
+ −
+ − default:
+ − doneflag = false;
+ − break;
+ − }
+ −
+ − if (doneflag) break;
+ − }
+ −
+ − switch (c) {
+ − case SS3:
+ − onegl = 3;
+ − break;
+ −
+ − case SS2:
+ − onegl = 2;
+ − break;
+ −
+ − case CSI: // should be in the 8bit section, but some BBS use this
+ − DCEvar = 0;
+ − DCEvars[0] = 0;
+ − DCEvars[1] = 0;
+ − DCEvars[2] = 0;
+ − DCEvars[3] = 0;
+ − term_state = TSTATE_CSI;
+ − break;
+ −
+ − case ESC:
+ − term_state = TSTATE_ESC;
+ − lastwaslf = 0;
+ − break;
+ −
+ − case 5: /* ENQ */
+ − write(answerBack, false);
+ − break;
+ −
+ − case 12:
+ − /* FormFeed, Home for the BBS world */
+ − deleteArea(0, 0, columns, rows, attributes);
+ − C = R = 0;
+ − break;
+ −
+ − case '\b': /* 8 */
+ − C--;
+ −
+ − if (C < 0)
+ − C = 0;
+ −
+ − lastwaslf = 0;
+ − break;
+ −
+ − case '\t':
+ − do {
+ − // Don't overwrite or insert! TABS are not destructive, but movement!
+ − C++;
+ − }
+ − while (C < columns && (Tabs[C] == 0));
+ −
+ − lastwaslf = 0;
+ − break;
+ −
+ − case '\r': // 13 CR
+ − C = 0;
+ − break;
+ −
+ − case '\n': // 10 LF
+ − if (debug > 3)
+ − debug("R= " + R + ", bm " + getBottomMargin() + ", tm=" + getTopMargin() + ", rows=" + rows);
+ −
+ − if (!vms) {
+ − if (lastwaslf != 0 && lastwaslf != c) // Ray: I do not understand this logic.
+ − break;
+ −
+ − lastwaslf = c;
+ − /*C = 0;*/
+ − }
+ −
+ − if (R == getBottomMargin() || R >= rows - 1)
+ − insertLine(R, 1, SCROLL_UP);
+ − else
+ − R++;
+ −
+ − break;
+ −
+ − case 7:
+ − beep();
+ − break;
+ −
+ − case '\016': /* SMACS , as */
+ − /* ^N, Shift out - Put G1 into GL */
+ − gl = 1;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '\017': /* RMACS , ae */
+ − /* ^O, Shift in - Put G0 into GL */
+ − gl = 0;
+ − usedcharsets = true;
+ − break;
+ −
+ − default: {
+ − int thisgl = gl;
+ −
+ − if (onegl >= 0) {
+ − thisgl = onegl;
+ − onegl = -1;
+ − }
+ −
+ − lastwaslf = 0;
+ −
+ − if (c < 32) {
+ − if (c != 0)
+ − if (debug > 0)
+ − debug("TSTATE_DATA char: " + ((int) c));
+ −
+ − /*break; some BBS really want those characters, like hearst etc. */
+ − if (c == 0) /* print 0 ... you bet */
+ − break;
+ − }
+ −
+ − if (C >= columns) {
+ − if (wraparound) {
+ − int bot = rows;
+ −
+ − // If we're in the scroll region, check against the bottom margin
+ − if (R <= getBottomMargin() && R >= getTopMargin())
+ − bot = getBottomMargin() + 1;
+ −
+ − if (R < bot - 1)
+ − R++;
+ − else {
+ − if (debug > 3) debug("scrolling due to wrap at " + R);
+ −
+ − insertLine(R, 1, SCROLL_UP);
+ − }
+ −
+ − C = 0;
+ − }
+ − else {
+ − // cursor stays on last character.
+ − C = columns - 1;
+ − }
+ − }
+ −
+ − boolean mapped = false;
+ −
+ − // Mapping if DEC Special is chosen charset
+ − if (usedcharsets) {
+ − if (c >= '\u0020' && c <= '\u007f') {
+ − switch (gx[thisgl]) {
+ − case '0':
+ −
+ − // Remap SCOANSI line drawing to VT100 line drawing chars
+ − // for our SCO using customers.
+ − if (terminalID.equals("scoansi") || terminalID.equals("ansi")) {
+ − for (int i = 0; i < scoansi_acs.length(); i += 2) {
+ − if (c == scoansi_acs.charAt(i)) {
+ − c = scoansi_acs.charAt(i + 1);
+ − break;
+ − }
+ − }
+ − }
+ −
+ − if (c >= '\u005f' && c <= '\u007e') {
+ − c = DECSPECIAL[(short) c - 0x5f];
+ − mapped = true;
+ − }
+ −
+ − break;
+ −
+ − case '<': // 'user preferred' is currently 'ISO Latin-1 suppl
+ − c = (char)((c & 0x7f) | 0x80);
+ − mapped = true;
+ − break;
+ −
+ − case 'A':
+ − case 'B': // Latin-1 , ASCII -> fall through
+ − mapped = true;
+ − break;
+ −
+ − default:
+ − debug("Unsupported GL mapping: " + gx[thisgl]);
+ − break;
+ − }
+ − }
+ −
+ − if (!mapped && (c >= '\u0080' && c <= '\u00ff')) {
+ − switch (gx[gr]) {
+ − case '0':
+ − if (c >= '\u00df' && c <= '\u00fe') {
+ − c = DECSPECIAL[c - '\u00df'];
+ − mapped = true;
+ − }
+ −
+ − break;
+ −
+ − case '<':
+ − case 'A':
+ − case 'B':
+ − mapped = true;
+ − break;
+ −
+ − default:
+ − debug("Unsupported GR mapping: " + gx[gr]);
+ − break;
+ − }
+ − }
+ − }
+ −
+ − if (!mapped && useibmcharset)
+ − c = map_cp850_unicode(c);
+ −
+ − /*if(true || (statusmode == 0)) { */
+ − if (isWide) {
+ − if (C >= columns - 1) {
+ − if (wraparound) {
+ − int bot = rows;
+ −
+ − // If we're in the scroll region, check against the bottom margin
+ − if (R <= getBottomMargin() && R >= getTopMargin())
+ − bot = getBottomMargin() + 1;
+ −
+ − if (R < bot - 1)
+ − R++;
+ − else {
+ − if (debug > 3) debug("scrolling due to wrap at " + R);
+ −
+ − insertLine(R, 1, SCROLL_UP);
+ − }
+ −
+ − C = 0;
+ − }
+ − else {
+ − // cursor stays on last wide character.
+ − C = columns - 2;
+ − }
+ − }
+ − }
+ −
+ − if (insertmode == 1) {
+ − if (isWide) {
+ − insertChar(C++, R, c, attributes | FULLWIDTH);
+ − insertChar(C, R, ' ', attributes | FULLWIDTH);
+ − }
+ − else
+ − insertChar(C, R, c, attributes);
+ − }
+ − else {
+ − if (isWide) {
+ − putChar(C++, R, c, attributes | FULLWIDTH);
+ − putChar(C, R, ' ', attributes | FULLWIDTH);
+ − }
+ − else
+ − putChar(C, R, c, attributes);
+ − }
+ −
+ − /*
+ − } else {
+ − if (insertmode==1) {
+ − insertChar(C, rows, c, attributes);
+ − } else {
+ − putChar(C, rows, c, attributes);
+ − }
+ − }
+ − */
+ − C++;
+ − break;
+ − }
+ − } /* switch(c) */
+ −
+ − break;
+ −
+ − case TSTATE_OSC:
+ − if ((c < 0x20) && (c != ESC)) {// NP - No printing character
+ − handle_osc(osc);
+ − term_state = TSTATE_DATA;
+ − break;
+ − }
+ −
+ − //but check for vt102 ESC \
+ − if (c == '\\' && osc.charAt(osc.length() - 1) == ESC) {
+ − handle_osc(osc);
+ − term_state = TSTATE_DATA;
+ − break;
+ − }
+ −
+ − osc = osc + c;
+ − break;
+ −
+ − case TSTATE_ESCSPACE:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case 'F': /* S7C1T, Disable output of 8-bit controls, use 7-bit */
+ − output8bit = false;
+ − break;
+ −
+ − case 'G': /* S8C1T, Enable output of 8-bit control codes*/
+ − output8bit = true;
+ − break;
+ −
+ − default:
+ − debug("ESC <space> " + c + " unhandled.");
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_ESC:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case ' ':
+ − term_state = TSTATE_ESCSPACE;
+ − break;
+ −
+ − case '#':
+ − term_state = TSTATE_ESCSQUARE;
+ − break;
+ −
+ − case 'c':
+ − /* Hard terminal reset */
+ − reset();
+ − break;
+ −
+ − case '[':
+ − DCEvar = 0;
+ − DCEvars[0] = 0;
+ − DCEvars[1] = 0;
+ − DCEvars[2] = 0;
+ − DCEvars[3] = 0;
+ − term_state = TSTATE_CSI;
+ − break;
+ −
+ − case ']':
+ − osc = "";
+ − term_state = TSTATE_OSC;
+ − break;
+ −
+ − case 'P':
+ − dcs = "";
+ − term_state = TSTATE_DCS;
+ − break;
+ −
+ − case 'A': /* CUU */
+ − R--;
+ −
+ − if (R < 0) R = 0;
+ −
+ − break;
+ −
+ − case 'B': /* CUD */
+ − R++;
+ −
+ − if (R >= rows) R = rows - 1;
+ −
+ − break;
+ −
+ − case 'C':
+ − C++;
+ −
+ − if (C >= columns) C = columns - 1;
+ −
+ − break;
+ −
+ − case 'I': // RI
+ − insertLine(R, 1, SCROLL_DOWN);
+ − break;
+ −
+ − case 'E': /* NEL */
+ − if (R == getBottomMargin() || R == rows - 1)
+ − insertLine(R, 1, SCROLL_UP);
+ − else
+ − R++;
+ −
+ − C = 0;
+ −
+ − if (debug > 1)
+ − debug("ESC E (at " + R + ")");
+ −
+ − break;
+ −
+ − case 'D': /* IND */
+ − if (R == getBottomMargin() || R == rows - 1)
+ − insertLine(R, 1, SCROLL_UP);
+ − else
+ − R++;
+ −
+ − if (debug > 1)
+ − debug("ESC D (at " + R + " )");
+ −
+ − break;
+ −
+ − case 'J': /* erase to end of screen */
+ − if (R < rows - 1)
+ − deleteArea(0, R + 1, columns, rows - R - 1, attributes);
+ −
+ − if (C < columns - 1)
+ − deleteArea(C, R, columns - C, 1, attributes);
+ −
+ − break;
+ −
+ − case 'K':
+ − if (C < columns - 1)
+ − deleteArea(C, R, columns - C, 1, attributes);
+ −
+ − break;
+ −
+ − case 'M': // RI
+ − debug("ESC M : R is " + R + ", tm is " + getTopMargin() + ", bm is " + getBottomMargin());
+ −
+ − if (R > getTopMargin()) { // just go up 1 line.
+ − R--;
+ − }
+ − else { // scroll down
+ − insertLine(R, 1, SCROLL_DOWN);
+ − }
+ −
+ − /* else do nothing ; */
+ − if (debug > 2)
+ − debug("ESC M ");
+ −
+ − break;
+ −
+ − case 'H':
+ − if (debug > 1)
+ − debug("ESC H at " + C);
+ −
+ − /* right border probably ...*/
+ − if (C >= columns)
+ − C = columns - 1;
+ −
+ − Tabs[C] = 1;
+ − break;
+ −
+ − case 'N': // SS2
+ − onegl = 2;
+ − break;
+ −
+ − case 'O': // SS3
+ − onegl = 3;
+ − break;
+ −
+ − case '=':
+ −
+ − /*application keypad*/
+ − if (debug > 0)
+ − debug("ESC =");
+ −
+ − keypadmode = true;
+ − break;
+ −
+ − case '<': /* vt52 mode off */
+ − vt52mode = false;
+ − break;
+ −
+ − case '>': /*normal keypad*/
+ − if (debug > 0)
+ − debug("ESC >");
+ −
+ − keypadmode = false;
+ − break;
+ −
+ − case '7': /* DECSC: save cursor, attributes */
+ − Sc = C;
+ − Sr = R;
+ − Sgl = gl;
+ − Sgr = gr;
+ − Sa = attributes;
+ − Sgx = new char[4];
+ −
+ − for (int i = 0; i < 4; i++) Sgx[i] = gx[i];
+ −
+ − if (debug > 1)
+ − debug("ESC 7");
+ −
+ − break;
+ −
+ − case '8': /* DECRC: restore cursor, attributes */
+ − C = Sc;
+ − R = Sr;
+ − gl = Sgl;
+ − gr = Sgr;
+ −
+ − if (Sgx != null)
+ − for (int i = 0; i < 4; i++) gx[i] = Sgx[i];
+ −
+ − attributes = Sa;
+ −
+ − if (debug > 1)
+ − debug("ESC 8");
+ −
+ − break;
+ −
+ − case '(': /* Designate G0 Character set (ISO 2022) */
+ − term_state = TSTATE_SETG0;
+ − usedcharsets = true;
+ − break;
+ −
+ − case ')': /* Designate G1 character set (ISO 2022) */
+ − term_state = TSTATE_SETG1;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '*': /* Designate G2 Character set (ISO 2022) */
+ − term_state = TSTATE_SETG2;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '+': /* Designate G3 Character set (ISO 2022) */
+ − term_state = TSTATE_SETG3;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '~': /* Locking Shift 1, right */
+ − gr = 1;
+ − usedcharsets = true;
+ − break;
+ −
+ − case 'n': /* Locking Shift 2 */
+ − gl = 2;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '}': /* Locking Shift 2, right */
+ − gr = 2;
+ − usedcharsets = true;
+ − break;
+ −
+ − case 'o': /* Locking Shift 3 */
+ − gl = 3;
+ − usedcharsets = true;
+ − break;
+ −
+ − case '|': /* Locking Shift 3, right */
+ − gr = 3;
+ − usedcharsets = true;
+ − break;
+ −
+ − case 'Y': /* vt52 cursor address mode , next chars are x,y */
+ − term_state = TSTATE_VT52Y;
+ − break;
+ −
+ − case '_':
+ − term_state = TSTATE_TITLE;
+ − break;
+ −
+ − case '\\':
+ − // TODO save title
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − default:
+ − debug("ESC unknown letter: " + c + " (" + ((int) c) + ")");
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_VT52X:
+ − C = c - 37;
+ −
+ − if (C < 0)
+ − C = 0;
+ − else if (C >= width)
+ − C = width - 1;
+ −
+ − term_state = TSTATE_VT52Y;
+ − break;
+ −
+ − case TSTATE_VT52Y:
+ − R = c - 37;
+ −
+ − if (R < 0)
+ − R = 0;
+ − else if (R >= height)
+ − R = height - 1;
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_SETG0:
+ − if (c != '0' && c != 'A' && c != 'B' && c != '<')
+ − debug("ESC ( " + c + ": G0 char set? (" + ((int) c) + ")");
+ − else {
+ − if (debug > 2) debug("ESC ( : G0 char set (" + c + " " + ((int) c) + ")");
+ −
+ − gx[0] = c;
+ − }
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_SETG1:
+ − if (c != '0' && c != 'A' && c != 'B' && c != '<') {
+ − debug("ESC ) " + c + " (" + ((int) c) + ") :G1 char set?");
+ − }
+ − else {
+ − if (debug > 2) debug("ESC ) :G1 char set (" + c + " " + ((int) c) + ")");
+ −
+ − gx[1] = c;
+ − }
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_SETG2:
+ − if (c != '0' && c != 'A' && c != 'B' && c != '<')
+ − debug("ESC*:G2 char set? (" + ((int) c) + ")");
+ − else {
+ − if (debug > 2) debug("ESC*:G2 char set (" + c + " " + ((int) c) + ")");
+ −
+ − gx[2] = c;
+ − }
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_SETG3:
+ − if (c != '0' && c != 'A' && c != 'B' && c != '<')
+ − debug("ESC+:G3 char set? (" + ((int) c) + ")");
+ − else {
+ − if (debug > 2) debug("ESC+:G3 char set (" + c + " " + ((int) c) + ")");
+ −
+ − gx[3] = c;
+ − }
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_ESCSQUARE:
+ − switch (c) {
+ − case '8':
+ − for (int i = 0; i < columns; i++)
+ − for (int j = 0; j < rows; j++)
+ − putChar(i, j, 'E', 0);
+ −
+ − break;
+ −
+ − default:
+ − debug("ESC # " + c + " not supported.");
+ − break;
+ − }
+ −
+ − term_state = TSTATE_DATA;
+ − break;
+ −
+ − case TSTATE_DCS:
+ − if (c == '\\' && dcs.charAt(dcs.length() - 1) == ESC) {
+ − handle_dcs(dcs);
+ − term_state = TSTATE_DATA;
+ − break;
+ − }
+ −
+ − dcs = dcs + c;
+ − break;
+ −
+ − case TSTATE_DCEQ:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case '0':
+ − case '1':
+ − case '2':
+ − case '3':
+ − case '4':
+ − case '5':
+ − case '6':
+ − case '7':
+ − case '8':
+ − case '9':
+ − DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48;
+ − term_state = TSTATE_DCEQ;
+ − break;
+ −
+ − case ';':
+ − DCEvar++;
+ − DCEvars[DCEvar] = 0;
+ − term_state = TSTATE_DCEQ;
+ − break;
+ −
+ − case 's': // XTERM_SAVE missing!
+ − if (true || debug > 1)
+ − debug("ESC [ ? " + DCEvars[0] + " s unimplemented!");
+ −
+ − break;
+ −
+ − case 'r': // XTERM_RESTORE
+ − if (true || debug > 1)
+ − debug("ESC [ ? " + DCEvars[0] + " r");
+ −
+ − /* DEC Mode reset */
+ − for (int i = 0; i <= DCEvar; i++) {
+ − switch (DCEvars[i]) {
+ − case 3: /* 80 columns*/
+ − setScreenSize(80, height, true);
+ − break;
+ −
+ − case 4: /* scrolling mode, smooth */
+ − break;
+ −
+ − case 5: /* light background */
+ − break;
+ −
+ − case 6: /* DECOM (Origin Mode) move inside margins. */
+ − moveoutsidemargins = true;
+ − break;
+ −
+ − case 7: /* DECAWM: Autowrap Mode */
+ − wraparound = false;
+ − break;
+ −
+ − case 12:/* local echo off */
+ − break;
+ −
+ − case 9: /* X10 mouse */
+ − case 1000: /* xterm style mouse report on */
+ − case 1001:
+ − case 1002:
+ − case 1003:
+ − mouserpt = DCEvars[i];
+ − break;
+ −
+ − default:
+ − debug("ESC [ ? " + DCEvars[0] + " r, unimplemented!");
+ − }
+ − }
+ −
+ − break;
+ −
+ − case 'h': // DECSET
+ − if (debug > 0)
+ − debug("ESC [ ? " + DCEvars[0] + " h");
+ −
+ − /* DEC Mode set */
+ − for (int i = 0; i <= DCEvar; i++) {
+ − switch (DCEvars[i]) {
+ − case 1: /* Application cursor keys */
+ − KeyUp[0] = "\u001bOA";
+ − KeyDown[0] = "\u001bOB";
+ − KeyRight[0] = "\u001bOC";
+ − KeyLeft[0] = "\u001bOD";
+ − break;
+ −
+ − case 2: /* DECANM */
+ − vt52mode = false;
+ − break;
+ −
+ − case 3: /* 132 columns*/
+ − setScreenSize(132, height, true);
+ − break;
+ −
+ − case 6: /* DECOM: move inside margins. */
+ − moveoutsidemargins = false;
+ − break;
+ −
+ − case 7: /* DECAWM: Autowrap Mode */
+ − wraparound = true;
+ − break;
+ −
+ − case 25: /* turn cursor on */
+ − showCursor(true);
+ − break;
+ −
+ − case 9: /* X10 mouse */
+ − case 1000: /* xterm style mouse report on */
+ − case 1001:
+ − case 1002:
+ − case 1003:
+ − mouserpt = DCEvars[i];
+ − break;
+ −
+ − /* unimplemented stuff, fall through */
+ − /* 4 - scrolling mode, smooth */
+ − /* 5 - light background */
+ − /* 12 - local echo off */
+ − /* 18 - DECPFF - Printer Form Feed Mode -> On */
+ − /* 19 - DECPEX - Printer Extent Mode -> Screen */
+ − default:
+ − debug("ESC [ ? " + DCEvars[0] + " h, unsupported.");
+ − break;
+ − }
+ − }
+ −
+ − break;
+ −
+ − case 'i': // DEC Printer Control, autoprint, echo screenchars to printer
+ −
+ − // This is different to CSI i!
+ − // Also: "Autoprint prints a final display line only when the
+ − // cursor is moved off the line by an autowrap or LF, FF, or
+ − // VT (otherwise do not print the line)."
+ − switch (DCEvars[0]) {
+ − case 1:
+ − if (debug > 1)
+ − debug("CSI ? 1 i : Print line containing cursor");
+ −
+ − break;
+ −
+ − case 4:
+ − if (debug > 1)
+ − debug("CSI ? 4 i : Start passthrough printing");
+ −
+ − break;
+ −
+ − case 5:
+ − if (debug > 1)
+ − debug("CSI ? 4 i : Stop passthrough printing");
+ −
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case 'l': //DECRST
+ −
+ − /* DEC Mode reset */
+ − if (debug > 0)
+ − debug("ESC [ ? " + DCEvars[0] + " l");
+ −
+ − for (int i = 0; i <= DCEvar; i++) {
+ − switch (DCEvars[i]) {
+ − case 1: /* Application cursor keys */
+ − KeyUp[0] = "\u001b[A";
+ − KeyDown[0] = "\u001b[B";
+ − KeyRight[0] = "\u001b[C";
+ − KeyLeft[0] = "\u001b[D";
+ − break;
+ −
+ − case 2: /* DECANM */
+ − vt52mode = true;
+ − break;
+ −
+ − case 3: /* 80 columns*/
+ − setScreenSize(80, height, true);
+ − break;
+ −
+ − case 6: /* DECOM: move outside margins. */
+ − moveoutsidemargins = true;
+ − break;
+ −
+ − case 7: /* DECAWM: Autowrap Mode OFF */
+ − wraparound = false;
+ − break;
+ −
+ − case 25: /* turn cursor off */
+ − showCursor(false);
+ − break;
+ −
+ − /* Unimplemented stuff: */
+ − /* 4 - scrolling mode, jump */
+ − /* 5 - dark background */
+ − /* 7 - DECAWM - no wrap around mode */
+ − /* 12 - local echo on */
+ − /* 18 - DECPFF - Printer Form Feed Mode -> Off*/
+ − /* 19 - DECPEX - Printer Extent Mode -> Scrolling Region */
+ − case 9: /* X10 mouse */
+ − case 1000: /* xterm style mouse report OFF */
+ − case 1001:
+ − case 1002:
+ − case 1003:
+ − mouserpt = 0;
+ − break;
+ −
+ − default:
+ − debug("ESC [ ? " + DCEvars[0] + " l, unsupported.");
+ − break;
+ − }
+ − }
+ −
+ − break;
+ −
+ − case 'n':
+ − if (debug > 0)
+ − debug("ESC [ ? " + DCEvars[0] + " n");
+ −
+ − switch (DCEvars[0]) {
+ − case 15:
+ − /* printer? no printer. */
+ − write((ESC) + "[?13n", false);
+ − debug("ESC[5n");
+ − break;
+ −
+ − default:
+ − debug("ESC [ ? " + DCEvars[0] + " n, unsupported.");
+ − break;
+ − }
+ −
+ − break;
+ −
+ − default:
+ − debug("ESC [ ? " + DCEvars[0] + " " + c + ", unsupported.");
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_CSI_EX:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case ESC:
+ − term_state = TSTATE_ESC;
+ − break;
+ −
+ − default:
+ − debug("Unknown character ESC[! character is " + (int) c);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_CSI_TICKS:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case 'p':
+ − debug("Conformance level: " + DCEvars[0] + " (unsupported)," + DCEvars[1]);
+ −
+ − if (DCEvars[0] == 61) {
+ − output8bit = false;
+ − break;
+ − }
+ −
+ − if (DCEvars[1] == 1) {
+ − output8bit = false;
+ − }
+ − else {
+ − output8bit = true; /* 0 or 2 */
+ − }
+ −
+ − break;
+ −
+ − default:
+ − debug("Unknown ESC [... \"" + c);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_CSI_EQUAL:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case '0':
+ − case '1':
+ − case '2':
+ − case '3':
+ − case '4':
+ − case '5':
+ − case '6':
+ − case '7':
+ − case '8':
+ − case '9':
+ − DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48;
+ − term_state = TSTATE_CSI_EQUAL;
+ − break;
+ −
+ − case ';':
+ − DCEvar++;
+ − DCEvars[DCEvar] = 0;
+ − term_state = TSTATE_CSI_EQUAL;
+ − break;
+ −
+ − case 'F': { /* SCO ANSI foreground */
+ − int newcolor;
+ − debug("ESC [ = " + DCEvars[0] + " F");
+ − attributes &= ~COLOR_FG;
+ − newcolor = ((DCEvars[0] & 1) << 2) |
+ − (DCEvars[0] & 2) |
+ − ((DCEvars[0] & 4) >> 2) ;
+ − attributes |= (newcolor + 1) << COLOR_FG_SHIFT;
+ − break;
+ − }
+ −
+ − case 'G': { /* SCO ANSI background */
+ − int newcolor;
+ − debug("ESC [ = " + DCEvars[0] + " G");
+ − attributes &= ~COLOR_BG;
+ − newcolor = ((DCEvars[0] & 1) << 2) |
+ − (DCEvars[0] & 2) |
+ − ((DCEvars[0] & 4) >> 2) ;
+ − attributes |= (newcolor + 1) << COLOR_BG_SHIFT;
+ − break;
+ − }
+ −
+ − default:
+ − debugStr.append("Unknown ESC [ = ");
+ −
+ − for (int i = 0; i <= DCEvar; i++) {
+ − debugStr.append(DCEvars[i])
+ − .append(',');
+ − }
+ −
+ − debugStr.append(c);
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_CSI_DOLLAR:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case '}':
+ − debug("Active Status Display now " + DCEvars[0]);
+ − statusmode = DCEvars[0];
+ − break;
+ −
+ − /* bad documentation?
+ − case '-':
+ − debug("Set Status Display now "+DCEvars[0]);
+ − break;
+ − */
+ − case '~':
+ − debug("Status Line mode now " + DCEvars[0]);
+ − break;
+ −
+ − default:
+ − debug("UNKNOWN Status Display code " + c + ", with Pn=" + DCEvars[0]);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_CSI:
+ − term_state = TSTATE_DATA;
+ −
+ − switch (c) {
+ − case '"':
+ − term_state = TSTATE_CSI_TICKS;
+ − break;
+ −
+ − case '$':
+ − term_state = TSTATE_CSI_DOLLAR;
+ − break;
+ −
+ − case '=':
+ − term_state = TSTATE_CSI_EQUAL;
+ − break;
+ −
+ − case '!':
+ − term_state = TSTATE_CSI_EX;
+ − break;
+ −
+ − case '?':
+ − DCEvar = 0;
+ − DCEvars[0] = 0;
+ − term_state = TSTATE_DCEQ;
+ − break;
+ −
+ − case '0':
+ − case '1':
+ − case '2':
+ − case '3':
+ − case '4':
+ − case '5':
+ − case '6':
+ − case '7':
+ − case '8':
+ − case '9':
+ − DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48;
+ − term_state = TSTATE_CSI;
+ − break;
+ −
+ − case ';':
+ − DCEvar++;
+ − DCEvars[DCEvar] = 0;
+ − term_state = TSTATE_CSI;
+ − break;
+ −
+ − case 'c':/* send primary device attributes */
+ − /* send (ESC[?61c) */
+ − String subcode = "";
+ −
+ − if (terminalID.equals("vt320")) subcode = "63;";
+ −
+ − if (terminalID.equals("vt220")) subcode = "62;";
+ −
+ − if (terminalID.equals("vt100")) subcode = "61;";
+ −
+ − write((ESC) + "[?" + subcode + "1;2c", false);
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " c");
+ −
+ − break;
+ −
+ − case 'q':
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " q");
+ −
+ − break;
+ −
+ − case 'g':
+ −
+ − /* used for tabsets */
+ − switch (DCEvars[0]) {
+ − case 3:/* clear them */
+ − Tabs = new byte[width];
+ − break;
+ −
+ − case 0:
+ − Tabs[C] = 0;
+ − break;
+ − }
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " g");
+ −
+ − break;
+ −
+ − case 'h':
+ − switch (DCEvars[0]) {
+ − case 4:
+ − insertmode = 1;
+ − break;
+ −
+ − case 20:
+ − debug("Setting CRLF to TRUE");
+ − sendcrlf = true;
+ − break;
+ −
+ − default:
+ − debug("unsupported: ESC [ " + DCEvars[0] + " h");
+ − break;
+ − }
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " h");
+ −
+ − break;
+ −
+ − case 'i': // Printer Controller mode.
+ −
+ − // "Transparent printing sends all output, except the CSI 4 i
+ − // termination string, to the printer and not the screen,
+ − // uses an 8-bit channel if no parity so NUL and DEL will be
+ − // seen by the printer and by the termination recognizer code,
+ − // and all translation and character set selections are
+ − // bypassed."
+ − switch (DCEvars[0]) {
+ − case 0:
+ − if (debug > 1)
+ − debug("CSI 0 i: Print Screen, not implemented.");
+ −
+ − break;
+ −
+ − case 4:
+ − if (debug > 1)
+ − debug("CSI 4 i: Enable Transparent Printing, not implemented.");
+ −
+ − break;
+ −
+ − case 5:
+ − if (debug > 1)
+ − debug("CSI 4/5 i: Disable Transparent Printing, not implemented.");
+ −
+ − break;
+ −
+ − default:
+ − debug("ESC [ " + DCEvars[0] + " i, unimplemented!");
+ − }
+ −
+ − break;
+ −
+ − case 'l':
+ − switch (DCEvars[0]) {
+ − case 4:
+ − insertmode = 0;
+ − break;
+ −
+ − case 20:
+ − debug("Setting CRLF to FALSE");
+ − sendcrlf = false;
+ − break;
+ −
+ − default:
+ − debug("ESC [ " + DCEvars[0] + " l, unimplemented!");
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case 'A': { // CUU
+ − int limit;
+ −
+ − /* FIXME: xterm only cares about 0 and topmargin */
+ − if (R >= getTopMargin()) {
+ − limit = getTopMargin();
+ − }
+ − else
+ − limit = 0;
+ −
+ − if (DCEvars[0] == 0)
+ − R--;
+ − else
+ − R -= DCEvars[0];
+ −
+ − if (R < limit)
+ − R = limit;
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " A");
+ −
+ − break;
+ − }
+ −
+ − case 'B': // CUD
+ − /* cursor down n (1) times */
+ − {
+ − int limit;
+ −
+ − if (R <= getBottomMargin()) {
+ − limit = getBottomMargin();
+ − }
+ − else
+ − limit = rows - 1;
+ −
+ − if (DCEvars[0] == 0)
+ − R++;
+ − else
+ − R += DCEvars[0];
+ −
+ − if (R > limit)
+ − R = limit;
+ − else {
+ − if (debug > 2) debug("Not limited.");
+ − }
+ −
+ − if (debug > 2) debug("to: " + R);
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " B (at C=" + C + ")");
+ −
+ − break;
+ − }
+ −
+ − case 'C':
+ − if (DCEvars[0] == 0)
+ − DCEvars[0] = 1;
+ −
+ − while (DCEvars[0]-- > 0) {
+ − C++;
+ − }
+ −
+ − if (C >= columns)
+ − C = columns - 1;
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " C");
+ −
+ − break;
+ −
+ − case 'd': // CVA
+ − R = DCEvars[0] - 1;
+ −
+ − if (R < 0)
+ − R = 0;
+ − else if (R >= height)
+ − R = height - 1;
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " d");
+ −
+ − break;
+ −
+ − case 'D':
+ − if (DCEvars[0] == 0)
+ − DCEvars[0] = 1;
+ −
+ − while (DCEvars[0]-- > 0) {
+ − C--;
+ − }
+ −
+ − if (C < 0) C = 0;
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " D");
+ −
+ − break;
+ −
+ − case 'r': // DECSTBM
+ − if (DCEvar > 0) { // Ray: Any argument is optional
+ − R = DCEvars[1] - 1;
+ −
+ − if (R < 0)
+ − R = rows - 1;
+ − else if (R >= rows) {
+ − R = rows - 1;
+ − }
+ − }
+ − else
+ − R = rows - 1;
+ −
+ − int bot = R;
+ −
+ − if (R >= DCEvars[0]) {
+ − R = DCEvars[0] - 1;
+ −
+ − if (R < 0)
+ − R = 0;
+ − }
+ −
+ − setMargins(R, bot);
+ − _SetCursor(0, 0);
+ −
+ − if (debug > 1)
+ − debug("ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r");
+ −
+ − break;
+ −
+ − case 'G': /* CUP / cursor absolute column */
+ − C = DCEvars[0];
+ −
+ − if (C < 0)
+ − C = 0;
+ − else if (C >= width)
+ − C = width - 1;
+ −
+ − if (debug > 1) debug("ESC [ " + DCEvars[0] + " G");
+ −
+ − break;
+ −
+ − case 'H': /* CUP / cursor position */
+ − /* gets 2 arguments */
+ − _SetCursor(DCEvars[0] - 1, DCEvars[1] - 1);
+ −
+ − if (debug > 2) {
+ − debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " H, moveoutsidemargins " + moveoutsidemargins);
+ − debug(" -> R now " + R + ", C now " + C);
+ − }
+ −
+ − break;
+ −
+ − case 'f': /* move cursor 2 */
+ − /* gets 2 arguments */
+ − R = DCEvars[0] - 1;
+ − C = DCEvars[1] - 1;
+ −
+ − if (C < 0)
+ − C = 0;
+ − else if (C >= width)
+ − C = width - 1;
+ −
+ − if (R < 0)
+ − R = 0;
+ − else if (R >= height)
+ − R = height - 1;
+ −
+ − if (debug > 2)
+ − debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " f");
+ −
+ − break;
+ −
+ − case 'S': /* ind aka 'scroll forward' */
+ − if (DCEvars[0] == 0)
+ − insertLine(getBottomMargin(), SCROLL_UP);
+ − else
+ − insertLine(getBottomMargin(), DCEvars[0], SCROLL_UP);
+ −
+ − break;
+ −
+ − case 'L':
+ −
+ − /* insert n lines */
+ − if (DCEvars[0] == 0)
+ − insertLine(R, SCROLL_DOWN);
+ − else
+ − insertLine(R, DCEvars[0], SCROLL_DOWN);
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + "" + (c) + " (at R " + R + ")");
+ −
+ − break;
+ −
+ − case 'T': /* 'ri' aka scroll backward */
+ − if (DCEvars[0] == 0)
+ − insertLine(getTopMargin(), SCROLL_DOWN);
+ − else
+ − insertLine(getTopMargin(), DCEvars[0], SCROLL_DOWN);
+ −
+ − break;
+ −
+ − case 'M':
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + "" + (c) + " at R=" + R);
+ −
+ − if (DCEvars[0] == 0)
+ − deleteLine(R);
+ − else
+ − for (int i = 0; i < DCEvars[0]; i++)
+ − deleteLine(R);
+ −
+ − break;
+ −
+ − case 'K':
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " K");
+ −
+ − /* clear in line */
+ − switch (DCEvars[0]) {
+ − case 6: /* 97801 uses ESC[6K for delete to end of line */
+ − case 0:/*clear to right*/
+ − if (C < columns - 1)
+ − deleteArea(C, R, columns - C, 1, attributes);
+ −
+ − break;
+ −
+ − case 1:/*clear to the left, including this */
+ − if (C > 0)
+ − deleteArea(0, R, C + 1, 1, attributes);
+ −
+ − break;
+ −
+ − case 2:/*clear whole line */
+ − deleteArea(0, R, columns, 1, attributes);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case 'J':
+ −
+ − /* clear below current line */
+ − switch (DCEvars[0]) {
+ − case 0:
+ − if (R < rows - 1)
+ − deleteArea(0, R + 1, columns, rows - R - 1, attributes);
+ −
+ − if (C < columns - 1)
+ − deleteArea(C, R, columns - C, 1, attributes);
+ −
+ − break;
+ −
+ − case 1:
+ − if (R > 0)
+ − deleteArea(0, 0, columns, R, attributes);
+ −
+ − if (C > 0)
+ − deleteArea(0, R, C + 1, 1, attributes); // include up to and including current
+ −
+ − break;
+ −
+ − case 2:
+ − deleteArea(0, 0, columns, rows, attributes);
+ − break;
+ − }
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " J");
+ −
+ − break;
+ −
+ − case '@':
+ − if (DCEvars[0] == 0) DCEvars[0] = 1;
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " @");
+ −
+ − for (int i = 0; i < DCEvars[0]; i++)
+ − insertChar(C, R, ' ', attributes);
+ −
+ − break;
+ −
+ − case 'X': {
+ − int toerase = DCEvars[0];
+ −
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " X, C=" + C + ",R=" + R);
+ −
+ − if (toerase == 0)
+ − toerase = 1;
+ −
+ − if (toerase + C > columns)
+ − toerase = columns - C;
+ −
+ − deleteArea(C, R, toerase, 1, attributes);
+ − // does not change cursor position
+ − break;
+ − }
+ −
+ − case 'P':
+ − if (debug > 1)
+ − debug("ESC [ " + DCEvars[0] + " P, C=" + C + ",R=" + R);
+ −
+ − if (DCEvars[0] == 0) DCEvars[0] = 1;
+ −
+ − for (int i = 0; i < DCEvars[0]; i++)
+ − deleteChar(C, R);
+ −
+ − break;
+ −
+ − case 'n':
+ − switch (DCEvars[0]) {
+ − case 5: /* malfunction? No malfunction. */
+ − writeSpecial((ESC) + "[0n");
+ −
+ − if (debug > 1)
+ − debug("ESC[5n");
+ −
+ − break;
+ −
+ − case 6:
+ − // DO NOT offset R and C by 1! (checked against /usr/X11R6/bin/resize
+ − // FIXME check again.
+ − // FIXME: but vttest thinks different???
+ − writeSpecial((ESC) + "[" + R + ";" + C + "R");
+ −
+ − if (debug > 1)
+ − debug("ESC[6n");
+ −
+ − break;
+ −
+ − default:
+ − if (debug > 0)
+ − debug("ESC [ " + DCEvars[0] + " n??");
+ −
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case 's': /* DECSC - save cursor */
+ − Sc = C;
+ − Sr = R;
+ − Sa = attributes;
+ −
+ − if (debug > 3)
+ − debug("ESC[s");
+ −
+ − break;
+ −
+ − case 'u': /* DECRC - restore cursor */
+ − C = Sc;
+ − R = Sr;
+ − attributes = Sa;
+ −
+ − if (debug > 3)
+ − debug("ESC[u");
+ −
+ − break;
+ −
+ − case 'm': /* attributes as color, bold , blink,*/
+ − if (debug > 3)
+ − debug("ESC [ ");
+ −
+ − if (DCEvar == 0 && DCEvars[0] == 0)
+ − attributes = 0;
+ −
+ − for (int i = 0; i <= DCEvar; i++) {
+ − switch (DCEvars[i]) {
+ − case 0:
+ − if (DCEvar > 0) {
+ − if (terminalID.equals("scoansi")) {
+ − attributes &= COLOR; /* Keeps color. Strange but true. */
+ − }
+ − else {
+ − attributes = 0;
+ − }
+ − }
+ −
+ − break;
+ −
+ − case 1:
+ − attributes |= BOLD;
+ − attributes &= ~LOW;
+ − break;
+ −
+ − case 2:
+ −
+ − /* SCO color hack mode */
+ − if (terminalID.equals("scoansi") && ((DCEvar - i) >= 2)) {
+ − int ncolor;
+ − attributes &= ~(COLOR | BOLD);
+ − ncolor = DCEvars[i + 1];
+ −
+ − if ((ncolor & 8) == 8)
+ − attributes |= BOLD;
+ −
+ − ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2);
+ − attributes |= ((ncolor) + 1) << COLOR_FG_SHIFT;
+ − ncolor = DCEvars[i + 2];
+ − ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2);
+ − attributes |= ((ncolor) + 1) << COLOR_BG_SHIFT;
+ − i += 2;
+ − }
+ − else {
+ − attributes |= LOW;
+ − }
+ −
+ − break;
+ −
+ − case 3: /* italics */
+ − attributes |= INVERT;
+ − break;
+ −
+ − case 4:
+ − attributes |= UNDERLINE;
+ − break;
+ −
+ − case 7:
+ − attributes |= INVERT;
+ − break;
+ −
+ − case 8:
+ − attributes |= INVISIBLE;
+ − break;
+ −
+ − case 5: /* blink on */
+ − break;
+ −
+ − /* 10 - ANSI X3.64-1979, select primary font, don't display control
+ − * chars, don't set bit 8 on output */
+ − case 10:
+ − gl = 0;
+ − usedcharsets = true;
+ − break;
+ −
+ − /* 11 - ANSI X3.64-1979, select second alt. font, display control
+ − * chars, set bit 8 on output */
+ − case 11: /* SMACS , as */
+ − case 12:
+ − gl = 1;
+ − usedcharsets = true;
+ − break;
+ −
+ − case 21: /* normal intensity */
+ − attributes &= ~(LOW | BOLD);
+ − break;
+ −
+ − case 23: /* italics off */
+ − attributes &= ~INVERT;
+ − break;
+ −
+ − case 25: /* blinking off */
+ − break;
+ −
+ − case 27:
+ − attributes &= ~INVERT;
+ − break;
+ −
+ − case 28:
+ − attributes &= ~INVISIBLE;
+ − break;
+ −
+ − case 24:
+ − attributes &= ~UNDERLINE;
+ − break;
+ −
+ − case 22:
+ − attributes &= ~BOLD;
+ − break;
+ −
+ − case 30:
+ − case 31:
+ − case 32:
+ − case 33:
+ − case 34:
+ − case 35:
+ − case 36:
+ − case 37:
+ − attributes &= ~COLOR_FG;
+ − attributes |= ((DCEvars[i] - 30) + 1) << COLOR_FG_SHIFT;
+ − break;
+ −
+ − case 38:
+ − if (DCEvars[i + 1] == 5) {
+ − attributes &= ~COLOR_FG;
+ − attributes |= ((DCEvars[i + 2]) + 1) << COLOR_FG_SHIFT;
+ − i += 2;
+ − }
+ −
+ − break;
+ −
+ − case 39:
+ − attributes &= ~COLOR_FG;
+ − break;
+ −
+ − case 40:
+ − case 41:
+ − case 42:
+ − case 43:
+ − case 44:
+ − case 45:
+ − case 46:
+ − case 47:
+ − attributes &= ~COLOR_BG;
+ − attributes |= ((DCEvars[i] - 40) + 1) << COLOR_BG_SHIFT;
+ − break;
+ −
+ − case 48:
+ − if (DCEvars[i + 1] == 5) {
+ − attributes &= ~COLOR_BG;
+ − attributes |= (DCEvars[i + 2] + 1) << COLOR_BG_SHIFT;
+ − i += 2;
+ − }
+ −
+ − break;
+ −
+ − case 49:
+ − attributes &= ~COLOR_BG;
+ − break;
+ −
+ − case 90:
+ − case 91:
+ − case 92:
+ − case 93:
+ − case 94:
+ − case 95:
+ − case 96:
+ − case 97:
+ − attributes &= ~COLOR_FG;
+ − attributes |= ((DCEvars[i] - 82) + 1) << COLOR_FG_SHIFT;
+ − break;
+ −
+ − case 100:
+ − case 101:
+ − case 102:
+ − case 103:
+ − case 104:
+ − case 105:
+ − case 106:
+ − case 107:
+ − attributes &= ~COLOR_BG;
+ − attributes |= ((DCEvars[i] - 92) + 1) << COLOR_BG_SHIFT;
+ − break;
+ −
+ − default:
+ − debugStr.append("ESC [ ")
+ − .append(DCEvars[i])
+ − .append(" m unknown...");
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − break;
+ − }
+ −
+ − if (debug > 3) {
+ − debugStr.append(DCEvars[i])
+ − .append(';');
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ − }
+ −
+ − if (debug > 3) {
+ − debugStr.append(" (attributes = ")
+ − .append(attributes)
+ − .append(")m");
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − }
+ −
+ − break;
+ −
+ − default:
+ − debugStr.append("ESC [ unknown letter: ")
+ − .append(c)
+ − .append(" (")
+ − .append((int)c)
+ − .append(')');
+ − debug(debugStr.toString());
+ − debugStr.setLength(0);
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case TSTATE_TITLE:
+ − switch (c) {
+ − case ESC:
+ − term_state = TSTATE_ESC;
+ − break;
+ −
+ − default:
+ − // TODO save title
+ − break;
+ − }
+ −
+ − break;
+ −
+ − default:
+ − term_state = TSTATE_DATA;
+ − break;
+ − }
+ −
+ − setCursorPosition(C, R);
+ − }
+ −
+ − /* hard reset the terminal */
+ − public void reset() {
+ − gx[0] = 'B';
+ − gx[1] = 'B';
+ − gx[2] = 'B';
+ − gx[3] = 'B';
+ − gl = 0; // default GL to G0
+ − gr = 2; // default GR to G2
+ − onegl = -1; // Single shift override
+ − /* reset tabs */
+ − int nw = width;
+ −
+ − if (nw < 132) nw = 132;
+ −
+ − Tabs = new byte[nw];
+ −
+ − for (int i = 0; i < nw; i += 8) {
+ − Tabs[i] = 1;
+ − }
+ −
+ − deleteArea(0, 0, width, height, attributes);
+ − setMargins(0, height);
+ − C = R = 0;
+ − _SetCursor(0, 0);
+ −
+ − if (display != null)
+ − display.resetColors();
+ −
+ − showCursor(true);
+ − /*FIXME:*/
+ − term_state = TSTATE_DATA;
+ − }
+ − }