5776803 [rkeene@sledge /home/rkeene/archive/floydssh/telnet]$ cat -n vt320.java
   1 /* This file is part of "The Java Telnet Application".
   2  *
   3  * (c) Matthias L. Jugel, Marcus Meißner 1996-2002. All Rights Reserved.
   4  * The file was changed by Radek Polak to work as midlet in MIDP 1.0
   5  *
   6  * Please visit http://javatelnet.org/ for updates and contact.
   7  *
   8  * --LICENSE NOTICE--
   9  * This program is free software; you can redistribute it and/or
  10  * modify it under the terms of the GNU General Public License
  11  * as published by the Free Software Foundation; either version 2
  12  * of the License, or (at your option) any later version.
  13  *
  14  * This program is distributed in the hope that it will be useful,
  15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17  * GNU General Public License for more details.
  18  *
  19  * You should have received a copy of the GNU General Public License
  20  * along with this program; if not, write to the Free Software
  21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22  * --LICENSE NOTICE--
  23  *
  24  */
  25 
  26 package telnet;
  27 
  28 
  29 /**
  30  * Implementation of a VT terminal emulation plus ANSI compatible.
  31  * <P>
  32  * <B>Maintainer:</B> Marcus Meißner
  33  *
  34  * @version $Id: vt320.java,v 2.91 2002/05/17 21:47:12 leo Exp $
  35  * @author  Matthias L. Jugel, Marcus Meißner
  36  */
  37 public class vt320 extends VDUBuffer {
  38 
  39   public final static int KEY_CONTROL = 0x01;
  40   public final static int KEY_SHIFT = 0x02;
  41   public final static int KEY_ALT = 0x04;
  42   public final static int KEY_ACTION = 0x08;
  43 
  44 
  45   /**
  46    * Write an answer back to the remote host. This is needed to be able to
  47    * send terminal answers requests like status and type information.
  48    * @param b the array of bytes to be sent
  49    */
  50   public void write(byte[] b) {
  51     /** before sending data transform it using telnet (which is sending it) */
  52     try {
  53       if (Telnet.emulation.localecho) {
  54         Telnet.emulation.putString(new String(b));
  55       }
  56       Telnet.sshIO.sendData(new String(b));
  57     }
  58     catch (java.io.IOException e) {
  59       Telnet.console.append(e.getMessage());
  60     }
  61   }
  62 
  63 
  64   /**
  65    * Play the beep sound ...
  66    */
  67   public void beep() { /* do nothing by default */
  68   }
  69 
  70   /**
  71    * Put string at current cursor position. Moves cursor
  72    * according to the String. Does NOT wrap.
  73    * @param s the string
  74    */
  75   public void putString(String s) {
  76     int len = s.length();
  77 
  78     if (len > 0) {
  79       markLine(R, 1);
  80       for (int i = 0; i < len; i++) {
  81         putChar(s.charAt(i), false);
  82       }
  83       setCursorPosition(C, R);
  84       redraw();
  85     }
  86   }
  87 
  88   protected void sendTelnetCommand(byte cmd) {
  89   }
  90 
  91   /**
  92    * Create a new vt320 terminal and intialize it with useful settings.
  93    */
  94   public vt320(int width, int height) {
  95     super(width, height);
  96     setVMS(false);
  97     setIBMCharset(false);
  98     setBufferSize(height);    // was 100 scroll lines back b4
  99 
 100     int nw = width;
 101     if (nw < 132) nw = 132; //catch possible later 132/80 resizes
 102     Tabs = new byte[nw];
 103     for (int i = 0; i < nw; i += 8) {
 104       Tabs[i] = 1;
 105     }
 106 
 107     /* top row of numpad */
 108     PF1 = "\u001bOP";
 109     PF2 = "\u001bOQ";
 110     PF3 = "\u001bOR";
 111     PF4 = "\u001bOS";
 112 
 113     /* the 3x2 keyblock on PC keyboards */
 114     Insert = new String[4];
 115     Remove = new String[4];
 116     KeyHome = new String[4];
 117     KeyEnd = new String[4];
 118     NextScn = new String[4];
 119     PrevScn = new String[4];
 120     Escape = new String[4];
 121     BackSpace = new String[4];
 122     TabKey = new String[4];
 123     Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~";
 124     Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~";
 125     PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~";
 126     NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~";
 127     KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001b[H";
 128     KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001b[F";
 129     Escape[0] = Escape[1] = Escape[2] = Escape[3] = "\u001b";
 130     if (vms) {
 131       BackSpace[1] = "" + (char) 10;    //  VMS shift deletes word back
 132       BackSpace[2] = "\u0018";  //  VMS control deletes line back
 133       BackSpace[0] = BackSpace[3] = "\u007f";   //  VMS other is delete
 134     } else {
 135       BackSpace[0] = BackSpace[1] = BackSpace[2] = BackSpace[3] = "\b";
 136     }
 137 
 138     /* some more VT100 keys */
 139     Find = "\u001b[1~";
 140     Select = "\u001b[4~";
 141     Help = "\u001b[28~";
 142     Do = "\u001b[29~";
 143 
 144     FunctionKey = new String[21];
 145     FunctionKey[0] = "";
 146     FunctionKey[1] = PF1;
 147     FunctionKey[2] = PF2;
 148     FunctionKey[3] = PF3;
 149     FunctionKey[4] = PF4;
 150     /* following are defined differently for vt220 / vt132 ... */
 151     FunctionKey[5] = "\u001b[15~";
 152     FunctionKey[6] = "\u001b[17~";
 153     FunctionKey[7] = "\u001b[18~";
 154     FunctionKey[8] = "\u001b[19~";
 155     FunctionKey[9] = "\u001b[20~";
 156     FunctionKey[10] = "\u001b[21~";
 157     FunctionKey[11] = "\u001b[23~";
 158     FunctionKey[12] = "\u001b[24~";
 159     FunctionKey[13] = "\u001b[25~";
 160     FunctionKey[14] = "\u001b[26~";
 161     FunctionKey[15] = Help;
 162     FunctionKey[16] = Do;
 163     FunctionKey[17] = "\u001b[31~";
 164     FunctionKey[18] = "\u001b[32~";
 165     FunctionKey[19] = "\u001b[33~";
 166     FunctionKey[20] = "\u001b[34~";
 167 
 168     FunctionKeyShift = new String[21];
 169     FunctionKeyAlt = new String[21];
 170     FunctionKeyCtrl = new String[21];
 171 
 172     for (int i = 0; i < 20; i++) {
 173       FunctionKeyShift[i] = "";
 174       FunctionKeyAlt[i] = "";
 175       FunctionKeyCtrl[i] = "";
 176     }
 177     FunctionKeyShift[15] = Find;
 178     FunctionKeyShift[16] = Select;
 179 
 180 
 181     TabKey[0] = "\u0009";
 182     TabKey[1] = "\u001bOP\u0009";
 183     TabKey[2] = TabKey[3] = "";
 184 
 185     KeyUp = new String[4];
 186     KeyUp[0] = "\u001b[A";
 187     KeyDown = new String[4];
 188     KeyDown[0] = "\u001b[B";
 189     KeyRight = new String[4];
 190     KeyRight[0] = "\u001b[C";
 191     KeyLeft = new String[4];
 192     KeyLeft[0] = "\u001b[D";
 193     Numpad = new String[10];
 194     Numpad[0] = "\u001bOp";
 195     Numpad[1] = "\u001bOq";
 196     Numpad[2] = "\u001bOr";
 197     Numpad[3] = "\u001bOs";
 198     Numpad[4] = "\u001bOt";
 199     Numpad[5] = "\u001bOu";
 200     Numpad[6] = "\u001bOv";
 201     Numpad[7] = "\u001bOw";
 202     Numpad[8] = "\u001bOx";
 203     Numpad[9] = "\u001bOy";
 204     KPMinus = PF4;
 205     KPComma = "\u001bOl";
 206     KPPeriod = "\u001bOn";
 207     KPEnter = "\u001bOM";
 208 
 209     NUMPlus = new String[4];
 210     NUMPlus[0] = "+";
 211     NUMDot = new String[4];
 212     NUMDot[0] = ".";
 213   }
 214 
 215   /**
 216    * Create a default vt320 terminal with 80 columns and 24 lines.
 217    */
 218   public vt320() {
 219     this(80, 24);
 220   }
 221 
 222   /**
 223    * Terminal is mouse-aware and requires (x,y) coordinates of
 224    * on the terminal (character coordinates) and the button clicked.
 225    * @param x
 226    * @param y
 227    * @param modifiers
 228    */
 229   public void mousePressed(int x, int y, int modifiers) {
 230     if (mouserpt == 0)
 231       return;
 232 
 233     int mods = modifiers;
 234     mousebut = 3;
 235     if ((mods & 16) == 16) mousebut = 0;
 236     if ((mods & 8) == 8) mousebut = 1;
 237     if ((mods & 4) == 4) mousebut = 2;
 238 
 239     int mousecode;
 240     if (mouserpt == 9)  /* X10 Mouse */
 241       mousecode = 0x20 | mousebut;
 242     else            /* normal xterm mouse reporting */
 243       mousecode = mousebut | 0x20 | ((mods & 7) << 2);
 244 
 245     byte b[] = new byte[6];
 246 
 247     b[0] = 27;
 248     b[1] = (byte) '[';
 249     b[2] = (byte) 'M';
 250     b[3] = (byte) mousecode;
 251     b[4] = (byte) (0x20 + x + 1);
 252     b[5] = (byte) (0x20 + y + 1);
 253 
 254     write(b); // FIXME: writeSpecial here
 255   }
 256 
 257   /**
 258    * Terminal is mouse-aware and requires the coordinates and button
 259    * of the release.
 260    * @param x
 261    * @param y
 262    * @param modifiers
 263    */
 264   public void mouseReleased(int x, int y, int modifiers) {
 265     if (mouserpt == 0)
 266       return;
 267 
 268     /* problem is tht modifiers still have the released button set in them.
 269     int mods = modifiers;
 270     mousebut = 3;
 271     if ((mods & 16)==16) mousebut=0;
 272     if ((mods &  8)==8 ) mousebut=1;
 273     if ((mods &  4)==4 ) mousebut=2;
 274     */
 275 
 276     int mousecode;
 277     if (mouserpt == 9)
 278       mousecode = 0x20 + mousebut;  /* same as press? appears so. */
 279     else
 280       mousecode = '#';
 281 
 282     byte b[] = new byte[6];
 283     b[0] = 27;
 284     b[1] = (byte) '[';
 285     b[2] = (byte) 'M';
 286     b[3] = (byte) mousecode;
 287     b[4] = (byte) (0x20 + x + 1);
 288     b[5] = (byte) (0x20 + y + 1);
 289     write(b); // FIXME: writeSpecial here
 290     mousebut = 0;
 291   }
 292 
 293 
 294   /** we should do localecho (passed from other modules). false is default */
 295   public boolean localecho = false;
 296 
 297   /**
 298    * Enable or disable the local echo property of the terminal.
 299    * @param echo true if the terminal should echo locally
 300    */
 301   public void setLocalEcho(boolean echo) {
 302     localecho = echo;
 303   }
 304 
 305   /**
 306    * Enable the VMS mode of the terminal to handle some things differently
 307    * for VMS hosts.
 308    * @param vms true for vms mode, false for normal mode
 309    */
 310   public void setVMS(boolean vms) {
 311     this.vms = vms;
 312   }
 313 
 314   /**
 315    * Enable the usage of the IBM character set used by some BBS's. Special
 316    * graphical character are available in this mode.
 317    * @param ibm true to use the ibm character set
 318    */
 319   public void setIBMCharset(boolean ibm) {
 320     useibmcharset = ibm;
 321   }
 322 
 323 
 324   /**
 325    * Set the terminal id used to identify this terminal.
 326    * @param terminalID the id string
 327    */
 328   public void setTerminalID(String terminalID) {
 329     this.terminalID = terminalID;
 330   }
 331 
 332   public void setAnswerBack(String ab) {
 333     this.answerBack = unEscape(ab);
 334   }
 335 
 336   /**
 337    * Get the terminal id used to identify this terminal.
 338    */
 339   public String getTerminalID() {
 340     return terminalID;
 341   }
 342 
 343   /**
 344    * A small conveniance method thar converts the string to a byte array
 345    * for sending.
 346    * @param s the string to be sent
 347    */
 348   private boolean write(String s, boolean doecho) {
 349     if (s == null) // aka the empty string.
 350       return true;
 351     /* NOTE: getBytes() honours some locale, it *CONVERTS* the string.
 352      * However, we output only 7bit stuff towards the target, and *some*
 353      * 8 bit control codes. We must not mess up the latter, so we do hand
 354      * by hand copy.
 355      */
 356 
 357     byte arr[] = new byte[s.length()];
 358     for (int i = 0; i < s.length(); i++) {
 359       arr[i] = (byte) s.charAt(i);
 360     }
 361     write(arr);
 362 
 363     if (doecho)
 364       putString(s);
 365     return true;
 366   }
 367 
 368   private boolean write(String s) {
 369     return write(s, localecho);
 370   }
 371 
 372   // ===================================================================
 373   // the actual terminal emulation code comes here:
 374   // ===================================================================
 375 
 376   private String terminalID = "vt320";
 377   private String answerBack = "Use Terminal.answerback to set ...\n";
 378 
 379   // X - COLUMNS, Y - ROWS
 380   public int R,C;
 381   int attributes = 0;
 382 
 383   int Sc,Sr,Sa,Stm,Sbm;
 384   char Sgr,Sgl;
 385   char Sgx[];
 386 
 387   int insertmode = 0;
 388   int statusmode = 0;
 389   boolean vt52mode = false;
 390   boolean keypadmode = false; /* false - numeric, true - application */
 391   boolean output8bit = false;
 392   int normalcursor = 0;
 393   boolean moveoutsidemargins = true;
 394   boolean wraparound = true;
 395   boolean sendcrlf = true;
 396   boolean capslock = false;
 397   boolean numlock = false;
 398   int mouserpt = 0;
 399   byte mousebut = 0;
 400 
 401   boolean useibmcharset = false;
 402 
 403   int lastwaslf = 0;
 404   boolean usedcharsets = false;
 405 
 406   private final static char ESC = 27;
 407   private final static char IND = 132;
 408   private final static char NEL = 133;
 409   private final static char RI = 141;
 410   private final static char SS2 = 142;
 411   private final static char SS3 = 143;
 412   private final static char DCS = 144;
 413   private final static char HTS = 136;
 414   private final static char CSI = 155;
 415   private final static char OSC = 157;
 416   private final static int TSTATE_DATA = 0;
 417   private final static int TSTATE_ESC = 1; /* ESC */
 418   private final static int TSTATE_CSI = 2; /* ESC [ */
 419   private final static int TSTATE_DCS = 3; /* ESC P */
 420   private final static int TSTATE_DCEQ = 4; /* ESC [? */
 421   private final static int TSTATE_ESCSQUARE = 5; /* ESC # */
 422   private final static int TSTATE_OSC = 6;       /* ESC ] */
 423   private final static int TSTATE_SETG0 = 7;     /* ESC (? */
 424   private final static int TSTATE_SETG1 = 8;     /* ESC )? */
 425   private final static int TSTATE_SETG2 = 9;     /* ESC *? */
 426   private final static int TSTATE_SETG3 = 10;    /* ESC +? */
 427   private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */
 428   private final static int TSTATE_CSI_EX = 12; /* ESC [ ! */
 429   private final static int TSTATE_ESCSPACE = 13; /* ESC <space> */
 430   private final static int TSTATE_VT52X = 14;
 431   private final static int TSTATE_VT52Y = 15;
 432   private final static int TSTATE_CSI_TICKS = 16;
 433 
 434   /* The graphics charsets
 435    * B - default ASCII
 436    * A - ISO Latin 1
 437    * 0 - DEC SPECIAL
 438    * < - User defined
 439    * ....
 440    */
 441   char gx[] = {// same initial set as in XTERM.
 442     'B', // g0
 443     '0', // g1
 444     'B', // g2
 445     'B', // g3
 446   };
 447   char gl = 0;      // default GL to G0
 448   char gr = 2;      // default GR to G2
 449   int onegl = -1;   // single shift override for GL.
 450 
 451   // Map from scoansi linedrawing to DEC _and_ unicode (for the stuff which
 452   // is not in linedrawing). Got from experimenting with scoadmin.
 453   private final static String scoansi_acs =
	"Tm7k3x4u?kZl@mYjEnB\u2566DqCtAvM\u2550:\u2551N\u2557I\u2554;\u2557H\u255a0a<\u255d";
 454   // array to store DEC Special -> Unicode mapping
 455   //  Unicode   DEC  Unicode name    (DEC name)
 456   private static char DECSPECIAL[] = {
 457     '\u0040', //5f blank
 458     '\u2666', //60 black diamond
 459     '\u2592', //61 grey square
 460     '\u2409', //62 Horizontal tab  (ht) pict. for control
 461     '\u240c', //63 Form Feed       (ff) pict. for control
 462     '\u240d', //64 Carriage Return (cr) pict. for control
 463     '\u240a', //65 Line Feed       (lf) pict. for control
 464     '\u00ba', //66 Masculine ordinal indicator
 465     '\u00b1', //67 Plus or minus sign
 466     '\u2424', //68 New Line        (nl) pict. for control
 467     '\u240b', //69 Vertical Tab    (vt) pict. for control
 468     '\u2518', //6a Forms light up   and left
 469     '\u2510', //6b Forms light down and left
 470     '\u250c', //6c Forms light down and right
 471     '\u2514', //6d Forms light up   and right
 472     '\u253c', //6e Forms light vertical and horizontal
 473     '\u2594', //6f Upper 1/8 block                        (Scan 1)
 474     '\u2580', //70 Upper 1/2 block                        (Scan 3)
 475     '\u2500', //71 Forms light horizontal or ?em dash?    (Scan 5)
 476     '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7)
 477     '\u005f', //73 \u005f underscore  or \u2581 lower 1/8 (Scan 9)
 478     '\u251c', //74 Forms light vertical and right
 479     '\u2524', //75 Forms light vertical and left
 480     '\u2534', //76 Forms light up   and horizontal
 481     '\u252c', //77 Forms light down and horizontal
 482     '\u2502', //78 vertical bar
 483     '\u2264', //79 less than or equal
 484     '\u2265', //7a greater than or equal
 485     '\u00b6', //7b paragraph
 486     '\u2260', //7c not equal
 487     '\u00a3', //7d Pound Sign (british)
 488     '\u00b7'  //7e Middle Dot
 489   };
 490 
 491   /** Strings to send on function key pressing */
 492   private String Numpad[];
 493   private String FunctionKey[];
 494   private String FunctionKeyShift[];
 495   private String FunctionKeyCtrl[];
 496   private String FunctionKeyAlt[];
 497   private String TabKey[];
 498   private String KeyUp[],KeyDown[],KeyLeft[],KeyRight[];
 499   private String KPMinus, KPComma, KPPeriod, KPEnter;
 500   private String PF1, PF2, PF3, PF4;
 501   private String Help, Do, Find, Select;
 502 
 503   private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[];
 504   private String Escape[], BackSpace[], NUMDot[], NUMPlus[];
 505 
 506   private String osc,dcs;  /* to memorize OSC & DCS control sequence */
 507 
 508   /** vt320 state variable (internal) */
 509   private int term_state = TSTATE_DATA;
 510   /** in vms mode, set by Terminal.VMS property */
 511   private boolean vms = false;
 512   /** Tabulators */
 513   private byte[] Tabs;
 514   /** The list of integers as used by CSI */
 515   private int[] DCEvars = new int[30];
 516   private int DCEvar;
 517 
 518   /**
 519    * Replace escape code characters (backslash + identifier) with their
 520    * respective codes.
 521    * @param tmp the string to be parsed
 522    * @return a unescaped string
 523    */
 524   static String unEscape(String tmp) {
 525     int idx = 0, oldidx = 0;
 526     String cmd;
 527     // System.err.println("unescape("+tmp+")");
 528     cmd = "";
 529     while ((idx = tmp.indexOf('\\', oldidx)) >= 0 &&
 530             ++idx <= tmp.length()) {
 531       cmd += tmp.substring(oldidx, idx - 1);
 532       if (idx == tmp.length()) return cmd;
 533       switch (tmp.charAt(idx)) {
 534         case 'b':
 535           cmd += "\b";
 536           break;
 537         case 'e':
 538           cmd += "\u001b";
 539           break;
 540         case 'n':
 541           cmd += "\n";
 542           break;
 543         case 'r':
 544           cmd += "\r";
 545           break;
 546         case 't':
 547           cmd += "\t";
 548           break;
 549         case 'v':
 550           cmd += "\u000b";
 551           break;
 552         case 'a':
 553           cmd += "\u0012";
 554           break;
 555         default :
 556           if ((tmp.charAt(idx) >= '0') && (tmp.charAt(idx) <= '9')) {
 557             int i;
 558             for (i = idx; i < tmp.length(); i++)
 559               if ((tmp.charAt(i) < '0') || (tmp.charAt(i) > '9'))
 560                 break;
 561             cmd += (char) Integer.parseInt(tmp.substring(idx, i));
 562             idx = i - 1;
 563           } else
 564             cmd += tmp.substring(idx, ++idx);
 565           break;
 566       }
 567       oldidx = ++idx;
 568     }
 569     if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx);
 570     return cmd;
 571   }
 572 
 573   /**
 574    * A small conveniance method thar converts a 7bit string to the 8bit
 575    * version depending on VT52/Output8Bit mode.
 576    *
 577    * @param s the string to be sent
 578    */
 579   private boolean writeSpecial(String s) {
 580     if (s == null)
 581       return true;
 582     if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == 'O'))) {
 583       if (vt52mode) {
 584         if ((s.charAt(2) >= 'P') && (s.charAt(2) <= 'S')) {
 585           s = "\u001b" + s.substring(2); /* ESC x */
 586         } else {
 587           s = "\u001b?" + s.substring(2); /* ESC ? x */
 588         }
 589       } else {
 590         if (output8bit) {
 591           s = "\u008f" + s.substring(2);  /* SS3 x */
 592         } /* else keep string as it is */
 593       }
 594     }
 595     if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == '['))) {
 596       if (output8bit) {
 597         s = "\u009b" + s.substring(2); /* CSI ... */
 598       } /* else keep */
 599     }
 600     return write(s, false);
 601   }
 602 
 603   /**
 604    * main keytyping event handler...
 605    */
 606   public void keyPressed(int keyCode, char keyChar, int modifiers) {
 607     boolean control = (modifiers & KEY_CONTROL) != 0;
 608     boolean shift = (modifiers & KEY_SHIFT) != 0;
 609     boolean alt = (modifiers & KEY_ALT) != 0;
 610 
 611     int keychr = keyChar;
 612 
 613     int xind;
 614     String fmap[];
 615     xind = 0;
 616     fmap = FunctionKey;
 617     if (shift) {
 618       fmap = FunctionKeyShift;
 619       xind = 1;
 620     }
 621     if (control) {
 622       fmap = FunctionKeyCtrl;
 623       xind = 2;
 624     }
 625     if (alt) {
 626       fmap = FunctionKeyAlt;
 627       xind = 3;
 628     }
 629 
 630     switch (keyCode) {
 631       case KeyEvent.VK_PAUSE:
 632         if (shift || control)
 633           sendTelnetCommand((byte) 243); // BREAK
 634         break;
 635       case KeyEvent.VK_F1:
 636         writeSpecial(fmap[1]);
 637         break;
 638       case KeyEvent.VK_F2:
 639         writeSpecial(fmap[2]);
 640         break;
 641       case KeyEvent.VK_F3:
 642         writeSpecial(fmap[3]);
 643         break;
 644       case KeyEvent.VK_F4:
 645         writeSpecial(fmap[4]);
 646         break;
 647       case KeyEvent.VK_F5:
 648         writeSpecial(fmap[5]);
 649         break;
 650       case KeyEvent.VK_F6:
 651         writeSpecial(fmap[6]);
 652         break;
 653       case KeyEvent.VK_F7:
 654         writeSpecial(fmap[7]);
 655         break;
 656       case KeyEvent.VK_F8:
 657         writeSpecial(fmap[8]);
 658         break;
 659       case KeyEvent.VK_F9:
 660         writeSpecial(fmap[9]);
 661         break;
 662       case KeyEvent.VK_F10:
 663         writeSpecial(fmap[10]);
 664         break;
 665       case KeyEvent.VK_F11:
 666         writeSpecial(fmap[11]);
 667         break;
 668       case KeyEvent.VK_F12:
 669         writeSpecial(fmap[12]);
 670         break;
 671       case KeyEvent.VK_UP:
 672         writeSpecial(KeyUp[xind]);
 673         break;
 674       case KeyEvent.VK_DOWN:
 675         writeSpecial(KeyDown[xind]);
 676         break;
 677       case KeyEvent.VK_LEFT:
 678         writeSpecial(KeyLeft[xind]);
 679         break;
 680       case KeyEvent.VK_RIGHT:
 681         writeSpecial(KeyRight[xind]);
 682         break;
 683       case KeyEvent.VK_PAGE_DOWN:
 684         writeSpecial(NextScn[xind]);
 685         break;
 686       case KeyEvent.VK_PAGE_UP:
 687         writeSpecial(PrevScn[xind]);
 688         break;
 689       case KeyEvent.VK_INSERT:
 690         writeSpecial(Insert[xind]);
 691         break;
 692       case KeyEvent.VK_DELETE:
 693         writeSpecial(Remove[xind]);
 694         break;
 695       case KeyEvent.VK_BACK_SPACE:
 696         writeSpecial(BackSpace[xind]);
 697     if (localecho) {
 698       if (BackSpace[xind] == "\b") {
 699         putString("\b \b"); // make the last char 'deleted'
 700       } else {
 701         putString(BackSpace[xind]); // echo it
 702       }
 703     }
 704         break;
 705       case KeyEvent.VK_HOME:
 706         writeSpecial(KeyHome[xind]);
 707         break;
 708       case KeyEvent.VK_END:
 709         writeSpecial(KeyEnd[xind]);
 710         break;
 711       case KeyEvent.VK_NUM_LOCK:
 712         if (vms && control) {
 713           writeSpecial(PF1);
 714         }
 715         if (!control)
 716           numlock = !numlock;
 717         break;
 718       case KeyEvent.VK_CAPS_LOCK:
 719         capslock = !capslock;
 720         return;
 721       case KeyEvent.VK_SHIFT:
 722       case KeyEvent.VK_CONTROL:
 723       case KeyEvent.VK_ALT:
 724         return;
 725       default:
 726         break;
 727     }
 728   }
 729 
 730   public void keyReleased(KeyEvent evt) {
 731     // ignore
 732   }
 733 
 734   /**
 735    * Handle key Typed events for the terminal, this will get
 736    * all normal key types, but no shift/alt/control/numlock.
 737    */
 738   public void keyTyped(int keyCode, char keyChar, int modifiers) {
 739 
 740 //    System.out.println("KEY TYPED keycode:"+keyCode+" keychar"+(int)keyChar+" modifiers:"+modifiers );
 741 
 742     boolean control = (modifiers & KEY_CONTROL) != 0;
 743     boolean shift = (modifiers & KEY_SHIFT) != 0;
 744     boolean alt = (modifiers & KEY_ALT) != 0;
 745 
 746     if (keyChar == '\t') {
 747       if (shift) {
 748         write(TabKey[1], false);
 749       } else {
 750         if (control) {
 751           write(TabKey[2], false);
 752         } else {
 753           if (alt) {
 754             write(TabKey[3], false);
 755           } else {
 756             write(TabKey[0], false);
 757           }
 758         }
 759       }
 760       return;
 761     }
 762     if (alt) {
 763       write("" + ((char) (keyChar | 0x80)));
 764       return;
 765     }
 766 
 767     if (((keyCode == KeyEvent.VK_ENTER) || (keyChar == 10))
 768             && !control) {
 769       write("\r", false);
 770       if (localecho) putString("\r\n"); // bad hack
 771       return;
 772     }
 773 
 774     if ((keyCode == 10) && !control) {
 775       write("\r", false);
 776       return;
 777     }
 778 
 779     // FIXME: on german PC keyboards you have to use Alt-Ctrl-q to get an @,
 780     // so we can't just use it here... will probably break some other VMS
 781     // codes.  -Marcus
 782     // if(((!vms && keyChar == '2') || keyChar == '@' || keyChar == ' ')
 783     //    && control)
 784     if (((!vms && keyChar == '2') || keyChar == ' ') && control)
 785       write("" + (char) 0);
 786 
 787     if (vms) {
 788       if (keyChar == 127 && !control) {
 789         if (shift)
 790           writeSpecial(Insert[0]);        //  VMS shift delete = insert
 791         else
 792           writeSpecial(Remove[0]);        //  VMS delete = remove
 793         return;
 794       } else if (control)
 795         switch (keyChar) {
 796           case '0':
 797             writeSpecial(Numpad[0]);
 798             return;
 799           case '1':
 800             writeSpecial(Numpad[1]);
 801             return;
 802           case '2':
 803             writeSpecial(Numpad[2]);
 804             return;
 805           case '3':
 806             writeSpecial(Numpad[3]);
 807             return;
 808           case '4':
 809             writeSpecial(Numpad[4]);
 810             return;
 811           case '5':
 812             writeSpecial(Numpad[5]);
 813             return;
 814           case '6':
 815             writeSpecial(Numpad[6]);
 816             return;
 817           case '7':
 818             writeSpecial(Numpad[7]);
 819             return;
 820           case '8':
 821             writeSpecial(Numpad[8]);
 822             return;
 823           case '9':
 824             writeSpecial(Numpad[9]);
 825             return;
 826           case '.':
 827             writeSpecial(KPPeriod);
 828             return;
 829           case '-':
 830           case 31:
 831             writeSpecial(KPMinus);
 832             return;
 833           case '+':
 834             writeSpecial(KPComma);
 835             return;
 836           case 10:
 837             writeSpecial(KPEnter);
 838             return;
 839           case '/':
 840             writeSpecial(PF2);
 841             return;
 842           case '*':
 843             writeSpecial(PF3);
 844             return;
 845             /* NUMLOCK handled in keyPressed */
 846           default:
 847             break;
 848         }
 849       /* Now what does this do and how did it get here. -Marcus
 850       if (shift && keyChar < 32) {
 851         write(PF1+(char)(keyChar + 64));
 852         return;
 853       }
 854       */
 855     }
 856 
 857 
 858     // FIXME: not used?
 859     String fmap[];
 860     int xind;
 861     xind = 0;
 862     fmap = FunctionKey;
 863     if (shift) {
 864       fmap = FunctionKeyShift;
 865       xind = 1;
 866     }
 867     if (control) {
 868       fmap = FunctionKeyCtrl;
 869       xind = 2;
 870     }
 871     if (alt) {
 872       fmap = FunctionKeyAlt;
 873       xind = 3;
 874     }
 875 
 876     if (keyCode == KeyEvent.VK_ESCAPE) {
 877       writeSpecial(Escape[xind]);
 878       return;
 879     }
 880 
 881     if ((modifiers & KEY_ACTION) != 0)
 882       switch (keyCode) {
 883         case KeyEvent.VK_NUMPAD0:
 884           writeSpecial(Numpad[0]);
 885           return;
 886         case KeyEvent.VK_NUMPAD1:
 887           writeSpecial(Numpad[1]);
 888           return;
 889         case KeyEvent.VK_NUMPAD2:
 890           writeSpecial(Numpad[2]);
 891           return;
 892         case KeyEvent.VK_NUMPAD3:
 893           writeSpecial(Numpad[3]);
 894           return;
 895         case KeyEvent.VK_NUMPAD4:
 896           writeSpecial(Numpad[4]);
 897           return;
 898         case KeyEvent.VK_NUMPAD5:
 899           writeSpecial(Numpad[5]);
 900           return;
 901         case KeyEvent.VK_NUMPAD6:
 902           writeSpecial(Numpad[6]);
 903           return;
 904         case KeyEvent.VK_NUMPAD7:
 905           writeSpecial(Numpad[7]);
 906           return;
 907         case KeyEvent.VK_NUMPAD8:
 908           writeSpecial(Numpad[8]);
 909           return;
 910         case KeyEvent.VK_NUMPAD9:
 911           writeSpecial(Numpad[9]);
 912           return;
 913         case KeyEvent.VK_DECIMAL:
 914           writeSpecial(NUMDot[xind]);
 915           return;
 916         case KeyEvent.VK_ADD:
 917           writeSpecial(NUMPlus[xind]);
 918           return;
 919       }
 920 
 921     if (!((keyChar == 8) || (keyChar == 127) || (keyChar == '\r') || (keyChar == '\n'))) {
 922       write("" + keyChar);
 923       return;
 924     }
 925   }
 926 
 927   private void handle_dcs(String dcs) {
 928   }
 929 
 930   private void handle_osc(String osc) {
 931   }
 932 
 933   private final static char unimap[] = {
 934     //#
 935     //#    Name:     cp437_DOSLatinUS to Unicode table
 936     //#    Unicode version: 1.1
 937     //#    Table version: 1.1
 938     //#    Table format:  Format A
 939     //#    Date:          03/31/95
 940     //#    Authors:       Michel Suignard <michelsu@microsoft.com>
 941     //#                   Lori Hoerth <lorih@microsoft.com>
 942     //#    General notes: none
 943     //#
 944     //#    Format: Three tab-separated columns
 945     //#        Column #1 is the cp1255_WinHebrew code (in hex)
 946     //#        Column #2 is the Unicode (in hex as 0xXXXX)
 947     //#        Column #3 is the Unicode name (follows a comment sign, '#')
 948     //#
 949     //#    The entries are in cp437_DOSLatinUS order
 950     //#
 951 
 952     0x0000, // #NULL
 953     0x0001, // #START OF HEADING
 954     0x0002, // #START OF TEXT
 955     0x0003, // #END OF TEXT
 956     0x0004, // #END OF TRANSMISSION
 957     0x0005, // #ENQUIRY
 958     0x0006, // #ACKNOWLEDGE
 959     0x0007, // #BELL
 960     0x0008, // #BACKSPACE
 961     0x0009, // #HORIZONTAL TABULATION
 962     0x000a, // #LINE FEED
 963     0x000b, // #VERTICAL TABULATION
 964     0x000c, // #FORM FEED
 965     0x000d, // #CARRIAGE RETURN
 966     0x000e, // #SHIFT OUT
 967     0x000f, // #SHIFT IN
 968     0x0010, // #DATA LINK ESCAPE
 969     0x0011, // #DEVICE CONTROL ONE
 970     0x0012, // #DEVICE CONTROL TWO
 971     0x0013, // #DEVICE CONTROL THREE
 972     0x0014, // #DEVICE CONTROL FOUR
 973     0x0015, // #NEGATIVE ACKNOWLEDGE
 974     0x0016, // #SYNCHRONOUS IDLE
 975     0x0017, // #END OF TRANSMISSION BLOCK
 976     0x0018, // #CANCEL
 977     0x0019, // #END OF MEDIUM
 978     0x001a, // #SUBSTITUTE
 979     0x001b, // #ESCAPE
 980     0x001c, // #FILE SEPARATOR
 981     0x001d, // #GROUP SEPARATOR
 982     0x001e, // #RECORD SEPARATOR
 983     0x001f, // #UNIT SEPARATOR
 984     0x0020, // #SPACE
 985     0x0021, // #EXCLAMATION MARK
 986     0x0022, // #QUOTATION MARK
 987     0x0023, // #NUMBER SIGN
 988     0x0024, // #DOLLAR SIGN
 989     0x0025, // #PERCENT SIGN
 990     0x0026, // #AMPERSAND
 991     0x0027, // #APOSTROPHE
 992     0x0028, // #LEFT PARENTHESIS
 993     0x0029, // #RIGHT PARENTHESIS
 994     0x002a, // #ASTERISK
 995     0x002b, // #PLUS SIGN
 996     0x002c, // #COMMA
 997     0x002d, // #HYPHEN-MINUS
 998     0x002e, // #FULL STOP
 999     0x002f, // #SOLIDUS
1000     0x0030, // #DIGIT ZERO
1001     0x0031, // #DIGIT ONE
1002     0x0032, // #DIGIT TWO
1003     0x0033, // #DIGIT THREE
1004     0x0034, // #DIGIT FOUR
1005     0x0035, // #DIGIT FIVE
1006     0x0036, // #DIGIT SIX
1007     0x0037, // #DIGIT SEVEN
1008     0x0038, // #DIGIT EIGHT
1009     0x0039, // #DIGIT NINE
1010     0x003a, // #COLON
1011     0x003b, // #SEMICOLON
1012     0x003c, // #LESS-THAN SIGN
1013     0x003d, // #EQUALS SIGN
1014     0x003e, // #GREATER-THAN SIGN
1015     0x003f, // #QUESTION MARK
1016     0x0040, // #COMMERCIAL AT
1017     0x0041, // #LATIN CAPITAL LETTER A
1018     0x0042, // #LATIN CAPITAL LETTER B
1019     0x0043, // #LATIN CAPITAL LETTER C
1020     0x0044, // #LATIN CAPITAL LETTER D
1021     0x0045, // #LATIN CAPITAL LETTER E
1022     0x0046, // #LATIN CAPITAL LETTER F
1023     0x0047, // #LATIN CAPITAL LETTER G
1024     0x0048, // #LATIN CAPITAL LETTER H
1025     0x0049, // #LATIN CAPITAL LETTER I
1026     0x004a, // #LATIN CAPITAL LETTER J
1027     0x004b, // #LATIN CAPITAL LETTER K
1028     0x004c, // #LATIN CAPITAL LETTER L
1029     0x004d, // #LATIN CAPITAL LETTER M
1030     0x004e, // #LATIN CAPITAL LETTER N
1031     0x004f, // #LATIN CAPITAL LETTER O
1032     0x0050, // #LATIN CAPITAL LETTER P
1033     0x0051, // #LATIN CAPITAL LETTER Q
1034     0x0052, // #LATIN CAPITAL LETTER R
1035     0x0053, // #LATIN CAPITAL LETTER S
1036     0x0054, // #LATIN CAPITAL LETTER T
1037     0x0055, // #LATIN CAPITAL LETTER U
1038     0x0056, // #LATIN CAPITAL LETTER V
1039     0x0057, // #LATIN CAPITAL LETTER W
1040     0x0058, // #LATIN CAPITAL LETTER X
1041     0x0059, // #LATIN CAPITAL LETTER Y
1042     0x005a, // #LATIN CAPITAL LETTER Z
1043     0x005b, // #LEFT SQUARE BRACKET
1044     0x005c, // #REVERSE SOLIDUS
1045     0x005d, // #RIGHT SQUARE BRACKET
1046     0x005e, // #CIRCUMFLEX ACCENT
1047     0x005f, // #LOW LINE
1048     0x0060, // #GRAVE ACCENT
1049     0x0061, // #LATIN SMALL LETTER A
1050     0x0062, // #LATIN SMALL LETTER B
1051     0x0063, // #LATIN SMALL LETTER C
1052     0x0064, // #LATIN SMALL LETTER D
1053     0x0065, // #LATIN SMALL LETTER E
1054     0x0066, // #LATIN SMALL LETTER F
1055     0x0067, // #LATIN SMALL LETTER G
1056     0x0068, // #LATIN SMALL LETTER H
1057     0x0069, // #LATIN SMALL LETTER I
1058     0x006a, // #LATIN SMALL LETTER J
1059     0x006b, // #LATIN SMALL LETTER K
1060     0x006c, // #LATIN SMALL LETTER L
1061     0x006d, // #LATIN SMALL LETTER M
1062     0x006e, // #LATIN SMALL LETTER N
1063     0x006f, // #LATIN SMALL LETTER O
1064     0x0070, // #LATIN SMALL LETTER P
1065     0x0071, // #LATIN SMALL LETTER Q
1066     0x0072, // #LATIN SMALL LETTER R
1067     0x0073, // #LATIN SMALL LETTER S
1068     0x0074, // #LATIN SMALL LETTER T
1069     0x0075, // #LATIN SMALL LETTER U
1070     0x0076, // #LATIN SMALL LETTER V
1071     0x0077, // #LATIN SMALL LETTER W
1072     0x0078, // #LATIN SMALL LETTER X
1073     0x0079, // #LATIN SMALL LETTER Y
1074     0x007a, // #LATIN SMALL LETTER Z
1075     0x007b, // #LEFT CURLY BRACKET
1076     0x007c, // #VERTICAL LINE
1077     0x007d, // #RIGHT CURLY BRACKET
1078     0x007e, // #TILDE
1079     0x007f, // #DELETE
1080     0x00c7, // #LATIN CAPITAL LETTER C WITH CEDILLA
1081     0x00fc, // #LATIN SMALL LETTER U WITH DIAERESIS
1082     0x00e9, // #LATIN SMALL LETTER E WITH ACUTE
1083     0x00e2, // #LATIN SMALL LETTER A WITH CIRCUMFLEX
1084     0x00e4, // #LATIN SMALL LETTER A WITH DIAERESIS
1085     0x00e0, // #LATIN SMALL LETTER A WITH GRAVE
1086     0x00e5, // #LATIN SMALL LETTER A WITH RING ABOVE
1087     0x00e7, // #LATIN SMALL LETTER C WITH CEDILLA
1088     0x00ea, // #LATIN SMALL LETTER E WITH CIRCUMFLEX
1089     0x00eb, // #LATIN SMALL LETTER E WITH DIAERESIS
1090     0x00e8, // #LATIN SMALL LETTER E WITH GRAVE
1091     0x00ef, // #LATIN SMALL LETTER I WITH DIAERESIS
1092     0x00ee, // #LATIN SMALL LETTER I WITH CIRCUMFLEX
1093     0x00ec, // #LATIN SMALL LETTER I WITH GRAVE
1094     0x00c4, // #LATIN CAPITAL LETTER A WITH DIAERESIS
1095     0x00c5, // #LATIN CAPITAL LETTER A WITH RING ABOVE
1096     0x00c9, // #LATIN CAPITAL LETTER E WITH ACUTE
1097     0x00e6, // #LATIN SMALL LIGATURE AE
1098     0x00c6, // #LATIN CAPITAL LIGATURE AE
1099     0x00f4, // #LATIN SMALL LETTER O WITH CIRCUMFLEX
1100     0x00f6, // #LATIN SMALL LETTER O WITH DIAERESIS
1101     0x00f2, // #LATIN SMALL LETTER O WITH GRAVE
1102     0x00fb, // #LATIN SMALL LETTER U WITH CIRCUMFLEX
1103     0x00f9, // #LATIN SMALL LETTER U WITH GRAVE
1104     0x00ff, // #LATIN SMALL LETTER Y WITH DIAERESIS
1105     0x00d6, // #LATIN CAPITAL LETTER O WITH DIAERESIS
1106     0x00dc, // #LATIN CAPITAL LETTER U WITH DIAERESIS
1107     0x00a2, // #CENT SIGN
1108     0x00a3, // #POUND SIGN
1109     0x00a5, // #YEN SIGN
1110     0x20a7, // #PESETA SIGN
1111     0x0192, // #LATIN SMALL LETTER F WITH HOOK
1112     0x00e1, // #LATIN SMALL LETTER A WITH ACUTE
1113     0x00ed, // #LATIN SMALL LETTER I WITH ACUTE
1114     0x00f3, // #LATIN SMALL LETTER O WITH ACUTE
1115     0x00fa, // #LATIN SMALL LETTER U WITH ACUTE
1116     0x00f1, // #LATIN SMALL LETTER N WITH TILDE
1117     0x00d1, // #LATIN CAPITAL LETTER N WITH TILDE
1118     0x00aa, // #FEMININE ORDINAL INDICATOR
1119     0x00ba, // #MASCULINE ORDINAL INDICATOR
1120     0x00bf, // #INVERTED QUESTION MARK
1121     0x2310, // #REVERSED NOT SIGN
1122     0x00ac, // #NOT SIGN
1123     0x00bd, // #VULGAR FRACTION ONE HALF
1124     0x00bc, // #VULGAR FRACTION ONE QUARTER
1125     0x00a1, // #INVERTED EXCLAMATION MARK
1126     0x00ab, // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
1127     0x00bb, // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
1128     0x2591, // #LIGHT SHADE
1129     0x2592, // #MEDIUM SHADE
1130     0x2593, // #DARK SHADE
1131     0x2502, // #BOX DRAWINGS LIGHT VERTICAL
1132     0x2524, // #BOX DRAWINGS LIGHT VERTICAL AND LEFT
1133     0x2561, // #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
1134     0x2562, // #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
1135     0x2556, // #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
1136     0x2555, // #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
1137     0x2563, // #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
1138     0x2551, // #BOX DRAWINGS DOUBLE VERTICAL
1139     0x2557, // #BOX DRAWINGS DOUBLE DOWN AND LEFT
1140     0x255d, // #BOX DRAWINGS DOUBLE UP AND LEFT
1141     0x255c, // #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
1142     0x255b, // #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
1143     0x2510, // #BOX DRAWINGS LIGHT DOWN AND LEFT
1144     0x2514, // #BOX DRAWINGS LIGHT UP AND RIGHT
1145     0x2534, // #BOX DRAWINGS LIGHT UP AND HORIZONTAL
1146     0x252c, // #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
1147     0x251c, // #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1148     0x2500, // #BOX DRAWINGS LIGHT HORIZONTAL
1149     0x253c, // #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1150     0x255e, // #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
1151     0x255f, // #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
1152     0x255a, // #BOX DRAWINGS DOUBLE UP AND RIGHT
1153     0x2554, // #BOX DRAWINGS DOUBLE DOWN AND RIGHT
1154     0x2569, // #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
1155     0x2566, // #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
1156     0x2560, // #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
1157     0x2550, // #BOX DRAWINGS DOUBLE HORIZONTAL
1158     0x256c, // #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
1159     0x2567, // #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
1160     0x2568, // #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
1161     0x2564, // #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
1162     0x2565, // #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
1163     0x2559, // #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
1164     0x2558, // #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
1165     0x2552, // #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
1166     0x2553, // #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
1167     0x256b, // #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
1168     0x256a, // #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
1169     0x2518, // #BOX DRAWINGS LIGHT UP AND LEFT
1170     0x250c, // #BOX DRAWINGS LIGHT DOWN AND RIGHT
1171     0x2588, // #FULL BLOCK
1172     0x2584, // #LOWER HALF BLOCK
1173     0x258c, // #LEFT HALF BLOCK
1174     0x2590, // #RIGHT HALF BLOCK
1175     0x2580, // #UPPER HALF BLOCK
1176     0x03b1, // #GREEK SMALL LETTER ALPHA
1177     0x00df, // #LATIN SMALL LETTER SHARP S
1178     0x0393, // #GREEK CAPITAL LETTER GAMMA
1179     0x03c0, // #GREEK SMALL LETTER PI
1180     0x03a3, // #GREEK CAPITAL LETTER SIGMA
1181     0x03c3, // #GREEK SMALL LETTER SIGMA
1182     0x00b5, // #MICRO SIGN
1183     0x03c4, // #GREEK SMALL LETTER TAU
1184     0x03a6, // #GREEK CAPITAL LETTER PHI
1185     0x0398, // #GREEK CAPITAL LETTER THETA
1186     0x03a9, // #GREEK CAPITAL LETTER OMEGA
1187     0x03b4, // #GREEK SMALL LETTER DELTA
1188     0x221e, // #INFINITY
1189     0x03c6, // #GREEK SMALL LETTER PHI
1190     0x03b5, // #GREEK SMALL LETTER EPSILON
1191     0x2229, // #INTERSECTION
1192     0x2261, // #IDENTICAL TO
1193     0x00b1, // #PLUS-MINUS SIGN
1194     0x2265, // #GREATER-THAN OR EQUAL TO
1195     0x2264, // #LESS-THAN OR EQUAL TO
1196     0x2320, // #TOP HALF INTEGRAL
1197     0x2321, // #BOTTOM HALF INTEGRAL
1198     0x00f7, // #DIVISION SIGN
1199     0x2248, // #ALMOST EQUAL TO
1200     0x00b0, // #DEGREE SIGN
1201     0x2219, // #BULLET OPERATOR
1202     0x00b7, // #MIDDLE DOT
1203     0x221a, // #SQUARE ROOT
1204     0x207f, // #SUPERSCRIPT LATIN SMALL LETTER N
1205     0x00b2, // #SUPERSCRIPT TWO
1206     0x25a0, // #BLACK SQUARE
1207     0x00a0, // #NO-BREAK SPACE
1208   };
1209 
1210   public char map_cp850_unicode(char x) {
1211     if (x >= 0x100)
1212       return x;
1213     return unimap[x];
1214   }
1215 
1216   private void _SetCursor(int row, int col) {
1217     int maxr = height;
1218     int tm = getTopMargin();
1219 
1220     R = (row < 0)?0:row;
1221     C = (col < 0)?0:col;
1222 
1223     if (!moveoutsidemargins) {
1224       R += tm;
1225       maxr = getBottomMargin();
1226     }
1227     if (R > maxr) R = maxr;
1228   }
1229 
1230   private void putChar(char c, boolean doshowcursor) {
1231     int rows = height; //statusline
1232     int columns = width;
1233     int tm = getTopMargin();
1234     int bm = getBottomMargin();
1235     // byte msg[];
1236     boolean mapped = false;
1237 
1238     markLine(R, 1);
1239     if (c > 255) {
1240       //return;
1241     }
1242 
1243 
1244     switch (term_state) {
1245       case TSTATE_DATA:
1246         /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset.
1247          * probably... but some BBS do anyway...
1248          */
1249         if (!useibmcharset) {
1250           boolean doneflag = true;
1251           switch (c) {
1252             case OSC:
1253               osc = "";
1254               term_state = TSTATE_OSC;
1255               break;
1256             case RI:
1257               if (R > tm)
1258                 R--;
1259               else
1260                 insertLine(R, 1, SCROLL_DOWN);
1261               break;
1262             case IND:
1263               if (R == bm || R == rows - 1)
1264                 insertLine(R, 1, SCROLL_UP);
1265               else
1266                 R++;
1267               break;
1268             case NEL:
1269               if (R == bm || R == rows - 1)
1270                 insertLine(R, 1, SCROLL_UP);
1271               else
1272                 R++;
1273               C = 0;
1274               break;
1275             case HTS:
1276               Tabs[C] = 1;
1277               break;
1278             case DCS:
1279               dcs = "";
1280               term_state = TSTATE_DCS;
1281               break;
1282             default:
1283               doneflag = false;
1284               break;
1285           }
1286           if (doneflag) break;
1287         }
1288         switch (c) {
1289           case SS3:
1290             onegl = 3;
1291             break;
1292           case SS2:
1293             onegl = 2;
1294             break;
1295           case CSI: // should be in the 8bit section, but some BBS use this
1296             DCEvar = 0;
1297             DCEvars[0] = 0;
1298             DCEvars[1] = 0;
1299             DCEvars[2] = 0;
1300             DCEvars[3] = 0;
1301             term_state = TSTATE_CSI;
1302             break;
1303           case ESC:
1304             term_state = TSTATE_ESC;
1305             lastwaslf = 0;
1306             break;
1307           case 5: /* ENQ */
1308             write(answerBack, false);
1309             break;
1310           case 12:
1311             /* FormFeed, Home for the BBS world */
1312             deleteArea(0, 0, columns, rows, attributes);
1313             C = R = 0;
1314             break;
1315           case '\b': /* 8 */
1316             C--;
1317             if (C < 0)
1318               C = 0;
1319             lastwaslf = 0;
1320             break;
1321           case '\t':
1322             do {
1323               // Don't overwrite or insert! TABS are not destructive, but movement!
1324               C++;
1325             } while (C < columns && (Tabs[C] == 0));
1326             lastwaslf = 0;
1327             break;
1328           case '\r':
1329             C = 0;
1330             break;
1331           case '\n':
1332             if (!vms) {
1333               if (lastwaslf != 0 && lastwaslf != c)   //  Ray: I do not understand this logic.
1334                 break;
1335               lastwaslf = c;
1336               /*C = 0;*/
1337             }
1338             if (R == bm || R >= rows - 1)
1339               insertLine(R, 1, SCROLL_UP);
1340             else
1341               R++;
1342             break;
1343           case 7:
1344             beep();
1345             break;
1346           case '\016': /* SMACS , as */
1347             /* ^N, Shift out - Put G1 into GL */
1348             gl = 1;
1349             usedcharsets = true;
1350             break;
1351           case '\017': /* RMACS , ae */
1352             /* ^O, Shift in - Put G0 into GL */
1353             gl = 0;
1354             usedcharsets = true;
1355             break;
1356           default:
1357             {
1358               int thisgl = gl;
1359 
1360               if (onegl >= 0) {
1361                 thisgl = onegl;
1362                 onegl = -1;
1363               }
1364               lastwaslf = 0;
1365               if (c < 32) {
1366                 if (c != 0)
1367                 /*break; some BBS really want those characters, like hearst etc. */
1368                 if (c == 0) /* print 0 ... you bet */
1369                   break;
1370               }
1371               if (C >= columns) {
1372                 if (wraparound) {
1373                   if (R < rows - 1)
1374                     R++;
1375                   else
1376                     insertLine(R, 1, SCROLL_UP);
1377                   C = 0;
1378                 } else {
1379                   // cursor stays on last character.
1380                   C = columns - 1;
1381                 }
1382               }
1383 
1384               // Mapping if DEC Special is chosen charset
1385               if (usedcharsets) {
1386                 if (c >= '\u0020' && c <= '\u007f') {
1387                   switch (gx[thisgl]) {
1388                     case '0':
1389                       // Remap SCOANSI line drawing to VT100 line drawing chars
1390                       // for our SCO using customers.
1391                       if (terminalID.equals("scoansi") || terminalID.equals("ansi")) {
1392                         for (int i = 0; i < scoansi_acs.length(); i += 2) {
1393                           if (c == scoansi_acs.charAt(i)) {
1394                             c = scoansi_acs.charAt(i + 1);
1395                             break;
1396                           }
1397                         }
1398                       }
1399                       if (c >= '\u005f' && c <= '\u007e') {
1400                         c = DECSPECIAL[(short) c - 0x5f];
1401                         mapped = true;
1402                       }
1403                       break;
1404                     case '<': // 'user preferred' is currently 'ISO Latin-1 suppl
1405                       c = (char) (((int) c & 0x7f) | 0x80);
1406                       mapped = true;
1407                       break;
1408                     case 'A':
1409                     case 'B': // Latin-1 , ASCII -> fall through
1410                       mapped = true;
1411                       break;
1412                     default:
1413                       break;
1414                   }
1415                 }
1416                 if (!mapped && (c >= '\u0080' && c <= '\u00ff')) {
1417                   switch (gx[gr]) {
1418                     case '0':
1419                       if (c >= '\u00df' && c <= '\u00fe') {
1420                         c = DECSPECIAL[c - '\u00df'];
1421                         mapped = true;
1422                       }
1423                       break;
1424                     case '<':
1425                     case 'A':
1426                     case 'B':
1427                       mapped = true;
1428                       break;
1429                     default:
1430                       break;
1431                   }
1432                 }
1433               }
1434               if (!mapped && useibmcharset)
1435                 c = map_cp850_unicode(c);
1436 
1437               /*if(true || (statusmode == 0)) { */
1438               if (insertmode == 1) {
1439                 insertChar(C, R, c, attributes);
1440               } else {
1441                 putChar(C, R, c, attributes);
1442               }
1443               /*
1444                 } else {
1445                 if (insertmode==1) {
1446                 insertChar(C, rows, c, attributes);
1447                 } else {
1448                 putChar(C, rows, c, attributes);
1449                 }
1450                 }
1451               */
1452               C++;
1453               break;
1454             }
1455         } /* switch(c) */
1456         break;
1457       case TSTATE_OSC:
1458         if ((c < 0x20) && (c != ESC)) {// NP - No printing character
1459           handle_osc(osc);
1460           term_state = TSTATE_DATA;
1461           break;
1462         }
1463         //but check for vt102 ESC \
1464         if (c == '\\' && osc.charAt(osc.length() - 1) == ESC) {
1465           handle_osc(osc);
1466           term_state = TSTATE_DATA;
1467           break;
1468         }
1469         osc = osc + c;
1470         break;
1471       case TSTATE_ESCSPACE:
1472         term_state = TSTATE_DATA;
1473         switch (c) {
1474           case 'F': /* S7C1T, Disable output of 8-bit controls, use 7-bit */
1475             output8bit = false;
1476             break;
1477           case 'G': /* S8C1T, Enable output of 8-bit control codes*/
1478             output8bit = true;
1479             break;
1480           default:
1481         }
1482         break;
1483       case TSTATE_ESC:
1484         term_state = TSTATE_DATA;
1485         switch (c) {
1486           case ' ':
1487             term_state = TSTATE_ESCSPACE;
1488             break;
1489           case '#':
1490             term_state = TSTATE_ESCSQUARE;
1491             break;
1492           case 'c':
1493             /* Hard terminal reset */
1494             /* reset character sets */
1495             gx[0] = 'B';
1496             gx[1] = '0';
1497             gx[2] = 'B';
1498             gx[3] = 'B';
1499             gl = 0;  // default GL to G0
1500             gr = 1;  // default GR to G1
1501             /* reset tabs */
1502             int nw = width;
1503             if (nw < 132) nw = 132;
1504             Tabs = new byte[nw];
1505             for (int i = 0; i < nw; i += 8) {
1506               Tabs[i] = 1;
1507             }
1508             /*FIXME:*/
1509             break;
1510           case '[':
1511             DCEvar = 0;
1512             DCEvars[0] = 0;
1513             DCEvars[1] = 0;
1514             DCEvars[2] = 0;
1515             DCEvars[3] = 0;
1516             term_state = TSTATE_CSI;
1517             break;
1518           case ']':
1519             osc = "";
1520             term_state = TSTATE_OSC;
1521             break;
1522           case 'P':
1523             dcs = "";
1524             term_state = TSTATE_DCS;
1525             break;
1526           case 'A': /* CUU */
1527             R--;
1528             if (R < 0) R = 0;
1529             break;
1530           case 'B': /* CUD */
1531             R++;
1532             if (R > rows - 1) R = rows - 1;
1533             break;
1534           case 'C':
1535             C++;
1536             if (C >= columns) C = columns - 1;
1537             break;
1538           case 'I': // RI
1539             insertLine(R, 1, SCROLL_DOWN);
1540             break;
1541           case 'E': /* NEL */
1542             if (R == bm || R == rows - 1)
1543               insertLine(R, 1, SCROLL_UP);
1544             else
1545               R++;
1546             C = 0;
1547             break;
1548           case 'D': /* IND */
1549             if (R == bm || R == rows - 1)
1550               insertLine(R, 1, SCROLL_UP);
1551             else
1552               R++;
1553             break;
1554           case 'J': /* erase to end of screen */
1555             if (R < rows - 1)
1556               deleteArea(0, R + 1, columns, rows - R - 1, attributes);
1557             if (C < columns - 1)
1558               deleteArea(C, R, columns - C, 1, attributes);
1559             break;
1560           case 'K':
1561             if (C < columns - 1)
1562               deleteArea(C, R, columns - C, 1, attributes);
1563             break;
1564           case 'M': // RI
1565             if (R > bm) // outside scrolling region
1566               break;
1567             if (R > tm) { // just go up 1 line.
1568               R--;
1569             } else { // scroll down
1570               insertLine(R, 1, SCROLL_DOWN);
1571             }
1572             /* else do nothing ; */
1573             break;
1574           case 'H':
1575             /* right border probably ...*/
1576             if (C >= columns)
1577               C = columns - 1;
1578             Tabs[C] = 1;
1579             break;
1580           case 'N': // SS2
1581             onegl = 2;
1582             break;
1583           case 'O': // SS3
1584             onegl = 3;
1585             break;
1586           case '=':
1587             /*application keypad*/
1588             keypadmode = true;
1589             break;
1590           case '<': /* vt52 mode off */
1591             vt52mode = false;
1592             break;
1593           case '>': /*normal keypad*/
1594             keypadmode = false;
1595             break;
1596           case '7': /*save cursor, attributes, margins */
1597             Sc = C;
1598             Sr = R;
1599             Sgl = gl;
1600             Sgr = gr;
1601             Sa = attributes;
1602             Sgx = new char[4];
1603             for (int i = 0; i < 4; i++) Sgx[i] = gx[i];
1604             Stm = getTopMargin();
1605             Sbm = getBottomMargin();
1606             break;
1607           case '8': /*restore cursor, attributes, margins */
1608             C = Sc;
1609             R = Sr;
1610             gl = Sgl;
1611             gr = Sgr;
1612             for (int i = 0; i < 4; i++) gx[i] = Sgx[i];
1613             setTopMargin(Stm);
1614             setBottomMargin(Sbm);
1615             attributes = Sa;
1616             break;
1617           case '(': /* Designate G0 Character set (ISO 2022) */
1618             term_state = TSTATE_SETG0;
1619             usedcharsets = true;
1620             break;
1621           case ')': /* Designate G1 character set (ISO 2022) */
1622             term_state = TSTATE_SETG1;
1623             usedcharsets = true;
1624             break;
1625           case '*': /* Designate G2 Character set (ISO 2022) */
1626             term_state = TSTATE_SETG2;
1627             usedcharsets = true;
1628             break;
1629           case '+': /* Designate G3 Character set (ISO 2022) */
1630             term_state = TSTATE_SETG3;
1631             usedcharsets = true;
1632             break;
1633           case '~': /* Locking Shift 1, right */
1634             gr = 1;
1635             usedcharsets = true;
1636             break;
1637           case 'n': /* Locking Shift 2 */
1638             gl = 2;
1639             usedcharsets = true;
1640             break;
1641           case '}': /* Locking Shift 2, right */
1642             gr = 2;
1643             usedcharsets = true;
1644             break;
1645           case 'o': /* Locking Shift 3 */
1646             gl = 3;
1647             usedcharsets = true;
1648             break;
1649           case '|': /* Locking Shift 3, right */
1650             gr = 3;
1651             usedcharsets = true;
1652             break;
1653           case 'Y': /* vt52 cursor address mode , next chars are x,y */
1654             term_state = TSTATE_VT52Y;
1655             break;
1656           default:
1657             break;
1658         }
1659         break;
1660       case TSTATE_VT52X:
1661         C = c - 37;
1662         term_state = TSTATE_VT52Y;
1663         break;
1664       case TSTATE_VT52Y:
1665         R = c - 37;
1666         term_state = TSTATE_DATA;
1667         break;
1668       case TSTATE_SETG0:
1669         if (!(c != '0' && c != 'A' && c != 'B' && c != '<'))
1670           gx[0] = c;
1671         term_state = TSTATE_DATA;
1672         break;
1673       case TSTATE_SETG1:
1674         if(!(c != '0' && c != 'A' && c != 'B' && c != '<')) {
1675           gx[1] = c;
1676         }
1677         term_state = TSTATE_DATA;
1678         break;
1679       case TSTATE_SETG2:
1680         if(! (c != '0' && c != 'A' && c != 'B' && c != '<'))
1681           gx[2] = c;
1682         term_state = TSTATE_DATA;
1683         break;
1684       case TSTATE_SETG3:
1685         if(! (c != '0' && c != 'A' && c != 'B' && c != '<'))
1686           gx[3] = c;
1687         term_state = TSTATE_DATA;
1688         break;
1689       case TSTATE_ESCSQUARE:
1690         switch (c) {
1691           case '8':
1692             for (int i = 0; i < columns; i++)
1693               for (int j = 0; j < rows; j++)
1694                 putChar(i, j, 'E', 0);
1695             break;
1696           default:
1697             break;
1698         }
1699         term_state = TSTATE_DATA;
1700         break;
1701       case TSTATE_DCS:
1702         if (c == '\\' && dcs.charAt(dcs.length() - 1) == ESC) {
1703           handle_dcs(dcs);
1704           term_state = TSTATE_DATA;
1705           break;
1706         }
1707         dcs = dcs + c;
1708         break;
1709 
1710       case TSTATE_DCEQ:
1711         term_state = TSTATE_DATA;
1712         switch (c) {
1713           case '0':
1714           case '1':
1715           case '2':
1716           case '3':
1717           case '4':
1718           case '5':
1719           case '6':
1720           case '7':
1721           case '8':
1722           case '9':
1723             DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + ((int) c) - 48;
1724             term_state = TSTATE_DCEQ;
1725             break;
1726           case ';':
1727             DCEvar++;
1728             DCEvars[DCEvar] = 0;
1729             term_state = TSTATE_DCEQ;
1730             break;
1731           case 's': // XTERM_SAVE missing!
1732             break;
1733           case 'r': // XTERM_RESTORE
1734             /* DEC Mode reset */
1735             for (int i = 0; i <= DCEvar; i++) {
1736               switch (DCEvars[i]) {
1737                 case 3: /* 80 columns*/
1738                   setScreenSize(80, height);
1739                   break;
1740                 case 4: /* scrolling mode, smooth */
1741                   break;
1742                 case 5: /* light background */
1743                   break;
1744                 case 6: /* DECOM (Origin Mode) move inside margins. */
1745                   moveoutsidemargins = true;
1746                   break;
1747                 case 7: /* DECAWM: Autowrap Mode */
1748                   wraparound = false;
1749                   break;
1750                 case 12:/* local echo off */
1751                   break;
1752                 case 9:     /* X10 mouse */
1753                 case 1000:  /* xterm style mouse report on */
1754                 case 1001:
1755                 case 1002:
1756                 case 1003:
1757                   mouserpt = DCEvars[i];
1758                   break;
1759                 default:
1760               }
1761             }
1762             break;
1763           case 'h': // DECSET
1764             /* DEC Mode set */
1765             for (int i = 0; i <= DCEvar; i++) {
1766               switch (DCEvars[i]) {
1767                 case 1:  /* Application cursor keys */
1768                   KeyUp[0] = "\u001bOA";
1769                   KeyDown[0] = "\u001bOB";
1770                   KeyRight[0] = "\u001bOC";
1771                   KeyLeft[0] = "\u001bOD";
1772                   break;
1773                 case 2: /* DECANM */
1774                   vt52mode = false;
1775                   break;
1776                 case 3: /* 132 columns*/
1777                   setScreenSize(132, height);
1778                   break;
1779                 case 6: /* DECOM: move inside margins. */
1780                   moveoutsidemargins = false;
1781                   break;
1782                 case 7: /* DECAWM: Autowrap Mode */
1783                   wraparound = true;
1784                   break;
1785                 case 25: /* turn cursor on */
1786                   showCursor(true);
1787                   redraw();
1788                   break;
1789                 case 9:     /* X10 mouse */
1790                 case 1000:  /* xterm style mouse report on */
1791                 case 1001:
1792                 case 1002:
1793                 case 1003:
1794                   mouserpt = DCEvars[i];
1795                   break;
1796 
1797                   /* unimplemented stuff, fall through */
1798                   /* 4  - scrolling mode, smooth */
1799                   /* 5  - light background */
1800                   /* 12 - local echo off */
1801                   /* 18 - DECPFF - Printer Form Feed Mode -> On */
1802                   /* 19 - DECPEX - Printer Extent Mode -> Screen */
1803                 default:
1804                   break;
1805               }
1806             }
1807             break;
1808           case 'i': // DEC Printer Control, autoprint, echo screenchars to printer
1809             // This is different to CSI i!
1810             // Also: "Autoprint prints a final display line only when the
1811             // cursor is moved off the line by an autowrap or LF, FF, or
1812             // VT (otherwise do not print the line)."
1813             switch (DCEvars[0]) {
1814               case 1:
1815                 break;
1816               case 4:
1817                 break;
1818               case 5:
1819                 break;
1820             }
1821             break;
1822           case 'l': //DECRST
1823             /* DEC Mode reset */
1824             for (int i = 0; i <= DCEvar; i++) {
1825               switch (DCEvars[i]) {
1826                 case 1:  /* Application cursor keys */
1827                   KeyUp[0] = "\u001b[A";
1828                   KeyDown[0] = "\u001b[B";
1829                   KeyRight[0] = "\u001b[C";
1830                   KeyLeft[0] = "\u001b[D";
1831                   break;
1832                 case 2: /* DECANM */
1833                   vt52mode = true;
1834                   break;
1835                 case 3: /* 80 columns*/
1836                   setScreenSize(80, height);
1837                   break;
1838                 case 6: /* DECOM: move outside margins. */
1839                   moveoutsidemargins = true;
1840                   break;
1841                 case 7: /* DECAWM: Autowrap Mode OFF */
1842                   wraparound = false;
1843                   break;
1844                 case 25: /* turn cursor off */
1845                   showCursor(false);
1846                   redraw();
1847                   break;
1848                   /* Unimplemented stuff: */
1849                   /* 4  - scrolling mode, jump */
1850                   /* 5  - dark background */
1851                   /* 7  - DECAWM - no wrap around mode */
1852                   /* 12 - local echo on */
1853                   /* 18 - DECPFF - Printer Form Feed Mode -> Off*/
1854                   /* 19 - DECPEX - Printer Extent Mode -> Scrolling Region */
1855                 case 9:     /* X10 mouse */
1856                 case 1000:  /* xterm style mouse report OFF */
1857                 case 1001:
1858                 case 1002:
1859                 case 1003:
1860                   mouserpt = 0;
1861                   break;
1862                 default:
1863                   break;
1864               }
1865             }
1866             break;
1867           case 'n':
1868             switch (DCEvars[0]) {
1869               case 15:
1870                 /* printer? no printer. */
1871                 write(((char) ESC) + "[?13n", false);
1872                 break;
1873               default:
1874                 break;
1875             }
1876             break;
1877           default:
1878             break;
1879         }
1880         break;
1881       case TSTATE_CSI_EX:
1882         term_state = TSTATE_DATA;
1883         switch (c) {
1884           case ESC:
1885             term_state = TSTATE_ESC;
1886             break;
1887           default:
1888             break;
1889         }
1890         break;
1891       case TSTATE_CSI_TICKS:
1892         term_state = TSTATE_DATA;
1893         switch (c) {
1894           case 'p':
1895             if (DCEvars[0] == 61) {
1896               output8bit = false;
1897               break;
1898             }
1899             if (DCEvars[1] == 1) {
1900               output8bit = false;
1901             } else {
1902               output8bit = true; /* 0 or 2 */
1903             }
1904             break;
1905           default:
1906             break;
1907         }
1908         break;
1909       case TSTATE_CSI_DOLLAR:
1910         term_state = TSTATE_DATA;
1911         switch (c) {
1912           case '}':
1913             statusmode = DCEvars[0];
1914             break;
1915           case '~':
1916             break;
1917           default:
1918             break;
1919         }
1920         break;
1921       case TSTATE_CSI:
1922         term_state = TSTATE_DATA;
1923         switch (c) {
1924           case '"':
1925             term_state = TSTATE_CSI_TICKS;
1926             break;
1927           case '$':
1928             term_state = TSTATE_CSI_DOLLAR;
1929             break;
1930           case '!':
1931             term_state = TSTATE_CSI_EX;
1932             break;
1933           case '?':
1934             DCEvar = 0;
1935             DCEvars[0] = 0;
1936             term_state = TSTATE_DCEQ;
1937             break;
1938           case '0':
1939           case '1':
1940           case '2':
1941           case '3':
1942           case '4':
1943           case '5':
1944           case '6':
1945           case '7':
1946           case '8':
1947           case '9':
1948             DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + ((int) c) - 48;
1949             term_state = TSTATE_CSI;
1950             break;
1951           case ';':
1952             DCEvar++;
1953             DCEvars[DCEvar] = 0;
1954             term_state = TSTATE_CSI;
1955             break;
1956           case 'c':/* send primary device attributes */
1957             /* send (ESC[?61c) */
1958 
1959             String subcode = "";
1960             if (terminalID.equals("vt320")) subcode = "63;";
1961             if (terminalID.equals("vt220")) subcode = "62;";
1962             if (terminalID.equals("vt100")) subcode = "61;";
1963             write(((char) ESC) + "[?" + subcode + "1;2c", false);
1964             break;
1965           case 'q':
1966             break;
1967           case 'g':
1968             /* used for tabsets */
1969             switch (DCEvars[0]) {
1970               case 3:/* clear them */
1971                 Tabs = new byte[width];
1972                 break;
1973               case 0:
1974                 Tabs[C] = 0;
1975                 break;
1976             }
1977             break;
1978           case 'h':
1979             switch (DCEvars[0]) {
1980               case 4:
1981                 insertmode = 1;
1982                 break;
1983               case 20:
1984                 sendcrlf = true;
1985                 break;
1986               default:
1987                 break;
1988             }
1989             break;
1990           case 'i': // Printer Controller mode.
1991             // "Transparent printing sends all output, except the CSI 4 i
1992             //  termination string, to the printer and not the screen,
1993             //  uses an 8-bit channel if no parity so NUL and DEL will be
1994             //  seen by the printer and by the termination recognizer code,
1995             //  and all translation and character set selections are
1996             //  bypassed."
1997             switch (DCEvars[0]) {
1998               case 0:
1999                 break;
2000               case 4:
2001                 break;
2002               case 5:
2003                 break;
2004               default:
2005             }
2006             break;
2007           case 'l':
2008             switch (DCEvars[0]) {
2009               case 4:
2010                 insertmode = 0;
2011                 break;
2012               case 20:
2013                 sendcrlf = false;
2014                 break;
2015               default:
2016                 break;
2017             }
2018             break;
2019           case 'A': // CUU
2020             {
2021               int limit;
2022               /* FIXME: xterm only cares about 0 and topmargin */
2023               if (R > bm)
2024                 limit = bm + 1;
2025               else if (R >= tm) {
2026                 limit = tm;
2027               } else
2028                 limit = 0;
2029               if (DCEvars[0] == 0)
2030                 R--;
2031               else
2032                 R -= DCEvars[0];
2033               if (R < limit)
2034                 R = limit;
2035               break;
2036             }
2037           case 'B': // CUD
2038             /* cursor down n (1) times */
2039             {
2040               int limit;
2041               if (R < tm)
2042                 limit = tm - 1;
2043               else if (R <= bm) {
2044                 limit = bm;
2045               } else
2046                 limit = rows - 1;
2047               if (DCEvars[0] == 0)
2048                 R++;
2049               else
2050                 R += DCEvars[0];
2051               if (R > limit)
2052                 R = limit;
2053               break;
2054             }
2055           case 'C':
2056             if (DCEvars[0] == 0)
2057               C++;
2058             else
2059               C += DCEvars[0];
2060             if (C > columns - 1)
2061               C = columns - 1;
2062             break;
2063           case 'd': // CVA
2064             R = DCEvars[0];
2065             break;
2066           case 'D':
2067             if (DCEvars[0] == 0)
2068               C--;
2069             else
2070               C -= DCEvars[0];
2071             if (C < 0) C = 0;
2072             break;
2073           case 'r': // DECSTBM
2074             if (DCEvar > 0)   //  Ray:  Any argument is optional
2075             {
2076               R = DCEvars[1] - 1;
2077               if (R < 0)
2078                 R = rows - 1;
2079               else if (R >= rows) {
2080                 R = rows - 1;
2081               }
2082             } else
2083               R = rows - 1;
2084             setBottomMargin(R);
2085             if (R >= DCEvars[0]) {
2086               R = DCEvars[0] - 1;
2087               if (R < 0)
2088                 R = 0;
2089             }
2090             setTopMargin(R);
2091             _SetCursor(0, 0);
2092             break;
2093           case 'G':  /* CUP  / cursor absolute column */
2094             C = DCEvars[0];
2095             break;
2096           case 'H':  /* CUP  / cursor position */
2097             /* gets 2 arguments */
2098             _SetCursor(DCEvars[0] - 1, DCEvars[1] - 1);
2099             break;
2100           case 'f':  /* move cursor 2 */
2101             /* gets 2 arguments */
2102             R = DCEvars[0] - 1;
2103             C = DCEvars[1] - 1;
2104             if (C < 0) C = 0;
2105             if (R < 0) R = 0;
2106             break;
2107           case 'S': /* ind aka 'scroll forward' */
2108             if (DCEvars[0] == 0)
2109               insertLine(rows - 1, SCROLL_UP);
2110             else
2111               insertLine(rows - 1, DCEvars[0], SCROLL_UP);
2112             break;
2113           case 'L':
2114             /* insert n lines */
2115             if (DCEvars[0] == 0)
2116               insertLine(R, SCROLL_DOWN);
2117             else
2118               insertLine(R, DCEvars[0], SCROLL_DOWN);
2119             break;
2120           case 'T': /* 'ri' aka scroll backward */
2121             if (DCEvars[0] == 0)
2122               insertLine(0, SCROLL_DOWN);
2123             else
2124               insertLine(0, DCEvars[0], SCROLL_DOWN);
2125             break;
2126           case 'M':
2127             if (DCEvars[0] == 0)
2128               deleteLine(R);
2129             else
2130               for (int i = 0; i < DCEvars[0]; i++)
2131                 deleteLine(R);
2132             break;
2133           case 'K':
2134             /* clear in line */
2135             switch (DCEvars[0]) {
2136               case 6: /* 97801 uses ESC[6K for delete to end of line */
2137               case 0:/*clear to right*/
2138                 if (C < columns - 1)
2139                   deleteArea(C, R, columns - C, 1, attributes);
2140                 break;
2141               case 1:/*clear to the left, including this */
2142                 if (C > 0)
2143                   deleteArea(0, R, C + 1, 1, attributes);
2144                 break;
2145               case 2:/*clear whole line */
2146                 deleteArea(0, R, columns, 1, attributes);
2147                 break;
2148             }
2149             break;
2150           case 'J':
2151             /* clear below current line */
2152             switch (DCEvars[0]) {
2153               case 0:
2154                 if (R < rows - 1)
2155                   deleteArea(0, R + 1, columns, rows - R - 1, attributes);
2156                 if (C < columns - 1)
2157                   deleteArea(C, R, columns - C, 1, attributes);
2158                 break;
2159               case 1:
2160                 if (R > 0)
2161                   deleteArea(0, 0, columns, R, attributes);
2162                 if (C > 0)
2163                   deleteArea(0, R, C + 1, 1, attributes);// include up to and including current
2164                 break;
2165               case 2:
2166                 deleteArea(0, 0, columns, rows, attributes);
2167                 break;
2168             }
2169             break;
2170           case '@':
2171             for (int i = 0; i < DCEvars[0]; i++)
2172               insertChar(C, R, ' ', attributes);
2173             break;
2174           case 'X':
2175             {
2176               int toerase = DCEvars[0];
2177               if (toerase == 0)
2178                 toerase = 1;
2179               if (toerase + C > columns)
2180                 toerase = columns - C;
2181               deleteArea(C, R, toerase, 1, attributes);
2182               // does not change cursor position
2183               break;
2184             }
2185           case 'P':
2186             if (DCEvars[0] == 0) DCEvars[0] = 1;
2187             for (int i = 0; i < DCEvars[0]; i++)
2188               deleteChar(C, R);
2189             break;
2190           case 'n':
2191             switch (DCEvars[0]) {
2192               case 5: /* malfunction? No malfunction. */
2193                 writeSpecial(((char) ESC) + "[0n");
2194                 break;
2195               case 6:
2196                 // DO NOT offset R and C by 1! (checked against /usr/X11R6/bin/resize
2197                 // FIXME check again.
2198                 // FIXME: but vttest thinks different???
2199                 writeSpecial(((char) ESC) + "[" + R + ";" + C + "R");
2200                 break;
2201               default:
2202                 break;
2203             }
2204             break;
2205           case 's':  /* DECSC - save cursor */
2206             Sc = C;
2207             Sr = R;
2208             Sa = attributes;
2209             break;
2210           case 'u': /* DECRC - restore cursor */
2211             C = Sc;
2212             R = Sr;
2213             attributes = Sa;
2214             break;
2215           case 'm':  /* attributes as color, bold , blink,*/
2216             if (DCEvar == 0 && DCEvars[0] == 0)
2217               attributes = 0;
2218             for (int i = 0; i <= DCEvar; i++) {
2219               switch (DCEvars[i]) {
2220                 case 0:
2221                   if (DCEvar > 0) {
2222                     if (terminalID.equals("scoansi")) {
2223                       attributes &= COLOR; /* Keeps color. Strange but true. */
2224                     } else {
2225                       attributes = 0;
2226                     }
2227                   }
2228                   break;
2229                 case 1:
2230                   attributes |= BOLD;
2231                   attributes &= ~LOW;
2232                   break;
2233                 case 2:
2234                   /* SCO color hack mode */
2235                   if (terminalID.equals("scoansi") && ((DCEvar - i) >= 2)) {
2236                     int ncolor;
2237                     attributes &= ~(COLOR | BOLD);
2238 
2239                     ncolor = DCEvars[i + 1];
2240                     if ((ncolor & 8) == 8)
2241                       attributes |= BOLD;
2242                     ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2);
2243                     attributes |= ((ncolor) + 1) << 4;
2244                     ncolor = DCEvars[i + 2];
2245                     ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2);
2246                     attributes |= ((ncolor) + 1) << 8;
2247                     i += 2;
2248                   } else {
2249                     attributes |= LOW;
2250                   }
2251                   break;
2252                 case 4:
2253                   attributes |= UNDERLINE;
2254                   break;
2255                 case 7:
2256                   attributes |= INVERT;
2257                   break;
2258                 case 5: /* blink on */
2259                   break;
2260                   /* 10 - ANSI X3.64-1979, select primary font, don't display control
2261                    *      chars, don't set bit 8 on output */
2262                 case 10:
2263                   gl = 0;
2264                   usedcharsets = true;
2265                   break;
2266                   /* 11 - ANSI X3.64-1979, select second alt. font, display control
2267                    *      chars, set bit 8 on output */
2268                 case 11: /* SMACS , as */
2269                 case 12:
2270                   gl = 1;
2271                   usedcharsets = true;
2272                   break;
2273                 case 21: /* normal intensity */
2274                   attributes &= ~(LOW | BOLD);
2275                   break;
2276                 case 25: /* blinking off */
2277                   break;
2278                 case 27:
2279                   attributes &= ~INVERT;
2280                   break;
2281                 case 24:
2282                   attributes &= ~UNDERLINE;
2283                   break;
2284                 case 22:
2285                   attributes &= ~BOLD;
2286                   break;
2287                 case 30:
2288                 case 31:
2289                 case 32:
2290                 case 33:
2291                 case 34:
2292                 case 35:
2293                 case 36:
2294                 case 37:
2295                   attributes &= ~COLOR_FG;
2296                   attributes |= ((DCEvars[i] - 30) + 1) << 4;
2297                   break;
2298                 case 39:
2299                   attributes &= ~COLOR_FG;
2300                   break;
2301                 case 40:
2302                 case 41:
2303                 case 42:
2304                 case 43:
2305                 case 44:
2306                 case 45:
2307                 case 46:
2308                 case 47:
2309                   attributes &= ~COLOR_BG;
2310                   attributes |= ((DCEvars[i] - 40) + 1) << 8;
2311                   break;
2312                 case 49:
2313                   attributes &= ~COLOR_BG;
2314                   break;
2315 
2316                 default:
2317                   break;
2318               }
2319             }
2320             break;
2321           default:
2322             break;
2323         }
2324         break;
2325       default:
2326         term_state = TSTATE_DATA;
2327         break;
2328     }
2329     if (C > columns) C = columns;
2330     if (R > rows) R = rows;
2331     if (C < 0) C = 0;
2332     if (R < 0) R = 0;
2333     if (doshowcursor)
2334       setCursorPosition(C, R);
2335     markLine(R, 1);
2336   }
2337 
2338   /* hard reset the terminal */
2339   public void reset() {
2340     gx[0] = 'B';
2341     gx[1] = '0';
2342     gx[2] = 'B';
2343     gx[3] = 'B';
2344     gl = 0;  // default GL to G0
2345     gr = 1;  // default GR to G1
2346     /* reset tabs */
2347     int nw = width;
2348     if (nw < 132) nw = 132;
2349     Tabs = new byte[nw];
2350     for (int i = 0; i < nw; i += 8) {
2351       Tabs[i] = 1;
2352     }
2353     /*FIXME:*/
2354     term_state = TSTATE_DATA;
2355   }
2356 }
5776804 [rkeene@sledge /home/rkeene/archive/floydssh/telnet]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2004-03-03 06:40:58