added applet mode, terminal window
[fleet.git] / src / de / mud / telnet / display / vt320.java
1 package de.mud.telnet.display;
2 /* "In case you would like to use the packages as libraries please
3  *  apply the GNU Library General Public License as documented in the
4  *  file COPYING.LIB." (from Telnet/Documentation/index.html)
5  */
6 /*
7  * vt320 -- a DEC VT320 Terminal emulation
8  * --
9  * $Id: vt320.java,v 1.56 1998/03/07 23:47:03 marcus Exp $
10  *
11  * This file is part of "The Java Telnet Applet".
12  *
13  * This is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * "The Java Telnet Applet" is distributed in the hope that it will be
19  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this software; see the file COPYING.  If not, write to the
25  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26  * Boston, MA 02111-1307, USA.
27  */
28
29 import java.awt.Scrollbar;
30 import java.awt.Event;
31 import java.awt.Dimension;
32 import java.awt.BorderLayout;
33 import java.awt.FlowLayout;
34 import java.util.Vector;
35
36 import java.applet.Applet;
37
38 /**
39  * A DEC VT320 Terminal Emulation (includes VT100/220 and ANSI).
40  *
41  * The terminal emulation accesses the applet parameters to configure itself.
42  * The following parameters may be set. Default values are written in
43  * <I>italics</I> and other possible values are <B>bold</B>.
44  * <DL>
45  *  <DT><TT>&lt;PARAM NAME="Fx" VALUE="<I>functionkeytext</I>"&gt</TT>
46  *  <DD>Sets the string sent when the function key Fx (x between 1 und 20)
47  *      is pressed.
48  *  <DT><TT>&lt;PARAM NAME="VTcolumns" VALUE="<I>80</I>"&gt</TT>
49  *  <DD>Sets the columns of the terminal initially. If the parameter
50  *      VTresize is set to <B>screen</B> this may change, else it is fixed.
51  *  <DT><TT>&lt;PARAM NAME="VTrows" VALUE="<I>24</I>"&gt</TT>
52  *  <DD>Sets the rows of the terminal initially. If the parameter
53  *      value of VTresize <B>screen</B> this may change!
54  *  <DT><TT>&lt;PARAM NAME="VTfont" VALUE="<I>Courier</I>"&gt</TT>
55  *  <DD>Sets the font to be used for the terminal. It is recommended to
56  *      use <I>Courier</I> or at least a fixed width font.
57  *  <DT><TT>&lt;PARAM NAME="VTfontsize" VALUE="<I>14</I>"&gt</TT>
58  *  <DD>Sets the font size for the terminal. If the parameter
59  *      value of VTresize is set to <B>font</B> this may change!
60  *  <DT><TT>&lt;PARAM NAME="VTresize" VALUE="<I>font</I>"&gt</TT>
61  *  <DD>This parameter determines what the terminal should do if the window
62  *      is resized. The default setting <I><B>font</B></I> will result in
63  *      resizing the font until is matches the window best. Other possible
64  *      values are <B>none</B> or <B>screen</B>. <B>none</B> will let nothing
65  *      happen and <B>screen</B> will let the display try to change the
66  *      amount of rows and columns to match the window best.
67  *  <DT><TT>&lt;PARAM NAME="VTscrollbar" VALUE="<I>false</I>"&gt</TT>
68  *  <DD>Setting this parameter to <B>true</B> will add a scrollbar west to
69  *      the terminal. Other possible values include <B>left</B> to put the
70  *      scrollbar on the left side of the terminal and <B>right</B> to put it
71  *      explicitely to the right side.
72  *  <DT><TT>&lt;PARAM NAME="VTid" VALUE="<I>vt320</I>"&gt</TT>
73  *  <DD>This parameter will override the terminal id <I>vt320</I>. It may
74  *      be used to determine special terminal abilities of VT Terminals.
75  *  <DT><TT>&lt;PARAM NAME="VTbuffer" VALUE="<I>xx</I>"&gt</TT>
76  *  <DD>Initially this parameter is the same as the VTrows parameter. It
77  *      cannot be less than the amount of rows on the display. It determines
78  *      the available scrollback buffer.
79  *  <DT><TT>&lt;PARAM NAME="VTcharset" VALUE="<I>none</I>"&gt</TT>
80  *  <DD>Setting this parameter to <B>ibm</B> will enable mapping of ibm
81  *      characters (as used in PC BBS systems) to UNICODE characters. Note
82  *      that those special characters probably won't show on UNIX systems
83  *      due to lack in X11 UNICODE support.
84  *  <DT><TT>&lt;PARAM NAME="VTvms" VALUE="<I>false</I>"&gt</TT>
85  *  <DD>Setting this parameter to <B>true</B> will change the Backspace key
86  *      into a delete key, cause the numeric keypad keys to emit VT100
87  *      codes when Ctrl is pressed, and make other VMS-important keyboard
88  *      definitions.
89  *  <DT><TT>&lt;PARAM NAME="F<I>nr</I>" VALUE="<I>string</I>"&gt</TT>
90  *  <DD>Function keys from <I>F1</I> to <I>F20</I> are programmable. You can
91  *      install any possible string including special characters, such as
92  *      <TABLE BORDER>
93  *      <TR><TD><TT>\e</TT></TD><TD>Escape</TD>
94  *      <TR><TD><TT>\b</TT></TD><TD>Backspace</TD>
95  *      <TR><TD><TT>\n</TT></TD><TD>Newline</TD>
96  *      <TR><TD><TT>\r</TT></TD><TD>Return</TD>
97  *      </TABLE>
98  *  <DT><TT>&lt;PARAM NAME="CF<I>nr</I>" VALUE="<I>string</I>"&gt</TT>
99  *  <DD>Function keys (with the Control-key pressed) from <I>CF1</I> to <I>CF20</I> are programmable too.
100  *  <DT><TT>&lt;PARAM NAME="SF<I>nr</I>" VALUE="<I>string</I>"&gt</TT>
101  *  <DD>Function keys (with the Shift-key pressed) from <I>SF1</I> to <I>SF20</I> are programmable too.
102  *  <DT><TT>&lt;PARAM NAME="AF<I>nr</I>" VALUE="<I>string</I>"&gt</TT>
103  *  <DD>Function keys (with the Alt-key pressed) from <I>AF1</I> to <I>AF20</I> are programmable too.
104  * </DL>
105  * @version $Id: vt320.java,v 1.56 1998/03/07 23:47:03 marcus Exp $
106  * @author  Matthias L. Jugel, Marcus Mei?ner
107  */
108 public class vt320 extends Terminal implements TerminalHost
109 {
110   /**
111    * Return the version of the terminal emulation and its display.
112    */
113   public String toString() { return "$Id: vt320.java,v 1.56 1998/03/07 23:47:03 marcus Exp $ "+display.version; }
114
115   // the input handler takes the keyboard input from us.
116   private TerminalHost host = this;
117
118   // due to a bug with Windows we need a keypress cache
119   private int pressedKey = ' ';
120   private long pressedWhen = ' ';
121
122   // The character display
123   private CharDisplay display;
124   private static int debug = 0;
125   private String terminalID = "vt320";
126
127   // X - COLUMNS, Y - ROWS
128   int  R,C;
129   int  Sc,Sr,Sa;
130   int  attributes  = 0;
131   int  insertmode  = 0;
132   int  statusmode = 0;
133   int  vt52mode  = 0;
134   int  normalcursor  = 0;
135   boolean originmode = false;
136   boolean sendcrlf = true;
137
138   private boolean  useibmcharset = false;
139
140   private  static  int  lastwaslf = 0;
141   private static  int i;
142   private final static char ESC = 27;
143   private final static char IND = 132;
144   private final static char NEL = 133;
145   private final static char RI  = 141;
146   private final static char HTS = 136;
147   private final static char DCS = 144;
148   private final static char CSI = 155;
149   private final static char OSC = 157;
150   private final static int TSTATE_DATA  = 0;
151   private final static int TSTATE_ESC  = 1; /* ESC */
152   private final static int TSTATE_CSI  = 2; /* ESC [ */
153   private final static int TSTATE_DCS  = 3; /* ESC P */
154   private final static int TSTATE_DCEQ  = 4; /* ESC [? */
155   private final static int TSTATE_ESCSQUARE= 5; /* ESC # */
156   private final static int TSTATE_OSC= 6;       /* ESC ] */
157   private final static int TSTATE_SETG0= 7;     /* ESC (? */
158   private final static int TSTATE_SETG1= 8;     /* ESC )? */
159   private final static int TSTATE_SETG2= 9;     /* ESC *? */
160   private final static int TSTATE_SETG3= 10;    /* ESC +? */
161   private final static int TSTATE_CSI_DOLLAR  = 11; /* ESC [ Pn $ */
162
163   /* The graphics charsets
164    * B - default ASCII
165    * A - default UK
166    * 0 - DEC SPECIAL
167    * < - User defined
168    * ....
169    */
170   private static char gx[] = {
171   'B',      // g0
172   '0',      // g1
173   'A',      // g2
174   '<',      // g3
175   };
176   private static char gr = 1;  // default GR to G1
177   private static char gl = 0;  // default GL to G0
178
179   // array to store DEC Special -> Unicode mapping
180   //  Unicode   DEC  Unicode name    (DEC name)
181   private static char DECSPECIAL[] = {
182     '\u0040', //5f blank
183     '\u2666', //60 black diamond
184     '\u2592', //61 grey square
185     '\u2409', //62 Horizontal tab  (ht) pict. for control
186     '\u240c', //63 Form Feed       (ff) pict. for control
187     '\u240d', //64 Carriage Return (cr) pict. for control
188     '\u240a', //65 Line Feed       (lf) pict. for control
189     '\u00ba', //66 Masculine ordinal indicator
190     '\u00b1', //67 Plus or minus sign
191     '\u2424', //68 New Line        (nl) pict. for control
192     '\u240b', //69 Vertical Tab    (vt) pict. for control
193     '\u2518', //6a Forms light up   and left
194     '\u2510', //6b Forms light down and left
195     '\u250c', //6c Forms light down and right
196     '\u2514', //6d Forms light up   and right
197     '\u253c', //6e Forms light vertical and horizontal
198     '\u2594', //6f Upper 1/8 block                        (Scan 1)
199     '\u2580', //70 Upper 1/2 block                        (Scan 3)
200     '\u2500', //71 Forms light horizontal or ?em dash?    (Scan 5)
201     '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7)
202     '\u005f', //73 \u005f underscore  or \u2581 lower 1/8 (Scan 9)
203     '\u251c', //74 Forms light vertical and right
204     '\u2524', //75 Forms light vertical and left
205     '\u2534', //76 Forms light up   and horizontal
206     '\u252c', //77 Forms light down and horizontal
207     '\u2502', //78 vertical bar
208     '\u2264', //79 less than or equal
209     '\u2265', //7a greater than or equal
210     '\u00b6', //7b paragraph
211     '\u2260', //7c not equal
212     '\u00a3', //7d Pound Sign (british)
213     '\u00b7'  //7e Middle Dot
214   };
215
216   private final static int KEYUP  = Event.UP % 1000;
217   private final static int KEYDOWN  = Event.DOWN % 1000;
218   private final static int KEYLEFT  = Event.LEFT % 1000;
219   private final static int KEYRIGHT  = Event.RIGHT % 1000;
220   private final static int KEYF1  = Event.F1 % 1000;
221   private final static int KEYF2  = Event.F2 % 1000;
222   private final static int KEYF3  = Event.F3 % 1000;
223   private final static int KEYF4  = Event.F4 % 1000;
224   private final static int KEYF5  = Event.F5 % 1000;
225   private final static int KEYF6  = Event.F6 % 1000;
226   private final static int KEYF7  = Event.F7 % 1000;
227   private final static int KEYF8  = Event.F8 % 1000;
228   private final static int KEYF9  = Event.F9 % 1000;
229   private final static int KEYF10  = Event.F10 % 1000;
230   private final static int KEYF11  = Event.F11 % 1000;
231   private final static int KEYF12  = Event.F12 % 1000;
232   private final static int KEYPGDN   = Event.PGDN % 1000;
233   private final static int KEYPGUP   = Event.PGUP % 1000;
234
235   private final static int KEYHOME  = Event.HOME % 1000;
236   private final static int KEYEND  = Event.END % 1000;
237
238   public static final int KEYPRINT_SCREEN  = 20;
239   public static final int KEYSCROLL_LOCK    = 21;
240   public static final int KEYCAPS_LOCK    = 22;
241   public static final int KEYNUM_LOCK    = 23;
242   public static final int KEYPAUSE    = 24;
243   public static final int KEYINSERT    = 25;
244
245     /**
246      * The Insert key.
247      */
248     public static final int INSERT    = 1025;
249
250   /**
251    * Strings to send on function key presseic
252    */
253   private String FunctionKey[];
254   private String FunctionKeyShift[];
255   private String FunctionKeyCtrl[];
256   private String FunctionKeyAlt[];
257   private String KeyUp;
258   private String KeyDown;
259   private String KeyLeft;
260   private String KeyRight;
261   private String KeyBacktab;
262   private String KeyTab;
263
264   private String KP0;
265   private String KP1;
266   private String KP2;
267   private String KP3;
268   private String KP4;
269   private String KP5;
270   private String KP6;
271   private String KP7;
272   private String KP8;
273   private String KP9;
274   private String KPMinus;
275   private String KPComma;
276   private String KPPeriod;
277   private String KPEnter;
278   private String PF1;
279   private String PF2;
280   private String PF3;
281   private String PF4;
282   private String Help;
283   private String Do;
284   private String Find;
285   private String Insert;
286   private String Remove;
287   private String Select;
288   private String PrevScn;
289   private String NextScn;
290
291
292   private String osc,dcs;  /* to memorize OSC & DCS control sequence */
293
294   private int term_state = TSTATE_DATA;
295   private boolean vms = false;
296   private byte[]  Tabs;
297   private int[]  DCEvars = new int [10];
298   private  int  DCEvar;
299
300   /* operation system we run on, Scrollbar hack */
301   private String osn = System.getProperty("os.name");
302
303   public String[][] getParameterInfo() {
304     String pinfo[][] = {
305     {"VTcolumns",  "Integer",   "Columns of the terminal"},
306     {"VTrows",     "Integer",   "Rows of the terminal"},
307     {"VTfont",     "String",    "Terminal font (default is Courier)"},
308     {"VTfontsize", "Integer",   "Font size"},
309     {"VTbuffer",   "Integer",   "Scrollback buffer size"},
310     {"VTscrollbar","Boolean",   "Enable or disable scrollbar"},
311     {"VTresize",   "String",    "One of none, font, screen"},
312     {"VTid",       "String",    "Terminal id, standard is VT320"},
313     {"VTcharset",  "String",    "Charset used"},
314     {"VTvms",      "Boolean",   "Enable or disable VMS key mappings"},
315     {"F1 - F20",   "String",    "Programmable Function Keys"},
316     {"SF1 - SF20",   "String",    "Programmable Shift-ed Function Keys"},
317     {"CF1 - CF20",   "String",    "Programmable Control-ed Function Keys"},
318     {"AF1 - AF20",   "String",    "Programmable Alt-ed Function Keys"},
319     };
320     return pinfo;
321   }
322
323   static String unEscape(String tmp) {
324       int idx = 0, oldidx = 0;
325       String cmd;
326
327       cmd = "";
328       while((idx = tmp.indexOf('\\', oldidx)) >= 0 &&
329             ++idx <= tmp.length()) {
330         cmd += tmp.substring(oldidx, idx-1);
331         if(idx == tmp.length()) return cmd;
332         switch(tmp.charAt(idx)) {
333         case 'b': cmd += "\b"; break;
334         case 'e': cmd += "\u001b"; break;
335         case 'n': cmd += "\n"; break;
336         case 'r': cmd += "\r"; break;
337         case 't': cmd += "\t"; break;
338         case 'v': cmd += "\u000b"; break;
339         case 'a': cmd += "\u0012"; break;
340         default : cmd += tmp.substring(idx, ++idx);break;
341         }
342         oldidx = ++idx;
343       }
344       if(oldidx <= tmp.length()) cmd += tmp.substring(oldidx);
345       return cmd;
346   }
347
348   /**
349    * Initialize terminal.
350    * @param parent the applet parent where to get parameters from
351    * @see display.Terminal
352    */
353   public void addNotify() {
354     if(display == null) {
355       String width = "80", height = "24", resize ="screen";
356       String font = "monaco", fs = "14", bufs = "100";
357       String scrb = "false";
358       String vms = "false";
359       String ibmcset = "false";
360
361       Applet applet = getParent() instanceof Applet ? (Applet)getParent() : null;
362
363       if(applet != null) {
364         try {
365           host = (TerminalHost)applet;
366         } catch(ClassCastException e) {
367           System.err.println("vt320: "+applet+" cannot receive terminal input");
368           host = this;
369         }
370
371         width  = applet.getParameter("VTcolumns");
372         height = applet.getParameter("VTrows");
373         font   = applet.getParameter("VTfont");
374         fs     = applet.getParameter("VTfontsize");
375         bufs   = applet.getParameter("VTbuffer");
376         scrb   = applet.getParameter("VTscrollbar");
377         vms    = applet.getParameter("VTvms");
378         resize = applet.getParameter("VTresize");
379         resize = resize == null ? "font" : resize;
380         ibmcset = applet.getParameter("VTcharset");
381         if ((ibmcset!=null)&&(ibmcset.equals("ibm")))
382           useibmcharset=true;
383
384         if(applet.getParameter("VTid") != null)
385           terminalID = applet.getParameter("VTid");
386       }
387
388       display = new CharDisplay(
389           width==null?80:(new Integer(width)).intValue(),
390           (height==null?24:(new Integer(height)).intValue()),
391           font==null?"Courier":font,
392           fs==null?14:(new Integer(fs)).intValue()
393       );
394       display.setBottomMargin((height==null?
395                                24:
396                                (new Integer(height)).intValue()) - 1);
397       display.setBufferSize(bufs==null?100:(new Integer(bufs)).intValue());
398       if(resize.equals("none"))
399         display.setResizeStrategy(CharDisplay.RESIZE_NONE);
400       else if(resize.equals("font"))
401         display.setResizeStrategy(CharDisplay.RESIZE_FONT);
402       else if(resize.equals("screen"))
403         display.setResizeStrategy(CharDisplay.RESIZE_SCREEN);
404
405       display.setResizeStrategy(CharDisplay.RESIZE_SCREEN);
406
407       display.setBorder(2, false);
408
409       setLayout(new BorderLayout());
410           display.setScrollbar("East");
411           /*
412       if(scrb != null && !scrb.equals("false")) {
413         if(scrb.equals("left") || scrb.equals("true"))
414           display.setScrollbar("West");
415         else if(scrb.equals("right"))
416           display.setScrollbar("East");
417         else
418           System.out.println("vt320: unknown scrollbar location: "+scrb);
419       }
420           */
421       if(vms != null && vms.equals("true"))
422       {
423         this.vms = true;
424       }
425       add("Center", display);
426       InitTerminalVars();
427       if (applet != null) for (int i=1;i<20;i++)
428       {
429         if (applet.getParameter("F"+i)!=null)
430           FunctionKey[i] = unEscape(applet.getParameter("F"+i));
431         if (applet.getParameter("SF"+i)!=null)
432           FunctionKeyShift[i] = unEscape(applet.getParameter("SF"+i));
433         if (applet.getParameter("CF"+i)!=null)
434           FunctionKeyCtrl[i] = unEscape(applet.getParameter("CF"+i));
435         if (applet.getParameter("AF"+i)!=null)
436           FunctionKeyAlt[i] = unEscape(applet.getParameter("AF"+i));
437       }
438     }
439     super.addNotify();
440   }
441
442   private void InitTerminalVars() {
443     int nw = display.getColumns();
444
445     if (nw<132) nw=132; //catch possible later 132/80 resizes
446     Tabs = new byte[nw];
447     for (int i=0;i<nw;i+=8) {
448       Tabs[i]=1;
449     }
450
451     PF1  = "\u001bOP";
452     PF2  = "\u001bOQ";
453     PF3  = "\u001bOR";
454     PF4  = "\u001bOS";
455
456     Find = "\u001b[1~";
457     Insert = "\u001b[2~";
458     Remove = "\u001b[3~";
459     Select = "\u001b[4~";
460     PrevScn = "\u001b[5~";
461     NextScn = "\u001b[6~";
462
463     Help = "\u001b[28~";
464     Do = "\u001b[29~";
465
466     FunctionKey = new String[21];
467     FunctionKey[0]= "";
468     FunctionKey[1]= PF1;
469     FunctionKey[2]= PF2;
470     FunctionKey[3]= PF3;
471     FunctionKey[4]= PF4;
472     /* following are defined differently for vt220 / vt132 ... */
473     FunctionKey[5]= "\u001b[15~";
474     FunctionKey[6]= "\u001b[17~";
475     FunctionKey[7]= "\u001b[18~";
476     FunctionKey[8]= "\u001b[19~";
477     FunctionKey[9]= "\u001b[20~";
478     FunctionKey[10]= "\u001b[21~";
479     FunctionKey[11]= "\u001b[23~";
480     FunctionKey[12]= "\u001b[24~";
481     FunctionKey[13]= "\u001b[25~";
482     FunctionKey[14]= "\u001b[26~";
483     FunctionKey[15]= Help;
484     FunctionKey[16]= Do;
485     FunctionKey[17]= "\u001b[31~";
486     FunctionKey[18]= "\u001b[32~";
487     FunctionKey[19]= "\u001b[33~";
488     FunctionKey[20]= "\u001b[34~";
489
490     FunctionKeyShift = new String[21];
491     FunctionKeyAlt = new String[21];
492     FunctionKeyCtrl = new String[21];
493
494     for (int i=0;i<20;i++)
495     {
496        FunctionKeyShift[i]="";
497        FunctionKeyAlt[i]="";
498        FunctionKeyCtrl[i]="";
499     }
500     FunctionKeyShift[15] = Find;
501     FunctionKeyShift[16] = Select;
502
503     KeyTab   = "\u0009";
504     KeyBacktab = "\u001bOP\u0009";
505     KeyUp    = "\u001b[A";
506     KeyDown  = "\u001b[B";
507     KeyRight  = "\u001b[C";
508     KeyLeft  = "\u001b[D";
509     KP0  = "\u001bOp";
510     KP1  = "\u001bOq";
511     KP2  = "\u001bOr";
512     KP3  = "\u001bOs";
513     KP4  = "\u001bOt";
514     KP5  = "\u001bOu";
515     KP6  = "\u001bOv";
516     KP7  = "\u001bOw";
517     KP8  = "\u001bOx";
518     KP9  = "\u001bOy";
519     KPMinus  = "\u001bOm";
520     KPComma  = "\u001bOl";
521     KPPeriod  = "\u001bOn";
522     KPEnter  = "\u001bOM";
523
524     /* ... */
525   }
526
527   public Dimension getSize() {
528     return new Dimension(display.getColumns(), display.getRows());
529   }
530
531   public String getTerminalType() { return terminalID; }
532
533   /**
534    * Handle events for the terminal. Only accept events for the scroll
535    * bar. Any other events have to be propagated to the parent.
536    * @param evt the event
537    */
538   public boolean handleEvent(Event evt) {
539     // request focus if mouse enters (necessary to avoid mistakes)
540     if(evt.id == Event.MOUSE_ENTER) { display.requestFocus(); return true; }
541     // give focus away if mouse leaves the window
542     if(evt.id == Event.MOUSE_EXIT) { nextFocus(); return true; }
543
544     // handle keyboard events
545
546     /* Netscape for windows does not send keyDown when period
547     * is pressed. This hack catches the keyUp event.
548     */
549     int id = evt.id;
550
551     boolean control = (((evt.CTRL_MASK & evt.modifiers)==0) ? false : true);
552     boolean shift = (((evt.SHIFT_MASK & evt.modifiers)==0) ? false : true );
553     boolean alt = (((evt.ALT_MASK & evt.modifiers)==0) ? false :true);
554
555     pressedKey:
556     {
557         if (pressedKey == 10
558             && (evt.key == 10
559             || evt.key == 13)
560             && evt.when - pressedWhen < 50)    //  Ray: Elliminate stuttering enter/return
561             break pressedKey;
562
563         int priorKey = pressedKey;
564         if(id == Event.KEY_PRESS)
565             pressedKey = evt.key;               //  Keep track of last pressed key
566         else if (evt.key == '.'
567             && evt.id != Event.KEY_RELEASE
568             && evt.key != pressedKey
569         ) {
570             pressedKey = 0;
571         } else
572             break pressedKey;
573         pressedWhen = evt.when;
574         if (evt.key == 10 && !control) {
575             if (sendcrlf)
576               host.send("\r\n"); /* YES, see RFC 854 */
577             else
578               host.send("\r"); /* YES, see RFC 854 */
579             return true;
580         } else
581 /* FIXME: on german PC keyboards you have to use Alt-Ctrl-q to get an @,
582  * so we can't just use it here... will probably break some other VMS stuff
583  * -Marcus
584         if (((!vms && evt.key == '2') || evt.key == '@' || evt.key == ' ') && control)
585  */
586         if (((!vms && evt.key == '2') || evt.key == ' ') && control)
587             return host.send("" + (char)0);
588         else if (vms) {
589             if (evt.key == 8) {
590                 if (shift && !control)
591                     return host.send("" + (char)10); //  VMS shift deletes word back
592                 if (control && !shift)
593                     return host.send("" + (char)24); //  VMS control deletes line back
594                 return host.send("" + (char)127);   //  VMS other is delete
595             }
596             if (evt.key == 127 && !control) {
597                 if (shift)
598                     return host.send(Insert); //  VMS shift delete = insert
599                 else
600                     return host.send(Remove); //  VMS delete = remove
601             }
602             if (control) {
603                 switch(evt.key) {
604                     case '0':
605                         return host.send(KP0);
606                     case '1':
607                         return host.send(KP1);
608                     case '2':
609                         return host.send(KP2);
610                     case '3':
611                         return host.send(KP3);
612                     case '4':
613                         return host.send(KP4);
614                     case '5':
615                         return host.send(KP5);
616                     case '6':
617                         return host.send(KP6);
618                     case '7':
619                         return host.send(KP7);
620                     case '8':
621                         return host.send(KP8);
622                     case '9':
623                         return host.send(KP9);
624                     case '.':
625                         return host.send(KPPeriod);
626                     case '-':
627                     case 31:
628                         return host.send(KPMinus);
629                     case '+':
630                         return host.send(KPComma);
631                     case 10:
632                         return host.send(KPEnter);
633                     case '/':
634                         return host.send(PF2);
635                     case '*':
636                         return host.send(PF3);
637                 }
638                 if (shift && evt.key < 32)
639                     return host.send(PF1+(char)(evt.key + 64));
640             }
641         }
642         // Hmmm. Outside the VMS case?
643         if (shift && (evt.key == '\t'))
644             return host.send(KeyBacktab);
645         else
646             return host.send(""+(char)evt.key);
647     }
648
649     String input = "";
650
651     if (evt.id == evt.KEY_ACTION && !control)
652     {
653       String fmap[];
654       /* bloodsucking little buggers at netscape
655        * don't keep to the standard java values
656        * of <ARROW> or <Fx>
657        */
658       fmap = FunctionKey;
659       if (shift)
660         fmap = FunctionKeyShift;
661       if (control)
662         fmap = FunctionKeyCtrl;
663       if (alt)
664         fmap = FunctionKeyAlt;
665       switch (evt.key % 1000) {
666       case KEYF1:
667         input = fmap[1];
668         break;
669       case KEYF2:
670         input = fmap[2];
671         break;
672       case KEYF3:
673         input = fmap[3];
674         break;
675       case KEYF4:
676         input = fmap[4];
677         break;
678       case KEYF5:
679         input = fmap[5];
680         break;
681       case KEYF6:
682         input = fmap[6];
683         break;
684       case KEYF7:
685         input = fmap[7];
686         break;
687       case KEYF8:
688         input = fmap[8];
689         break;
690       case KEYF9:
691         input = fmap[9];
692         break;
693       case KEYF10:
694         input = fmap[10];
695         break;
696       case KEYF11:
697         input = fmap[11];
698         break;
699       case KEYF12:
700         input = fmap[12];
701         break;
702       case KEYUP:
703         input = KeyUp;
704         break;
705       case KEYDOWN:
706         input = KeyDown;
707         break;
708       case KEYLEFT:
709         input = KeyLeft;
710         break;
711       case KEYRIGHT:
712         input = KeyRight;
713         break;
714       case KEYPGDN:
715         input = NextScn;
716         break;
717       case KEYPGUP:
718         input = PrevScn;
719         break;
720       case KEYINSERT:
721         input = Insert;
722         break;
723 //  The following cases fall through if not in VMS mode.
724       case KEYHOME:
725         if (vms)
726         {
727             input = "" + (char)8;
728             break;
729         }
730         //FALLTHROUGH
731       case KEYEND:
732         if (vms)
733         {
734             input = "" + (char)5;
735             break;
736         }
737         //FALLTHROUGH
738       case KEYNUM_LOCK:
739         if (vms && control) {
740             if (pressedKey != evt.key) {
741                 pressedKey = evt.key;
742                 input = PF1;
743             } else
744                 pressedKey = ' ';   //  Here, we eat a second numlock since that returns numlock state
745         }
746         break;
747       default:
748         /*if (debug>0)*/
749           System.out.println("vt320: unknown event:"+(int)evt.key);
750         break;
751       }
752     }
753
754     if(input != null && input.length() > 0)
755       return host.send(input);
756
757     return false;
758   }
759
760   /**
761    * Dummy method to handle input events (String).
762    * This is only needed if our parent is not TerminalHost
763    * @param s String to handle
764    * @return always true
765    * @see display.TerminalHost
766    */
767   public boolean send(String s) {
768     putString(s);
769     return true;
770   }
771
772   private void handle_dcs(String dcs) {
773       if (debug>1)
774           System.out.println("DCS: "+dcs);
775   }
776   private void handle_osc(String osc) {
777       if (debug>1)
778           System.out.println("OSC: "+osc);
779   }
780
781   /**
782   * Put String at current cursor position. Moves cursor
783   * according to the String. Does NOT wrap.
784   * @param s the string
785   */
786   public void putString(String s) {
787     int  i,len=s.length();
788
789     display.markLine(R,1);
790     for (i=0;i<len;i++)
791       putChar(s.charAt(i),false);
792     display.setCursorPos(C, R);
793     display.redraw();
794   }
795
796   public void putChar(char c) {
797     putChar(c,true);
798     display.redraw();
799   }
800
801   public final static char unimap[] = {
802 //#
803 //#    Name:     cp437_DOSLatinUS to Unicode table
804 //#    Unicode version: 1.1
805 //#    Table version: 1.1
806 //#    Table format:  Format A
807 //#    Date:          03/31/95
808 //#    Authors:       Michel Suignard <michelsu@microsoft.com>
809 //#                   Lori Hoerth <lorih@microsoft.com>
810 //#    General notes: none
811 //#
812 //#    Format: Three tab-separated columns
813 //#        Column #1 is the cp1255_WinHebrew code (in hex)
814 //#        Column #2 is the Unicode (in hex as 0xXXXX)
815 //#        Column #3 is the Unicode name (follows a comment sign, '#')
816 //#
817 //#    The entries are in cp437_DOSLatinUS order
818 //#
819
820   0x0000,// #NULL
821   0x0001,// #START OF HEADING
822   0x0002,// #START OF TEXT
823   0x0003,// #END OF TEXT
824   0x0004,// #END OF TRANSMISSION
825   0x0005,// #ENQUIRY
826   0x0006,// #ACKNOWLEDGE
827   0x0007,// #BELL
828   0x0008,// #BACKSPACE
829   0x0009,// #HORIZONTAL TABULATION
830   0x000a,// #LINE FEED
831   0x000b,// #VERTICAL TABULATION
832   0x000c,// #FORM FEED
833   0x000d,// #CARRIAGE RETURN
834   0x000e,// #SHIFT OUT
835   0x000f,// #SHIFT IN
836   0x0010,// #DATA LINK ESCAPE
837   0x0011,// #DEVICE CONTROL ONE
838   0x0012,// #DEVICE CONTROL TWO
839   0x0013,// #DEVICE CONTROL THREE
840   0x0014,// #DEVICE CONTROL FOUR
841   0x0015,// #NEGATIVE ACKNOWLEDGE
842   0x0016,// #SYNCHRONOUS IDLE
843   0x0017,// #END OF TRANSMISSION BLOCK
844   0x0018,// #CANCEL
845   0x0019,// #END OF MEDIUM
846   0x001a,// #SUBSTITUTE
847   0x001b,// #ESCAPE
848   0x001c,// #FILE SEPARATOR
849   0x001d,// #GROUP SEPARATOR
850   0x001e,// #RECORD SEPARATOR
851   0x001f,// #UNIT SEPARATOR
852   0x0020,// #SPACE
853   0x0021,// #EXCLAMATION MARK
854   0x0022,// #QUOTATION MARK
855   0x0023,// #NUMBER SIGN
856   0x0024,// #DOLLAR SIGN
857   0x0025,// #PERCENT SIGN
858   0x0026,// #AMPERSAND
859   0x0027,// #APOSTROPHE
860   0x0028,// #LEFT PARENTHESIS
861   0x0029,// #RIGHT PARENTHESIS
862   0x002a,// #ASTERISK
863   0x002b,// #PLUS SIGN
864   0x002c,// #COMMA
865   0x002d,// #HYPHEN-MINUS
866   0x002e,// #FULL STOP
867   0x002f,// #SOLIDUS
868   0x0030,// #DIGIT ZERO
869   0x0031,// #DIGIT ONE
870   0x0032,// #DIGIT TWO
871   0x0033,// #DIGIT THREE
872   0x0034,// #DIGIT FOUR
873   0x0035,// #DIGIT FIVE
874   0x0036,// #DIGIT SIX
875   0x0037,// #DIGIT SEVEN
876   0x0038,// #DIGIT EIGHT
877   0x0039,// #DIGIT NINE
878   0x003a,// #COLON
879   0x003b,// #SEMICOLON
880   0x003c,// #LESS-THAN SIGN
881   0x003d,// #EQUALS SIGN
882   0x003e,// #GREATER-THAN SIGN
883   0x003f,// #QUESTION MARK
884   0x0040,// #COMMERCIAL AT
885   0x0041,// #LATIN CAPITAL LETTER A
886   0x0042,// #LATIN CAPITAL LETTER B
887   0x0043,// #LATIN CAPITAL LETTER C
888   0x0044,// #LATIN CAPITAL LETTER D
889   0x0045,// #LATIN CAPITAL LETTER E
890   0x0046,// #LATIN CAPITAL LETTER F
891   0x0047,// #LATIN CAPITAL LETTER G
892   0x0048,// #LATIN CAPITAL LETTER H
893   0x0049,// #LATIN CAPITAL LETTER I
894   0x004a,// #LATIN CAPITAL LETTER J
895   0x004b,// #LATIN CAPITAL LETTER K
896   0x004c,// #LATIN CAPITAL LETTER L
897   0x004d,// #LATIN CAPITAL LETTER M
898   0x004e,// #LATIN CAPITAL LETTER N
899   0x004f,// #LATIN CAPITAL LETTER O
900   0x0050,// #LATIN CAPITAL LETTER P
901   0x0051,// #LATIN CAPITAL LETTER Q
902   0x0052,// #LATIN CAPITAL LETTER R
903   0x0053,// #LATIN CAPITAL LETTER S
904   0x0054,// #LATIN CAPITAL LETTER T
905   0x0055,// #LATIN CAPITAL LETTER U
906   0x0056,// #LATIN CAPITAL LETTER V
907   0x0057,// #LATIN CAPITAL LETTER W
908   0x0058,// #LATIN CAPITAL LETTER X
909   0x0059,// #LATIN CAPITAL LETTER Y
910   0x005a,// #LATIN CAPITAL LETTER Z
911   0x005b,// #LEFT SQUARE BRACKET
912   0x005c,// #REVERSE SOLIDUS
913   0x005d,// #RIGHT SQUARE BRACKET
914   0x005e,// #CIRCUMFLEX ACCENT
915   0x005f,// #LOW LINE
916   0x0060,// #GRAVE ACCENT
917   0x0061,// #LATIN SMALL LETTER A
918   0x0062,// #LATIN SMALL LETTER B
919   0x0063,// #LATIN SMALL LETTER C
920   0x0064,// #LATIN SMALL LETTER D
921   0x0065,// #LATIN SMALL LETTER E
922   0x0066,// #LATIN SMALL LETTER F
923   0x0067,// #LATIN SMALL LETTER G
924   0x0068,// #LATIN SMALL LETTER H
925   0x0069,// #LATIN SMALL LETTER I
926   0x006a,// #LATIN SMALL LETTER J
927   0x006b,// #LATIN SMALL LETTER K
928   0x006c,// #LATIN SMALL LETTER L
929   0x006d,// #LATIN SMALL LETTER M
930   0x006e,// #LATIN SMALL LETTER N
931   0x006f,// #LATIN SMALL LETTER O
932   0x0070,// #LATIN SMALL LETTER P
933   0x0071,// #LATIN SMALL LETTER Q
934   0x0072,// #LATIN SMALL LETTER R
935   0x0073,// #LATIN SMALL LETTER S
936   0x0074,// #LATIN SMALL LETTER T
937   0x0075,// #LATIN SMALL LETTER U
938   0x0076,// #LATIN SMALL LETTER V
939   0x0077,// #LATIN SMALL LETTER W
940   0x0078,// #LATIN SMALL LETTER X
941   0x0079,// #LATIN SMALL LETTER Y
942   0x007a,// #LATIN SMALL LETTER Z
943   0x007b,// #LEFT CURLY BRACKET
944   0x007c,// #VERTICAL LINE
945   0x007d,// #RIGHT CURLY BRACKET
946   0x007e,// #TILDE
947   0x007f,// #DELETE
948   0x00c7,// #LATIN CAPITAL LETTER C WITH CEDILLA
949   0x00fc,// #LATIN SMALL LETTER U WITH DIAERESIS
950   0x00e9,// #LATIN SMALL LETTER E WITH ACUTE
951   0x00e2,// #LATIN SMALL LETTER A WITH CIRCUMFLEX
952   0x00e4,// #LATIN SMALL LETTER A WITH DIAERESIS
953   0x00e0,// #LATIN SMALL LETTER A WITH GRAVE
954   0x00e5,// #LATIN SMALL LETTER A WITH RING ABOVE
955   0x00e7,// #LATIN SMALL LETTER C WITH CEDILLA
956   0x00ea,// #LATIN SMALL LETTER E WITH CIRCUMFLEX
957   0x00eb,// #LATIN SMALL LETTER E WITH DIAERESIS
958   0x00e8,// #LATIN SMALL LETTER E WITH GRAVE
959   0x00ef,// #LATIN SMALL LETTER I WITH DIAERESIS
960   0x00ee,// #LATIN SMALL LETTER I WITH CIRCUMFLEX
961   0x00ec,// #LATIN SMALL LETTER I WITH GRAVE
962   0x00c4,// #LATIN CAPITAL LETTER A WITH DIAERESIS
963   0x00c5,// #LATIN CAPITAL LETTER A WITH RING ABOVE
964   0x00c9,// #LATIN CAPITAL LETTER E WITH ACUTE
965   0x00e6,// #LATIN SMALL LIGATURE AE
966   0x00c6,// #LATIN CAPITAL LIGATURE AE
967   0x00f4,// #LATIN SMALL LETTER O WITH CIRCUMFLEX
968   0x00f6,// #LATIN SMALL LETTER O WITH DIAERESIS
969   0x00f2,// #LATIN SMALL LETTER O WITH GRAVE
970   0x00fb,// #LATIN SMALL LETTER U WITH CIRCUMFLEX
971   0x00f9,// #LATIN SMALL LETTER U WITH GRAVE
972   0x00ff,// #LATIN SMALL LETTER Y WITH DIAERESIS
973   0x00d6,// #LATIN CAPITAL LETTER O WITH DIAERESIS
974   0x00dc,// #LATIN CAPITAL LETTER U WITH DIAERESIS
975   0x00a2,// #CENT SIGN
976   0x00a3,// #POUND SIGN
977   0x00a5,// #YEN SIGN
978   0x20a7,// #PESETA SIGN
979   0x0192,// #LATIN SMALL LETTER F WITH HOOK
980   0x00e1,// #LATIN SMALL LETTER A WITH ACUTE
981   0x00ed,// #LATIN SMALL LETTER I WITH ACUTE
982   0x00f3,// #LATIN SMALL LETTER O WITH ACUTE
983   0x00fa,// #LATIN SMALL LETTER U WITH ACUTE
984   0x00f1,// #LATIN SMALL LETTER N WITH TILDE
985   0x00d1,// #LATIN CAPITAL LETTER N WITH TILDE
986   0x00aa,// #FEMININE ORDINAL INDICATOR
987   0x00ba,// #MASCULINE ORDINAL INDICATOR
988   0x00bf,// #INVERTED QUESTION MARK
989   0x2310,// #REVERSED NOT SIGN
990   0x00ac,// #NOT SIGN
991   0x00bd,// #VULGAR FRACTION ONE HALF
992   0x00bc,// #VULGAR FRACTION ONE QUARTER
993   0x00a1,// #INVERTED EXCLAMATION MARK
994   0x00ab,// #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
995   0x00bb,// #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
996   0x2591,// #LIGHT SHADE
997   0x2592,// #MEDIUM SHADE
998   0x2593,// #DARK SHADE
999   0x2502,// #BOX DRAWINGS LIGHT VERTICAL
1000   0x2524,// #BOX DRAWINGS LIGHT VERTICAL AND LEFT
1001   0x2561,// #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
1002   0x2562,// #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
1003   0x2556,// #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
1004   0x2555,// #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
1005   0x2563,// #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
1006   0x2551,// #BOX DRAWINGS DOUBLE VERTICAL
1007   0x2557,// #BOX DRAWINGS DOUBLE DOWN AND LEFT
1008   0x255d,// #BOX DRAWINGS DOUBLE UP AND LEFT
1009   0x255c,// #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
1010   0x255b,// #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
1011   0x2510,// #BOX DRAWINGS LIGHT DOWN AND LEFT
1012   0x2514,// #BOX DRAWINGS LIGHT UP AND RIGHT
1013   0x2534,// #BOX DRAWINGS LIGHT UP AND HORIZONTAL
1014   0x252c,// #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
1015   0x251c,// #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1016   0x2500,// #BOX DRAWINGS LIGHT HORIZONTAL
1017   0x253c,// #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1018   0x255e,// #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
1019   0x255f,// #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
1020   0x255a,// #BOX DRAWINGS DOUBLE UP AND RIGHT
1021   0x2554,// #BOX DRAWINGS DOUBLE DOWN AND RIGHT
1022   0x2569,// #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
1023   0x2566,// #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
1024   0x2560,// #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
1025   0x2550,// #BOX DRAWINGS DOUBLE HORIZONTAL
1026   0x256c,// #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
1027   0x2567,// #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
1028   0x2568,// #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
1029   0x2564,// #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
1030   0x2565,// #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
1031   0x2559,// #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
1032   0x2558,// #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
1033   0x2552,// #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
1034   0x2553,// #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
1035   0x256b,// #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
1036   0x256a,// #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
1037   0x2518,// #BOX DRAWINGS LIGHT UP AND LEFT
1038   0x250c,// #BOX DRAWINGS LIGHT DOWN AND RIGHT
1039   0x2588,// #FULL BLOCK
1040   0x2584,// #LOWER HALF BLOCK
1041   0x258c,// #LEFT HALF BLOCK
1042   0x2590,// #RIGHT HALF BLOCK
1043   0x2580,// #UPPER HALF BLOCK
1044   0x03b1,// #GREEK SMALL LETTER ALPHA
1045   0x00df,// #LATIN SMALL LETTER SHARP S
1046   0x0393,// #GREEK CAPITAL LETTER GAMMA
1047   0x03c0,// #GREEK SMALL LETTER PI
1048   0x03a3,// #GREEK CAPITAL LETTER SIGMA
1049   0x03c3,// #GREEK SMALL LETTER SIGMA
1050   0x00b5,// #MICRO SIGN
1051   0x03c4,// #GREEK SMALL LETTER TAU
1052   0x03a6,// #GREEK CAPITAL LETTER PHI
1053   0x0398,// #GREEK CAPITAL LETTER THETA
1054   0x03a9,// #GREEK CAPITAL LETTER OMEGA
1055   0x03b4,// #GREEK SMALL LETTER DELTA
1056   0x221e,// #INFINITY
1057   0x03c6,// #GREEK SMALL LETTER PHI
1058   0x03b5,// #GREEK SMALL LETTER EPSILON
1059   0x2229,// #INTERSECTION
1060   0x2261,// #IDENTICAL TO
1061   0x00b1,// #PLUS-MINUS SIGN
1062   0x2265,// #GREATER-THAN OR EQUAL TO
1063   0x2264,// #LESS-THAN OR EQUAL TO
1064   0x2320,// #TOP HALF INTEGRAL
1065   0x2321,// #BOTTOM HALF INTEGRAL
1066   0x00f7,// #DIVISION SIGN
1067   0x2248,// #ALMOST EQUAL TO
1068   0x00b0,// #DEGREE SIGN
1069   0x2219,// #BULLET OPERATOR
1070   0x00b7,// #MIDDLE DOT
1071   0x221a,// #SQUARE ROOT
1072   0x207f,// #SUPERSCRIPT LATIN SMALL LETTER N
1073   0x00b2,// #SUPERSCRIPT TWO
1074   0x25a0,// #BLACK SQUARE
1075   0x00a0,// #NO-BREAK SPACE
1076   };
1077
1078   public char map_cp850_unicode(char x) {
1079     if (x>=0x100)
1080       return x;
1081     return unimap[x];
1082   }
1083
1084   private void _SetCursor(int row,int col) {
1085     int maxr = display.getRows();
1086     int tm = display.getTopMargin();
1087
1088     R = (row<0)?0:row;
1089     C = (col<0)?0:col;
1090
1091     if (originmode) {
1092         R       += display.getTopMargin();
1093         maxr     = display.getBottomMargin();
1094     }
1095     if (R>maxr) R = maxr;
1096   }
1097
1098   public void putChar(char c,boolean doshowcursor) {
1099     Dimension size;
1100     int  rows = display.getRows() ; //statusline
1101     int  columns = display.getColumns();
1102     int  tm = display.getTopMargin();
1103     int  bm = display.getBottomMargin();
1104     String  tosend;
1105     Vector  vec;
1106     byte  msg[];
1107
1108     if (debug>4) System.out.println("putChar("+c+" ["+((int)c)+"]) at R="+R+" , C="+C+", columns="+columns+", rows="+rows);
1109     display.markLine(R,1);
1110     if (c>255) {
1111       if (debug>0)
1112         System.out.println("char > 255:"+((int)c));
1113       return;
1114     }
1115     switch (term_state) {
1116     case TSTATE_DATA:
1117       /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset.
1118        * probably... but some BBS do anyway...
1119        */
1120       if (!useibmcharset) {
1121         boolean doneflag = true;
1122         switch (c) {
1123         case OSC:
1124           osc="";
1125           term_state = TSTATE_OSC;
1126           break;
1127         case RI:
1128           if (R>tm)
1129             R--;
1130           else
1131             display.insertLine(R,1,display.SCROLL_DOWN);
1132           if (debug>1)
1133             System.out.println("RI");
1134           break;
1135         case IND:
1136           if (R == tm - 1 || R == bm || R == rows - 1) //  Ray: not bottom margin - 1
1137             display.insertLine(R,1,display.SCROLL_UP);
1138           else
1139             R++;
1140           if (debug>1)
1141             System.out.println("IND (at "+R+" )");
1142           break;
1143         case NEL:
1144           if (R == tm - 1 || R == bm || R == rows - 1) //  Ray: not bottom margin - 1
1145             display.insertLine(R,1,display.SCROLL_UP);
1146           else
1147             R++;
1148           C=0;
1149           if (debug>1)
1150             System.out.println("NEL (at "+R+" )");
1151           break;
1152         case HTS:
1153           Tabs[C] = 1;
1154           if (debug>1)
1155             System.out.println("HTS");
1156           break;
1157         case DCS:
1158           dcs="";
1159           term_state = TSTATE_DCS;
1160           break;
1161         default:
1162           doneflag = false;
1163           break;
1164         }
1165         if (doneflag) break;
1166       }
1167       switch (c) {
1168       case CSI: // should be in the 8bit section, but some BBS use this
1169         term_state = TSTATE_DCEQ;
1170         break;
1171       case ESC:
1172         term_state = TSTATE_ESC;
1173         lastwaslf=0;
1174         break;
1175       case '\b':
1176         C--;
1177         if (C<0)
1178           C=0;
1179         lastwaslf = 0;
1180         break;
1181       case '\t':
1182         if (insertmode == 1) {
1183           int  nr,newc;
1184
1185           newc = C;
1186           do {
1187             display.insertChar(C,R,' ',attributes);
1188             newc++;
1189           } while (newc<columns && Tabs[newc]==0);
1190         } else {
1191           do {
1192             display.putChar(C++,R,' ',attributes);
1193           } while (C<columns && (Tabs[C]==0));
1194         }
1195         lastwaslf = 0;
1196         break;
1197       case '\r':
1198         C=0;
1199         break;
1200       case '\n':
1201         if (debug>3)
1202                 System.out.println("R= "+R+", bm "+bm+", tm="+tm+", rows="+rows);
1203         if (!vms)
1204         {
1205             if (lastwaslf!=0 && lastwaslf!=c)   //  Ray: I do not understand this logic.
1206               break;
1207             lastwaslf=c;
1208             C = 0;
1209         }
1210         if (R == tm - 1 || R == bm || R >= rows - 1)
1211             display.insertLine(R,1);
1212         else
1213             R++;
1214         break;
1215       case '\016':
1216         /* ^N, Shift out - Put G1 into GL */
1217         gl = 1;
1218         break;
1219       case '\017':
1220         /* ^O, Shift in - Put G0 into GL */
1221         gl = 0;
1222         break;
1223       default:
1224         lastwaslf=0;
1225         if (c<32) {
1226           if (c!=0)
1227             if (debug>0)
1228               System.out.println("TSTATE_DATA char: "+((int)c));
1229           break;
1230         }
1231         if(C >= columns) {
1232           if(R < rows - 1)
1233             R++;
1234           else
1235             display.insertLine(R,display.SCROLL_UP);
1236           C = 0;
1237         }
1238
1239         // Mapping if DEC Special is chosen charset
1240         if ( gx[gl] == '0' ) {
1241           if ( c >= '\u005f' && c <= '\u007e' ) {
1242           if (debug>3)
1243             System.out.print("Mapping "+c+" (index "+((short)c-0x5f)+" to ");
1244           c = DECSPECIAL[(short)c - 0x5f];
1245           if (debug>3)
1246             System.out.println(c+" ("+(int)c+")");
1247           }
1248         }
1249 /*
1250         if ( gx[gr] == '0' ) {
1251           if ( c >= '\u00bf' && c <= '\u00fe' ) {
1252           if (debug>2)
1253             System.out.print("Mapping "+c);
1254             c = DECSPECIAL[(short)c - 0xbf];
1255             if (debug>2)
1256               System.out.println("to "+c);
1257           }
1258         }
1259 */
1260         if (useibmcharset)
1261           c = map_cp850_unicode(c);
1262
1263         /*if(true || (statusmode == 0)) { */
1264         if (debug>4) System.out.println("output "+c+" at "+C+","+R);
1265           if (insertmode==1) {
1266             display.insertChar(C, R, c, attributes);
1267           } else {
1268             display.putChar(C, R, c, attributes);
1269           }
1270         /*
1271         } else {
1272           if (insertmode==1) {
1273             display.insertChar(C, rows, c, attributes);
1274           } else {
1275             display.putChar(C, rows, c, attributes);
1276           }
1277         }
1278         */
1279         C++;
1280         break;
1281       } /* switch(c) */
1282       break;
1283     case TSTATE_OSC:
1284       if ((c<0x20) && (c!=ESC)) {// NP - No printing character
1285         handle_osc(osc);
1286         term_state = TSTATE_DATA;
1287         break;
1288       }
1289       //but check for vt102 ESC \
1290       if (c=='\\' && osc.charAt(osc.length()-1)==ESC) {
1291         handle_osc(osc);
1292         term_state = TSTATE_DATA;
1293         break;
1294       }
1295       osc = osc + c;
1296       break;
1297     case TSTATE_ESC:
1298       switch (c) {
1299       case '#':
1300         term_state = TSTATE_ESCSQUARE;
1301         break;
1302       case 'c':
1303         /* Hard terminal reset */
1304         /*FIXME:*/
1305         term_state = TSTATE_DATA;
1306         break;
1307       case '[':
1308         term_state = TSTATE_CSI;
1309         DCEvar    = 0;
1310         DCEvars[0]  = 0;
1311         DCEvars[1]  = 0;
1312         DCEvars[2]  = 0;
1313         DCEvars[3]  = 0;
1314         break;
1315         case ']':
1316         osc="";
1317         term_state = TSTATE_OSC;
1318         break;
1319       case 'P':
1320         dcs="";
1321         term_state = TSTATE_DCS;
1322         break;
1323       case 'E':
1324         if (R == tm - 1 || R == bm || R == rows - 1) //  Ray: not bottom margin - 1
1325           display.insertLine(R,1,display.SCROLL_UP);
1326         else
1327           R++;
1328         C=0;
1329         if (debug>1)
1330           System.out.println("ESC E (at "+R+")");
1331         term_state = TSTATE_DATA;
1332         break;
1333       case 'D':
1334         if (R == tm - 1 || R == bm || R == rows - 1)
1335           display.insertLine(R,1,display.SCROLL_UP);
1336         else
1337           R++;
1338         if (debug>1)
1339           System.out.println("ESC D (at "+R+" )");
1340         term_state = TSTATE_DATA;
1341         break;
1342       case 'M': // IL
1343         if ((R>=tm) && (R<=bm)) // in scrolregion
1344           display.insertLine(R,1,display.SCROLL_DOWN);
1345         /* else do nothing ; */
1346         if (debug>1)
1347           System.out.println("ESC M ");
1348         term_state = TSTATE_DATA;
1349         break;
1350       case 'H':
1351         if (debug>1)
1352           System.out.println("ESC H at "+C);
1353         /* right border probably ...*/
1354         if (C>=columns)
1355           C=columns-1;
1356         Tabs[C] = 1;
1357         term_state = TSTATE_DATA;
1358         break;
1359       case '=':
1360         /*application keypad*/
1361         if (debug>0)
1362           System.out.println("ESC =");
1363         term_state = TSTATE_DATA;
1364         break;
1365       case '>':
1366         /*normal keypad*/
1367         if (debug>0)
1368           System.out.println("ESC >");
1369         term_state = TSTATE_DATA;
1370         break;
1371       case '7':
1372         /*save cursor */
1373         Sc = C;
1374         Sr = R;
1375         Sa = attributes;
1376         if (debug>1)
1377           System.out.println("ESC 7");
1378         term_state = TSTATE_DATA;
1379         break;
1380       case '8':
1381         /*restore cursor */
1382         C = Sc;
1383         R = Sr;
1384         attributes = Sa;
1385         term_state = TSTATE_DATA;
1386         if (debug>1)
1387           System.out.println("ESC 7");
1388         break;
1389       case '(':
1390         /* Designate G0 Character set (ISO 2022) */
1391         term_state = TSTATE_SETG0;
1392         break;
1393       case ')':
1394         /* Designate G0 character set (ISO 2022) */
1395         term_state = TSTATE_SETG1;
1396         break;
1397       case '*':
1398         /* Designate G1 Character set (ISO 2022) */
1399         term_state = TSTATE_SETG2;
1400         break;
1401       case '+':
1402         /* Designate G1 Character set (ISO 2022) */
1403         term_state = TSTATE_SETG3;
1404         break;
1405       case '~':
1406         /* Locking Shift 1, right */
1407         term_state = TSTATE_DATA;
1408         gr = 1;
1409         break;
1410       case 'n':
1411         /* Locking Shift 2 */
1412         term_state = TSTATE_DATA;
1413         gl = 2;
1414         break;
1415       case '}':
1416         /* Locking Shift 2, right */
1417         term_state = TSTATE_DATA;
1418         gr = 2;
1419         break;
1420       case 'o':
1421         /* Locking Shift 3 */
1422         term_state = TSTATE_DATA;
1423         gl = 3;
1424         break;
1425       case '|':
1426         /* Locking Shift 3, right */
1427         term_state = TSTATE_DATA;
1428         gr = 3;
1429         break;
1430       default:
1431         System.out.println("ESC unknown letter: ("+((int)c)+")");
1432         term_state = TSTATE_DATA;
1433         break;
1434       }
1435       break;
1436     case TSTATE_SETG0:
1437       if(c!='0' && c!='A' && c!='B')
1438         System.out.println("ESC ( : G0 char set?  ("+((int)c)+")");
1439       else {
1440         if (debug>2) System.out.println("ESC ( : G0 char set  ("+c+" "+((int)c)+")");
1441         gx[0] = c;
1442       }
1443       term_state = TSTATE_DATA;
1444       break;
1445     case TSTATE_SETG1:
1446       if(c!='0' && c!='A' && c!='B')
1447         System.out.println("ESC ) :G1 char set?  ("+((int)c)+")");
1448       else {
1449         if (debug>2) System.out.println("ESC ) :G1 char set  ("+c+" "+((int)c)+")");
1450         gx[1] = c;
1451       }
1452       term_state = TSTATE_DATA;
1453       break;
1454     case TSTATE_SETG2:
1455       if(c!='0' && c!='A' && c!='B')
1456         System.out.println("ESC*:G2 char set?  ("+((int)c)+")");
1457       else {
1458         if (debug>2) System.out.println("ESC*:G2 char set  ("+c+" "+((int)c)+")");
1459         gx[2] = c;
1460       }
1461       term_state = TSTATE_DATA;
1462       break;
1463     case TSTATE_SETG3:
1464       if(c!='0' && c!='A' && c!='B')
1465         System.out.println("ESC+:G3 char set?  ("+((int)c)+")");
1466       else {
1467         if (debug>2) System.out.println("ESC+:G3 char set  ("+c+" "+((int)c)+")");
1468         gx[3] = c;
1469       }
1470       term_state = TSTATE_DATA;
1471       break;
1472     case TSTATE_ESCSQUARE:
1473       switch (c) {
1474       case '8':
1475         for (int i=0;i<columns;i++)
1476           for (int j=0;j<rows;j++)
1477             display.putChar(i,j,'E',0);
1478         break;
1479       default:
1480         System.out.println("ESC # "+c+" not supported.");
1481         break;
1482       }
1483       term_state = TSTATE_DATA;
1484       break;
1485     case TSTATE_DCS:
1486       if (c=='\\' && dcs.charAt(dcs.length()-1)==ESC) {
1487         handle_dcs(dcs);
1488         term_state = TSTATE_DATA;
1489         break;
1490       }
1491       dcs = dcs + c;
1492       break;
1493     case TSTATE_DCEQ:
1494       switch (c) {
1495       case '0':
1496       case '1':
1497       case '2':
1498       case '3':
1499       case '4':
1500       case '5':
1501       case '6':
1502       case '7':
1503       case '8':
1504       case '9':
1505         DCEvars[DCEvar]=DCEvars[DCEvar]*10+((int)c)-48;
1506         break;
1507       case 'r': // XTERM_RESTORE
1508         if (true || debug>1)
1509           System.out.println("ESC [ ? "+DCEvars[0]+" r");
1510         /* DEC Mode reset */
1511         switch (DCEvars[0]){
1512         case 3: /* 80 columns*/
1513           size = display.size();
1514           display.setWindowSize(80,rows);
1515           layout();
1516           break;
1517         case 4: /* scrolling mode, smooth */
1518           break;
1519         case 5: /* light background */
1520           break;
1521         case 6: /* move inside margins ? */
1522           originmode = false;
1523           break;
1524         case 12:/* local echo off */
1525           break;
1526         }
1527         term_state = TSTATE_DATA;
1528         break;
1529       case 'h': // DECSET
1530         if (debug>0)
1531           System.out.println("ESC [ ? "+DCEvars[0]+" h");
1532         /* DEC Mode set */
1533         switch (DCEvars[0]){
1534         case 1:  /* Application cursor keys */
1535           KeyUp  = "\u001bOA";
1536           KeyDown  = "\u001bOB";
1537           KeyRight= "\u001bOC";
1538           KeyLeft  = "\u001bOD";
1539           break;
1540         case 3: /* 132 columns*/
1541           size = display.size();
1542           display.setWindowSize(132,rows);
1543           layout();
1544           break;
1545         case 4: /* scrolling mode, smooth */
1546           break;
1547         case 5: /* light background */
1548           break;
1549         case 6: /* move inside margins ? */
1550           originmode = true;
1551           break;
1552         case 12:/* local echo off */
1553           break;
1554         }
1555         term_state = TSTATE_DATA;
1556         break;
1557       case 'l': //DECRST
1558         /* DEC Mode reset */
1559         if (debug>0)
1560           System.out.println("ESC [ ? "+DCEvars[0]+" l");
1561         switch (DCEvars[0]){
1562         case 1:  /* Application cursor keys */
1563           KeyUp  = "\u001b[A";
1564           KeyDown  = "\u001b[B";
1565           KeyRight= "\u001b[C";
1566           KeyLeft  = "\u001b[D";
1567           break;
1568         case 3: /* 80 columns*/
1569           size = display.size();
1570           display.setWindowSize(80,rows);
1571           layout();
1572           break;
1573         case 4: /* scrolling mode, jump */
1574           break;
1575         case 5: /* dark background */
1576           break;
1577         case 6: /* move outside margins ? */
1578           originmode = false;
1579           break;
1580         case 12:/* local echo on */
1581           break;
1582         }
1583         term_state = TSTATE_DATA;
1584         break;
1585       case ';':
1586         DCEvar++;
1587         DCEvars[DCEvar] = 0;
1588         break;
1589       case 'n':
1590         if (debug>0)
1591           System.out.println("ESC [ ? "+DCEvars[0]+" n");
1592         switch (DCEvars[0]) {
1593         case 15:
1594           /* printer? no printer. */
1595           host.send(((char)ESC)+"[?13n");
1596           System.out.println("ESC[5n");
1597           break;
1598         default:break;
1599         }
1600         term_state = TSTATE_DATA;
1601         break;
1602       default:
1603         if (debug>0)
1604           System.out.println("ESC [ ? "+DCEvars[0]+" "+c);
1605         term_state = TSTATE_DATA;
1606         break;
1607       }
1608       break;
1609     case TSTATE_CSI_DOLLAR:
1610       switch (c) {
1611       case '}':
1612         System.out.println("Active Status Display now "+DCEvars[0]);
1613         statusmode = DCEvars[0];
1614         break;
1615 /* bad documentation?
1616       case '-':
1617         System.out.println("Set Status Display now "+DCEvars[0]);
1618         break;
1619  */
1620       case '~':
1621         System.out.println("Status Line mode now "+DCEvars[0]);
1622         break;
1623       default:
1624         System.out.println("UNKNOWN Status Display code "+c+", with Pn="+DCEvars[0]);
1625         break;
1626       }
1627       term_state = TSTATE_DATA;
1628       break;
1629     case TSTATE_CSI:
1630       switch (c) {
1631       case '$':
1632         term_state=TSTATE_CSI_DOLLAR;
1633         break;
1634       case '?':
1635         DCEvar=0;
1636         DCEvars[0]=0;
1637         term_state=TSTATE_DCEQ;
1638         break;
1639       case '0':
1640       case '1':
1641       case '2':
1642       case '3':
1643       case '4':
1644       case '5':
1645       case '6':
1646       case '7':
1647       case '8':
1648       case '9':
1649         DCEvars[DCEvar]=DCEvars[DCEvar]*10+((int)c)-48;
1650         break;
1651       case ';':
1652         DCEvar++;
1653         DCEvars[DCEvar] = 0;
1654         break;
1655       case 'c':/* send primary device attributes */
1656         /* send (ESC[?61c) */
1657         host.send(((char)ESC)+"[?1;2c");
1658         term_state = TSTATE_DATA;
1659         if (debug>1)
1660           System.out.println("ESC [ "+DCEvars[0]+" c");
1661         break;
1662       case 'q':
1663         if (debug>1)
1664           System.out.println("ESC [ "+DCEvars[0]+" q");
1665         term_state = TSTATE_DATA;
1666         break;
1667       case 'g':
1668         /* used for tabsets */
1669         switch (DCEvars[0]){
1670         case 3:/* clear them */
1671           int nw = display.getColumns();
1672           Tabs = new byte[nw];
1673           break;
1674         case 0:
1675           Tabs[C] = 0;
1676           break;
1677         }
1678         if (debug>1)
1679           System.out.println("ESC [ "+DCEvars[0]+" g");
1680         term_state = TSTATE_DATA;
1681         break;
1682       case 'h':
1683         switch (DCEvars[0]) {
1684         case 4:
1685           insertmode = 1;
1686           break;
1687         case 20:
1688           sendcrlf = true;
1689           break;
1690         default:
1691           System.out.println("unsupported: ESC [ "+DCEvars[0]+" h");
1692           break;
1693         }
1694         term_state = TSTATE_DATA;
1695         if (debug>1)
1696           System.out.println("ESC [ "+DCEvars[0]+" h");
1697         break;
1698       case 'l':
1699         switch (DCEvars[0]) {
1700         case 4:
1701           insertmode = 0;
1702           break;
1703         case 20:
1704     sendcrlf = false;
1705     break;
1706         }
1707         term_state = TSTATE_DATA;
1708         if (debug>1)
1709           System.out.println("ESC [ "+DCEvars[0]+" l");
1710         break;
1711       case 'A': // CUU
1712       {
1713         int limit;
1714         /* FIXME: xterm only cares about 0 and topmargin */
1715         if (R > bm)
1716             limit = bm+1;
1717         else if (R >= tm) {
1718             limit = tm;
1719         } else
1720             limit = 0;
1721         if (DCEvars[0]==0)
1722           R--;
1723         else
1724           R-=DCEvars[0];
1725         if (R < limit)
1726             R = limit;
1727         term_state = TSTATE_DATA;
1728         if (debug>1)
1729           System.out.println("ESC [ "+DCEvars[0]+" A");
1730         break;
1731       }
1732       case 'B': // CUD
1733         /* cursor down n (1) times */
1734       {
1735         int limit;
1736         if (R < tm)
1737             limit = tm-1;
1738         else if (R <= bm) {
1739             limit = bm;
1740         } else
1741             limit = rows - 1;
1742         if (DCEvars[0]==0)
1743           R++;
1744         else
1745           R+=DCEvars[0];
1746         if (R > limit)
1747             R = limit;
1748         else {
1749             if (debug>2) System.out.println("Not limited.");
1750         }
1751         if (debug>2) System.out.println("to: " + R);
1752         term_state = TSTATE_DATA;
1753         if (debug>1)
1754           System.out.println("ESC [ "+DCEvars[0]+" B (at C="+C+")");
1755         break;
1756       }
1757       case 'C':
1758         if (DCEvars[0]==0)
1759           C++;
1760         else
1761           C+=DCEvars[0];
1762         if (C>columns-1)
1763           C=columns-1;
1764         term_state = TSTATE_DATA;
1765         if (debug>1)
1766           System.out.println("ESC [ "+DCEvars[0]+" C");
1767         break;
1768       case 'd': // CVA
1769         R = DCEvars[0];
1770         System.out.println("ESC [ "+DCEvars[0]+" d");
1771         term_state = TSTATE_DATA;
1772         break;
1773       case 'D':
1774         if (DCEvars[0]==0)
1775           C--;
1776         else
1777           C-=DCEvars[0];
1778         if (C<0) C=0;
1779         term_state = TSTATE_DATA;
1780         if (debug>1)
1781           System.out.println("ESC [ "+DCEvars[0]+" D");
1782         break;
1783       case 'r': // DECSTBM
1784         if (DCEvar>0)   //  Ray:  Any argument is optional
1785         {
1786           R = DCEvars[1]-1;
1787           if (R < 0)
1788             R = rows-1;
1789           else if (R >= rows) {
1790             R = rows - 1;
1791           }
1792         } else
1793           R = rows - 1;
1794         display.setBottomMargin(DCEvars[1]-1);
1795         if (R >= DCEvars[0])
1796         {
1797           R = DCEvars[0]-1;
1798           if (R < 0)
1799             R = 0;
1800         }
1801         display.setTopMargin(DCEvars[0]-1);
1802         _SetCursor(0,0);
1803         if (debug>1)
1804           System.out.println("ESC ["+DCEvars[0]+" ; "+DCEvars[1]+" r");
1805         term_state = TSTATE_DATA;
1806         break;
1807       case 'G':  /* CUP  / cursor absolute column */
1808         C = DCEvars[0];
1809         System.out.println("ESC [ "+DCEvars[0]+" G");
1810         term_state = TSTATE_DATA;
1811         break;
1812       case 'H':  /* CUP  / cursor position */
1813         /* gets 2 arguments */
1814         _SetCursor(DCEvars[0]-1,DCEvars[1]-1);
1815         term_state = TSTATE_DATA;
1816         if (debug>2) {
1817           System.out.println("ESC [ "+DCEvars[0]+";"+DCEvars[1]+" H, originmode "+originmode);
1818           System.out.println("  -> R now "+R+", C now "+C);
1819         }
1820         break;
1821       case 'f':  /* move cursor 2 */
1822         /* gets 2 arguments */
1823         R = DCEvars[0]-1;
1824         C = DCEvars[1]-1;
1825         if (C<0) C=0;
1826         if (R<0) R=0;
1827         term_state = TSTATE_DATA;
1828         if (debug>2)
1829           System.out.println("ESC [ "+DCEvars[0]+";"+DCEvars[1]+" f");
1830         break;
1831       case 'L':
1832         /* insert n lines */
1833         if (DCEvars[0]==0)
1834           display.insertLine(R,display.SCROLL_DOWN);
1835         else
1836           display.insertLine(R,DCEvars[0],display.SCROLL_DOWN);
1837         term_state = TSTATE_DATA;
1838         if (debug>1)
1839           System.out.println("ESC [ "+DCEvars[0]+" L");
1840         break;
1841       case 'M':
1842         if (debug>1)
1843           System.out.println("ESC [ "+DCEvars[0]+"M at R="+R);
1844         if (DCEvars[0]==0)
1845           display.deleteLine(R);
1846         else
1847           for (int i=0;i<DCEvars[0];i++)
1848             display.deleteLine(R);
1849         term_state = TSTATE_DATA;
1850         break;
1851       case 'K':
1852         if (debug>1)
1853           System.out.println("ESC [ "+DCEvars[0]+" K");
1854         /* clear in line */
1855         switch (DCEvars[0]) {
1856         case 0:/*clear to right*/
1857           if (C<columns-1)
1858             display.deleteArea(C,R,columns-C,1);
1859           break;
1860         case 1:/*clear to the left*/
1861           if (C>0)
1862             display.deleteArea(0,R,C,1);    // Ray: Should at least include character before this one, not C-1
1863           break;
1864         case 2:/*clear whole line */
1865           display.deleteArea(0,R,columns,1);
1866           break;
1867         }
1868         term_state = TSTATE_DATA;
1869         break;
1870       case 'J':
1871         /* clear display.below current line */
1872         switch (DCEvars[0]) {
1873         case 0:
1874           if (R<rows-1)
1875             display.deleteArea(0,R + 1,columns,rows-R-1);
1876           if (C<columns-1)
1877             display.deleteArea(C,R,columns-C,1);
1878           break;
1879         case 1:
1880           if (R>0)
1881             display.deleteArea(0,0,columns,R-1);
1882           if (C>0)
1883             display.deleteArea(0,R,C,1);    // Ray: Should at least include character before this one, not C-1
1884           break;
1885         case 2:
1886           display.deleteArea(0,0,columns,rows);
1887           break;
1888         }
1889         if (debug>1)
1890           System.out.println("ESC [ "+DCEvars[0]+" J");
1891         term_state = TSTATE_DATA;
1892         break;
1893       case '@':
1894         if (debug>1)
1895           System.out.println("ESC [ "+DCEvars[0]+" @");
1896         for (int i=0;i<DCEvars[0];i++)
1897           display.insertChar(C,R,' ',attributes);
1898         term_state = TSTATE_DATA;
1899         break;
1900       case 'P':
1901         if (debug>1)
1902           System.out.println("ESC [ "+DCEvars[0]+" P, C="+C+",R="+R);
1903         for (int i=0;i<DCEvars[0];i++)
1904           display.deleteChar(C,R);
1905         term_state = TSTATE_DATA;
1906         break;
1907       case 'n':
1908         switch (DCEvars[0]){
1909         case 5: /* malfunction? No malfunction. */
1910           host.send(((char)ESC)+"[0n");
1911           if(debug > 1)
1912             System.out.println("ESC[5n");
1913           break;
1914         case 6:
1915           host.send(((char)ESC)+"["+R+";"+C+"R");
1916           if(debug > 1)
1917             System.out.println("ESC[6n");
1918           break;
1919         default:
1920           if (debug>0)
1921             System.out.println("ESC [ "+DCEvars[0]+" n??");
1922           break;
1923         }
1924         term_state = TSTATE_DATA;
1925         break;
1926       case 'm':  /* attributes as color, bold , blink,*/
1927         if (debug>1)
1928           System.out.print("ESC [ ");
1929         if (DCEvar == 0 && DCEvars[0] == 0)
1930           attributes = 0;
1931         for (i=0;i<=DCEvar;i++) {
1932           switch (DCEvars[i]) {
1933           case 0:
1934             if (DCEvar>0)
1935               attributes =0;
1936             break;
1937           case 4:
1938             attributes |= CharDisplay.UNDERLINE;
1939             break;
1940           case 1:
1941             attributes |= CharDisplay.BOLD;
1942             break;
1943           case 7:
1944             attributes |= CharDisplay.INVERT;
1945             break;
1946           case 5: /* blink on */
1947             break;
1948           case 25: /* blinking off */
1949             break;
1950           case 27:
1951             attributes &= ~CharDisplay.INVERT;
1952             break;
1953           case 24:
1954             attributes &= ~CharDisplay.UNDERLINE;
1955             break;
1956           case 22:
1957             attributes &= ~CharDisplay.BOLD;
1958             break;
1959           case 30:
1960           case 31:
1961           case 32:
1962           case 33:
1963           case 34:
1964           case 35:
1965           case 36:
1966           case 37:
1967             attributes &= ~(0xf<<3);
1968             attributes |= ((DCEvars[i]-30)+1)<<3;
1969             break;
1970           case 39:
1971             attributes &= ~(0xf<<3);
1972             break;
1973           case 40:
1974           case 41:
1975           case 42:
1976           case 43:
1977           case 44:
1978           case 45:
1979           case 46:
1980           case 47:
1981             attributes &= ~(0xf<<7);
1982             attributes |= ((DCEvars[i]-40)+1)<<7;
1983             break;
1984           case 49:
1985             attributes &= ~(0xf<<7);
1986             break;
1987
1988           default:
1989             System.out.println("ESC [ "+DCEvars[i]+" m unknown...");
1990             break;
1991           }
1992           if (debug>1)
1993             System.out.print(""+DCEvars[i]+";");
1994         }
1995         if (debug>1)
1996           System.out.print(" (attributes = "+attributes+")m \n");
1997         term_state = TSTATE_DATA;
1998         break;
1999       default:
2000         if (debug>0)
2001           System.out.println("ESC [ unknown letter:"+c+" ("+((int)c)+")");
2002         term_state = TSTATE_DATA;
2003         break;
2004       }
2005       break;
2006     default:
2007       term_state = TSTATE_DATA;
2008       break;
2009     }
2010     if (C > columns) C = columns;
2011     if (R > rows)  R = rows;
2012     if (C < 0)  C = 0;
2013     if (R < 0)  R = 0;
2014     if (doshowcursor)
2015       display.setCursorPos(C, R);
2016     display.markLine(R,1);
2017   }
2018 }