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 } |