Mercurial > 510Connectbot
annotate app/src/main/java/de/mud/terminal/vt320.java @ 518:9acc51a5a98f
Added tag stable-1.9.4-6 for changeset 947ea334735d
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 31 May 2024 13:35:44 -0600 |
parents | f698820bffdf |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". | |
3 * | |
4 * (c) Matthias L. Jugel, Marcus Meiner 1996-2005. All Rights Reserved. | |
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 de.mud.terminal; | |
27 | |
28 import android.text.AndroidCharacter; | |
29 | |
30 import java.util.Properties; | |
31 | |
32 /** | |
33 * Implementation of a VT terminal emulation plus ANSI compatible. | |
34 * <P> | |
35 * <B>Maintainer:</B> Marcus Meißner | |
36 * | |
37 * @version $Id: vt320.java 507 2005-10-25 10:14:52Z marcus $ | |
38 * @author Matthias L. Jugel, Marcus Meißner | |
39 */ | |
40 public abstract class vt320 extends VDUBuffer implements VDUInput { | |
41 | |
42 /** the debug level */ | |
43 private final static int debug = 0; | |
44 private StringBuilder debugStr; | |
45 public abstract void debug(String notice); | |
46 | |
47 /** | |
48 * Write an answer back to the remote host. This is needed to be able to | |
49 * send terminal answers requests like status and type information. | |
50 * @param b the array of bytes to be sent | |
51 */ | |
52 public abstract void write(byte[] b); | |
53 | |
54 /** | |
55 * Write an answer back to the remote host. This is needed to be able to | |
56 * send terminal answers requests like status and type information. | |
57 * @param b the byte to be sent | |
58 */ | |
59 public abstract void write(int b); | |
60 | |
61 /** | |
62 * No more bytes to read from the transport, hook here to test screen changes | |
63 */ | |
64 public void testChanged() { | |
65 /* do nothing by default */ | |
66 } | |
67 | |
496
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
68 // monitor injecting a field |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
69 public void setField(int l, int c, char [] d) { |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
70 // ignore line and column, just send the bytes to the host. |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
71 int n = d.length; |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
72 byte [] b = new byte [n]; |
112
77ac18bc1b2f
cleanup java formatting
Carl Byington <carl@five-ten-sg.com>
parents:
104
diff
changeset
|
73 |
77ac18bc1b2f
cleanup java formatting
Carl Byington <carl@five-ten-sg.com>
parents:
104
diff
changeset
|
74 for (int i = 0; i < n; i++) b[i] = (byte)(d[i] & 0x00ff); |
77ac18bc1b2f
cleanup java formatting
Carl Byington <carl@five-ten-sg.com>
parents:
104
diff
changeset
|
75 |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
76 write(b); |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
77 } |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
78 |
496
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
79 // monitor simulating function key depress |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
80 public void keyDepressed(int keyCode) { |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
81 keyPressed(keyCode, ' ', 0); |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
82 } |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
83 |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
84 // monitor simulating ascii key depress |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
85 public void keyUnicodeDepressed(int keyCode) { |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
86 write((byte)(keyCode & 0x00ff)); |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
87 } |
f698820bffdf
add socket2 monitor protocol
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
88 |
148
69333ca1563c
add ptt button p2 preference
Carl Byington <carl@five-ten-sg.com>
parents:
112
diff
changeset
|
89 public void monitorKey(boolean down) { |
69333ca1563c
add ptt button p2 preference
Carl Byington <carl@five-ten-sg.com>
parents:
112
diff
changeset
|
90 // do nothing |
69333ca1563c
add ptt button p2 preference
Carl Byington <carl@five-ten-sg.com>
parents:
112
diff
changeset
|
91 } |
69333ca1563c
add ptt button p2 preference
Carl Byington <carl@five-ten-sg.com>
parents:
112
diff
changeset
|
92 |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
56
diff
changeset
|
93 /** |
0 | 94 * Play the beep sound ... |
95 */ | |
96 public void beep() { | |
97 /* do nothing by default */ | |
98 } | |
99 | |
41
9621ac4dd5eb
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
100 public void redrawPassthru() { |
9621ac4dd5eb
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
101 redraw(); // VDUBuffer.redraw is protected |
9621ac4dd5eb
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
102 } |
9621ac4dd5eb
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
103 |
0 | 104 /** |
105 * Convenience function for putString(char[], int, int) | |
106 */ | |
107 public void putString(String s) { | |
108 int len = s.length(); | |
109 char[] tmp = new char[len]; | |
110 s.getChars(0, len, tmp, 0); | |
111 putString(tmp, null, 0, len); | |
112 } | |
113 | |
114 /** | |
115 * Put string at current cursor position. Moves cursor | |
116 * according to the String. Does NOT wrap. | |
117 * @param s character array | |
118 * @param start place to start in array | |
119 * @param len number of characters to process | |
120 */ | |
121 public void putString(char[] s, byte[] fullwidths, int start, int len) { | |
122 if (len > 0) { | |
123 //markLine(R, 1); | |
124 int lastChar = -1; | |
125 char c; | |
126 boolean isWide = false; | |
127 | |
128 for (int i = 0; i < len; i++) { | |
129 c = s[start + i]; | |
130 | |
131 // Shortcut for my favorite ASCII | |
132 if (c <= 0x7F) { | |
133 if (lastChar != -1) | |
134 putChar((char) lastChar, isWide, false); | |
135 | |
136 lastChar = c; | |
137 isWide = false; | |
138 } | |
139 else if (!Character.isLowSurrogate(c) && !Character.isHighSurrogate(c)) { | |
140 if (Character.getType(c) == Character.NON_SPACING_MARK) { | |
141 if (lastChar != -1) { | |
142 char nc = Precomposer.precompose((char) lastChar, c); | |
143 putChar(nc, isWide, false); | |
144 lastChar = -1; | |
145 } | |
146 } | |
147 else { | |
148 if (lastChar != -1) | |
149 putChar((char) lastChar, isWide, false); | |
150 | |
151 lastChar = c; | |
152 | |
153 if (fullwidths != null) { | |
154 final byte width = fullwidths[i]; | |
155 isWide = (width == AndroidCharacter.EAST_ASIAN_WIDTH_WIDE) | |
156 || (width == AndroidCharacter.EAST_ASIAN_WIDTH_FULL_WIDTH); | |
157 } | |
158 } | |
159 } | |
160 } | |
161 | |
162 if (lastChar != -1) | |
163 putChar((char) lastChar, isWide, false); | |
164 | |
165 setCursorPosition(C, R); | |
166 redraw(); | |
167 } | |
168 } | |
169 | |
170 protected void sendTelnetCommand(byte cmd) { | |
171 /* do nothing by default */ | |
172 } | |
173 | |
174 /** | |
175 * Sent the changed window size from the terminal to all listeners. | |
176 */ | |
177 protected void setWindowSize(int c, int r) { | |
178 /* To be overridden by Terminal.java */ | |
179 } | |
180 | |
181 @Override | |
182 public void setScreenSize(int c, int r, boolean broadcast) { | |
183 int oldrows = height; | |
184 | |
185 if (debug > 2) { | |
186 if (debugStr == null) | |
187 debugStr = new StringBuilder(); | |
188 | |
189 debugStr.append("setscreensize (") | |
190 .append(c) | |
191 .append(',') | |
192 .append(r) | |
193 .append(',') | |
194 .append(broadcast) | |
195 .append(')'); | |
196 debug(debugStr.toString()); | |
197 debugStr.setLength(0); | |
198 } | |
199 | |
200 super.setScreenSize(c, r, false); | |
201 boolean cursorChanged = false; | |
202 | |
203 // Don't let the cursor go off the screen. | |
204 if (C >= c) { | |
205 C = c - 1; | |
206 cursorChanged = true; | |
207 } | |
208 | |
209 if (R >= r) { | |
210 R = r - 1; | |
211 cursorChanged = true; | |
212 } | |
213 | |
214 if (cursorChanged) { | |
215 setCursorPosition(C, R); | |
216 redraw(); | |
217 } | |
218 | |
219 if (broadcast) { | |
220 setWindowSize(c, r); /* broadcast up */ | |
221 } | |
222 } | |
223 | |
224 | |
225 /** | |
226 * Create a new vt320 terminal and intialize it with useful settings. | |
227 */ | |
228 public vt320(int width, int height) { | |
229 super(width, height); | |
230 debugStr = new StringBuilder(); | |
231 setVMS(false); | |
232 setIBMCharset(false); | |
233 setTerminalID("vt320"); | |
234 setBufferSize(100); | |
235 //setBorder(2, false); | |
236 gx = new char[4]; | |
237 reset(); | |
238 /* top row of numpad */ | |
239 PF1 = "\u001bOP"; | |
240 PF2 = "\u001bOQ"; | |
241 PF3 = "\u001bOR"; | |
242 PF4 = "\u001bOS"; | |
243 /* the 3x2 keyblock on PC keyboards */ | |
244 Insert = new String[4]; | |
245 Remove = new String[4]; | |
246 KeyHome = new String[4]; | |
247 KeyEnd = new String[4]; | |
248 NextScn = new String[4]; | |
249 PrevScn = new String[4]; | |
250 Escape = new String[4]; | |
251 BackSpace = new String[4]; | |
252 TabKey = new String[4]; | |
253 Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~"; | |
254 Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~"; | |
255 PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~"; | |
256 NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~"; | |
257 KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001b[H"; | |
258 KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001b[F"; | |
259 Escape[0] = Escape[1] = Escape[2] = Escape[3] = "\u001b"; | |
260 | |
261 if (vms) { | |
262 BackSpace[1] = "" + (char) 10; // VMS shift deletes word back | |
263 BackSpace[2] = "\u0018"; // VMS control deletes line back | |
264 BackSpace[0] = BackSpace[3] = "\u007f"; // VMS other is delete | |
265 } | |
266 else { | |
267 //BackSpace[0] = BackSpace[1] = BackSpace[2] = BackSpace[3] = "\b"; | |
268 // ConnectBot modifications. | |
269 BackSpace[0] = "\b"; | |
270 BackSpace[1] = "\u007f"; | |
271 BackSpace[2] = "\u001b[3~"; | |
272 BackSpace[3] = "\u001b[2~"; | |
273 } | |
274 | |
275 /* some more VT100 keys */ | |
276 Find = "\u001b[1~"; | |
277 Select = "\u001b[4~"; | |
278 Help = "\u001b[28~"; | |
279 Do = "\u001b[29~"; | |
280 FunctionKey = new String[21]; | |
281 FunctionKey[0] = ""; | |
282 FunctionKey[1] = PF1; | |
283 FunctionKey[2] = PF2; | |
284 FunctionKey[3] = PF3; | |
285 FunctionKey[4] = PF4; | |
286 /* following are defined differently for vt220 / vt132 ... */ | |
287 FunctionKey[5] = "\u001b[15~"; | |
288 FunctionKey[6] = "\u001b[17~"; | |
289 FunctionKey[7] = "\u001b[18~"; | |
290 FunctionKey[8] = "\u001b[19~"; | |
291 FunctionKey[9] = "\u001b[20~"; | |
292 FunctionKey[10] = "\u001b[21~"; | |
293 FunctionKey[11] = "\u001b[23~"; | |
294 FunctionKey[12] = "\u001b[24~"; | |
295 FunctionKey[13] = "\u001b[25~"; | |
296 FunctionKey[14] = "\u001b[26~"; | |
297 FunctionKey[15] = Help; | |
298 FunctionKey[16] = Do; | |
299 FunctionKey[17] = "\u001b[31~"; | |
300 FunctionKey[18] = "\u001b[32~"; | |
301 FunctionKey[19] = "\u001b[33~"; | |
302 FunctionKey[20] = "\u001b[34~"; | |
303 FunctionKeyShift = new String[21]; | |
304 FunctionKeyAlt = new String[21]; | |
305 FunctionKeyCtrl = new String[21]; | |
306 | |
307 for (int i = 0; i < 20; i++) { | |
308 FunctionKeyShift[i] = ""; | |
309 FunctionKeyAlt[i] = ""; | |
310 FunctionKeyCtrl[i] = ""; | |
311 } | |
312 | |
313 FunctionKeyShift[15] = Find; | |
314 FunctionKeyShift[16] = Select; | |
315 TabKey[0] = "\u0009"; | |
316 TabKey[1] = "\u001bOP\u0009"; | |
317 TabKey[2] = TabKey[3] = ""; | |
318 KeyUp = new String[4]; | |
319 KeyUp[0] = "\u001b[A"; | |
320 KeyDown = new String[4]; | |
321 KeyDown[0] = "\u001b[B"; | |
322 KeyRight = new String[4]; | |
323 KeyRight[0] = "\u001b[C"; | |
324 KeyLeft = new String[4]; | |
325 KeyLeft[0] = "\u001b[D"; | |
326 Numpad = new String[10]; | |
327 Numpad[0] = "\u001bOp"; | |
328 Numpad[1] = "\u001bOq"; | |
329 Numpad[2] = "\u001bOr"; | |
330 Numpad[3] = "\u001bOs"; | |
331 Numpad[4] = "\u001bOt"; | |
332 Numpad[5] = "\u001bOu"; | |
333 Numpad[6] = "\u001bOv"; | |
334 Numpad[7] = "\u001bOw"; | |
335 Numpad[8] = "\u001bOx"; | |
336 Numpad[9] = "\u001bOy"; | |
337 KPMinus = PF4; | |
338 KPComma = "\u001bOl"; | |
339 KPPeriod = "\u001bOn"; | |
340 KPEnter = "\u001bOM"; | |
341 NUMPlus = new String[4]; | |
342 NUMPlus[0] = "+"; | |
343 NUMDot = new String[4]; | |
344 NUMDot[0] = "."; | |
345 } | |
346 | |
347 public void setBackspace(int type) { | |
348 switch (type) { | |
349 case DELETE_IS_DEL: | |
350 BackSpace[0] = "\u007f"; | |
351 BackSpace[1] = "\b"; | |
352 break; | |
353 | |
354 case DELETE_IS_BACKSPACE: | |
355 BackSpace[0] = "\b"; | |
356 BackSpace[1] = "\u007f"; | |
357 break; | |
358 } | |
359 } | |
360 | |
361 /** | |
362 * Create a default vt320 terminal with 80 columns and 24 lines. | |
363 */ | |
364 public vt320() { | |
365 this(80, 24); | |
366 } | |
367 | |
368 /** | |
369 * Terminal is mouse-aware and requires (x,y) coordinates of | |
370 * on the terminal (character coordinates) and the button clicked. | |
371 * @param x | |
372 * @param y | |
373 * @param modifiers | |
374 */ | |
375 public void mousePressed(int x, int y, int modifiers) { | |
376 if (mouserpt == 0) | |
377 return; | |
378 | |
379 int mods = modifiers; | |
380 mousebut = 3; | |
381 | |
382 if ((mods & 16) == 16) mousebut = 0; | |
383 | |
384 if ((mods & 8) == 8) mousebut = 1; | |
385 | |
386 if ((mods & 4) == 4) mousebut = 2; | |
387 | |
388 int mousecode; | |
389 | |
390 if (mouserpt == 9) /* X10 Mouse */ | |
391 mousecode = 0x20 | mousebut; | |
392 else /* normal xterm mouse reporting */ | |
393 mousecode = mousebut | 0x20 | ((mods & 7) << 2); | |
394 | |
395 byte b[] = new byte[6]; | |
396 b[0] = 27; | |
397 b[1] = (byte) '['; | |
398 b[2] = (byte) 'M'; | |
399 b[3] = (byte) mousecode; | |
400 b[4] = (byte)(0x20 + x + 1); | |
401 b[5] = (byte)(0x20 + y + 1); | |
402 write(b); // FIXME: writeSpecial here | |
403 } | |
404 | |
405 /** | |
406 * Terminal is mouse-aware and requires the coordinates and button | |
407 * of the release. | |
408 * @param x | |
409 * @param y | |
410 * @param modifiers | |
411 */ | |
412 public void mouseReleased(int x, int y, int modifiers) { | |
413 if (mouserpt == 0) | |
414 return; | |
415 | |
416 /* problem is tht modifiers still have the released button set in them. | |
417 int mods = modifiers; | |
418 mousebut = 3; | |
419 if ((mods & 16)==16) mousebut=0; | |
420 if ((mods & 8)==8 ) mousebut=1; | |
421 if ((mods & 4)==4 ) mousebut=2; | |
422 */ | |
423 int mousecode; | |
424 | |
425 if (mouserpt == 9) | |
426 mousecode = 0x20 + mousebut; /* same as press? appears so. */ | |
427 else | |
428 mousecode = '#'; | |
429 | |
430 byte b[] = new byte[6]; | |
431 b[0] = 27; | |
432 b[1] = (byte) '['; | |
433 b[2] = (byte) 'M'; | |
434 b[3] = (byte) mousecode; | |
435 b[4] = (byte)(0x20 + x + 1); | |
436 b[5] = (byte)(0x20 + y + 1); | |
437 write(b); // FIXME: writeSpecial here | |
438 mousebut = 0; | |
439 } | |
440 | |
441 | |
442 /** we should do localecho (passed from other modules). false is default */ | |
443 private boolean localecho = false; | |
444 | |
445 /** | |
446 * Enable or disable the local echo property of the terminal. | |
447 * @param echo true if the terminal should echo locally | |
448 */ | |
449 public void setLocalEcho(boolean echo) { | |
450 localecho = echo; | |
451 } | |
452 | |
453 /** | |
454 * Enable the VMS mode of the terminal to handle some things differently | |
455 * for VMS hosts. | |
456 * @param vms true for vms mode, false for normal mode | |
457 */ | |
458 public void setVMS(boolean vms) { | |
459 this.vms = vms; | |
460 } | |
461 | |
462 /** | |
463 * Enable the usage of the IBM character set used by some BBS's. Special | |
464 * graphical character are available in this mode. | |
465 * @param ibm true to use the ibm character set | |
466 */ | |
467 public void setIBMCharset(boolean ibm) { | |
468 useibmcharset = ibm; | |
469 } | |
470 | |
471 /** | |
472 * Override the standard key codes used by the terminal emulation. | |
473 * @param codes a properties object containing key code definitions | |
474 */ | |
475 public void setKeyCodes(Properties codes) { | |
476 String res, prefixes[] = {"", "S", "C", "A"}; | |
477 int i; | |
478 | |
479 for (i = 0; i < 10; i++) { | |
480 res = codes.getProperty("NUMPAD" + i); | |
481 | |
482 if (res != null) Numpad[i] = unEscape(res); | |
483 } | |
484 | |
485 for (i = 1; i < 20; i++) { | |
486 res = codes.getProperty("F" + i); | |
487 | |
488 if (res != null) FunctionKey[i] = unEscape(res); | |
489 | |
490 res = codes.getProperty("SF" + i); | |
491 | |
492 if (res != null) FunctionKeyShift[i] = unEscape(res); | |
493 | |
494 res = codes.getProperty("CF" + i); | |
495 | |
496 if (res != null) FunctionKeyCtrl[i] = unEscape(res); | |
497 | |
498 res = codes.getProperty("AF" + i); | |
499 | |
500 if (res != null) FunctionKeyAlt[i] = unEscape(res); | |
501 } | |
502 | |
503 for (i = 0; i < 4; i++) { | |
504 res = codes.getProperty(prefixes[i] + "PGUP"); | |
505 | |
506 if (res != null) PrevScn[i] = unEscape(res); | |
507 | |
508 res = codes.getProperty(prefixes[i] + "PGDOWN"); | |
509 | |
510 if (res != null) NextScn[i] = unEscape(res); | |
511 | |
512 res = codes.getProperty(prefixes[i] + "END"); | |
513 | |
514 if (res != null) KeyEnd[i] = unEscape(res); | |
515 | |
516 res = codes.getProperty(prefixes[i] + "HOME"); | |
517 | |
518 if (res != null) KeyHome[i] = unEscape(res); | |
519 | |
520 res = codes.getProperty(prefixes[i] + "INSERT"); | |
521 | |
522 if (res != null) Insert[i] = unEscape(res); | |
523 | |
524 res = codes.getProperty(prefixes[i] + "REMOVE"); | |
525 | |
526 if (res != null) Remove[i] = unEscape(res); | |
527 | |
528 res = codes.getProperty(prefixes[i] + "UP"); | |
529 | |
530 if (res != null) KeyUp[i] = unEscape(res); | |
531 | |
532 res = codes.getProperty(prefixes[i] + "DOWN"); | |
533 | |
534 if (res != null) KeyDown[i] = unEscape(res); | |
535 | |
536 res = codes.getProperty(prefixes[i] + "LEFT"); | |
537 | |
538 if (res != null) KeyLeft[i] = unEscape(res); | |
539 | |
540 res = codes.getProperty(prefixes[i] + "RIGHT"); | |
541 | |
542 if (res != null) KeyRight[i] = unEscape(res); | |
543 | |
544 res = codes.getProperty(prefixes[i] + "ESCAPE"); | |
545 | |
546 if (res != null) Escape[i] = unEscape(res); | |
547 | |
548 res = codes.getProperty(prefixes[i] + "BACKSPACE"); | |
549 | |
550 if (res != null) BackSpace[i] = unEscape(res); | |
551 | |
552 res = codes.getProperty(prefixes[i] + "TAB"); | |
553 | |
554 if (res != null) TabKey[i] = unEscape(res); | |
555 | |
556 res = codes.getProperty(prefixes[i] + "NUMPLUS"); | |
557 | |
558 if (res != null) NUMPlus[i] = unEscape(res); | |
559 | |
560 res = codes.getProperty(prefixes[i] + "NUMDECIMAL"); | |
561 | |
562 if (res != null) NUMDot[i] = unEscape(res); | |
563 } | |
564 } | |
565 | |
566 /** | |
567 * Set the terminal id used to identify this terminal. | |
568 * @param terminalID the id string | |
569 */ | |
570 public void setTerminalID(String terminalID) { | |
571 this.terminalID = terminalID; | |
572 | |
573 if (terminalID.equals("scoansi")) { | |
574 FunctionKey[1] = "\u001b[M"; FunctionKey[2] = "\u001b[N"; | |
575 FunctionKey[3] = "\u001b[O"; FunctionKey[4] = "\u001b[P"; | |
576 FunctionKey[5] = "\u001b[Q"; FunctionKey[6] = "\u001b[R"; | |
577 FunctionKey[7] = "\u001b[S"; FunctionKey[8] = "\u001b[T"; | |
578 FunctionKey[9] = "\u001b[U"; FunctionKey[10] = "\u001b[V"; | |
579 FunctionKey[11] = "\u001b[W"; FunctionKey[12] = "\u001b[X"; | |
580 FunctionKey[13] = "\u001b[Y"; FunctionKey[14] = "?"; | |
581 FunctionKey[15] = "\u001b[a"; FunctionKey[16] = "\u001b[b"; | |
582 FunctionKey[17] = "\u001b[c"; FunctionKey[18] = "\u001b[d"; | |
583 FunctionKey[19] = "\u001b[e"; FunctionKey[20] = "\u001b[f"; | |
584 PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[I"; | |
585 NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[G"; | |
586 // more theoretically. | |
587 } | |
588 } | |
589 | |
590 public void setAnswerBack(String ab) { | |
591 this.answerBack = unEscape(ab); | |
592 } | |
593 | |
594 /** | |
595 * Get the terminal id used to identify this terminal. | |
596 */ | |
597 public String getTerminalID() { | |
598 return terminalID; | |
599 } | |
600 | |
601 /** | |
602 * A small conveniance method thar converts the string to a byte array | |
603 * for sending. | |
604 * @param s the string to be sent | |
605 */ | |
606 private boolean write(String s, boolean doecho) { | |
607 if (debug > 2) { | |
608 debugStr.append("write(|") | |
609 .append(s) | |
610 .append("|,") | |
611 .append(doecho); | |
612 debug(debugStr.toString()); | |
613 debugStr.setLength(0); | |
614 } | |
615 | |
616 if (s == null) // aka the empty string. | |
617 return true; | |
618 | |
619 /* NOTE: getBytes() honours some locale, it *CONVERTS* the string. | |
620 * However, we output only 7bit stuff towards the target, and *some* | |
621 * 8 bit control codes. We must not mess up the latter, so we do hand | |
622 * by hand copy. | |
623 */ | |
624 byte arr[] = new byte[s.length()]; | |
625 | |
626 for (int i = 0; i < s.length(); i++) { | |
627 arr[i] = (byte) s.charAt(i); | |
628 } | |
629 | |
630 write(arr); | |
631 | |
632 if (doecho) | |
633 putString(s); | |
634 | |
635 return true; | |
636 } | |
637 | |
638 private boolean write(int s, boolean doecho) { | |
639 if (debug > 2) { | |
640 debugStr.append("write(|") | |
641 .append(s) | |
642 .append("|,") | |
643 .append(doecho); | |
644 debug(debugStr.toString()); | |
645 debugStr.setLength(0); | |
646 } | |
647 | |
648 write(s); | |
649 | |
650 // TODO check if character is wide | |
651 if (doecho) | |
652 putChar((char)s, false, false); | |
653 | |
654 return true; | |
655 } | |
656 | |
657 private boolean write(String s) { | |
658 return write(s, localecho); | |
659 } | |
660 | |
661 // =================================================================== | |
662 // the actual terminal emulation code comes here: | |
663 // =================================================================== | |
664 | |
665 private String terminalID = "vt320"; | |
666 private String answerBack = "Use Terminal.answerback to set ...\n"; | |
667 | |
668 // X - COLUMNS, Y - ROWS | |
669 int R, C; | |
670 int attributes = 0; | |
671 | |
672 int Sc, Sr, Sa, Stm, Sbm; | |
673 char Sgr, Sgl; | |
674 char Sgx[]; | |
675 | |
676 int insertmode = 0; | |
677 int statusmode = 0; | |
678 boolean vt52mode = false; | |
679 boolean keypadmode = false; /* false - numeric, true - application */ | |
680 boolean output8bit = false; | |
681 int normalcursor = 0; | |
682 boolean moveoutsidemargins = true; | |
683 boolean wraparound = true; | |
684 boolean sendcrlf = true; | |
685 boolean capslock = false; | |
686 boolean numlock = false; | |
687 int mouserpt = 0; | |
688 byte mousebut = 0; | |
689 | |
690 boolean useibmcharset = false; | |
691 | |
692 int lastwaslf = 0; | |
693 boolean usedcharsets = false; | |
694 | |
695 private final static char ESC = 27; | |
696 private final static char IND = 132; | |
697 private final static char NEL = 133; | |
698 private final static char RI = 141; | |
699 private final static char SS2 = 142; | |
700 private final static char SS3 = 143; | |
701 private final static char DCS = 144; | |
702 private final static char HTS = 136; | |
703 private final static char CSI = 155; | |
704 private final static char OSC = 157; | |
705 private final static int TSTATE_DATA = 0; | |
706 private final static int TSTATE_ESC = 1; /* ESC */ | |
707 private final static int TSTATE_CSI = 2; /* ESC [ */ | |
708 private final static int TSTATE_DCS = 3; /* ESC P */ | |
709 private final static int TSTATE_DCEQ = 4; /* ESC [? */ | |
710 private final static int TSTATE_ESCSQUARE = 5; /* ESC # */ | |
711 private final static int TSTATE_OSC = 6; /* ESC ] */ | |
712 private final static int TSTATE_SETG0 = 7; /* ESC (? */ | |
713 private final static int TSTATE_SETG1 = 8; /* ESC )? */ | |
714 private final static int TSTATE_SETG2 = 9; /* ESC *? */ | |
715 private final static int TSTATE_SETG3 = 10; /* ESC +? */ | |
716 private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */ | |
717 private final static int TSTATE_CSI_EX = 12; /* ESC [ ! */ | |
718 private final static int TSTATE_ESCSPACE = 13; /* ESC <space> */ | |
719 private final static int TSTATE_VT52X = 14; | |
720 private final static int TSTATE_VT52Y = 15; | |
721 private final static int TSTATE_CSI_TICKS = 16; | |
722 private final static int TSTATE_CSI_EQUAL = 17; /* ESC [ = */ | |
723 private final static int TSTATE_TITLE = 18; /* xterm title */ | |
724 | |
725 /* Keys we support */ | |
175
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
726 public final static int KEY_PAUSE = 1; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
727 public final static int KEY_F1 = 2; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
728 public final static int KEY_F2 = 3; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
729 public final static int KEY_F3 = 4; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
730 public final static int KEY_F4 = 5; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
731 public final static int KEY_F5 = 6; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
732 public final static int KEY_F6 = 7; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
733 public final static int KEY_F7 = 8; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
734 public final static int KEY_F8 = 9; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
735 public final static int KEY_F9 = 10; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
736 public final static int KEY_F10 = 11; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
737 public final static int KEY_F11 = 12; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
738 public final static int KEY_F12 = 13; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
739 public final static int KEY_F13 = 14; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
740 public final static int KEY_F14 = 15; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
741 public final static int KEY_F15 = 16; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
742 public final static int KEY_F16 = 17; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
743 public final static int KEY_F17 = 18; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
744 public final static int KEY_F18 = 19; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
745 public final static int KEY_F19 = 20; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
746 public final static int KEY_F20 = 21; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
747 public final static int KEY_F21 = 22; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
748 public final static int KEY_F22 = 23; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
749 public final static int KEY_F23 = 24; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
750 public final static int KEY_F24 = 25; // only used by tn5250 |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
751 public final static int KEY_UP = 26; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
752 public final static int KEY_DOWN = 27; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
753 public final static int KEY_LEFT = 28; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
754 public final static int KEY_RIGHT = 29; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
755 public final static int KEY_PAGE_DOWN = 30; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
756 public final static int KEY_PAGE_UP = 31; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
757 public final static int KEY_INSERT = 32; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
758 public final static int KEY_DELETE = 33; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
759 public final static int KEY_BACK_SPACE = 34; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
760 public final static int KEY_HOME = 35; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
761 public final static int KEY_END = 36; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
762 public final static int KEY_NUM_LOCK = 37; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
763 public final static int KEY_CAPS_LOCK = 38; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
764 public final static int KEY_SHIFT = 39; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
765 public final static int KEY_CONTROL = 40; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
766 public final static int KEY_ALT = 41; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
767 public final static int KEY_ENTER = 42; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
768 public final static int KEY_NUMPAD0 = 43; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
769 public final static int KEY_NUMPAD1 = 44; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
770 public final static int KEY_NUMPAD2 = 45; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
771 public final static int KEY_NUMPAD3 = 46; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
772 public final static int KEY_NUMPAD4 = 47; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
773 public final static int KEY_NUMPAD5 = 48; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
774 public final static int KEY_NUMPAD6 = 49; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
775 public final static int KEY_NUMPAD7 = 50; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
776 public final static int KEY_NUMPAD8 = 51; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
777 public final static int KEY_NUMPAD9 = 52; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
778 public final static int KEY_DECIMAL = 53; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
779 public final static int KEY_ADD = 54; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
780 public final static int KEY_ESCAPE = 55; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
781 public final static int KEY_TAB = 56; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
782 public final static int KEY_SYSREQ = 57; // only used by tn5250 |
0 | 783 |
784 public final static int DELETE_IS_DEL = 0; | |
785 public final static int DELETE_IS_BACKSPACE = 1; | |
786 | |
787 /* The graphics charsets | |
788 * B - default ASCII | |
789 * A - ISO Latin 1 | |
790 * 0 - DEC SPECIAL | |
791 * < - User defined | |
792 * .... | |
793 */ | |
794 char gx[]; | |
795 char gl; // GL (left charset) | |
796 char gr; // GR (right charset) | |
797 int onegl; // single shift override for GL. | |
798 | |
799 // Map from scoansi linedrawing to DEC _and_ unicode (for the stuff which | |
800 // is not in linedrawing). Got from experimenting with scoadmin. | |
801 private final static String scoansi_acs = "Tm7k3x4u?kZl@mYjEnB\u2566DqCtAvM\u2550:\u2551N\u2557I\u2554;\u2557H\u255a0a<\u255d"; | |
802 // array to store DEC Special -> Unicode mapping | |
803 // Unicode DEC Unicode name (DEC name) | |
804 private static char DECSPECIAL[] = { | |
805 '\u0040', //5f blank | |
806 '\u2666', //60 black diamond | |
807 '\u2592', //61 grey square | |
808 '\u2409', //62 Horizontal tab (ht) pict. for control | |
809 '\u240c', //63 Form Feed (ff) pict. for control | |
810 '\u240d', //64 Carriage Return (cr) pict. for control | |
811 '\u240a', //65 Line Feed (lf) pict. for control | |
812 '\u00ba', //66 Masculine ordinal indicator | |
813 '\u00b1', //67 Plus or minus sign | |
814 '\u2424', //68 New Line (nl) pict. for control | |
815 '\u240b', //69 Vertical Tab (vt) pict. for control | |
816 '\u2518', //6a Forms light up and left | |
817 '\u2510', //6b Forms light down and left | |
818 '\u250c', //6c Forms light down and right | |
819 '\u2514', //6d Forms light up and right | |
820 '\u253c', //6e Forms light vertical and horizontal | |
821 '\u2594', //6f Upper 1/8 block (Scan 1) | |
822 '\u2580', //70 Upper 1/2 block (Scan 3) | |
823 '\u2500', //71 Forms light horizontal or ?em dash? (Scan 5) | |
824 '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7) | |
825 '\u005f', //73 \u005f underscore or \u2581 lower 1/8 (Scan 9) | |
826 '\u251c', //74 Forms light vertical and right | |
827 '\u2524', //75 Forms light vertical and left | |
828 '\u2534', //76 Forms light up and horizontal | |
829 '\u252c', //77 Forms light down and horizontal | |
830 '\u2502', //78 vertical bar | |
831 '\u2264', //79 less than or equal | |
832 '\u2265', //7a greater than or equal | |
833 '\u00b6', //7b paragraph | |
834 '\u2260', //7c not equal | |
835 '\u00a3', //7d Pound Sign (british) | |
836 '\u00b7' //7e Middle Dot | |
837 }; | |
838 | |
839 /** Strings to send on function key pressing */ | |
840 private String Numpad[]; | |
841 private String FunctionKey[]; | |
842 private String FunctionKeyShift[]; | |
843 private String FunctionKeyCtrl[]; | |
844 private String FunctionKeyAlt[]; | |
845 private String TabKey[]; | |
846 private String KeyUp[], KeyDown[], KeyLeft[], KeyRight[]; | |
847 private String KPMinus, KPComma, KPPeriod, KPEnter; | |
848 private String PF1, PF2, PF3, PF4; | |
849 private String Help, Do, Find, Select; | |
850 | |
851 private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[]; | |
852 private String Escape[], BackSpace[], NUMDot[], NUMPlus[]; | |
853 | |
854 private String osc, dcs; /* to memorize OSC & DCS control sequence */ | |
855 | |
856 /** vt320 state variable (internal) */ | |
857 private int term_state = TSTATE_DATA; | |
858 /** in vms mode, set by Terminal.VMS property */ | |
859 private boolean vms = false; | |
860 /** Tabulators */ | |
861 private byte[] Tabs; | |
862 /** The list of integers as used by CSI */ | |
863 private int[] DCEvars = new int[30]; | |
864 private int DCEvar; | |
865 | |
866 /** | |
867 * Replace escape code characters (backslash + identifier) with their | |
868 * respective codes. | |
869 * @param tmp the string to be parsed | |
870 * @return a unescaped string | |
871 */ | |
872 static String unEscape(String tmp) { | |
873 int idx = 0, oldidx = 0; | |
874 String cmd; | |
875 // f.println("unescape("+tmp+")"); | |
876 cmd = ""; | |
877 | |
878 while ((idx = tmp.indexOf('\\', oldidx)) >= 0 && | |
879 ++idx <= tmp.length()) { | |
880 cmd += tmp.substring(oldidx, idx - 1); | |
881 | |
882 if (idx == tmp.length()) return cmd; | |
883 | |
884 switch (tmp.charAt(idx)) { | |
885 case 'b': | |
886 cmd += "\b"; | |
887 break; | |
888 | |
889 case 'e': | |
890 cmd += "\u001b"; | |
891 break; | |
892 | |
893 case 'n': | |
894 cmd += "\n"; | |
895 break; | |
896 | |
897 case 'r': | |
898 cmd += "\r"; | |
899 break; | |
900 | |
901 case 't': | |
902 cmd += "\t"; | |
903 break; | |
904 | |
905 case 'v': | |
906 cmd += "\u000b"; | |
907 break; | |
908 | |
909 case 'a': | |
910 cmd += "\u0012"; | |
911 break; | |
912 | |
913 default : | |
914 if ((tmp.charAt(idx) >= '0') && (tmp.charAt(idx) <= '9')) { | |
915 int i; | |
916 | |
917 for (i = idx; i < tmp.length(); i++) | |
918 if ((tmp.charAt(i) < '0') || (tmp.charAt(i) > '9')) | |
919 break; | |
920 | |
921 cmd += (char) Integer.parseInt(tmp.substring(idx, i)); | |
922 idx = i - 1; | |
923 } | |
924 else | |
925 cmd += tmp.substring(idx, ++idx); | |
926 | |
927 break; | |
928 } | |
929 | |
930 oldidx = ++idx; | |
931 } | |
932 | |
933 if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx); | |
934 | |
935 return cmd; | |
936 } | |
937 | |
938 /** | |
939 * A small conveniance method thar converts a 7bit string to the 8bit | |
940 * version depending on VT52/Output8Bit mode. | |
941 * | |
942 * @param s the string to be sent | |
943 */ | |
944 private boolean writeSpecial(String s) { | |
945 if (s == null) | |
946 return true; | |
947 | |
948 if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == 'O'))) { | |
949 if (vt52mode) { | |
950 if ((s.charAt(2) >= 'P') && (s.charAt(2) <= 'S')) { | |
951 s = "\u001b" + s.substring(2); /* ESC x */ | |
952 } | |
953 else { | |
954 s = "\u001b?" + s.substring(2); /* ESC ? x */ | |
955 } | |
956 } | |
957 else { | |
958 if (output8bit) { | |
959 s = "\u008f" + s.substring(2); /* SS3 x */ | |
960 } /* else keep string as it is */ | |
961 } | |
962 } | |
963 | |
964 if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == '['))) { | |
965 if (output8bit) { | |
966 s = "\u009b" + s.substring(2); /* CSI ... */ | |
967 } /* else keep */ | |
968 } | |
969 | |
970 return write(s, false); | |
971 } | |
972 | |
973 /** | |
104
171e0a977544
cleanup keystroke handling
Carl Byington <carl@five-ten-sg.com>
parents:
72
diff
changeset
|
974 * main keytyping event handler for all the special function and modifier keys |
171e0a977544
cleanup keystroke handling
Carl Byington <carl@five-ten-sg.com>
parents:
72
diff
changeset
|
975 * the normal keys are processed by write(byte b); |
0 | 976 */ |
977 public void keyPressed(int keyCode, char keyChar, int modifiers) { | |
978 boolean control = (modifiers & VDUInput.KEY_CONTROL) != 0; | |
979 boolean shift = (modifiers & VDUInput.KEY_SHIFT) != 0; | |
980 boolean alt = (modifiers & VDUInput.KEY_ALT) != 0; | |
981 | |
982 if (debug > 1) { | |
983 debugStr.append("keyPressed(") | |
984 .append(keyCode) | |
985 .append(", ") | |
986 .append((int)keyChar) | |
987 .append(", ") | |
988 .append(modifiers) | |
989 .append(')'); | |
990 debug(debugStr.toString()); | |
991 debugStr.setLength(0); | |
992 } | |
993 | |
994 int xind; | |
995 String fmap[]; | |
996 xind = 0; | |
997 fmap = FunctionKey; | |
998 | |
999 if (shift) { | |
1000 fmap = FunctionKeyShift; | |
1001 xind = 1; | |
1002 } | |
1003 | |
1004 if (control) { | |
1005 fmap = FunctionKeyCtrl; | |
1006 xind = 2; | |
1007 } | |
1008 | |
1009 if (alt) { | |
1010 fmap = FunctionKeyAlt; | |
1011 xind = 3; | |
1012 } | |
1013 | |
1014 switch (keyCode) { | |
1015 case KEY_PAUSE: | |
1016 if (shift || control) | |
1017 sendTelnetCommand((byte) 243); // BREAK | |
1018 | |
1019 break; | |
1020 | |
1021 case KEY_F1: | |
1022 writeSpecial(fmap[1]); | |
1023 break; | |
1024 | |
1025 case KEY_F2: | |
1026 writeSpecial(fmap[2]); | |
1027 break; | |
1028 | |
1029 case KEY_F3: | |
1030 writeSpecial(fmap[3]); | |
1031 break; | |
1032 | |
1033 case KEY_F4: | |
1034 writeSpecial(fmap[4]); | |
1035 break; | |
1036 | |
1037 case KEY_F5: | |
1038 writeSpecial(fmap[5]); | |
1039 break; | |
1040 | |
1041 case KEY_F6: | |
1042 writeSpecial(fmap[6]); | |
1043 break; | |
1044 | |
1045 case KEY_F7: | |
1046 writeSpecial(fmap[7]); | |
1047 break; | |
1048 | |
1049 case KEY_F8: | |
1050 writeSpecial(fmap[8]); | |
1051 break; | |
1052 | |
1053 case KEY_F9: | |
1054 writeSpecial(fmap[9]); | |
1055 break; | |
1056 | |
1057 case KEY_F10: | |
1058 writeSpecial(fmap[10]); | |
1059 break; | |
1060 | |
1061 case KEY_F11: | |
1062 writeSpecial(fmap[11]); | |
1063 break; | |
1064 | |
1065 case KEY_F12: | |
1066 writeSpecial(fmap[12]); | |
1067 break; | |
1068 | |
175
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1069 case KEY_F13: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1070 case KEY_F14: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1071 case KEY_F15: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1072 case KEY_F16: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1073 case KEY_F17: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1074 case KEY_F18: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1075 case KEY_F19: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1076 case KEY_F20: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1077 case KEY_F21: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1078 case KEY_F22: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1079 case KEY_F23: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1080 case KEY_F24: |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1081 break; |
2a7199ad90be
send cursor movement caused by user keystrokes to the monitor
Carl Byington <carl@five-ten-sg.com>
parents:
167
diff
changeset
|
1082 |
0 | 1083 case KEY_UP: |
1084 writeSpecial(KeyUp[xind]); | |
1085 break; | |
1086 | |
1087 case KEY_DOWN: | |
1088 writeSpecial(KeyDown[xind]); | |
1089 break; | |
1090 | |
1091 case KEY_LEFT: | |
1092 writeSpecial(KeyLeft[xind]); | |
1093 break; | |
1094 | |
1095 case KEY_RIGHT: | |
1096 writeSpecial(KeyRight[xind]); | |
1097 break; | |
1098 | |
1099 case KEY_PAGE_DOWN: | |
1100 writeSpecial(NextScn[xind]); | |
1101 break; | |
1102 | |
1103 case KEY_PAGE_UP: | |
1104 writeSpecial(PrevScn[xind]); | |
1105 break; | |
1106 | |
1107 case KEY_INSERT: | |
1108 writeSpecial(Insert[xind]); | |
1109 break; | |
1110 | |
1111 case KEY_DELETE: | |
1112 writeSpecial(Remove[xind]); | |
1113 break; | |
1114 | |
1115 case KEY_BACK_SPACE: | |
1116 writeSpecial(BackSpace[xind]); | |
1117 | |
1118 if (localecho) { | |
1119 if (BackSpace[xind] == "\b") { | |
1120 putString("\b \b"); // make the last char 'deleted' | |
1121 } | |
1122 else { | |
1123 putString(BackSpace[xind]); // echo it | |
1124 } | |
1125 } | |
1126 | |
1127 break; | |
1128 | |
1129 case KEY_HOME: | |
1130 writeSpecial(KeyHome[xind]); | |
1131 break; | |
1132 | |
1133 case KEY_END: | |
1134 writeSpecial(KeyEnd[xind]); | |
1135 break; | |
1136 | |
1137 case KEY_NUM_LOCK: | |
1138 if (vms && control) { | |
1139 writeSpecial(PF1); | |
1140 } | |
1141 | |
1142 if (!control) | |
1143 numlock = !numlock; | |
1144 | |
1145 break; | |
1146 | |
1147 case KEY_CAPS_LOCK: | |
1148 capslock = !capslock; | |
53
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1149 break; |
0 | 1150 |
1151 case KEY_SHIFT: | |
1152 case KEY_CONTROL: | |
1153 case KEY_ALT: | |
53
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1154 break; |
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1155 |
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1156 case KEY_ESCAPE: |
104
171e0a977544
cleanup keystroke handling
Carl Byington <carl@five-ten-sg.com>
parents:
72
diff
changeset
|
1157 writeSpecial(Escape[xind]); |
53
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1158 break; |
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1159 |
56
556c387889b9
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
53
diff
changeset
|
1160 case KEY_ENTER: |
556c387889b9
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
53
diff
changeset
|
1161 write(0x0d); |
556c387889b9
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
53
diff
changeset
|
1162 break; |
556c387889b9
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
53
diff
changeset
|
1163 |
53
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1164 case KEY_TAB: |
104
171e0a977544
cleanup keystroke handling
Carl Byington <carl@five-ten-sg.com>
parents:
72
diff
changeset
|
1165 writeSpecial(TabKey[xind]); |
53
e872762ec105
start tn5250 integration
Carl Byington <carl@five-ten-sg.com>
parents:
45
diff
changeset
|
1166 break; |
0 | 1167 |
1168 default: | |
1169 break; | |
1170 } | |
1171 } | |
1172 | |
1173 private void handle_dcs(String dcs) { | |
1174 debugStr.append("DCS: ") | |
1175 .append(dcs); | |
1176 debug(debugStr.toString()); | |
1177 debugStr.setLength(0); | |
1178 } | |
1179 | |
1180 private void handle_osc(String osc) { | |
1181 if (osc.length() > 2 && osc.substring(0, 2).equals("4;")) { | |
1182 // Define color palette | |
1183 String[] colorData = osc.split(";"); | |
1184 | |
1185 try { | |
1186 int colorIndex = Integer.parseInt(colorData[1]); | |
1187 | |
1188 if ("rgb:".equals(colorData[2].substring(0, 4))) { | |
1189 String[] rgb = colorData[2].substring(4).split("/"); | |
1190 int red = Integer.parseInt(rgb[0].substring(0, 2), 16) & 0xFF; | |
1191 int green = Integer.parseInt(rgb[1].substring(0, 2), 16) & 0xFF; | |
1192 int blue = Integer.parseInt(rgb[2].substring(0, 2), 16) & 0xFF; | |
1193 display.setColor(colorIndex, red, green, blue); | |
1194 } | |
1195 } | |
1196 catch (Exception e) { | |
1197 debugStr.append("OSC: invalid color sequence encountered: ") | |
1198 .append(osc); | |
1199 debug(debugStr.toString()); | |
1200 debugStr.setLength(0); | |
1201 } | |
1202 } | |
1203 else | |
1204 debug("OSC: " + osc); | |
1205 } | |
1206 | |
1207 private final static char unimap[] = { | |
1208 //# | |
1209 //# Name: cp437_DOSLatinUS to Unicode table | |
1210 //# Unicode version: 1.1 | |
1211 //# Table version: 1.1 | |
1212 //# Table format: Format A | |
1213 //# Date: 03/31/95 | |
1214 //# Authors: Michel Suignard <michelsu@microsoft.com> | |
1215 //# Lori Hoerth <lorih@microsoft.com> | |
1216 //# General notes: none | |
1217 //# | |
1218 //# Format: Three tab-separated columns | |
1219 //# Column #1 is the cp1255_WinHebrew code (in hex) | |
1220 //# Column #2 is the Unicode (in hex as 0xXXXX) | |
1221 //# Column #3 is the Unicode name (follows a comment sign, '#') | |
1222 //# | |
1223 //# The entries are in cp437_DOSLatinUS order | |
1224 //# | |
1225 | |
1226 0x0000, // #NULL | |
1227 0x0001, // #START OF HEADING | |
1228 0x0002, // #START OF TEXT | |
1229 0x0003, // #END OF TEXT | |
1230 0x0004, // #END OF TRANSMISSION | |
1231 0x0005, // #ENQUIRY | |
1232 0x0006, // #ACKNOWLEDGE | |
1233 0x0007, // #BELL | |
1234 0x0008, // #BACKSPACE | |
1235 0x0009, // #HORIZONTAL TABULATION | |
1236 0x000a, // #LINE FEED | |
1237 0x000b, // #VERTICAL TABULATION | |
1238 0x000c, // #FORM FEED | |
1239 0x000d, // #CARRIAGE RETURN | |
1240 0x000e, // #SHIFT OUT | |
1241 0x000f, // #SHIFT IN | |
1242 0x0010, // #DATA LINK ESCAPE | |
1243 0x0011, // #DEVICE CONTROL ONE | |
1244 0x0012, // #DEVICE CONTROL TWO | |
1245 0x0013, // #DEVICE CONTROL THREE | |
1246 0x0014, // #DEVICE CONTROL FOUR | |
1247 0x0015, // #NEGATIVE ACKNOWLEDGE | |
1248 0x0016, // #SYNCHRONOUS IDLE | |
1249 0x0017, // #END OF TRANSMISSION BLOCK | |
1250 0x0018, // #CANCEL | |
1251 0x0019, // #END OF MEDIUM | |
1252 0x001a, // #SUBSTITUTE | |
1253 0x001b, // #ESCAPE | |
1254 0x001c, // #FILE SEPARATOR | |
1255 0x001d, // #GROUP SEPARATOR | |
1256 0x001e, // #RECORD SEPARATOR | |
1257 0x001f, // #UNIT SEPARATOR | |
1258 0x0020, // #SPACE | |
1259 0x0021, // #EXCLAMATION MARK | |
1260 0x0022, // #QUOTATION MARK | |
1261 0x0023, // #NUMBER SIGN | |
1262 0x0024, // #DOLLAR SIGN | |
1263 0x0025, // #PERCENT SIGN | |
1264 0x0026, // #AMPERSAND | |
1265 0x0027, // #APOSTROPHE | |
1266 0x0028, // #LEFT PARENTHESIS | |
1267 0x0029, // #RIGHT PARENTHESIS | |
1268 0x002a, // #ASTERISK | |
1269 0x002b, // #PLUS SIGN | |
1270 0x002c, // #COMMA | |
1271 0x002d, // #HYPHEN-MINUS | |
1272 0x002e, // #FULL STOP | |
1273 0x002f, // #SOLIDUS | |
1274 0x0030, // #DIGIT ZERO | |
1275 0x0031, // #DIGIT ONE | |
1276 0x0032, // #DIGIT TWO | |
1277 0x0033, // #DIGIT THREE | |
1278 0x0034, // #DIGIT FOUR | |
1279 0x0035, // #DIGIT FIVE | |
1280 0x0036, // #DIGIT SIX | |
1281 0x0037, // #DIGIT SEVEN | |
1282 0x0038, // #DIGIT EIGHT | |
1283 0x0039, // #DIGIT NINE | |
1284 0x003a, // #COLON | |
1285 0x003b, // #SEMICOLON | |
1286 0x003c, // #LESS-THAN SIGN | |
1287 0x003d, // #EQUALS SIGN | |
1288 0x003e, // #GREATER-THAN SIGN | |
1289 0x003f, // #QUESTION MARK | |
1290 0x0040, // #COMMERCIAL AT | |
1291 0x0041, // #LATIN CAPITAL LETTER A | |
1292 0x0042, // #LATIN CAPITAL LETTER B | |
1293 0x0043, // #LATIN CAPITAL LETTER C | |
1294 0x0044, // #LATIN CAPITAL LETTER D | |
1295 0x0045, // #LATIN CAPITAL LETTER E | |
1296 0x0046, // #LATIN CAPITAL LETTER F | |
1297 0x0047, // #LATIN CAPITAL LETTER G | |
1298 0x0048, // #LATIN CAPITAL LETTER H | |
1299 0x0049, // #LATIN CAPITAL LETTER I | |
1300 0x004a, // #LATIN CAPITAL LETTER J | |
1301 0x004b, // #LATIN CAPITAL LETTER K | |
1302 0x004c, // #LATIN CAPITAL LETTER L | |
1303 0x004d, // #LATIN CAPITAL LETTER M | |
1304 0x004e, // #LATIN CAPITAL LETTER N | |
1305 0x004f, // #LATIN CAPITAL LETTER O | |
1306 0x0050, // #LATIN CAPITAL LETTER P | |
1307 0x0051, // #LATIN CAPITAL LETTER Q | |
1308 0x0052, // #LATIN CAPITAL LETTER R | |
1309 0x0053, // #LATIN CAPITAL LETTER S | |
1310 0x0054, // #LATIN CAPITAL LETTER T | |
1311 0x0055, // #LATIN CAPITAL LETTER U | |
1312 0x0056, // #LATIN CAPITAL LETTER V | |
1313 0x0057, // #LATIN CAPITAL LETTER W | |
1314 0x0058, // #LATIN CAPITAL LETTER X | |
1315 0x0059, // #LATIN CAPITAL LETTER Y | |
1316 0x005a, // #LATIN CAPITAL LETTER Z | |
1317 0x005b, // #LEFT SQUARE BRACKET | |
1318 0x005c, // #REVERSE SOLIDUS | |
1319 0x005d, // #RIGHT SQUARE BRACKET | |
1320 0x005e, // #CIRCUMFLEX ACCENT | |
1321 0x005f, // #LOW LINE | |
1322 0x0060, // #GRAVE ACCENT | |
1323 0x0061, // #LATIN SMALL LETTER A | |
1324 0x0062, // #LATIN SMALL LETTER B | |
1325 0x0063, // #LATIN SMALL LETTER C | |
1326 0x0064, // #LATIN SMALL LETTER D | |
1327 0x0065, // #LATIN SMALL LETTER E | |
1328 0x0066, // #LATIN SMALL LETTER F | |
1329 0x0067, // #LATIN SMALL LETTER G | |
1330 0x0068, // #LATIN SMALL LETTER H | |
1331 0x0069, // #LATIN SMALL LETTER I | |
1332 0x006a, // #LATIN SMALL LETTER J | |
1333 0x006b, // #LATIN SMALL LETTER K | |
1334 0x006c, // #LATIN SMALL LETTER L | |
1335 0x006d, // #LATIN SMALL LETTER M | |
1336 0x006e, // #LATIN SMALL LETTER N | |
1337 0x006f, // #LATIN SMALL LETTER O | |
1338 0x0070, // #LATIN SMALL LETTER P | |
1339 0x0071, // #LATIN SMALL LETTER Q | |
1340 0x0072, // #LATIN SMALL LETTER R | |
1341 0x0073, // #LATIN SMALL LETTER S | |
1342 0x0074, // #LATIN SMALL LETTER T | |
1343 0x0075, // #LATIN SMALL LETTER U | |
1344 0x0076, // #LATIN SMALL LETTER V | |
1345 0x0077, // #LATIN SMALL LETTER W | |
1346 0x0078, // #LATIN SMALL LETTER X | |
1347 0x0079, // #LATIN SMALL LETTER Y | |
1348 0x007a, // #LATIN SMALL LETTER Z | |
1349 0x007b, // #LEFT CURLY BRACKET | |
1350 0x007c, // #VERTICAL LINE | |
1351 0x007d, // #RIGHT CURLY BRACKET | |
1352 0x007e, // #TILDE | |
1353 0x007f, // #DELETE | |
1354 0x00c7, // #LATIN CAPITAL LETTER C WITH CEDILLA | |
1355 0x00fc, // #LATIN SMALL LETTER U WITH DIAERESIS | |
1356 0x00e9, // #LATIN SMALL LETTER E WITH ACUTE | |
1357 0x00e2, // #LATIN SMALL LETTER A WITH CIRCUMFLEX | |
1358 0x00e4, // #LATIN SMALL LETTER A WITH DIAERESIS | |
1359 0x00e0, // #LATIN SMALL LETTER A WITH GRAVE | |
1360 0x00e5, // #LATIN SMALL LETTER A WITH RING ABOVE | |
1361 0x00e7, // #LATIN SMALL LETTER C WITH CEDILLA | |
1362 0x00ea, // #LATIN SMALL LETTER E WITH CIRCUMFLEX | |
1363 0x00eb, // #LATIN SMALL LETTER E WITH DIAERESIS | |
1364 0x00e8, // #LATIN SMALL LETTER E WITH GRAVE | |
1365 0x00ef, // #LATIN SMALL LETTER I WITH DIAERESIS | |
1366 0x00ee, // #LATIN SMALL LETTER I WITH CIRCUMFLEX | |
1367 0x00ec, // #LATIN SMALL LETTER I WITH GRAVE | |
1368 0x00c4, // #LATIN CAPITAL LETTER A WITH DIAERESIS | |
1369 0x00c5, // #LATIN CAPITAL LETTER A WITH RING ABOVE | |
1370 0x00c9, // #LATIN CAPITAL LETTER E WITH ACUTE | |
1371 0x00e6, // #LATIN SMALL LIGATURE AE | |
1372 0x00c6, // #LATIN CAPITAL LIGATURE AE | |
1373 0x00f4, // #LATIN SMALL LETTER O WITH CIRCUMFLEX | |
1374 0x00f6, // #LATIN SMALL LETTER O WITH DIAERESIS | |
1375 0x00f2, // #LATIN SMALL LETTER O WITH GRAVE | |
1376 0x00fb, // #LATIN SMALL LETTER U WITH CIRCUMFLEX | |
1377 0x00f9, // #LATIN SMALL LETTER U WITH GRAVE | |
1378 0x00ff, // #LATIN SMALL LETTER Y WITH DIAERESIS | |
1379 0x00d6, // #LATIN CAPITAL LETTER O WITH DIAERESIS | |
1380 0x00dc, // #LATIN CAPITAL LETTER U WITH DIAERESIS | |
1381 0x00a2, // #CENT SIGN | |
1382 0x00a3, // #POUND SIGN | |
1383 0x00a5, // #YEN SIGN | |
1384 0x20a7, // #PESETA SIGN | |
1385 0x0192, // #LATIN SMALL LETTER F WITH HOOK | |
1386 0x00e1, // #LATIN SMALL LETTER A WITH ACUTE | |
1387 0x00ed, // #LATIN SMALL LETTER I WITH ACUTE | |
1388 0x00f3, // #LATIN SMALL LETTER O WITH ACUTE | |
1389 0x00fa, // #LATIN SMALL LETTER U WITH ACUTE | |
1390 0x00f1, // #LATIN SMALL LETTER N WITH TILDE | |
1391 0x00d1, // #LATIN CAPITAL LETTER N WITH TILDE | |
1392 0x00aa, // #FEMININE ORDINAL INDICATOR | |
1393 0x00ba, // #MASCULINE ORDINAL INDICATOR | |
1394 0x00bf, // #INVERTED QUESTION MARK | |
1395 0x2310, // #REVERSED NOT SIGN | |
1396 0x00ac, // #NOT SIGN | |
1397 0x00bd, // #VULGAR FRACTION ONE HALF | |
1398 0x00bc, // #VULGAR FRACTION ONE QUARTER | |
1399 0x00a1, // #INVERTED EXCLAMATION MARK | |
1400 0x00ab, // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK | |
1401 0x00bb, // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK | |
1402 0x2591, // #LIGHT SHADE | |
1403 0x2592, // #MEDIUM SHADE | |
1404 0x2593, // #DARK SHADE | |
1405 0x2502, // #BOX DRAWINGS LIGHT VERTICAL | |
1406 0x2524, // #BOX DRAWINGS LIGHT VERTICAL AND LEFT | |
1407 0x2561, // #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE | |
1408 0x2562, // #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE | |
1409 0x2556, // #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE | |
1410 0x2555, // #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE | |
1411 0x2563, // #BOX DRAWINGS DOUBLE VERTICAL AND LEFT | |
1412 0x2551, // #BOX DRAWINGS DOUBLE VERTICAL | |
1413 0x2557, // #BOX DRAWINGS DOUBLE DOWN AND LEFT | |
1414 0x255d, // #BOX DRAWINGS DOUBLE UP AND LEFT | |
1415 0x255c, // #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE | |
1416 0x255b, // #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE | |
1417 0x2510, // #BOX DRAWINGS LIGHT DOWN AND LEFT | |
1418 0x2514, // #BOX DRAWINGS LIGHT UP AND RIGHT | |
1419 0x2534, // #BOX DRAWINGS LIGHT UP AND HORIZONTAL | |
1420 0x252c, // #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL | |
1421 0x251c, // #BOX DRAWINGS LIGHT VERTICAL AND RIGHT | |
1422 0x2500, // #BOX DRAWINGS LIGHT HORIZONTAL | |
1423 0x253c, // #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL | |
1424 0x255e, // #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE | |
1425 0x255f, // #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE | |
1426 0x255a, // #BOX DRAWINGS DOUBLE UP AND RIGHT | |
1427 0x2554, // #BOX DRAWINGS DOUBLE DOWN AND RIGHT | |
1428 0x2569, // #BOX DRAWINGS DOUBLE UP AND HORIZONTAL | |
1429 0x2566, // #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL | |
1430 0x2560, // #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT | |
1431 0x2550, // #BOX DRAWINGS DOUBLE HORIZONTAL | |
1432 0x256c, // #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL | |
1433 0x2567, // #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE | |
1434 0x2568, // #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE | |
1435 0x2564, // #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE | |
1436 0x2565, // #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE | |
1437 0x2559, // #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE | |
1438 0x2558, // #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE | |
1439 0x2552, // #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE | |
1440 0x2553, // #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE | |
1441 0x256b, // #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE | |
1442 0x256a, // #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE | |
1443 0x2518, // #BOX DRAWINGS LIGHT UP AND LEFT | |
1444 0x250c, // #BOX DRAWINGS LIGHT DOWN AND RIGHT | |
1445 0x2588, // #FULL BLOCK | |
1446 0x2584, // #LOWER HALF BLOCK | |
1447 0x258c, // #LEFT HALF BLOCK | |
1448 0x2590, // #RIGHT HALF BLOCK | |
1449 0x2580, // #UPPER HALF BLOCK | |
1450 0x03b1, // #GREEK SMALL LETTER ALPHA | |
1451 0x00df, // #LATIN SMALL LETTER SHARP S | |
1452 0x0393, // #GREEK CAPITAL LETTER GAMMA | |
1453 0x03c0, // #GREEK SMALL LETTER PI | |
1454 0x03a3, // #GREEK CAPITAL LETTER SIGMA | |
1455 0x03c3, // #GREEK SMALL LETTER SIGMA | |
1456 0x00b5, // #MICRO SIGN | |
1457 0x03c4, // #GREEK SMALL LETTER TAU | |
1458 0x03a6, // #GREEK CAPITAL LETTER PHI | |
1459 0x0398, // #GREEK CAPITAL LETTER THETA | |
1460 0x03a9, // #GREEK CAPITAL LETTER OMEGA | |
1461 0x03b4, // #GREEK SMALL LETTER DELTA | |
1462 0x221e, // #INFINITY | |
1463 0x03c6, // #GREEK SMALL LETTER PHI | |
1464 0x03b5, // #GREEK SMALL LETTER EPSILON | |
1465 0x2229, // #INTERSECTION | |
1466 0x2261, // #IDENTICAL TO | |
1467 0x00b1, // #PLUS-MINUS SIGN | |
1468 0x2265, // #GREATER-THAN OR EQUAL TO | |
1469 0x2264, // #LESS-THAN OR EQUAL TO | |
1470 0x2320, // #TOP HALF INTEGRAL | |
1471 0x2321, // #BOTTOM HALF INTEGRAL | |
1472 0x00f7, // #DIVISION SIGN | |
1473 0x2248, // #ALMOST EQUAL TO | |
1474 0x00b0, // #DEGREE SIGN | |
1475 0x2219, // #BULLET OPERATOR | |
1476 0x00b7, // #MIDDLE DOT | |
1477 0x221a, // #SQUARE ROOT | |
1478 0x207f, // #SUPERSCRIPT LATIN SMALL LETTER N | |
1479 0x00b2, // #SUPERSCRIPT TWO | |
1480 0x25a0, // #BLACK SQUARE | |
1481 0x00a0, // #NO-BREAK SPACE | |
1482 }; | |
1483 | |
1484 public char map_cp850_unicode(char x) { | |
1485 if (x >= 0x100) | |
1486 return x; | |
1487 | |
1488 return unimap[x]; | |
1489 } | |
1490 | |
1491 private void _SetCursor(int row, int col) { | |
1492 int maxr = height - 1; | |
1493 int tm = getTopMargin(); | |
1494 R = (row < 0) ? 0 : row; | |
1495 C = (col < 0) ? 0 : (col >= width) ? width - 1 : col; | |
1496 | |
1497 if (!moveoutsidemargins) { | |
1498 R += tm; | |
1499 maxr = getBottomMargin(); | |
1500 } | |
1501 | |
1502 if (R > maxr) R = maxr; | |
1503 } | |
1504 | |
1505 private void putChar(char c, boolean isWide, boolean doshowcursor) { | |
1506 int rows = this.height; //statusline | |
1507 int columns = this.width; | |
1508 | |
1509 // byte msg[]; | |
1510 // if (debug > 4) { | |
1511 // debugStr.append("putChar(") | |
1512 // .append(c) | |
1513 // .append(" [") | |
1514 // .append((int) c) | |
1515 // .append("]) at R=") | |
1516 // .append(R) | |
1517 // .append(" , C=") | |
1518 // .append(C) | |
1519 // .append(", columns=") | |
1520 // .append(columns) | |
1521 // .append(", rows=") | |
1522 // .append(rows); | |
1523 // debug(debugStr.toString()); | |
1524 // debugStr.setLength(0); | |
1525 // } | |
1526 // markLine(R, 1); | |
1527 // if (c > 255) { | |
1528 // if (debug > 0) | |
1529 // debug("char > 255:" + (int) c); | |
1530 // //return; | |
1531 // } | |
1532 switch (term_state) { | |
1533 case TSTATE_DATA: | |
1534 | |
1535 /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset. | |
1536 * probably... but some BBS do anyway... | |
1537 */ | |
1538 if (!useibmcharset) { | |
1539 boolean doneflag = true; | |
1540 | |
1541 switch (c) { | |
1542 case OSC: | |
1543 osc = ""; | |
1544 term_state = TSTATE_OSC; | |
1545 break; | |
1546 | |
1547 case RI: | |
1548 if (R > getTopMargin()) | |
1549 R--; | |
1550 else | |
1551 insertLine(R, 1, SCROLL_DOWN); | |
1552 | |
1553 if (debug > 1) | |
1554 debug("RI"); | |
1555 | |
1556 break; | |
1557 | |
1558 case IND: | |
1559 if (debug > 2) { | |
1560 debugStr.append("IND at ") | |
1561 .append(R) | |
1562 .append(", tm is ") | |
1563 .append(getTopMargin()) | |
1564 .append(", bm is ") | |
1565 .append(getBottomMargin()); | |
1566 debug(debugStr.toString()); | |
1567 debugStr.setLength(0); | |
1568 } | |
1569 | |
1570 if (R == getBottomMargin() || R == rows - 1) | |
1571 insertLine(R, 1, SCROLL_UP); | |
1572 else | |
1573 R++; | |
1574 | |
1575 if (debug > 1) | |
1576 debug("IND (at " + R + " )"); | |
1577 | |
1578 break; | |
1579 | |
1580 case NEL: | |
1581 if (R == getBottomMargin() || R == rows - 1) | |
1582 insertLine(R, 1, SCROLL_UP); | |
1583 else | |
1584 R++; | |
1585 | |
1586 C = 0; | |
1587 | |
1588 if (debug > 1) | |
1589 debug("NEL (at " + R + " )"); | |
1590 | |
1591 break; | |
1592 | |
1593 case HTS: | |
1594 Tabs[C] = 1; | |
1595 | |
1596 if (debug > 1) | |
1597 debug("HTS"); | |
1598 | |
1599 break; | |
1600 | |
1601 case DCS: | |
1602 dcs = ""; | |
1603 term_state = TSTATE_DCS; | |
1604 break; | |
1605 | |
1606 default: | |
1607 doneflag = false; | |
1608 break; | |
1609 } | |
1610 | |
1611 if (doneflag) break; | |
1612 } | |
1613 | |
1614 switch (c) { | |
1615 case SS3: | |
1616 onegl = 3; | |
1617 break; | |
1618 | |
1619 case SS2: | |
1620 onegl = 2; | |
1621 break; | |
1622 | |
1623 case CSI: // should be in the 8bit section, but some BBS use this | |
1624 DCEvar = 0; | |
1625 DCEvars[0] = 0; | |
1626 DCEvars[1] = 0; | |
1627 DCEvars[2] = 0; | |
1628 DCEvars[3] = 0; | |
1629 term_state = TSTATE_CSI; | |
1630 break; | |
1631 | |
1632 case ESC: | |
1633 term_state = TSTATE_ESC; | |
1634 lastwaslf = 0; | |
1635 break; | |
1636 | |
1637 case 5: /* ENQ */ | |
1638 write(answerBack, false); | |
1639 break; | |
1640 | |
1641 case 12: | |
1642 /* FormFeed, Home for the BBS world */ | |
1643 deleteArea(0, 0, columns, rows, attributes); | |
1644 C = R = 0; | |
1645 break; | |
1646 | |
1647 case '\b': /* 8 */ | |
1648 C--; | |
1649 | |
1650 if (C < 0) | |
1651 C = 0; | |
1652 | |
1653 lastwaslf = 0; | |
1654 break; | |
1655 | |
1656 case '\t': | |
1657 do { | |
1658 // Don't overwrite or insert! TABS are not destructive, but movement! | |
1659 C++; | |
1660 } | |
1661 while (C < columns && (Tabs[C] == 0)); | |
1662 | |
1663 lastwaslf = 0; | |
1664 break; | |
1665 | |
1666 case '\r': // 13 CR | |
1667 C = 0; | |
1668 break; | |
1669 | |
1670 case '\n': // 10 LF | |
1671 if (debug > 3) | |
1672 debug("R= " + R + ", bm " + getBottomMargin() + ", tm=" + getTopMargin() + ", rows=" + rows); | |
1673 | |
1674 if (!vms) { | |
1675 if (lastwaslf != 0 && lastwaslf != c) // Ray: I do not understand this logic. | |
1676 break; | |
1677 | |
1678 lastwaslf = c; | |
1679 /*C = 0;*/ | |
1680 } | |
1681 | |
1682 if (R == getBottomMargin() || R >= rows - 1) | |
1683 insertLine(R, 1, SCROLL_UP); | |
1684 else | |
1685 R++; | |
1686 | |
1687 break; | |
1688 | |
1689 case 7: | |
1690 beep(); | |
1691 break; | |
1692 | |
1693 case '\016': /* SMACS , as */ | |
1694 /* ^N, Shift out - Put G1 into GL */ | |
1695 gl = 1; | |
1696 usedcharsets = true; | |
1697 break; | |
1698 | |
1699 case '\017': /* RMACS , ae */ | |
1700 /* ^O, Shift in - Put G0 into GL */ | |
1701 gl = 0; | |
1702 usedcharsets = true; | |
1703 break; | |
1704 | |
1705 default: { | |
1706 int thisgl = gl; | |
1707 | |
1708 if (onegl >= 0) { | |
1709 thisgl = onegl; | |
1710 onegl = -1; | |
1711 } | |
1712 | |
1713 lastwaslf = 0; | |
1714 | |
1715 if (c < 32) { | |
1716 if (c != 0) | |
1717 if (debug > 0) | |
1718 debug("TSTATE_DATA char: " + ((int) c)); | |
1719 | |
1720 /*break; some BBS really want those characters, like hearst etc. */ | |
1721 if (c == 0) /* print 0 ... you bet */ | |
1722 break; | |
1723 } | |
1724 | |
1725 if (C >= columns) { | |
1726 if (wraparound) { | |
1727 int bot = rows; | |
1728 | |
1729 // If we're in the scroll region, check against the bottom margin | |
1730 if (R <= getBottomMargin() && R >= getTopMargin()) | |
1731 bot = getBottomMargin() + 1; | |
1732 | |
1733 if (R < bot - 1) | |
1734 R++; | |
1735 else { | |
1736 if (debug > 3) debug("scrolling due to wrap at " + R); | |
1737 | |
1738 insertLine(R, 1, SCROLL_UP); | |
1739 } | |
1740 | |
1741 C = 0; | |
1742 } | |
1743 else { | |
1744 // cursor stays on last character. | |
1745 C = columns - 1; | |
1746 } | |
1747 } | |
1748 | |
1749 boolean mapped = false; | |
1750 | |
1751 // Mapping if DEC Special is chosen charset | |
1752 if (usedcharsets) { | |
1753 if (c >= '\u0020' && c <= '\u007f') { | |
1754 switch (gx[thisgl]) { | |
1755 case '0': | |
1756 | |
1757 // Remap SCOANSI line drawing to VT100 line drawing chars | |
1758 // for our SCO using customers. | |
1759 if (terminalID.equals("scoansi") || terminalID.equals("ansi")) { | |
1760 for (int i = 0; i < scoansi_acs.length(); i += 2) { | |
1761 if (c == scoansi_acs.charAt(i)) { | |
1762 c = scoansi_acs.charAt(i + 1); | |
1763 break; | |
1764 } | |
1765 } | |
1766 } | |
1767 | |
1768 if (c >= '\u005f' && c <= '\u007e') { | |
1769 c = DECSPECIAL[(short) c - 0x5f]; | |
1770 mapped = true; | |
1771 } | |
1772 | |
1773 break; | |
1774 | |
1775 case '<': // 'user preferred' is currently 'ISO Latin-1 suppl | |
1776 c = (char)((c & 0x7f) | 0x80); | |
1777 mapped = true; | |
1778 break; | |
1779 | |
1780 case 'A': | |
1781 case 'B': // Latin-1 , ASCII -> fall through | |
1782 mapped = true; | |
1783 break; | |
1784 | |
1785 default: | |
1786 debug("Unsupported GL mapping: " + gx[thisgl]); | |
1787 break; | |
1788 } | |
1789 } | |
1790 | |
1791 if (!mapped && (c >= '\u0080' && c <= '\u00ff')) { | |
1792 switch (gx[gr]) { | |
1793 case '0': | |
1794 if (c >= '\u00df' && c <= '\u00fe') { | |
1795 c = DECSPECIAL[c - '\u00df']; | |
1796 mapped = true; | |
1797 } | |
1798 | |
1799 break; | |
1800 | |
1801 case '<': | |
1802 case 'A': | |
1803 case 'B': | |
1804 mapped = true; | |
1805 break; | |
1806 | |
1807 default: | |
1808 debug("Unsupported GR mapping: " + gx[gr]); | |
1809 break; | |
1810 } | |
1811 } | |
1812 } | |
1813 | |
1814 if (!mapped && useibmcharset) | |
1815 c = map_cp850_unicode(c); | |
1816 | |
1817 /*if(true || (statusmode == 0)) { */ | |
1818 if (isWide) { | |
1819 if (C >= columns - 1) { | |
1820 if (wraparound) { | |
1821 int bot = rows; | |
1822 | |
1823 // If we're in the scroll region, check against the bottom margin | |
1824 if (R <= getBottomMargin() && R >= getTopMargin()) | |
1825 bot = getBottomMargin() + 1; | |
1826 | |
1827 if (R < bot - 1) | |
1828 R++; | |
1829 else { | |
1830 if (debug > 3) debug("scrolling due to wrap at " + R); | |
1831 | |
1832 insertLine(R, 1, SCROLL_UP); | |
1833 } | |
1834 | |
1835 C = 0; | |
1836 } | |
1837 else { | |
1838 // cursor stays on last wide character. | |
1839 C = columns - 2; | |
1840 } | |
1841 } | |
1842 } | |
1843 | |
1844 if (insertmode == 1) { | |
1845 if (isWide) { | |
1846 insertChar(C++, R, c, attributes | FULLWIDTH); | |
1847 insertChar(C, R, ' ', attributes | FULLWIDTH); | |
1848 } | |
1849 else | |
1850 insertChar(C, R, c, attributes); | |
1851 } | |
1852 else { | |
1853 if (isWide) { | |
1854 putChar(C++, R, c, attributes | FULLWIDTH); | |
1855 putChar(C, R, ' ', attributes | FULLWIDTH); | |
1856 } | |
1857 else | |
1858 putChar(C, R, c, attributes); | |
1859 } | |
1860 | |
1861 /* | |
1862 } else { | |
1863 if (insertmode==1) { | |
1864 insertChar(C, rows, c, attributes); | |
1865 } else { | |
1866 putChar(C, rows, c, attributes); | |
1867 } | |
1868 } | |
1869 */ | |
1870 C++; | |
1871 break; | |
1872 } | |
1873 } /* switch(c) */ | |
1874 | |
1875 break; | |
1876 | |
1877 case TSTATE_OSC: | |
1878 if ((c < 0x20) && (c != ESC)) {// NP - No printing character | |
1879 handle_osc(osc); | |
1880 term_state = TSTATE_DATA; | |
1881 break; | |
1882 } | |
1883 | |
1884 //but check for vt102 ESC \ | |
1885 if (c == '\\' && osc.charAt(osc.length() - 1) == ESC) { | |
1886 handle_osc(osc); | |
1887 term_state = TSTATE_DATA; | |
1888 break; | |
1889 } | |
1890 | |
1891 osc = osc + c; | |
1892 break; | |
1893 | |
1894 case TSTATE_ESCSPACE: | |
1895 term_state = TSTATE_DATA; | |
1896 | |
1897 switch (c) { | |
1898 case 'F': /* S7C1T, Disable output of 8-bit controls, use 7-bit */ | |
1899 output8bit = false; | |
1900 break; | |
1901 | |
1902 case 'G': /* S8C1T, Enable output of 8-bit control codes*/ | |
1903 output8bit = true; | |
1904 break; | |
1905 | |
1906 default: | |
1907 debug("ESC <space> " + c + " unhandled."); | |
1908 } | |
1909 | |
1910 break; | |
1911 | |
1912 case TSTATE_ESC: | |
1913 term_state = TSTATE_DATA; | |
1914 | |
1915 switch (c) { | |
1916 case ' ': | |
1917 term_state = TSTATE_ESCSPACE; | |
1918 break; | |
1919 | |
1920 case '#': | |
1921 term_state = TSTATE_ESCSQUARE; | |
1922 break; | |
1923 | |
1924 case 'c': | |
1925 /* Hard terminal reset */ | |
1926 reset(); | |
1927 break; | |
1928 | |
1929 case '[': | |
1930 DCEvar = 0; | |
1931 DCEvars[0] = 0; | |
1932 DCEvars[1] = 0; | |
1933 DCEvars[2] = 0; | |
1934 DCEvars[3] = 0; | |
1935 term_state = TSTATE_CSI; | |
1936 break; | |
1937 | |
1938 case ']': | |
1939 osc = ""; | |
1940 term_state = TSTATE_OSC; | |
1941 break; | |
1942 | |
1943 case 'P': | |
1944 dcs = ""; | |
1945 term_state = TSTATE_DCS; | |
1946 break; | |
1947 | |
1948 case 'A': /* CUU */ | |
1949 R--; | |
1950 | |
1951 if (R < 0) R = 0; | |
1952 | |
1953 break; | |
1954 | |
1955 case 'B': /* CUD */ | |
1956 R++; | |
1957 | |
1958 if (R >= rows) R = rows - 1; | |
1959 | |
1960 break; | |
1961 | |
1962 case 'C': | |
1963 C++; | |
1964 | |
1965 if (C >= columns) C = columns - 1; | |
1966 | |
1967 break; | |
1968 | |
1969 case 'I': // RI | |
1970 insertLine(R, 1, SCROLL_DOWN); | |
1971 break; | |
1972 | |
1973 case 'E': /* NEL */ | |
1974 if (R == getBottomMargin() || R == rows - 1) | |
1975 insertLine(R, 1, SCROLL_UP); | |
1976 else | |
1977 R++; | |
1978 | |
1979 C = 0; | |
1980 | |
1981 if (debug > 1) | |
1982 debug("ESC E (at " + R + ")"); | |
1983 | |
1984 break; | |
1985 | |
1986 case 'D': /* IND */ | |
1987 if (R == getBottomMargin() || R == rows - 1) | |
1988 insertLine(R, 1, SCROLL_UP); | |
1989 else | |
1990 R++; | |
1991 | |
1992 if (debug > 1) | |
1993 debug("ESC D (at " + R + " )"); | |
1994 | |
1995 break; | |
1996 | |
1997 case 'J': /* erase to end of screen */ | |
1998 if (R < rows - 1) | |
1999 deleteArea(0, R + 1, columns, rows - R - 1, attributes); | |
2000 | |
2001 if (C < columns - 1) | |
2002 deleteArea(C, R, columns - C, 1, attributes); | |
2003 | |
2004 break; | |
2005 | |
2006 case 'K': | |
2007 if (C < columns - 1) | |
2008 deleteArea(C, R, columns - C, 1, attributes); | |
2009 | |
2010 break; | |
2011 | |
2012 case 'M': // RI | |
2013 debug("ESC M : R is " + R + ", tm is " + getTopMargin() + ", bm is " + getBottomMargin()); | |
2014 | |
2015 if (R > getTopMargin()) { // just go up 1 line. | |
2016 R--; | |
2017 } | |
2018 else { // scroll down | |
2019 insertLine(R, 1, SCROLL_DOWN); | |
2020 } | |
2021 | |
2022 /* else do nothing ; */ | |
2023 if (debug > 2) | |
2024 debug("ESC M "); | |
2025 | |
2026 break; | |
2027 | |
2028 case 'H': | |
2029 if (debug > 1) | |
2030 debug("ESC H at " + C); | |
2031 | |
2032 /* right border probably ...*/ | |
2033 if (C >= columns) | |
2034 C = columns - 1; | |
2035 | |
2036 Tabs[C] = 1; | |
2037 break; | |
2038 | |
2039 case 'N': // SS2 | |
2040 onegl = 2; | |
2041 break; | |
2042 | |
2043 case 'O': // SS3 | |
2044 onegl = 3; | |
2045 break; | |
2046 | |
2047 case '=': | |
2048 | |
2049 /*application keypad*/ | |
2050 if (debug > 0) | |
2051 debug("ESC ="); | |
2052 | |
2053 keypadmode = true; | |
2054 break; | |
2055 | |
2056 case '<': /* vt52 mode off */ | |
2057 vt52mode = false; | |
2058 break; | |
2059 | |
2060 case '>': /*normal keypad*/ | |
2061 if (debug > 0) | |
2062 debug("ESC >"); | |
2063 | |
2064 keypadmode = false; | |
2065 break; | |
2066 | |
2067 case '7': /* DECSC: save cursor, attributes */ | |
2068 Sc = C; | |
2069 Sr = R; | |
2070 Sgl = gl; | |
2071 Sgr = gr; | |
2072 Sa = attributes; | |
2073 Sgx = new char[4]; | |
2074 | |
2075 for (int i = 0; i < 4; i++) Sgx[i] = gx[i]; | |
2076 | |
2077 if (debug > 1) | |
2078 debug("ESC 7"); | |
2079 | |
2080 break; | |
2081 | |
2082 case '8': /* DECRC: restore cursor, attributes */ | |
2083 C = Sc; | |
2084 R = Sr; | |
2085 gl = Sgl; | |
2086 gr = Sgr; | |
2087 | |
2088 if (Sgx != null) | |
2089 for (int i = 0; i < 4; i++) gx[i] = Sgx[i]; | |
2090 | |
2091 attributes = Sa; | |
2092 | |
2093 if (debug > 1) | |
2094 debug("ESC 8"); | |
2095 | |
2096 break; | |
2097 | |
2098 case '(': /* Designate G0 Character set (ISO 2022) */ | |
2099 term_state = TSTATE_SETG0; | |
2100 usedcharsets = true; | |
2101 break; | |
2102 | |
2103 case ')': /* Designate G1 character set (ISO 2022) */ | |
2104 term_state = TSTATE_SETG1; | |
2105 usedcharsets = true; | |
2106 break; | |
2107 | |
2108 case '*': /* Designate G2 Character set (ISO 2022) */ | |
2109 term_state = TSTATE_SETG2; | |
2110 usedcharsets = true; | |
2111 break; | |
2112 | |
2113 case '+': /* Designate G3 Character set (ISO 2022) */ | |
2114 term_state = TSTATE_SETG3; | |
2115 usedcharsets = true; | |
2116 break; | |
2117 | |
2118 case '~': /* Locking Shift 1, right */ | |
2119 gr = 1; | |
2120 usedcharsets = true; | |
2121 break; | |
2122 | |
2123 case 'n': /* Locking Shift 2 */ | |
2124 gl = 2; | |
2125 usedcharsets = true; | |
2126 break; | |
2127 | |
2128 case '}': /* Locking Shift 2, right */ | |
2129 gr = 2; | |
2130 usedcharsets = true; | |
2131 break; | |
2132 | |
2133 case 'o': /* Locking Shift 3 */ | |
2134 gl = 3; | |
2135 usedcharsets = true; | |
2136 break; | |
2137 | |
2138 case '|': /* Locking Shift 3, right */ | |
2139 gr = 3; | |
2140 usedcharsets = true; | |
2141 break; | |
2142 | |
2143 case 'Y': /* vt52 cursor address mode , next chars are x,y */ | |
2144 term_state = TSTATE_VT52Y; | |
2145 break; | |
2146 | |
2147 case '_': | |
2148 term_state = TSTATE_TITLE; | |
2149 break; | |
2150 | |
2151 case '\\': | |
2152 // TODO save title | |
2153 term_state = TSTATE_DATA; | |
2154 break; | |
2155 | |
2156 default: | |
2157 debug("ESC unknown letter: " + c + " (" + ((int) c) + ")"); | |
2158 break; | |
2159 } | |
2160 | |
2161 break; | |
2162 | |
2163 case TSTATE_VT52X: | |
2164 C = c - 37; | |
2165 | |
2166 if (C < 0) | |
2167 C = 0; | |
2168 else if (C >= width) | |
2169 C = width - 1; | |
2170 | |
2171 term_state = TSTATE_VT52Y; | |
2172 break; | |
2173 | |
2174 case TSTATE_VT52Y: | |
2175 R = c - 37; | |
2176 | |
2177 if (R < 0) | |
2178 R = 0; | |
2179 else if (R >= height) | |
2180 R = height - 1; | |
2181 | |
2182 term_state = TSTATE_DATA; | |
2183 break; | |
2184 | |
2185 case TSTATE_SETG0: | |
2186 if (c != '0' && c != 'A' && c != 'B' && c != '<') | |
2187 debug("ESC ( " + c + ": G0 char set? (" + ((int) c) + ")"); | |
2188 else { | |
2189 if (debug > 2) debug("ESC ( : G0 char set (" + c + " " + ((int) c) + ")"); | |
2190 | |
2191 gx[0] = c; | |
2192 } | |
2193 | |
2194 term_state = TSTATE_DATA; | |
2195 break; | |
2196 | |
2197 case TSTATE_SETG1: | |
2198 if (c != '0' && c != 'A' && c != 'B' && c != '<') { | |
2199 debug("ESC ) " + c + " (" + ((int) c) + ") :G1 char set?"); | |
2200 } | |
2201 else { | |
2202 if (debug > 2) debug("ESC ) :G1 char set (" + c + " " + ((int) c) + ")"); | |
2203 | |
2204 gx[1] = c; | |
2205 } | |
2206 | |
2207 term_state = TSTATE_DATA; | |
2208 break; | |
2209 | |
2210 case TSTATE_SETG2: | |
2211 if (c != '0' && c != 'A' && c != 'B' && c != '<') | |
2212 debug("ESC*:G2 char set? (" + ((int) c) + ")"); | |
2213 else { | |
2214 if (debug > 2) debug("ESC*:G2 char set (" + c + " " + ((int) c) + ")"); | |
2215 | |
2216 gx[2] = c; | |
2217 } | |
2218 | |
2219 term_state = TSTATE_DATA; | |
2220 break; | |
2221 | |
2222 case TSTATE_SETG3: | |
2223 if (c != '0' && c != 'A' && c != 'B' && c != '<') | |
2224 debug("ESC+:G3 char set? (" + ((int) c) + ")"); | |
2225 else { | |
2226 if (debug > 2) debug("ESC+:G3 char set (" + c + " " + ((int) c) + ")"); | |
2227 | |
2228 gx[3] = c; | |
2229 } | |
2230 | |
2231 term_state = TSTATE_DATA; | |
2232 break; | |
2233 | |
2234 case TSTATE_ESCSQUARE: | |
2235 switch (c) { | |
2236 case '8': | |
2237 for (int i = 0; i < columns; i++) | |
2238 for (int j = 0; j < rows; j++) | |
2239 putChar(i, j, 'E', 0); | |
2240 | |
2241 break; | |
2242 | |
2243 default: | |
2244 debug("ESC # " + c + " not supported."); | |
2245 break; | |
2246 } | |
2247 | |
2248 term_state = TSTATE_DATA; | |
2249 break; | |
2250 | |
2251 case TSTATE_DCS: | |
2252 if (c == '\\' && dcs.charAt(dcs.length() - 1) == ESC) { | |
2253 handle_dcs(dcs); | |
2254 term_state = TSTATE_DATA; | |
2255 break; | |
2256 } | |
2257 | |
2258 dcs = dcs + c; | |
2259 break; | |
2260 | |
2261 case TSTATE_DCEQ: | |
2262 term_state = TSTATE_DATA; | |
2263 | |
2264 switch (c) { | |
2265 case '0': | |
2266 case '1': | |
2267 case '2': | |
2268 case '3': | |
2269 case '4': | |
2270 case '5': | |
2271 case '6': | |
2272 case '7': | |
2273 case '8': | |
2274 case '9': | |
2275 DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; | |
2276 term_state = TSTATE_DCEQ; | |
2277 break; | |
2278 | |
2279 case ';': | |
2280 DCEvar++; | |
2281 DCEvars[DCEvar] = 0; | |
2282 term_state = TSTATE_DCEQ; | |
2283 break; | |
2284 | |
2285 case 's': // XTERM_SAVE missing! | |
2286 if (true || debug > 1) | |
2287 debug("ESC [ ? " + DCEvars[0] + " s unimplemented!"); | |
2288 | |
2289 break; | |
2290 | |
2291 case 'r': // XTERM_RESTORE | |
2292 if (true || debug > 1) | |
2293 debug("ESC [ ? " + DCEvars[0] + " r"); | |
2294 | |
2295 /* DEC Mode reset */ | |
2296 for (int i = 0; i <= DCEvar; i++) { | |
2297 switch (DCEvars[i]) { | |
2298 case 3: /* 80 columns*/ | |
2299 setScreenSize(80, height, true); | |
2300 break; | |
2301 | |
2302 case 4: /* scrolling mode, smooth */ | |
2303 break; | |
2304 | |
2305 case 5: /* light background */ | |
2306 break; | |
2307 | |
2308 case 6: /* DECOM (Origin Mode) move inside margins. */ | |
2309 moveoutsidemargins = true; | |
2310 break; | |
2311 | |
2312 case 7: /* DECAWM: Autowrap Mode */ | |
2313 wraparound = false; | |
2314 break; | |
2315 | |
2316 case 12:/* local echo off */ | |
2317 break; | |
2318 | |
2319 case 9: /* X10 mouse */ | |
2320 case 1000: /* xterm style mouse report on */ | |
2321 case 1001: | |
2322 case 1002: | |
2323 case 1003: | |
2324 mouserpt = DCEvars[i]; | |
2325 break; | |
2326 | |
2327 default: | |
2328 debug("ESC [ ? " + DCEvars[0] + " r, unimplemented!"); | |
2329 } | |
2330 } | |
2331 | |
2332 break; | |
2333 | |
2334 case 'h': // DECSET | |
2335 if (debug > 0) | |
2336 debug("ESC [ ? " + DCEvars[0] + " h"); | |
2337 | |
2338 /* DEC Mode set */ | |
2339 for (int i = 0; i <= DCEvar; i++) { | |
2340 switch (DCEvars[i]) { | |
2341 case 1: /* Application cursor keys */ | |
2342 KeyUp[0] = "\u001bOA"; | |
2343 KeyDown[0] = "\u001bOB"; | |
2344 KeyRight[0] = "\u001bOC"; | |
2345 KeyLeft[0] = "\u001bOD"; | |
2346 break; | |
2347 | |
2348 case 2: /* DECANM */ | |
2349 vt52mode = false; | |
2350 break; | |
2351 | |
2352 case 3: /* 132 columns*/ | |
2353 setScreenSize(132, height, true); | |
2354 break; | |
2355 | |
2356 case 6: /* DECOM: move inside margins. */ | |
2357 moveoutsidemargins = false; | |
2358 break; | |
2359 | |
2360 case 7: /* DECAWM: Autowrap Mode */ | |
2361 wraparound = true; | |
2362 break; | |
2363 | |
2364 case 25: /* turn cursor on */ | |
2365 showCursor(true); | |
2366 break; | |
2367 | |
2368 case 9: /* X10 mouse */ | |
2369 case 1000: /* xterm style mouse report on */ | |
2370 case 1001: | |
2371 case 1002: | |
2372 case 1003: | |
2373 mouserpt = DCEvars[i]; | |
2374 break; | |
2375 | |
2376 /* unimplemented stuff, fall through */ | |
2377 /* 4 - scrolling mode, smooth */ | |
2378 /* 5 - light background */ | |
2379 /* 12 - local echo off */ | |
2380 /* 18 - DECPFF - Printer Form Feed Mode -> On */ | |
2381 /* 19 - DECPEX - Printer Extent Mode -> Screen */ | |
2382 default: | |
2383 debug("ESC [ ? " + DCEvars[0] + " h, unsupported."); | |
2384 break; | |
2385 } | |
2386 } | |
2387 | |
2388 break; | |
2389 | |
2390 case 'i': // DEC Printer Control, autoprint, echo screenchars to printer | |
2391 | |
2392 // This is different to CSI i! | |
2393 // Also: "Autoprint prints a final display line only when the | |
2394 // cursor is moved off the line by an autowrap or LF, FF, or | |
2395 // VT (otherwise do not print the line)." | |
2396 switch (DCEvars[0]) { | |
2397 case 1: | |
2398 if (debug > 1) | |
2399 debug("CSI ? 1 i : Print line containing cursor"); | |
2400 | |
2401 break; | |
2402 | |
2403 case 4: | |
2404 if (debug > 1) | |
2405 debug("CSI ? 4 i : Start passthrough printing"); | |
2406 | |
2407 break; | |
2408 | |
2409 case 5: | |
2410 if (debug > 1) | |
2411 debug("CSI ? 4 i : Stop passthrough printing"); | |
2412 | |
2413 break; | |
2414 } | |
2415 | |
2416 break; | |
2417 | |
2418 case 'l': //DECRST | |
2419 | |
2420 /* DEC Mode reset */ | |
2421 if (debug > 0) | |
2422 debug("ESC [ ? " + DCEvars[0] + " l"); | |
2423 | |
2424 for (int i = 0; i <= DCEvar; i++) { | |
2425 switch (DCEvars[i]) { | |
2426 case 1: /* Application cursor keys */ | |
2427 KeyUp[0] = "\u001b[A"; | |
2428 KeyDown[0] = "\u001b[B"; | |
2429 KeyRight[0] = "\u001b[C"; | |
2430 KeyLeft[0] = "\u001b[D"; | |
2431 break; | |
2432 | |
2433 case 2: /* DECANM */ | |
2434 vt52mode = true; | |
2435 break; | |
2436 | |
2437 case 3: /* 80 columns*/ | |
2438 setScreenSize(80, height, true); | |
2439 break; | |
2440 | |
2441 case 6: /* DECOM: move outside margins. */ | |
2442 moveoutsidemargins = true; | |
2443 break; | |
2444 | |
2445 case 7: /* DECAWM: Autowrap Mode OFF */ | |
2446 wraparound = false; | |
2447 break; | |
2448 | |
2449 case 25: /* turn cursor off */ | |
2450 showCursor(false); | |
2451 break; | |
2452 | |
2453 /* Unimplemented stuff: */ | |
2454 /* 4 - scrolling mode, jump */ | |
2455 /* 5 - dark background */ | |
2456 /* 7 - DECAWM - no wrap around mode */ | |
2457 /* 12 - local echo on */ | |
2458 /* 18 - DECPFF - Printer Form Feed Mode -> Off*/ | |
2459 /* 19 - DECPEX - Printer Extent Mode -> Scrolling Region */ | |
2460 case 9: /* X10 mouse */ | |
2461 case 1000: /* xterm style mouse report OFF */ | |
2462 case 1001: | |
2463 case 1002: | |
2464 case 1003: | |
2465 mouserpt = 0; | |
2466 break; | |
2467 | |
2468 default: | |
2469 debug("ESC [ ? " + DCEvars[0] + " l, unsupported."); | |
2470 break; | |
2471 } | |
2472 } | |
2473 | |
2474 break; | |
2475 | |
2476 case 'n': | |
2477 if (debug > 0) | |
2478 debug("ESC [ ? " + DCEvars[0] + " n"); | |
2479 | |
2480 switch (DCEvars[0]) { | |
2481 case 15: | |
2482 /* printer? no printer. */ | |
2483 write((ESC) + "[?13n", false); | |
2484 debug("ESC[5n"); | |
2485 break; | |
2486 | |
2487 default: | |
2488 debug("ESC [ ? " + DCEvars[0] + " n, unsupported."); | |
2489 break; | |
2490 } | |
2491 | |
2492 break; | |
2493 | |
2494 default: | |
2495 debug("ESC [ ? " + DCEvars[0] + " " + c + ", unsupported."); | |
2496 break; | |
2497 } | |
2498 | |
2499 break; | |
2500 | |
2501 case TSTATE_CSI_EX: | |
2502 term_state = TSTATE_DATA; | |
2503 | |
2504 switch (c) { | |
2505 case ESC: | |
2506 term_state = TSTATE_ESC; | |
2507 break; | |
2508 | |
2509 default: | |
2510 debug("Unknown character ESC[! character is " + (int) c); | |
2511 break; | |
2512 } | |
2513 | |
2514 break; | |
2515 | |
2516 case TSTATE_CSI_TICKS: | |
2517 term_state = TSTATE_DATA; | |
2518 | |
2519 switch (c) { | |
2520 case 'p': | |
2521 debug("Conformance level: " + DCEvars[0] + " (unsupported)," + DCEvars[1]); | |
2522 | |
2523 if (DCEvars[0] == 61) { | |
2524 output8bit = false; | |
2525 break; | |
2526 } | |
2527 | |
2528 if (DCEvars[1] == 1) { | |
2529 output8bit = false; | |
2530 } | |
2531 else { | |
2532 output8bit = true; /* 0 or 2 */ | |
2533 } | |
2534 | |
2535 break; | |
2536 | |
2537 default: | |
2538 debug("Unknown ESC [... \"" + c); | |
2539 break; | |
2540 } | |
2541 | |
2542 break; | |
2543 | |
2544 case TSTATE_CSI_EQUAL: | |
2545 term_state = TSTATE_DATA; | |
2546 | |
2547 switch (c) { | |
2548 case '0': | |
2549 case '1': | |
2550 case '2': | |
2551 case '3': | |
2552 case '4': | |
2553 case '5': | |
2554 case '6': | |
2555 case '7': | |
2556 case '8': | |
2557 case '9': | |
2558 DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; | |
2559 term_state = TSTATE_CSI_EQUAL; | |
2560 break; | |
2561 | |
2562 case ';': | |
2563 DCEvar++; | |
2564 DCEvars[DCEvar] = 0; | |
2565 term_state = TSTATE_CSI_EQUAL; | |
2566 break; | |
2567 | |
2568 case 'F': { /* SCO ANSI foreground */ | |
2569 int newcolor; | |
2570 debug("ESC [ = " + DCEvars[0] + " F"); | |
2571 attributes &= ~COLOR_FG; | |
2572 newcolor = ((DCEvars[0] & 1) << 2) | | |
2573 (DCEvars[0] & 2) | | |
2574 ((DCEvars[0] & 4) >> 2) ; | |
2575 attributes |= (newcolor + 1) << COLOR_FG_SHIFT; | |
2576 break; | |
2577 } | |
2578 | |
2579 case 'G': { /* SCO ANSI background */ | |
2580 int newcolor; | |
2581 debug("ESC [ = " + DCEvars[0] + " G"); | |
2582 attributes &= ~COLOR_BG; | |
2583 newcolor = ((DCEvars[0] & 1) << 2) | | |
2584 (DCEvars[0] & 2) | | |
2585 ((DCEvars[0] & 4) >> 2) ; | |
2586 attributes |= (newcolor + 1) << COLOR_BG_SHIFT; | |
2587 break; | |
2588 } | |
2589 | |
2590 default: | |
2591 debugStr.append("Unknown ESC [ = "); | |
2592 | |
2593 for (int i = 0; i <= DCEvar; i++) { | |
2594 debugStr.append(DCEvars[i]) | |
2595 .append(','); | |
2596 } | |
2597 | |
2598 debugStr.append(c); | |
2599 debug(debugStr.toString()); | |
2600 debugStr.setLength(0); | |
2601 break; | |
2602 } | |
2603 | |
2604 break; | |
2605 | |
2606 case TSTATE_CSI_DOLLAR: | |
2607 term_state = TSTATE_DATA; | |
2608 | |
2609 switch (c) { | |
2610 case '}': | |
2611 debug("Active Status Display now " + DCEvars[0]); | |
2612 statusmode = DCEvars[0]; | |
2613 break; | |
2614 | |
2615 /* bad documentation? | |
2616 case '-': | |
2617 debug("Set Status Display now "+DCEvars[0]); | |
2618 break; | |
2619 */ | |
2620 case '~': | |
2621 debug("Status Line mode now " + DCEvars[0]); | |
2622 break; | |
2623 | |
2624 default: | |
2625 debug("UNKNOWN Status Display code " + c + ", with Pn=" + DCEvars[0]); | |
2626 break; | |
2627 } | |
2628 | |
2629 break; | |
2630 | |
2631 case TSTATE_CSI: | |
2632 term_state = TSTATE_DATA; | |
2633 | |
2634 switch (c) { | |
2635 case '"': | |
2636 term_state = TSTATE_CSI_TICKS; | |
2637 break; | |
2638 | |
2639 case '$': | |
2640 term_state = TSTATE_CSI_DOLLAR; | |
2641 break; | |
2642 | |
2643 case '=': | |
2644 term_state = TSTATE_CSI_EQUAL; | |
2645 break; | |
2646 | |
2647 case '!': | |
2648 term_state = TSTATE_CSI_EX; | |
2649 break; | |
2650 | |
2651 case '?': | |
2652 DCEvar = 0; | |
2653 DCEvars[0] = 0; | |
2654 term_state = TSTATE_DCEQ; | |
2655 break; | |
2656 | |
2657 case '0': | |
2658 case '1': | |
2659 case '2': | |
2660 case '3': | |
2661 case '4': | |
2662 case '5': | |
2663 case '6': | |
2664 case '7': | |
2665 case '8': | |
2666 case '9': | |
2667 DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; | |
2668 term_state = TSTATE_CSI; | |
2669 break; | |
2670 | |
2671 case ';': | |
2672 DCEvar++; | |
2673 DCEvars[DCEvar] = 0; | |
2674 term_state = TSTATE_CSI; | |
2675 break; | |
2676 | |
2677 case 'c':/* send primary device attributes */ | |
2678 /* send (ESC[?61c) */ | |
2679 String subcode = ""; | |
2680 | |
2681 if (terminalID.equals("vt320")) subcode = "63;"; | |
2682 | |
2683 if (terminalID.equals("vt220")) subcode = "62;"; | |
2684 | |
2685 if (terminalID.equals("vt100")) subcode = "61;"; | |
2686 | |
2687 write((ESC) + "[?" + subcode + "1;2c", false); | |
2688 | |
2689 if (debug > 1) | |
2690 debug("ESC [ " + DCEvars[0] + " c"); | |
2691 | |
2692 break; | |
2693 | |
2694 case 'q': | |
2695 if (debug > 1) | |
2696 debug("ESC [ " + DCEvars[0] + " q"); | |
2697 | |
2698 break; | |
2699 | |
2700 case 'g': | |
2701 | |
2702 /* used for tabsets */ | |
2703 switch (DCEvars[0]) { | |
2704 case 3:/* clear them */ | |
2705 Tabs = new byte[width]; | |
2706 break; | |
2707 | |
2708 case 0: | |
2709 Tabs[C] = 0; | |
2710 break; | |
2711 } | |
2712 | |
2713 if (debug > 1) | |
2714 debug("ESC [ " + DCEvars[0] + " g"); | |
2715 | |
2716 break; | |
2717 | |
2718 case 'h': | |
2719 switch (DCEvars[0]) { | |
2720 case 4: | |
2721 insertmode = 1; | |
2722 break; | |
2723 | |
2724 case 20: | |
2725 debug("Setting CRLF to TRUE"); | |
2726 sendcrlf = true; | |
2727 break; | |
2728 | |
2729 default: | |
2730 debug("unsupported: ESC [ " + DCEvars[0] + " h"); | |
2731 break; | |
2732 } | |
2733 | |
2734 if (debug > 1) | |
2735 debug("ESC [ " + DCEvars[0] + " h"); | |
2736 | |
2737 break; | |
2738 | |
2739 case 'i': // Printer Controller mode. | |
2740 | |
2741 // "Transparent printing sends all output, except the CSI 4 i | |
2742 // termination string, to the printer and not the screen, | |
2743 // uses an 8-bit channel if no parity so NUL and DEL will be | |
2744 // seen by the printer and by the termination recognizer code, | |
2745 // and all translation and character set selections are | |
2746 // bypassed." | |
2747 switch (DCEvars[0]) { | |
2748 case 0: | |
2749 if (debug > 1) | |
2750 debug("CSI 0 i: Print Screen, not implemented."); | |
2751 | |
2752 break; | |
2753 | |
2754 case 4: | |
2755 if (debug > 1) | |
2756 debug("CSI 4 i: Enable Transparent Printing, not implemented."); | |
2757 | |
2758 break; | |
2759 | |
2760 case 5: | |
2761 if (debug > 1) | |
2762 debug("CSI 4/5 i: Disable Transparent Printing, not implemented."); | |
2763 | |
2764 break; | |
2765 | |
2766 default: | |
2767 debug("ESC [ " + DCEvars[0] + " i, unimplemented!"); | |
2768 } | |
2769 | |
2770 break; | |
2771 | |
2772 case 'l': | |
2773 switch (DCEvars[0]) { | |
2774 case 4: | |
2775 insertmode = 0; | |
2776 break; | |
2777 | |
2778 case 20: | |
2779 debug("Setting CRLF to FALSE"); | |
2780 sendcrlf = false; | |
2781 break; | |
2782 | |
2783 default: | |
2784 debug("ESC [ " + DCEvars[0] + " l, unimplemented!"); | |
2785 break; | |
2786 } | |
2787 | |
2788 break; | |
2789 | |
2790 case 'A': { // CUU | |
2791 int limit; | |
2792 | |
2793 /* FIXME: xterm only cares about 0 and topmargin */ | |
2794 if (R >= getTopMargin()) { | |
2795 limit = getTopMargin(); | |
2796 } | |
2797 else | |
2798 limit = 0; | |
2799 | |
2800 if (DCEvars[0] == 0) | |
2801 R--; | |
2802 else | |
2803 R -= DCEvars[0]; | |
2804 | |
2805 if (R < limit) | |
2806 R = limit; | |
2807 | |
2808 if (debug > 1) | |
2809 debug("ESC [ " + DCEvars[0] + " A"); | |
2810 | |
2811 break; | |
2812 } | |
2813 | |
2814 case 'B': // CUD | |
2815 /* cursor down n (1) times */ | |
2816 { | |
2817 int limit; | |
2818 | |
2819 if (R <= getBottomMargin()) { | |
2820 limit = getBottomMargin(); | |
2821 } | |
2822 else | |
2823 limit = rows - 1; | |
2824 | |
2825 if (DCEvars[0] == 0) | |
2826 R++; | |
2827 else | |
2828 R += DCEvars[0]; | |
2829 | |
2830 if (R > limit) | |
2831 R = limit; | |
2832 else { | |
2833 if (debug > 2) debug("Not limited."); | |
2834 } | |
2835 | |
2836 if (debug > 2) debug("to: " + R); | |
2837 | |
2838 if (debug > 1) | |
2839 debug("ESC [ " + DCEvars[0] + " B (at C=" + C + ")"); | |
2840 | |
2841 break; | |
2842 } | |
2843 | |
2844 case 'C': | |
2845 if (DCEvars[0] == 0) | |
2846 DCEvars[0] = 1; | |
2847 | |
2848 while (DCEvars[0]-- > 0) { | |
2849 C++; | |
2850 } | |
2851 | |
2852 if (C >= columns) | |
2853 C = columns - 1; | |
2854 | |
2855 if (debug > 1) | |
2856 debug("ESC [ " + DCEvars[0] + " C"); | |
2857 | |
2858 break; | |
2859 | |
2860 case 'd': // CVA | |
2861 R = DCEvars[0] - 1; | |
2862 | |
2863 if (R < 0) | |
2864 R = 0; | |
2865 else if (R >= height) | |
2866 R = height - 1; | |
2867 | |
2868 if (debug > 1) | |
2869 debug("ESC [ " + DCEvars[0] + " d"); | |
2870 | |
2871 break; | |
2872 | |
2873 case 'D': | |
2874 if (DCEvars[0] == 0) | |
2875 DCEvars[0] = 1; | |
2876 | |
2877 while (DCEvars[0]-- > 0) { | |
2878 C--; | |
2879 } | |
2880 | |
2881 if (C < 0) C = 0; | |
2882 | |
2883 if (debug > 1) | |
2884 debug("ESC [ " + DCEvars[0] + " D"); | |
2885 | |
2886 break; | |
2887 | |
2888 case 'r': // DECSTBM | |
2889 if (DCEvar > 0) { // Ray: Any argument is optional | |
2890 R = DCEvars[1] - 1; | |
2891 | |
2892 if (R < 0) | |
2893 R = rows - 1; | |
2894 else if (R >= rows) { | |
2895 R = rows - 1; | |
2896 } | |
2897 } | |
2898 else | |
2899 R = rows - 1; | |
2900 | |
2901 int bot = R; | |
2902 | |
2903 if (R >= DCEvars[0]) { | |
2904 R = DCEvars[0] - 1; | |
2905 | |
2906 if (R < 0) | |
2907 R = 0; | |
2908 } | |
2909 | |
2910 setMargins(R, bot); | |
2911 _SetCursor(0, 0); | |
2912 | |
2913 if (debug > 1) | |
2914 debug("ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r"); | |
2915 | |
2916 break; | |
2917 | |
2918 case 'G': /* CUP / cursor absolute column */ | |
2919 C = DCEvars[0]; | |
2920 | |
2921 if (C < 0) | |
2922 C = 0; | |
2923 else if (C >= width) | |
2924 C = width - 1; | |
2925 | |
2926 if (debug > 1) debug("ESC [ " + DCEvars[0] + " G"); | |
2927 | |
2928 break; | |
2929 | |
2930 case 'H': /* CUP / cursor position */ | |
2931 /* gets 2 arguments */ | |
2932 _SetCursor(DCEvars[0] - 1, DCEvars[1] - 1); | |
2933 | |
2934 if (debug > 2) { | |
2935 debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " H, moveoutsidemargins " + moveoutsidemargins); | |
2936 debug(" -> R now " + R + ", C now " + C); | |
2937 } | |
2938 | |
2939 break; | |
2940 | |
2941 case 'f': /* move cursor 2 */ | |
2942 /* gets 2 arguments */ | |
2943 R = DCEvars[0] - 1; | |
2944 C = DCEvars[1] - 1; | |
2945 | |
2946 if (C < 0) | |
2947 C = 0; | |
2948 else if (C >= width) | |
2949 C = width - 1; | |
2950 | |
2951 if (R < 0) | |
2952 R = 0; | |
2953 else if (R >= height) | |
2954 R = height - 1; | |
2955 | |
2956 if (debug > 2) | |
2957 debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " f"); | |
2958 | |
2959 break; | |
2960 | |
2961 case 'S': /* ind aka 'scroll forward' */ | |
2962 if (DCEvars[0] == 0) | |
2963 insertLine(getBottomMargin(), SCROLL_UP); | |
2964 else | |
2965 insertLine(getBottomMargin(), DCEvars[0], SCROLL_UP); | |
2966 | |
2967 break; | |
2968 | |
2969 case 'L': | |
2970 | |
2971 /* insert n lines */ | |
2972 if (DCEvars[0] == 0) | |
2973 insertLine(R, SCROLL_DOWN); | |
2974 else | |
2975 insertLine(R, DCEvars[0], SCROLL_DOWN); | |
2976 | |
2977 if (debug > 1) | |
2978 debug("ESC [ " + DCEvars[0] + "" + (c) + " (at R " + R + ")"); | |
2979 | |
2980 break; | |
2981 | |
2982 case 'T': /* 'ri' aka scroll backward */ | |
2983 if (DCEvars[0] == 0) | |
2984 insertLine(getTopMargin(), SCROLL_DOWN); | |
2985 else | |
2986 insertLine(getTopMargin(), DCEvars[0], SCROLL_DOWN); | |
2987 | |
2988 break; | |
2989 | |
2990 case 'M': | |
2991 if (debug > 1) | |
2992 debug("ESC [ " + DCEvars[0] + "" + (c) + " at R=" + R); | |
2993 | |
2994 if (DCEvars[0] == 0) | |
2995 deleteLine(R); | |
2996 else | |
2997 for (int i = 0; i < DCEvars[0]; i++) | |
2998 deleteLine(R); | |
2999 | |
3000 break; | |
3001 | |
3002 case 'K': | |
3003 if (debug > 1) | |
3004 debug("ESC [ " + DCEvars[0] + " K"); | |
3005 | |
3006 /* clear in line */ | |
3007 switch (DCEvars[0]) { | |
3008 case 6: /* 97801 uses ESC[6K for delete to end of line */ | |
3009 case 0:/*clear to right*/ | |
3010 if (C < columns - 1) | |
3011 deleteArea(C, R, columns - C, 1, attributes); | |
3012 | |
3013 break; | |
3014 | |
3015 case 1:/*clear to the left, including this */ | |
3016 if (C > 0) | |
3017 deleteArea(0, R, C + 1, 1, attributes); | |
3018 | |
3019 break; | |
3020 | |
3021 case 2:/*clear whole line */ | |
3022 deleteArea(0, R, columns, 1, attributes); | |
3023 break; | |
3024 } | |
3025 | |
3026 break; | |
3027 | |
3028 case 'J': | |
3029 | |
3030 /* clear below current line */ | |
3031 switch (DCEvars[0]) { | |
3032 case 0: | |
3033 if (R < rows - 1) | |
3034 deleteArea(0, R + 1, columns, rows - R - 1, attributes); | |
3035 | |
3036 if (C < columns - 1) | |
3037 deleteArea(C, R, columns - C, 1, attributes); | |
3038 | |
3039 break; | |
3040 | |
3041 case 1: | |
3042 if (R > 0) | |
3043 deleteArea(0, 0, columns, R, attributes); | |
3044 | |
3045 if (C > 0) | |
3046 deleteArea(0, R, C + 1, 1, attributes); // include up to and including current | |
3047 | |
3048 break; | |
3049 | |
3050 case 2: | |
3051 deleteArea(0, 0, columns, rows, attributes); | |
3052 break; | |
3053 } | |
3054 | |
3055 if (debug > 1) | |
3056 debug("ESC [ " + DCEvars[0] + " J"); | |
3057 | |
3058 break; | |
3059 | |
3060 case '@': | |
3061 if (DCEvars[0] == 0) DCEvars[0] = 1; | |
3062 | |
3063 if (debug > 1) | |
3064 debug("ESC [ " + DCEvars[0] + " @"); | |
3065 | |
3066 for (int i = 0; i < DCEvars[0]; i++) | |
3067 insertChar(C, R, ' ', attributes); | |
3068 | |
3069 break; | |
3070 | |
3071 case 'X': { | |
3072 int toerase = DCEvars[0]; | |
3073 | |
3074 if (debug > 1) | |
3075 debug("ESC [ " + DCEvars[0] + " X, C=" + C + ",R=" + R); | |
3076 | |
3077 if (toerase == 0) | |
3078 toerase = 1; | |
3079 | |
3080 if (toerase + C > columns) | |
3081 toerase = columns - C; | |
3082 | |
3083 deleteArea(C, R, toerase, 1, attributes); | |
3084 // does not change cursor position | |
3085 break; | |
3086 } | |
3087 | |
3088 case 'P': | |
3089 if (debug > 1) | |
3090 debug("ESC [ " + DCEvars[0] + " P, C=" + C + ",R=" + R); | |
3091 | |
3092 if (DCEvars[0] == 0) DCEvars[0] = 1; | |
3093 | |
3094 for (int i = 0; i < DCEvars[0]; i++) | |
3095 deleteChar(C, R); | |
3096 | |
3097 break; | |
3098 | |
3099 case 'n': | |
3100 switch (DCEvars[0]) { | |
3101 case 5: /* malfunction? No malfunction. */ | |
3102 writeSpecial((ESC) + "[0n"); | |
3103 | |
3104 if (debug > 1) | |
3105 debug("ESC[5n"); | |
3106 | |
3107 break; | |
3108 | |
3109 case 6: | |
3110 // DO NOT offset R and C by 1! (checked against /usr/X11R6/bin/resize | |
3111 // FIXME check again. | |
3112 // FIXME: but vttest thinks different??? | |
3113 writeSpecial((ESC) + "[" + R + ";" + C + "R"); | |
3114 | |
3115 if (debug > 1) | |
3116 debug("ESC[6n"); | |
3117 | |
3118 break; | |
3119 | |
3120 default: | |
3121 if (debug > 0) | |
3122 debug("ESC [ " + DCEvars[0] + " n??"); | |
3123 | |
3124 break; | |
3125 } | |
3126 | |
3127 break; | |
3128 | |
3129 case 's': /* DECSC - save cursor */ | |
3130 Sc = C; | |
3131 Sr = R; | |
3132 Sa = attributes; | |
3133 | |
3134 if (debug > 3) | |
3135 debug("ESC[s"); | |
3136 | |
3137 break; | |
3138 | |
3139 case 'u': /* DECRC - restore cursor */ | |
3140 C = Sc; | |
3141 R = Sr; | |
3142 attributes = Sa; | |
3143 | |
3144 if (debug > 3) | |
3145 debug("ESC[u"); | |
3146 | |
3147 break; | |
3148 | |
3149 case 'm': /* attributes as color, bold , blink,*/ | |
3150 if (debug > 3) | |
3151 debug("ESC [ "); | |
3152 | |
3153 if (DCEvar == 0 && DCEvars[0] == 0) | |
3154 attributes = 0; | |
3155 | |
3156 for (int i = 0; i <= DCEvar; i++) { | |
3157 switch (DCEvars[i]) { | |
3158 case 0: | |
3159 if (DCEvar > 0) { | |
3160 if (terminalID.equals("scoansi")) { | |
3161 attributes &= COLOR; /* Keeps color. Strange but true. */ | |
3162 } | |
3163 else { | |
3164 attributes = 0; | |
3165 } | |
3166 } | |
3167 | |
3168 break; | |
3169 | |
3170 case 1: | |
3171 attributes |= BOLD; | |
3172 attributes &= ~LOW; | |
3173 break; | |
3174 | |
3175 case 2: | |
3176 | |
3177 /* SCO color hack mode */ | |
3178 if (terminalID.equals("scoansi") && ((DCEvar - i) >= 2)) { | |
3179 int ncolor; | |
3180 attributes &= ~(COLOR | BOLD); | |
3181 ncolor = DCEvars[i + 1]; | |
3182 | |
3183 if ((ncolor & 8) == 8) | |
3184 attributes |= BOLD; | |
3185 | |
3186 ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); | |
3187 attributes |= ((ncolor) + 1) << COLOR_FG_SHIFT; | |
3188 ncolor = DCEvars[i + 2]; | |
3189 ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); | |
3190 attributes |= ((ncolor) + 1) << COLOR_BG_SHIFT; | |
3191 i += 2; | |
3192 } | |
3193 else { | |
3194 attributes |= LOW; | |
3195 } | |
3196 | |
3197 break; | |
3198 | |
3199 case 3: /* italics */ | |
3200 attributes |= INVERT; | |
3201 break; | |
3202 | |
3203 case 4: | |
3204 attributes |= UNDERLINE; | |
3205 break; | |
3206 | |
3207 case 7: | |
3208 attributes |= INVERT; | |
3209 break; | |
3210 | |
3211 case 8: | |
3212 attributes |= INVISIBLE; | |
3213 break; | |
3214 | |
3215 case 5: /* blink on */ | |
3216 break; | |
3217 | |
3218 /* 10 - ANSI X3.64-1979, select primary font, don't display control | |
3219 * chars, don't set bit 8 on output */ | |
3220 case 10: | |
3221 gl = 0; | |
3222 usedcharsets = true; | |
3223 break; | |
3224 | |
3225 /* 11 - ANSI X3.64-1979, select second alt. font, display control | |
3226 * chars, set bit 8 on output */ | |
3227 case 11: /* SMACS , as */ | |
3228 case 12: | |
3229 gl = 1; | |
3230 usedcharsets = true; | |
3231 break; | |
3232 | |
3233 case 21: /* normal intensity */ | |
3234 attributes &= ~(LOW | BOLD); | |
3235 break; | |
3236 | |
3237 case 23: /* italics off */ | |
3238 attributes &= ~INVERT; | |
3239 break; | |
3240 | |
3241 case 25: /* blinking off */ | |
3242 break; | |
3243 | |
3244 case 27: | |
3245 attributes &= ~INVERT; | |
3246 break; | |
3247 | |
3248 case 28: | |
3249 attributes &= ~INVISIBLE; | |
3250 break; | |
3251 | |
3252 case 24: | |
3253 attributes &= ~UNDERLINE; | |
3254 break; | |
3255 | |
3256 case 22: | |
3257 attributes &= ~BOLD; | |
3258 break; | |
3259 | |
3260 case 30: | |
3261 case 31: | |
3262 case 32: | |
3263 case 33: | |
3264 case 34: | |
3265 case 35: | |
3266 case 36: | |
3267 case 37: | |
3268 attributes &= ~COLOR_FG; | |
3269 attributes |= ((DCEvars[i] - 30) + 1) << COLOR_FG_SHIFT; | |
3270 break; | |
3271 | |
3272 case 38: | |
3273 if (DCEvars[i + 1] == 5) { | |
3274 attributes &= ~COLOR_FG; | |
3275 attributes |= ((DCEvars[i + 2]) + 1) << COLOR_FG_SHIFT; | |
3276 i += 2; | |
3277 } | |
3278 | |
3279 break; | |
3280 | |
3281 case 39: | |
3282 attributes &= ~COLOR_FG; | |
3283 break; | |
3284 | |
3285 case 40: | |
3286 case 41: | |
3287 case 42: | |
3288 case 43: | |
3289 case 44: | |
3290 case 45: | |
3291 case 46: | |
3292 case 47: | |
3293 attributes &= ~COLOR_BG; | |
3294 attributes |= ((DCEvars[i] - 40) + 1) << COLOR_BG_SHIFT; | |
3295 break; | |
3296 | |
3297 case 48: | |
3298 if (DCEvars[i + 1] == 5) { | |
3299 attributes &= ~COLOR_BG; | |
3300 attributes |= (DCEvars[i + 2] + 1) << COLOR_BG_SHIFT; | |
3301 i += 2; | |
3302 } | |
3303 | |
3304 break; | |
3305 | |
3306 case 49: | |
3307 attributes &= ~COLOR_BG; | |
3308 break; | |
3309 | |
3310 case 90: | |
3311 case 91: | |
3312 case 92: | |
3313 case 93: | |
3314 case 94: | |
3315 case 95: | |
3316 case 96: | |
3317 case 97: | |
3318 attributes &= ~COLOR_FG; | |
3319 attributes |= ((DCEvars[i] - 82) + 1) << COLOR_FG_SHIFT; | |
3320 break; | |
3321 | |
3322 case 100: | |
3323 case 101: | |
3324 case 102: | |
3325 case 103: | |
3326 case 104: | |
3327 case 105: | |
3328 case 106: | |
3329 case 107: | |
3330 attributes &= ~COLOR_BG; | |
3331 attributes |= ((DCEvars[i] - 92) + 1) << COLOR_BG_SHIFT; | |
3332 break; | |
3333 | |
3334 default: | |
3335 debugStr.append("ESC [ ") | |
3336 .append(DCEvars[i]) | |
3337 .append(" m unknown..."); | |
3338 debug(debugStr.toString()); | |
3339 debugStr.setLength(0); | |
3340 break; | |
3341 } | |
3342 | |
3343 if (debug > 3) { | |
3344 debugStr.append(DCEvars[i]) | |
3345 .append(';'); | |
3346 debug(debugStr.toString()); | |
3347 debugStr.setLength(0); | |
3348 } | |
3349 } | |
3350 | |
3351 if (debug > 3) { | |
3352 debugStr.append(" (attributes = ") | |
3353 .append(attributes) | |
3354 .append(")m"); | |
3355 debug(debugStr.toString()); | |
3356 debugStr.setLength(0); | |
3357 } | |
3358 | |
3359 break; | |
3360 | |
3361 default: | |
3362 debugStr.append("ESC [ unknown letter: ") | |
3363 .append(c) | |
3364 .append(" (") | |
3365 .append((int)c) | |
3366 .append(')'); | |
3367 debug(debugStr.toString()); | |
3368 debugStr.setLength(0); | |
3369 break; | |
3370 } | |
3371 | |
3372 break; | |
3373 | |
3374 case TSTATE_TITLE: | |
3375 switch (c) { | |
3376 case ESC: | |
3377 term_state = TSTATE_ESC; | |
3378 break; | |
3379 | |
3380 default: | |
3381 // TODO save title | |
3382 break; | |
3383 } | |
3384 | |
3385 break; | |
3386 | |
3387 default: | |
3388 term_state = TSTATE_DATA; | |
3389 break; | |
3390 } | |
3391 | |
3392 setCursorPosition(C, R); | |
3393 } | |
3394 | |
3395 /* hard reset the terminal */ | |
3396 public void reset() { | |
3397 gx[0] = 'B'; | |
3398 gx[1] = 'B'; | |
3399 gx[2] = 'B'; | |
3400 gx[3] = 'B'; | |
3401 gl = 0; // default GL to G0 | |
3402 gr = 2; // default GR to G2 | |
3403 onegl = -1; // Single shift override | |
3404 /* reset tabs */ | |
3405 int nw = width; | |
3406 | |
3407 if (nw < 132) nw = 132; | |
3408 | |
3409 Tabs = new byte[nw]; | |
3410 | |
3411 for (int i = 0; i < nw; i += 8) { | |
3412 Tabs[i] = 1; | |
3413 } | |
3414 | |
3415 deleteArea(0, 0, width, height, attributes); | |
3416 setMargins(0, height); | |
3417 C = R = 0; | |
3418 _SetCursor(0, 0); | |
3419 | |
3420 if (display != null) | |
3421 display.resetColors(); | |
3422 | |
3423 showCursor(true); | |
3424 /*FIXME:*/ | |
3425 term_state = TSTATE_DATA; | |
3426 } | |
3427 } |