RS232CTerminal.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: package xeij;
14:
15: import java.awt.datatransfer.*;
16: import java.awt.event.*;
17: import java.io.*;
18: import java.net.*;
19: import java.nio.*;
20: import java.nio.channels.*;
21: import java.nio.charset.*;
22: import java.util.*;
23: import java.util.zip.*;
24: import javax.swing.*;
25: import javax.swing.event.*;
26:
27: import com.fazecast.jSerialComm.*;
28:
29: public class RS232CTerminal {
30:
31: public static final int TRM_MAX_OUTPUT_LENGTH = 1024 * 256;
32: public static final int TRM_CUT_OUTPUT_LENGTH = TRM_MAX_OUTPUT_LENGTH + 1024 * 16;
33:
34:
35: public static JFrame trmFrame;
36: public static ScrollTextArea trmBoard;
37: public static JPopupMenu trmPopupMenu;
38: public static JMenuItem trmPopupCutMenuItem;
39: public static JMenuItem trmPopupCopyMenuItem;
40: public static JMenuItem trmPopupPasteMenuItem;
41: public static JMenuItem trmPopupSelectAllMenuItem;
42: public static JMenuItem trmPopupSendCtrlCMenuItem;
43: public static StringBuilder trmOutputBuilder;
44: public static int trmOutputEnd;
45: public static int trmOutputSJIS1;
46:
47:
48: public static SerialPort[] trmPortArray;
49: public static int trmNumberOfPorts;
50:
51: public static int trmTcpipRow;
52:
53: public static int trmPppRow;
54:
55:
56:
57:
58:
59:
60:
61: public static int trmRows;
62: public static String[] trmRowName;
63: public static int[] trmRowToCol;
64:
65: public static int trmNumberOfAUXs;
66:
67:
68: public static int trmCols;
69: public static String[] trmColName;
70: public static int[] trmColToRow;
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101: static class Connection implements SerialPortDataListener {
102: int row;
103: int col;
104: int index;
105: String text;
106: boolean connected;
107: JCheckBox checkBox;
108: Box box;
109:
110:
111: ByteQueue row2colQueue;
112: ByteQueue col2rowQueue;
113: boolean row2colReset;
114: boolean col2rowReset;
115:
116:
117: boolean cts;
118: boolean dcd;
119: boolean dsr;
120: boolean ri;
121:
122:
123: @Override public int getListeningEvents () {
124: return (SerialPort.LISTENING_EVENT_DATA_AVAILABLE |
125:
126: SerialPort.LISTENING_EVENT_CARRIER_DETECT |
127: SerialPort.LISTENING_EVENT_DSR |
128: SerialPort.LISTENING_EVENT_RING_INDICATOR);
129: }
130: @Override public void serialEvent (SerialPortEvent spe) {
131: SerialPort port = spe.getSerialPort ();
132: int type = spe.getEventType ();
133: if ((type & SerialPort.LISTENING_EVENT_DATA_AVAILABLE) != 0) {
134: for (;;) {
135: int k = Math.min (port.bytesAvailable (),
136: row2colQueue.unused ());
137: if (k == 0) {
138: break;
139: }
140: byte[] b = new byte[k];
141: port.readBytes (b, k);
142: row2colQueue.write (b, 0, k);
143: }
144: }
145:
146:
147:
148:
149: if ((type & SerialPort.LISTENING_EVENT_CARRIER_DETECT) != 0) {
150: dcd = port.getDCD ();
151: }
152: if ((type & SerialPort.LISTENING_EVENT_DSR) != 0) {
153: dsr = port.getDSR ();
154: }
155: if ((type & SerialPort.LISTENING_EVENT_RING_INDICATOR) != 0) {
156: ri = port.getRI ();
157: }
158: }
159:
160:
161: boolean polling;
162: Thread row2colThread;
163: Thread col2rowThread;
164:
165:
166: class TerminalThread extends Thread {
167: @Override public void run () {
168: ByteQueue queue = (col == 0 ? row2colQueue : col2rowQueue);
169: while (polling) {
170: if (col == 0 ? row2colReset : col2rowReset) {
171: if (col == 0) {
172: row2colReset = false;
173: } else {
174: col2rowReset = false;
175: }
176: queue.clear ();
177: } else {
178: for (int k = queue.used (); k != 0; k = queue.used ()) {
179: byte[] b = new byte[k];
180: queue.read (b, 0, k);
181: for (int i = 0; i < k; i++) {
182: trmPrintSJIS (b[i] & 0xff);
183: }
184: }
185: }
186: try {
187: Thread.sleep (100);
188: } catch (InterruptedException ie) {
189: }
190: }
191: }
192: }
193:
194:
195: class SerialPortThread extends Thread {
196: @Override public void run () {
197: SerialPort port = trmPortArray[row - 1];
198: ByteQueue queue = col2rowQueue;
199: while (polling) {
200: if (col2rowReset) {
201: col2rowReset = false;
202: queue.clear ();
203: port.flushIOBuffers ();
204: } else {
205: for (int k = queue.used (); k != 0; k = queue.used ()) {
206: byte[] b = new byte[k];
207: queue.read (b, 0, k);
208: port.writeBytes (b, k);
209: }
210: }
211: try {
212: Thread.sleep (10);
213: } catch (InterruptedException ie) {
214: }
215: }
216: }
217: }
218:
219:
220: class TCPIPThread extends Thread {
221: @Override public void run () {
222: ByteQueue queue = col2rowQueue;
223: while (polling) {
224: if (col2rowReset) {
225: col2rowReset = false;
226: queue.clear ();
227: } else {
228: for (int k = queue.used (); k != 0; k = queue.used ()) {
229: byte[] b = new byte[k];
230: queue.read (b, 0, k);
231: trmTcpipWrite (b, 0, k);
232: }
233: }
234: try {
235: Thread.sleep (10);
236: } catch (InterruptedException ie) {
237: }
238: }
239: }
240: }
241:
242:
243: class PPPThread extends Thread {
244: @Override public void run () {
245: ByteQueue queue = col2rowQueue;
246: try {
247: while (polling) {
248: if (col2rowReset) {
249: col2rowReset = false;
250: queue.clear ();
251: } else {
252: for (int k = queue.used (); k != 0; k = queue.used ()) {
253: byte[] b = new byte[k];
254: queue.read (b, 0, k);
255: int i = 0;
256: while (trmPppModemLayer && i < k) {
257: int c = b[i++] & 0xff;
258: if (c != '\r') {
259: trmPppModemCommand.append ((char) c);
260: } else {
261: String s = trmPppModemCommand.toString ();
262: trmPppModemCommand.delete (0, trmPppModemCommand.length ());
263: byte[] bb;
264: if (false) {
265: bb = "NO CARRIER\r\n".getBytes ();
266: } else if (s.startsWith ("ATDT")) {
267: bb = "CONNECT\r\n".getBytes ();
268: trmPppModemLayer = false;
269: if (trmPppDebug) {
270: System.out.println ("modem layer ended");
271: }
272: } else if (s.startsWith ("AT")) {
273: bb = "OK\r\n".getBytes ();
274: } else {
275: bb = "ERROR\r\n".getBytes ();
276: }
277: row2colQueue.write (bb, 0, bb.length);
278: }
279: }
280: if (i < k) {
281: if (trmPppDebug) {
282: System.out.print ("pppd stdin");
283: for (int j = i; j < k; j++) {
284: System.out.printf (" %02X", b[j] & 0xff);
285: }
286: System.out.println ();
287: }
288: trmPppStdinStream.write (b, i, k - i);
289: trmPppStdinStream.flush ();
290: }
291: }
292: }
293: try {
294: Thread.sleep (10);
295: } catch (InterruptedException ie) {
296: }
297: }
298: } catch (IOException ioe) {
299: }
300: }
301: }
302:
303: }
304:
305:
306:
307:
308:
309:
310:
311: public static final String TRM_TCPIP_DEFAULT_HOST = "0.0.0.0";
312: public static final int TRM_TCPIP_DEFAULT_PORT = 54321;
313: public static final boolean TRM_TCPIP_DEFAULT_UTF8 = false;
314: public static String trmTcpipHost;
315: public static int trmTcpipPort;
316: public static boolean trmTcpipUTF8;
317: public static DecimalSpinner trmTcpipSpinner;
318: public static JCheckBox trmTcpipCheckBox;
319: public static ByteBuffer trmTcpipReadBuffer;
320: public static CompletionHandler<Integer, Void> trmTcpipReadHander;
321: public static CompletionHandler<AsynchronousSocketChannel, Void> trmTcpipAcceptHandler;
322: public static ByteQueue trmTcpipReadQueue;
323: public static SocketAddress trmTcpipPortAddress;
324: public static AsynchronousServerSocketChannel trmTcpipPortChannel;
325: public static final int TRM_TCPIP_BUFFER_SIZE = 4096;
326: public static AsynchronousSocketChannel trmTcpipSessionChannel;
327: public static SocketAddress trmTcpipClientAddress;
328: public static int trmTcpipToUTF8Pool;
329: public static int trmTcpipToSJISPool;
330:
331:
332:
333: public static void trmTcpipInit () {
334:
335: trmTcpipHost = Settings.sgsGetString ("tcpiphost", TRM_TCPIP_DEFAULT_HOST);
336: trmTcpipPort = Settings.sgsGetInt ("tcpipport", TRM_TCPIP_DEFAULT_PORT, 0, 65535);
337: trmTcpipUTF8 = Settings.sgsGetOnOff ("tcpiputf8", TRM_TCPIP_DEFAULT_UTF8);
338:
339: trmTcpipSpinner = ComponentFactory.createDecimalSpinner (
340: trmTcpipPort, 0, 65535, 1, 0,
341: new ChangeListener () {
342: @Override public void stateChanged (ChangeEvent ce) {
343: trmTcpipPort = trmTcpipSpinner.getIntValue ();
344: }
345: });
346:
347: trmTcpipCheckBox = ComponentFactory.createCheckBox (
348: trmTcpipUTF8, "UTF-8",
349: new ActionListener () {
350: @Override public void actionPerformed (ActionEvent ae) {
351: trmTcpipUTF8 = trmTcpipCheckBox.isSelected ();
352: }
353: });
354:
355: trmTcpipReadBuffer = ByteBuffer.allocate (TRM_TCPIP_BUFFER_SIZE);
356:
357: trmTcpipReadHander = new CompletionHandler<Integer, Void> () {
358:
359: @Override public void completed (Integer bytesRead, Void a) {
360: int l = (int) bytesRead;
361: if (l == -1) {
362: trmTcpipCloseSession (true);
363: return;
364: }
365: byte[] b = new byte[l];
366: int o = 0;
367: trmTcpipReadBuffer.flip ();
368: trmTcpipReadBuffer.get (b, o, l);
369: if (false) {
370: for (int i = 0; i < l; i++) {
371: System.out.printf ("%02x ", 0xff & b[o + i]);
372: }
373: System.out.println ();
374: }
375: byte[] bb = b;
376: int ll = l;
377: if (trmTcpipUTF8) {
378:
379: int pool = trmTcpipToSJISPool;
380: bb = new byte[2 * l];
381: ll = 0;
382: for (int i = 0; i < l; i++) {
383: int u = (pool << 8) | (0xff & b[o + i]);
384: if ((u & 0xffffffe0) == 0x000000c0 ||
385: (u & 0xfffffff0) == 0x000000e0 ||
386: (u & 0xfffff0c0) == 0x0000e080 ||
387: (u & 0xfffffff8) == 0x000000f0 ||
388: (u & 0xfffff8c0) == 0x0000f080 ||
389: (u & 0xfff8c0c0) == 0x00f08080) {
390: pool = u;
391: continue;
392: }
393: pool = 0;
394: if ((u & 0xffffff80) == 0x00000000) {
395: } else if ((u & 0xffffe0c0) == 0x0000c080) {
396: u = ((u & 0x00001f00) >> 2) | (u & 0x0000003f);
397: } else if ((u & 0xfff0c0c0) == 0x00e08080) {
398: u = ((u & 0x000f0000) >> 4) | ((u & 0x00003f00) >> 2) | (u & 0x0000003f);
399: } else if ((u & 0xf8c0c0c0) == 0xf0808080) {
400: u = ((u & 0x07000000) >> 6) | ((u & 0x003f0000) >> 4) | ((u & 0x00003f00) >> 2) | (u & 0x0000003f);
401: if (0x10ffff < u) {
402: u = '※';
403: } else if (0x00ffff < u) {
404:
405:
406:
407:
408:
409: u = '※';
410: }
411: } else {
412: u = '※';
413: }
414: int s = CharacterCode.chrCharToSJIS[u];
415: if (s == 0 && u != 0) {
416: s = 0x81a6;
417: }
418: if (0x00ff < s) {
419: bb[ll++] = (byte) (s >> 8);
420: }
421: bb[ll++] = (byte) s;
422: }
423: trmTcpipToSJISPool = pool;
424: }
425: trmTcpipReadQueue.write (bb, 0, ll);
426:
427: if (trmTcpipSessionChannel != null) {
428: trmTcpipReadBuffer.clear ();
429: trmTcpipSessionChannel.read (trmTcpipReadBuffer, null, trmTcpipReadHander);
430: }
431: }
432:
433: @Override public void failed (Throwable t, Void a) {
434: String message = t.getMessage ();
435: if (message != null) {
436: System.err.println (message);
437: }
438: trmTcpipCloseSession (true);
439: }
440: };
441:
442: trmTcpipAcceptHandler = new CompletionHandler<AsynchronousSocketChannel, Void> () {
443:
444: @Override public void completed (AsynchronousSocketChannel sessionChannel, Void a) {
445: trmTcpipSessionChannel = sessionChannel;
446:
447: trmTcpipToUTF8Pool = 0;
448: trmTcpipToSJISPool = 0;
449: try {
450: trmTcpipClientAddress = trmTcpipSessionChannel.getRemoteAddress ();
451: } catch (IOException ioe) {
452: ioe.printStackTrace ();
453: }
454: System.out.println (Multilingual.mlnJapanese ?
455: trmTcpipClientAddress + " と接続しました" :
456: trmTcpipClientAddress + " connected");
457:
458: if (trmTcpipSessionChannel != null) {
459: trmTcpipReadBuffer.clear ();
460: trmTcpipSessionChannel.read (trmTcpipReadBuffer, null, trmTcpipReadHander);
461: }
462: }
463:
464: @Override public void failed (Throwable t, Void a) {
465: String message = t.getMessage ();
466: if (message != null) {
467: System.err.println (message);
468: }
469: trmTcpipClosePort ();
470: }
471: };
472: }
473:
474:
475:
476: public static void trmTcpipTini () {
477:
478: Settings.sgsPutString ("tcpiphost", trmTcpipHost);
479: Settings.sgsPutInt ("tcpipport", trmTcpipPort);
480: Settings.sgsPutOnOff ("tcpiputf8", trmTcpipUTF8);
481: }
482:
483:
484:
485:
486: public static boolean trmTcpipOpenPort (ByteQueue readQueue) {
487: trmTcpipReadQueue = readQueue;
488: trmTcpipPortAddress = new InetSocketAddress (trmTcpipHost, trmTcpipPort);
489:
490: try {
491: trmTcpipPortChannel = AsynchronousServerSocketChannel.open ().bind (trmTcpipPortAddress);
492: } catch (IOException ioe) {
493: ioe.printStackTrace ();
494: System.out.println (Multilingual.mlnJapanese ?
495: trmTcpipPortAddress + " を開けません" :
496: trmTcpipPortAddress + " not opened");
497: return false;
498: }
499: System.out.println (Multilingual.mlnJapanese ?
500: trmTcpipPortAddress + " を開きました" :
501: trmTcpipPortAddress + " opened");
502:
503: if (trmTcpipPortChannel != null) {
504: trmTcpipPortChannel.accept (null, trmTcpipAcceptHandler);
505: }
506: return true;
507: }
508:
509:
510:
511: public static void trmTcpipClosePort () {
512: if (trmTcpipPortAddress != null) {
513: System.out.println (Multilingual.mlnJapanese ?
514: trmTcpipPortAddress + " を閉じました" :
515: trmTcpipPortAddress + " closed");
516: trmTcpipPortAddress = null;
517: }
518:
519: if (trmTcpipPortChannel != null &&
520: trmTcpipPortChannel.isOpen ()) {
521: try {
522: trmTcpipPortChannel.close ();
523: } catch (IOException ioe) {
524: ioe.printStackTrace ();
525: }
526: }
527: trmTcpipPortChannel = null;
528:
529: trmTcpipCloseSession (false);
530: }
531:
532:
533:
534:
535:
536:
537: public static void trmTcpipWrite (byte[] b, int o, int l) {
538: if (trmTcpipSessionChannel != null) {
539: byte[] bb = b;
540: int ll = l;
541: if (trmTcpipUTF8) {
542:
543: int pool = trmTcpipToUTF8Pool;
544: bb = new byte[3 * l];
545: ll = 0;
546: for (int i = 0; i < l; i++) {
547: int s = (pool << 8) | (0xff & b[o + i]);
548: if ((0x0080 <= s && s <= 0x009f) || (0x00e0 <= s && s <= 0x00ff)) {
549: pool = s;
550: continue;
551: }
552: pool = 0;
553: int u = CharacterCode.chrSJISToChar[s];
554: if (u == 0 && s != 0) {
555: u = '\ufffd';
556: }
557: if (u <= 0x007f) {
558: bb[ll++] = (byte) u;
559: } else if (u <= 0x07ff) {
560: bb[ll++] = (byte) (0xc0 | (u >> 6));
561: bb[ll++] = (byte) (0x80 | (u & 0x3f));
562: } else {
563: bb[ll++] = (byte) (0xe0 | (u >> 12));
564: bb[ll++] = (byte) (0x80 | ((u >> 6) & 0x3f));
565: bb[ll++] = (byte) (0x80 | (u & 0x3f));
566: }
567: }
568: trmTcpipToUTF8Pool = pool;
569: }
570: ByteBuffer buffer = ByteBuffer.allocate (ll);
571: buffer.put (bb, 0, ll);
572: buffer.flip ();
573: try {
574: trmTcpipSessionChannel.write (buffer).get ();
575: } catch (Throwable t) {
576: String message = t.getMessage ();
577: if (message != null) {
578: System.err.println (message);
579: }
580: trmTcpipCloseSession (true);
581: }
582: }
583: }
584:
585:
586:
587:
588: public static void trmTcpipCloseSession (boolean reconnect) {
589: if (trmTcpipSessionChannel == null) {
590: return;
591: }
592: if (trmTcpipClientAddress != null) {
593: System.out.println (Multilingual.mlnJapanese ?
594: trmTcpipClientAddress + " との接続を閉じました" :
595: trmTcpipClientAddress + " disconnected");
596: trmTcpipClientAddress = null;
597: }
598:
599: try {
600: trmTcpipSessionChannel.close ();
601: } catch (IOException ioe) {
602: ioe.printStackTrace ();
603: }
604: trmTcpipSessionChannel = null;
605: if (reconnect) {
606:
607: if (trmTcpipPortChannel != null) {
608: trmTcpipPortChannel.accept (null, trmTcpipAcceptHandler);
609: }
610: }
611: }
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623: public static String trmPppAddress;
624: public static boolean trmPppDebug;
625: public static boolean trmPppDirect;
626: public static boolean trmPppLog;
627: public static boolean trmPppServer;
628:
629: public static boolean trmPppAvailable;
630: public static ByteQueue trmPppReadQueue;
631: public static Process trmPppProcess;
632: public static OutputStream trmPppStdinStream;
633: public static Thread trmPppStdoutGobbler;
634: public static Thread trmPppStderrGobbler;
635: public static boolean trmPppModemLayer;
636: public static StringBuilder trmPppModemCommand;
637:
638:
639:
640: public static void trmPppInit () {
641:
642: trmPppAddress = Settings.sgsGetString ("pppaddress", "192.168.10.1:192.168.10.2");
643: trmPppDebug = Settings.sgsGetOnOff ("pppdebug", false);
644: trmPppDirect = Settings.sgsGetOnOff ("pppdirect", false);
645: trmPppLog = Settings.sgsGetOnOff ("ppplog", false);
646: trmPppServer = Settings.sgsGetOnOff ("pppserver", false);
647:
648: trmPppAvailable = trmPppServer && new File ("/usr/sbin/pppd").exists ();
649: }
650:
651:
652:
653: public static void trmPppTini () {
654:
655: Settings.sgsPutString ("pppaddress", trmPppAddress);
656: Settings.sgsPutOnOff ("pppdebug", trmPppDebug);
657: Settings.sgsPutOnOff ("pppdirect", trmPppDirect);
658: Settings.sgsPutOnOff ("ppplog", trmPppLog);
659: Settings.sgsPutOnOff ("pppserver", trmPppServer);
660: }
661:
662:
663:
664:
665: public static boolean trmPppOpenPort (ByteQueue readQueue) {
666:
667: trmPppReadQueue = readQueue;
668: trmPppProcess = null;
669: trmPppStdinStream = null;
670: trmPppModemLayer = false;
671: if (!trmPppDirect) {
672: trmPppModemLayer = true;
673: if (trmPppDebug) {
674: System.out.println ("modem layer started");
675: }
676: }
677: trmPppModemCommand = new StringBuilder ();
678: try {
679: trmPppProcess = new ProcessBuilder (
680: "sudo", "pppd",
681: trmPppAddress,
682: "asyncmap", "0",
683: "default-asyncmap",
684: "local",
685: "mru", "1500",
686: "mtu", "1500",
687: "noaccomp",
688: "noauth",
689: "nobsdcomp",
690: "noccp",
691: "nodeflate",
692: "nodeflatedraft",
693: "nodetach",
694: "noipv6",
695: "nopcomp",
696: "nopredictor1",
697: "notty",
698: "novj",
699: "novjccomp",
700: "passive",
701: "silent"
702: ).start ();
703: System.out.println ("pppd started");
704: trmPppStdinStream = trmPppProcess.getOutputStream ();
705: } catch (IOException ioe) {
706: ioe.printStackTrace ();
707: return false;
708: }
709:
710: trmPppStdoutGobbler = new Thread (() -> {
711: if (trmPppDebug) {
712: System.out.println ("pppd stdout gobbler started");
713: }
714: try (var is = trmPppProcess.getInputStream ()) {
715: byte[] b = new byte[1024];
716: while (trmPppProcess != null) {
717: int k = is.read (b);
718: if (0 < k) {
719: if (trmPppDebug) {
720: System.out.print ("pppd stdout");
721: for (int i = 0; i < k; i++) {
722: System.out.printf (" %02X", b[i] & 0xff);
723: }
724: System.out.println ();
725: }
726: trmPppReadQueue.write (b, 0, k);
727: }
728: }
729: } catch (IOException ioe) {
730: }
731: if (trmPppDebug) {
732: System.out.println ("pppd stdout gobbler ended");
733: }
734: });
735: trmPppStdoutGobbler.start ();
736:
737: trmPppStderrGobbler = new Thread (() -> {
738: if (trmPppDebug) {
739: System.out.println ("pppd stderr gobbler started");
740: }
741: try (var is = trmPppProcess.getErrorStream ()) {
742: byte[] b = new byte[1024];
743: while (trmPppProcess != null) {
744: int k = is.read (b);
745: if (0 < k && trmPppLog) {
746: System.out.print ("pppd stderr ");
747: for (int i = 0; i < k; i++) {
748: System.out.printf ("%c", b[i] & 0xff);
749: }
750: }
751: }
752: } catch (IOException ioe) {
753: }
754: if (trmPppDebug) {
755: System.out.println ("pppd stderr gobbler ended");
756: }
757: });
758: trmPppStderrGobbler.start ();
759: return true;
760: }
761:
762:
763:
764: public static void trmPppClosePort () {
765:
766: trmPppProcess.destroy ();
767: trmPppProcess = null;
768: System.out.println ("pppd destroyed");
769:
770: try {
771: trmPppStdoutGobbler.join (100L);
772: } catch (InterruptedException ie) {
773: }
774:
775: try {
776: trmPppStderrGobbler.join (100L);
777: } catch (InterruptedException ie) {
778: }
779: }
780:
781:
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793:
794:
795: public static boolean trmAUXFlowControlRTS;
796: public static boolean trmAUXFlowControlXON;
797: public static boolean trmAUXNotReceiving;
798:
799:
800: public static int trmAUXDataBuffer;
801: public static boolean trmAUXDataAvailable;
802:
803:
804:
805: public static int trmAUXReadData () {
806: trmAUXDataAvailable = false;
807: return trmAUXDataBuffer;
808: }
809:
810:
811:
812: public static void trmAUXWriteData (int data) {
813: int col = 1;
814: int row = trmColToRow[col];
815: if (row < 0) {
816: return;
817: }
818: data &= 0xff;
819: if (trmAUXFlowControlXON) {
820: if (data == 0x11) {
821: trmAUXNotReceiving = false;
822: return;
823: } else if (data == 0x13) {
824: trmAUXNotReceiving = true;
825: return;
826: }
827: }
828: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (data);
829:
830: trmAUXSendEmpty = false;
831: TickerQueue.tkqAdd (trmAUXSendTicker, XEiJ.mpuClockTime + Z8530.scc1aInterval);
832: }
833:
834:
835:
836:
837: public static void trmAUXSetNotReceiving (boolean notReceiving) {
838: trmAUXNotReceiving = notReceiving;
839: }
840:
841:
842:
843: public static boolean trmAUXDTR;
844: public static void trmAUXSetDTR (boolean dtr) {
845: if (trmAUXDTR != dtr) {
846: trmAUXDTR = dtr;
847: if (trmAUXConnection != null) {
848: int row = trmAUXConnection.row;
849: SerialPort port = row < 1 || trmNumberOfPorts < row ? null : trmPortArray[row - 1];
850: if (port != null) {
851: if (dtr) {
852: port.setDTR ();
853: } else {
854: port.clearDTR ();
855: }
856: }
857: }
858: }
859: }
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882: public static int trmAUXReadRR0 () {
883: return (trmAUXConnection == null ? 0 :
884: (trmAUXConnection.cts ? 1 << 5 : 0 << 5) |
885: (trmAUXConnection.dsr ? 1 << 3 : 0 << 3) |
886: (trmAUXSendEmpty ? 1 << 2 : 0 << 2) |
887: (trmAUXDataAvailable ? 1 << 0 : 0 << 0));
888: }
889:
890:
891:
892: public static int trmMUSReadRR0 () {
893: return (trmAUXConnection == null ? 0 :
894: (trmAUXConnection.ri ? 1 << 5 : 0 << 5) |
895: (trmAUXConnection.dcd ? 1 << 3 : 0 << 3));
896: }
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908: public static boolean trmAUXSendEmpty;
909: public static final TickerQueue.Ticker trmAUXSendTicker = new TickerQueue.Ticker () {
910: @Override protected void tick () {
911: trmAUXSendEmpty = true;
912: if ((Z8530.sccMIE & Z8530.scc1aSendMask) != 0) {
913: Z8530.scc1aSendRR3 = Z8530.SCC_1A_SEND_MASK;
914: Z8530.scc1aSendRequest = Z8530.SCC_1A_SEND_MASK;
915: XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
916: }
917: }
918: };
919:
920:
921: public static Connection trmAUXConnection;
922: public static final TickerQueue.Ticker trmAUXTicker = new TickerQueue.Ticker () {
923: @Override protected void tick () {
924: long interval = XEiJ.TMR_FREQ / 1000 * 1;
925: ByteQueue queue = trmAUXConnection.row2colQueue;
926: if (trmAUXConnection.row2colReset) {
927: trmAUXConnection.row2colReset = false;
928: queue.clear ();
929: } else if (!trmAUXNotReceiving &&
930: queue.used () != 0) {
931: trmAUXDataBuffer = queue.read ();
932: trmAUXDataAvailable = true;
933: if ((Z8530.sccMIE & Z8530.scc1aReceiveMask) != 0 &&
934: Z8530.scc1aReceiveRR3 == 0) {
935: Z8530.scc1aReceiveRR3 = Z8530.SCC_1A_RECEIVE_MASK;
936: Z8530.scc1aReceiveRequest = Z8530.SCC_1A_RECEIVE_MASK;
937: XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
938: }
939: interval = Z8530.scc1aInterval;
940: }
941: TickerQueue.tkqAdd (trmAUXTicker, XEiJ.mpuClockTime + interval);
942: }
943: };
944:
945: public static int trmRSDRV202Head;
946: public static int trmTMSIO031Head;
947: public static int trmBSIO021Head;
948:
949:
950:
951:
952:
953:
954:
955:
956: public static final TickerQueue.Ticker trmAUXFlowControlTicker = new TickerQueue.Ticker () {
957: @Override protected void tick () {
958: int set232c = MC68060.mmuPeekLongData (0x04c0, 1);
959: int modeAddress = (0x00fc0000 <= set232c && set232c < 0x01000000 ? 0x0926 :
960: set232c == trmRSDRV202Head + 0x03ba ? trmRSDRV202Head + 0x0ab2 :
961: set232c == trmTMSIO031Head + 0x0210 ? trmTMSIO031Head + 0x0a42 :
962: set232c == trmBSIO021Head + 0x013A ? trmBSIO021Head + 0x074a :
963: 0);
964: if (modeAddress == 0) {
965: return;
966: }
967: int mode = MC68060.mmuPeekWordZeroData (modeAddress, 1);
968: if (mode == 0x0000 || mode == 0xffff) {
969: return;
970: }
971: boolean rts = (mode & 0x0080) != 0;
972: boolean xon = !rts && (mode & 0x0200) != 0;
973: if (trmAUXFlowControlRTS == rts &&
974: trmAUXFlowControlXON == xon) {
975: return;
976: }
977: trmAUXFlowControlRTS = rts;
978: trmAUXFlowControlXON = xon;
979: if (false) {
980: System.out.printf ("flowcontrol=%s\n", rts ? "rts" : xon ? "xon" : "none");
981: }
982: int row = trmColToRow[1];
983: SerialPort port = row < 1 || trmNumberOfPorts < row ? null : trmPortArray[row - 1];
984: if (port != null) {
985: port.setFlowControl (rts ? (SerialPort.FLOW_CONTROL_RTS_ENABLED |
986: SerialPort.FLOW_CONTROL_CTS_ENABLED) :
987: xon ? (SerialPort.FLOW_CONTROL_XONXOFF_IN_ENABLED |
988: SerialPort.FLOW_CONTROL_XONXOFF_OUT_ENABLED) :
989: SerialPort.FLOW_CONTROL_DISABLED);
990: }
991: }
992: };
993:
994:
995:
996: public static void trmAUXReset () {
997: if (trmAUXConnection != null) {
998: TickerQueue.tkqRemove (trmAUXFlowControlTicker);
999:
1000: trmAUXConnection.row2colReset = true;
1001: trmAUXConnection.col2rowReset = true;
1002: }
1003: }
1004:
1005:
1006: public static Connection[] trmConnectionArray;
1007: public static Box trmConnectionBox;
1008: public static ActionListener trmConnectionListener;
1009: public static boolean trmRefreshEnabled;
1010: public static JButton trmRefreshButton;
1011:
1012: public static boolean trmSettingsEnabled;
1013: public static String[] trmBaudRateArray;
1014: public static int trmBaudRateIndex;
1015: public static String[] trmDataBitsArray;
1016: public static int trmDataBitsIndex;
1017: public static String[] trmParityArray;
1018: public static int trmParityIndex;
1019: public static String[] trmStopBitsArray;
1020: public static int trmStopBitsIndex;
1021: public static String[] trmFlowControlArray;
1022: public static int trmFlowControlIndex;
1023: public static JComboBox<String> trmBaudRateComboBox;
1024: public static JComboBox<String> trmDataBitsComboBox;
1025: public static JComboBox<String> trmParityComboBox;
1026: public static JComboBox<String> trmStopBitsComboBox;
1027: public static JComboBox<String> trmFlowControlComboBox;
1028:
1029: public static boolean trmSendEnabled;
1030: public static JButton trmSendButton;
1031: public static JFileChooser trmSendFileChooser;
1032: public static JDialog trmSendDialog;
1033: public static SendThread trmSendThread;
1034:
1035: public static JTextField trmAdditionalTextField;
1036:
1037:
1038:
1039: public static void trmInitConnection () {
1040:
1041: trmBaudRateArray = new String[] { "75", "150", "300", "600", "1200", "2400", "4800", "9600", "19200", "31250", "38400", "50000", "57600", "76800", "115200", "230400" };
1042: trmBaudRateIndex = 10;
1043: trmDataBitsArray = new String[] { "B5", "B6", "B7", "B8" };
1044: trmDataBitsIndex = 3;
1045: trmParityArray = new String[] { "PN", "PO", "PE" };
1046: trmParityIndex = 0;
1047: trmStopBitsArray = new String[] { "S1", "S1.5", "S2" };
1048: trmStopBitsIndex = 0;
1049: trmFlowControlArray = new String[] { "NONE", "XON", "RTS" };
1050: trmFlowControlIndex = 2;
1051: trmBaudRateComboBox = null;
1052: trmDataBitsComboBox = null;
1053: trmParityComboBox = null;
1054: trmStopBitsComboBox = null;
1055: trmFlowControlComboBox = null;
1056:
1057: for (String keyword : Settings.sgsGetString ("terminalsettings").split ("/")) {
1058: for (int i = 0; i < trmBaudRateArray.length; i++) {
1059: if (trmBaudRateArray[i].equals (keyword)) {
1060: trmBaudRateIndex = i;
1061: break;
1062: }
1063: }
1064: for (int i = 0; i < trmDataBitsArray.length; i++) {
1065: if (trmDataBitsArray[i].equals (keyword)) {
1066: trmDataBitsIndex = i;
1067: break;
1068: }
1069: }
1070: for (int i = 0; i < trmParityArray.length; i++) {
1071: if (trmParityArray[i].equals (keyword)) {
1072: trmParityIndex = i;
1073: break;
1074: }
1075: }
1076: for (int i = 0; i < trmStopBitsArray.length; i++) {
1077: if (trmStopBitsArray[i].equals (keyword)) {
1078: trmStopBitsIndex = i;
1079: break;
1080: }
1081: }
1082: for (int i = 0; i < trmFlowControlArray.length; i++) {
1083: if (trmFlowControlArray[i].equals (keyword)) {
1084: trmFlowControlIndex = i;
1085: break;
1086: }
1087: }
1088: }
1089:
1090: trmSendButton = null;
1091: trmSendFileChooser = null;
1092: trmSendDialog = null;
1093: trmSendThread = null;
1094:
1095: trmPortArray = new SerialPort[0];
1096: trmNumberOfPorts = 0;
1097:
1098: trmTcpipRow = -1;
1099:
1100: trmPppRow = -1;
1101:
1102: trmRows = 1;
1103: trmRowName = new String[1];
1104: trmRowName[0] = "Terminal";
1105: trmRowToCol = new int[1];
1106: Arrays.fill (trmRowToCol, -1);
1107:
1108: trmNumberOfAUXs = 0;
1109:
1110: trmCols = 1;
1111: trmColName = new String[1];
1112: trmColName[0] = "Terminal";
1113: trmColToRow = new int[1];
1114: Arrays.fill (trmColToRow, -1);
1115:
1116: {
1117: String text = Settings.sgsGetString ("additionalport");
1118: try {
1119: text = URLDecoder.decode (text, "UTF-8");
1120: } catch (UnsupportedEncodingException uee) {
1121: text = "";
1122: }
1123: trmAdditionalTextField = ComponentFactory.createTextField (text, 30);
1124: }
1125:
1126: trmTcpipInit ();
1127:
1128: trmPppInit ();
1129:
1130: trmConnectionArray = new Connection[0];
1131: trmConnectionBox = ComponentFactory.createVerticalBox (
1132: Box.createVerticalGlue (),
1133: ComponentFactory.createHorizontalBox (
1134: Multilingual.mlnText (
1135: ComponentFactory.createLabel ("Additional port "),
1136: "ja", "追加ポート "
1137: ),
1138: trmAdditionalTextField,
1139: Multilingual.mlnText (
1140: ComponentFactory.createLabel (" TCP/IP port "),
1141: "ja", " TCP/IP ポート "
1142: ),
1143: trmTcpipSpinner,
1144: Box.createHorizontalStrut (5),
1145: trmTcpipCheckBox,
1146: Box.createHorizontalGlue ()
1147: )
1148: );
1149: trmConnectionListener = new ActionListener () {
1150: @Override public void actionPerformed (ActionEvent ae) {
1151: String command = ae.getActionCommand ();
1152: for (Connection connection : trmConnectionArray) {
1153: if (connection.text.equals (command)) {
1154: if (connection.connected) {
1155: trmDisconnect (connection);
1156: } else {
1157: trmConnect (connection);
1158: }
1159: break;
1160: }
1161: }
1162: }
1163: };
1164: trmRefreshEnabled = false;
1165: trmRefreshButton = null;
1166: trmSettingsEnabled = false;
1167: trmSendEnabled = false;
1168:
1169: trmUpdateConnection ();
1170:
1171: HashSet<String> map = new HashSet<String> ();
1172: for (String encodedText : Settings.sgsGetString ("rs232cconnection").split ("/")) {
1173: try {
1174: map.add (URLDecoder.decode (encodedText, "UTF-8"));
1175: } catch (UnsupportedEncodingException uee) {
1176: }
1177: }
1178: for (Connection connection : trmConnectionArray) {
1179: if (map.contains (connection.text)) {
1180: trmConnect (connection);
1181: }
1182: }
1183: }
1184:
1185:
1186:
1187: public static void trmTiniConnection () {
1188:
1189: {
1190: StringBuilder sb = new StringBuilder ();
1191: for (Connection connection : trmConnectionArray) {
1192: if (connection.connected) {
1193: if (sb.length () != 0) {
1194: sb.append ('/');
1195: }
1196: try {
1197: sb.append (URLEncoder.encode (connection.text, "UTF-8"));
1198: } catch (UnsupportedEncodingException uee) {
1199: }
1200: }
1201: }
1202: Settings.sgsPutString ("rs232cconnection", sb.toString ());
1203: }
1204:
1205: {
1206: String text = trmAdditionalTextField.getText ();
1207: try {
1208: text = URLEncoder.encode (text, "UTF-8");
1209: } catch (UnsupportedEncodingException uee) {
1210: text = "";
1211: }
1212: Settings.sgsPutString ("additionalport", text);
1213: }
1214:
1215: trmTcpipTini ();
1216:
1217: trmPppTini ();
1218:
1219: {
1220: StringBuilder sb = new StringBuilder ();
1221: sb.append (trmBaudRateArray[trmBaudRateIndex]);
1222: sb.append ('/');
1223: sb.append (trmDataBitsArray[trmDataBitsIndex]);
1224: sb.append ('/');
1225: sb.append (trmParityArray[trmParityIndex]);
1226: sb.append ('/');
1227: sb.append (trmStopBitsArray[trmStopBitsIndex]);
1228: sb.append ('/');
1229: sb.append (trmFlowControlArray[trmFlowControlIndex]);
1230: Settings.sgsPutString ("terminalsettings", sb.toString ());
1231: }
1232:
1233: for (Connection connection : trmConnectionArray) {
1234: trmDisconnect (connection);
1235: }
1236: }
1237:
1238:
1239:
1240: public static boolean trmIsConnectionUpdatable () {
1241: for (Connection connection : trmConnectionArray) {
1242: if (connection.row != 0 &&
1243: connection.connected) {
1244: return false;
1245: }
1246: }
1247: return true;
1248: }
1249:
1250:
1251:
1252: public static void trmUpdateConnection () {
1253:
1254: if (!trmIsConnectionUpdatable ()) {
1255: return;
1256: }
1257:
1258: ArrayList<SerialPort> portList = new ArrayList<SerialPort> ();
1259: try {
1260: for (SerialPort port : SerialPort.getCommPorts ()) {
1261: portList.add (port);
1262: }
1263: } catch (Throwable t) {
1264:
1265: }
1266: for (String descriptor : trmAdditionalTextField.getText ().split (",")) {
1267: descriptor = descriptor.trim ();
1268: if (!descriptor.equals ("")) {
1269: try {
1270: SerialPort port = SerialPort.getCommPort (descriptor);
1271: if (port != null) {
1272: if (false) {
1273: for (SerialPort anotherPort : portList) {
1274: if (port.getDescriptivePortName ().equals (anotherPort.getDescriptivePortName ())) {
1275: port = null;
1276: break;
1277: }
1278: }
1279: }
1280: if (port != null) {
1281: portList.add (port);
1282: }
1283: } else {
1284: System.out.println (descriptor + " not found");
1285: }
1286: } catch (SerialPortInvalidPortException spipe) {
1287: System.out.println (spipe.toString ());
1288: }
1289: }
1290: }
1291: trmNumberOfPorts = portList.size ();
1292: trmPortArray = portList.toArray (new SerialPort[trmNumberOfPorts]);
1293:
1294: trmTcpipRow = (1 +
1295: trmNumberOfPorts);
1296:
1297: if (trmPppAvailable) {
1298: trmPppRow = (1 +
1299: trmNumberOfPorts +
1300: (0 <= trmTcpipRow ? 1 : 0));
1301: } else {
1302: trmPppRow = -1;
1303: }
1304:
1305: trmRows = (1 +
1306: trmNumberOfPorts +
1307: (0 <= trmTcpipRow ? 1 : 0) +
1308: (0 <= trmPppRow ? 1 : 0));
1309: trmRowName = new String[trmRows];
1310:
1311: trmRowName[0] = "Terminal";
1312:
1313: for (int row = 1; row <= trmNumberOfPorts; row++) {
1314: SerialPort port = trmPortArray[row - 1];
1315: trmRowName[row] = port.getSystemPortName () + "(" + port.getPortDescription () + ")";
1316: }
1317:
1318: if (0 <= trmTcpipRow) {
1319: trmRowName[trmTcpipRow] = "TCP/IP";
1320: }
1321:
1322: if (0 <= trmPppRow) {
1323: trmRowName[trmPppRow] = "PPP server";
1324: }
1325: trmRowToCol = new int[trmRows];
1326: Arrays.fill (trmRowToCol, -1);
1327:
1328: trmNumberOfAUXs = 1;
1329:
1330: trmCols = (1 +
1331: trmNumberOfAUXs);
1332: trmColName = new String[trmCols];
1333: trmColName[0] = "Terminal";
1334: for (int col = 1; col < trmCols; col++) {
1335: trmColName[col] = col == 1 ? "AUX" : "AUX" + col;
1336: }
1337: trmColToRow = new int[trmCols];
1338: Arrays.fill (trmColToRow, -1);
1339:
1340: for (int index = trmConnectionArray.length - 1; 0 <= index; index--) {
1341: trmConnectionBox.remove (index);
1342: }
1343: trmConnectionArray = new Connection[trmCols * trmRows - 1];
1344: for (int row = 0; row < trmRows; row++) {
1345: for (int col = 0; col < trmCols; col++) {
1346: if (col == 0 && row == 0) {
1347: continue;
1348: }
1349: Connection connection = new Connection ();
1350: connection.row = row;
1351: connection.col = col;
1352: connection.index = trmCols * row + col - 1;
1353: connection.text = trmRowName[row] + " ⇔ " + trmColName[col];
1354: connection.connected = false;
1355: connection.checkBox =
1356: ComponentFactory.createCheckBox (connection.connected, connection.text, trmConnectionListener);
1357: connection.box =
1358: ComponentFactory.createHorizontalBox (
1359: connection.checkBox,
1360: Box.createHorizontalGlue ());
1361: trmConnectionArray[connection.index] = connection;
1362: trmConnectionBox.add (connection.box, connection.index);
1363: }
1364: }
1365: trmUpdateComponents ();
1366: trmConnectionBox.validate ();
1367: }
1368:
1369:
1370:
1371:
1372:
1373: public static void trmUpdateComponents () {
1374: boolean updatable = true;
1375: boolean configurable = false;
1376: boolean transferable = false;
1377: for (Connection connection : trmConnectionArray) {
1378: if (connection.connected) {
1379: connection.checkBox.setEnabled (true);
1380: if (1 <= connection.row && connection.row <= trmNumberOfPorts) {
1381: updatable = false;
1382: if (connection.col == 0) {
1383: configurable = true;
1384: }
1385: }
1386: if (connection.row == 0 ||
1387: connection.col == 0) {
1388: transferable = true;
1389: }
1390: } else {
1391: connection.checkBox.setEnabled (trmIsConnectable (connection));
1392: }
1393: }
1394: trmRefreshEnabled = updatable;
1395: if (trmRefreshButton != null) {
1396: trmRefreshButton.setEnabled (updatable);
1397: }
1398: trmSettingsEnabled = configurable;
1399: trmSendEnabled = transferable;
1400: if (trmBaudRateComboBox != null) {
1401: trmBaudRateComboBox.setEnabled (configurable);
1402: trmDataBitsComboBox.setEnabled (configurable);
1403: trmParityComboBox.setEnabled (configurable);
1404: trmStopBitsComboBox.setEnabled (configurable);
1405: trmFlowControlComboBox.setEnabled (configurable);
1406: trmSendButton.setEnabled (transferable);
1407: }
1408: }
1409:
1410:
1411:
1412: public static boolean trmIsConnectable (Connection connection) {
1413: if (!connection.connected) {
1414: for (Connection connection2 : trmConnectionArray) {
1415: if (connection != connection2 &&
1416: connection2.connected &&
1417: (((connection.row == 0 || connection.col == 0) &&
1418: (connection2.row == 0 || connection2.col == 0)) ||
1419: connection.row == connection2.row ||
1420: connection.col == connection2.col)) {
1421: return false;
1422: }
1423: }
1424: }
1425: return true;
1426: }
1427:
1428:
1429:
1430: public static void trmConnect (Connection connection) {
1431:
1432: if (connection.connected ||
1433: !trmIsConnectable (connection)) {
1434: return;
1435: }
1436:
1437: connection.connected = true;
1438: connection.checkBox.setSelected (true);
1439: trmRowToCol[connection.row] = connection.col;
1440: trmColToRow[connection.col] = connection.row;
1441: trmUpdateComponents ();
1442:
1443: connection.row2colQueue = new ByteQueue ();
1444: connection.col2rowQueue = new ByteQueue ();
1445:
1446: connection.cts = true;
1447: connection.dcd = true;
1448: connection.dsr = false;
1449: connection.ri = false;
1450: if (1 <= connection.row && connection.row <= trmNumberOfPorts) {
1451:
1452: SerialPort port = trmPortArray[connection.row - 1];
1453: port.openPort ();
1454: System.out.println (Multilingual.mlnJapanese ?
1455: connection.text + " を開きました" :
1456: connection.text + " opened");
1457: port.setComPortTimeouts (SerialPort.TIMEOUT_WRITE_BLOCKING | SerialPort.TIMEOUT_READ_BLOCKING, 0, 0);
1458: port.setFlowControl (SerialPort.FLOW_CONTROL_DISABLED);
1459:
1460: trmReflectSettings (connection.col);
1461:
1462: if (trmAUXDTR) {
1463: port.setDTR ();
1464: } else {
1465: port.clearDTR ();
1466: }
1467:
1468:
1469: connection.dcd = port.getDCD ();
1470: connection.dsr = port.getDSR ();
1471: connection.ri = port.getRI ();
1472:
1473: port.addDataListener (connection);
1474: } else if (connection.row == trmTcpipRow) {
1475:
1476: if (!trmTcpipOpenPort (connection.row2colQueue)) {
1477:
1478:
1479: }
1480:
1481:
1482:
1483:
1484:
1485: } else if (connection.row == trmPppRow) {
1486:
1487: if (!trmPppOpenPort (connection.row2colQueue)) {
1488:
1489:
1490: }
1491:
1492:
1493:
1494:
1495:
1496: }
1497:
1498: connection.polling = true;
1499: connection.row2colThread = (connection.col == 0 ? connection.new TerminalThread () :
1500: null);
1501: connection.col2rowThread = (connection.row == 0 ? connection.new TerminalThread () :
1502: connection.row == trmTcpipRow ? connection.new TCPIPThread () :
1503: connection.row == trmPppRow ? connection.new PPPThread () :
1504: connection.new SerialPortThread ());
1505: for (int i = 0; i < 2; i++) {
1506: Thread thread = (i == 0 ? connection.row2colThread : connection.col2rowThread);
1507: if (thread != null) {
1508: thread.start ();
1509: }
1510: }
1511:
1512: if (connection.col == 1) {
1513: trmAUXNotReceiving = false;
1514: trmAUXDataBuffer = 0;
1515: trmAUXDataAvailable = false;
1516: trmAUXConnection = connection;
1517: TickerQueue.tkqAdd (trmAUXTicker, XEiJ.mpuClockTime + XEiJ.TMR_FREQ / 1000 * 1);
1518:
1519: trmAUXSendEmpty = true;
1520: }
1521: }
1522:
1523:
1524:
1525: public static void trmDisconnect (Connection connection) {
1526:
1527: if (!connection.connected) {
1528: return;
1529: }
1530:
1531: connection.connected = false;
1532: connection.checkBox.setSelected (connection.connected);
1533: trmRowToCol[connection.row] = -1;
1534: trmColToRow[connection.col] = -1;
1535: trmUpdateComponents ();
1536:
1537: if (trmAUXConnection != null) {
1538: TickerQueue.tkqRemove (trmAUXTicker);
1539: trmAUXConnection = null;
1540: }
1541:
1542: connection.polling = false;
1543: for (int i = 0; i < 2; i++) {
1544: Thread thread = (i == 0 ? connection.row2colThread : connection.col2rowThread);
1545: if (thread != null) {
1546: connection.row2colThread = null;
1547: if (thread.isAlive ()) {
1548: thread.interrupt ();
1549: try {
1550: thread.join ();
1551: } catch (InterruptedException ie) {
1552: }
1553: }
1554: }
1555: }
1556:
1557: if (connection.col == 1) {
1558: TickerQueue.tkqRemove (trmAUXSendTicker);
1559: }
1560:
1561: connection.cts = false;
1562: connection.dcd = false;
1563: connection.dsr = false;
1564: connection.ri = false;
1565: if (1 <= connection.row && connection.row <= trmNumberOfPorts) {
1566: SerialPort port = trmPortArray[connection.row - 1];
1567:
1568: port.removeDataListener ();
1569:
1570: port.closePort ();
1571: System.out.println (Multilingual.mlnJapanese ?
1572: connection.text + " を閉じました" :
1573: connection.text + " closed");
1574: } else if (connection.row == trmTcpipRow) {
1575:
1576: trmTcpipClosePort ();
1577: } else if (connection.row == trmPppRow) {
1578:
1579: trmPppClosePort ();
1580: }
1581:
1582: connection.row2colQueue.clear ();
1583: connection.col2rowQueue.clear ();
1584: connection.row2colQueue = null;
1585: connection.col2rowQueue = null;
1586: }
1587:
1588:
1589:
1590: public static void trmSetBaudRate (int index) {
1591: if (0 <= index && index < trmBaudRateArray.length) {
1592: trmBaudRateIndex = index;
1593: trmReflectSettings (0);
1594: }
1595: }
1596:
1597:
1598:
1599: public static void trmSetDataBits (int index) {
1600: if (0 <= index && index < trmDataBitsArray.length) {
1601: trmDataBitsIndex = index;
1602: trmReflectSettings (0);
1603: }
1604: }
1605:
1606:
1607:
1608: public static void trmSetParity (int index) {
1609: if (0 <= index && index < trmParityArray.length) {
1610: trmParityIndex = index;
1611: trmReflectSettings (0);
1612: }
1613: }
1614:
1615:
1616:
1617: public static void trmSetStopBits (int index) {
1618: if (0 <= index && index < trmStopBitsArray.length) {
1619: trmStopBitsIndex = index;
1620: trmReflectSettings (0);
1621: }
1622: }
1623:
1624:
1625:
1626: public static void trmSetFlowControl (int index) {
1627: if (0 <= index && index < trmFlowControlArray.length) {
1628: trmFlowControlIndex = index;
1629: trmReflectSettings (0);
1630: }
1631: }
1632:
1633:
1634:
1635: public static void trmReflectSettings (int col) {
1636: int row = trmColToRow[col];
1637: SerialPort port = row < 1 || trmNumberOfPorts < row ? null : trmPortArray[row - 1];
1638: if (col == 0) {
1639: String baudRate = trmBaudRateArray[trmBaudRateIndex];
1640: String dataBits = trmDataBitsArray[trmDataBitsIndex];
1641: String stopBits = trmStopBitsArray[trmStopBitsIndex];
1642: String parity = trmParityArray[trmParityIndex];
1643: String flowControl = trmFlowControlArray[trmFlowControlIndex];
1644: if (port != null) {
1645: port.setComPortParameters (Integer.parseInt (baudRate, 10),
1646: Integer.parseInt (dataBits.substring (1), 10),
1647: stopBits.equals ("S1.5") ? SerialPort.ONE_POINT_FIVE_STOP_BITS :
1648: stopBits.equals ("S2") ? SerialPort.TWO_STOP_BITS : SerialPort.ONE_STOP_BIT,
1649: parity.equals ("PO") ? SerialPort.ODD_PARITY :
1650: parity.equals ("PE") ? SerialPort.EVEN_PARITY : SerialPort.NO_PARITY);
1651: port.setFlowControl (flowControl.equals ("RTS") ? (SerialPort.FLOW_CONTROL_RTS_ENABLED |
1652: SerialPort.FLOW_CONTROL_CTS_ENABLED) :
1653: flowControl.equals ("XON") ? (SerialPort.FLOW_CONTROL_XONXOFF_IN_ENABLED |
1654: SerialPort.FLOW_CONTROL_XONXOFF_OUT_ENABLED) :
1655: SerialPort.FLOW_CONTROL_DISABLED);
1656: }
1657: } else if (col == 1) {
1658: double rate = Z8530.sccFreq / (double) ((Z8530.scc1aBaudRateGen + 2) << (Z8530.scc1aClockModeShift + 1));
1659: double bits = (1.0 +
1660: (Z8530.scc1aRxBits == 0 ? 5.0 :
1661: Z8530.scc1aRxBits == 1 ? 7.0 :
1662: Z8530.scc1aRxBits == 2 ? 6.0 : 8.0) +
1663: ((Z8530.scc1aParity & 1) == 0 ? 0.0 : 1.0) +
1664: (Z8530.scc1aStop == 0 ? 0.0 :
1665: Z8530.scc1aStop == 1 ? 1.0 :
1666: Z8530.scc1aStop == 2 ? 1.5 : 2.0));
1667: double interval = bits / rate;
1668: if (false) {
1669: System.out.printf ("%08x baudrate=%.3fbps interval=%.3fus\n", XEiJ.regPC0, rate, interval * 1e+6);
1670: }
1671: Z8530.scc1aInterval = Math.round (interval * (double) XEiJ.TMR_FREQ);
1672:
1673: if (port != null) {
1674: port.setComPortParameters ((int) Math.round (rate),
1675: Z8530.scc1aRxBits == 0b00 ? 5 :
1676: Z8530.scc1aRxBits == 0b01 ? 7 :
1677: Z8530.scc1aRxBits == 0b10 ? 6 : 8,
1678: Z8530.scc1aStop == 0b10 ? SerialPort.ONE_POINT_FIVE_STOP_BITS :
1679: Z8530.scc1aStop == 0b11 ? SerialPort.TWO_STOP_BITS : SerialPort.ONE_STOP_BIT,
1680: Z8530.scc1aParity == 0b01 ? SerialPort.ODD_PARITY :
1681: Z8530.scc1aParity == 0b11 ? SerialPort.EVEN_PARITY : SerialPort.NO_PARITY);
1682: }
1683:
1684:
1685: TickerQueue.tkqAdd (trmAUXFlowControlTicker, XEiJ.mpuClockTime + XEiJ.TMR_FREQ * 500 / 1000000);
1686: } else {
1687:
1688: }
1689: }
1690:
1691:
1692:
1693:
1694: public static void trmInit () {
1695: trmFrame = null;
1696: trmBoard = null;
1697: trmPopupMenu = null;
1698: trmPopupCutMenuItem = null;
1699: trmPopupCopyMenuItem = null;
1700: trmPopupPasteMenuItem = null;
1701: trmPopupSelectAllMenuItem = null;
1702: trmPopupSendCtrlCMenuItem = null;
1703: trmOutputBuilder = new StringBuilder ();
1704: trmOutputEnd = 0;
1705: trmOutputSJIS1 = 0;
1706:
1707: trmInitConnection ();
1708: trmReset ();
1709: }
1710:
1711: public static void trmReset () {
1712: trmRSDRV202Head = 0;
1713: trmTMSIO031Head = 0;
1714: trmBSIO021Head = 0;
1715: trmAUXFlowControlXON = false;
1716: trmAUXFlowControlRTS = false;
1717: }
1718:
1719:
1720:
1721: public static void trmTini () {
1722: trmTiniConnection ();
1723: }
1724:
1725:
1726:
1727:
1728: public static void trmMake () {
1729:
1730:
1731: trmBoard = ComponentFactory.createScrollTextArea (
1732: trmOutputBuilder.toString (),
1733: 650, 350,
1734: true);
1735: trmOutputBuilder = null;
1736: trmBoard.setUnderlineCursorOn (true);
1737: trmBoard.setLineWrap (true);
1738: trmBoard.addDocumentListener (new DocumentListener () {
1739: @Override public void changedUpdate (DocumentEvent de) {
1740: }
1741: @Override public void insertUpdate (DocumentEvent de) {
1742: if (de.getOffset () < trmOutputEnd) {
1743: trmOutputEnd += de.getLength ();
1744: }
1745: }
1746: @Override public void removeUpdate (DocumentEvent de) {
1747: if (de.getOffset () < trmOutputEnd) {
1748: trmOutputEnd -= Math.min (de.getLength (), trmOutputEnd - de.getOffset ());
1749: }
1750: }
1751: });
1752: trmBoard.addKeyListener (new KeyAdapter () {
1753: @Override public void keyPressed (KeyEvent ke) {
1754: int keyCode = ke.getKeyCode ();
1755: if (keyCode == KeyEvent.VK_ENTER) {
1756: ke.consume ();
1757: trmEnter ();
1758: } else if (keyCode == KeyEvent.VK_PAUSE) {
1759: ke.consume ();
1760: trmSendString ("\u0003");
1761: }
1762: }
1763: });
1764:
1765:
1766: ActionListener popupActionListener = new ActionListener () {
1767: @Override public void actionPerformed (ActionEvent ae) {
1768: switch (ae.getActionCommand ()) {
1769: case "Cut":
1770: trmCut ();
1771: break;
1772: case "Copy":
1773: trmCopy ();
1774: break;
1775: case "Paste":
1776: trmPaste ();
1777: break;
1778: case "Select All":
1779: trmSelectAll ();
1780: break;
1781: case "Send ^C":
1782: trmSendString ("\u0003");
1783: break;
1784: }
1785: }
1786: };
1787: trmPopupMenu = ComponentFactory.createPopupMenu (
1788: trmPopupCutMenuItem = Multilingual.mlnText (
1789: ComponentFactory.createMenuItem ("Cut", 'T', popupActionListener),
1790: "ja", "切り取り"),
1791: trmPopupCopyMenuItem = Multilingual.mlnText (
1792: ComponentFactory.createMenuItem ("Copy", 'C', popupActionListener),
1793: "ja", "コピー"),
1794: trmPopupPasteMenuItem = Multilingual.mlnText (
1795: ComponentFactory.createMenuItem ("Paste", 'P', popupActionListener),
1796: "ja", "貼り付け"),
1797: ComponentFactory.createHorizontalSeparator (),
1798: trmPopupSelectAllMenuItem = Multilingual.mlnText (
1799: ComponentFactory.createMenuItem ("Select All", 'A', popupActionListener),
1800: "ja", "すべて選択"),
1801: ComponentFactory.createHorizontalSeparator (),
1802: trmPopupSendCtrlCMenuItem = Multilingual.mlnText (
1803: ComponentFactory.createMenuItem ("Send ^C", popupActionListener),
1804: "ja", "^C 送信")
1805: );
1806: trmBoard.addMouseListener (new MouseAdapter () {
1807: @Override public void mousePressed (MouseEvent me) {
1808: trmShowPopup (me);
1809: }
1810: @Override public void mouseReleased (MouseEvent me) {
1811: trmShowPopup (me);
1812: }
1813: });
1814:
1815:
1816: ActionListener listener = new ActionListener () {
1817: @Override public void actionPerformed (ActionEvent ae) {
1818: Object source = ae.getSource ();
1819: String command = ae.getActionCommand ();
1820: switch (command) {
1821: case "Refresh":
1822: trmUpdateConnection ();
1823: break;
1824: case "Baud rate":
1825: trmSetBaudRate (((JComboBox) source).getSelectedIndex ());
1826: break;
1827: case "Data bits":
1828: trmSetDataBits (((JComboBox) source).getSelectedIndex ());
1829: break;
1830: case "Parity":
1831: trmSetParity (((JComboBox) source).getSelectedIndex ());
1832: break;
1833: case "Stop bits":
1834: trmSetStopBits (((JComboBox) source).getSelectedIndex ());
1835: break;
1836: case "Flow control":
1837: trmSetFlowControl (((JComboBox) source).getSelectedIndex ());
1838: break;
1839: case "Send file":
1840: trmSendFile ();
1841: break;
1842: case "7.3728MHz":
1843: Z8530.sccFreq = ((JCheckBox) source).isSelected () ? 7372800.0 : 5000000.0;
1844: break;
1845: default:
1846: System.out.println ("unknown action command " + command);
1847: }
1848: }
1849: };
1850:
1851:
1852: trmRefreshButton =
1853: ComponentFactory.setEnabled (
1854: Multilingual.mlnText (
1855: ComponentFactory.createButton ("Refresh", listener),
1856: "ja", "更新"),
1857: trmRefreshEnabled);
1858: trmBaudRateComboBox =
1859: ComponentFactory.setEnabled (
1860: Multilingual.mlnToolTipText (
1861: ComponentFactory.createComboBox (
1862: trmBaudRateIndex, "Baud rate", listener, trmBaudRateArray),
1863: "ja", "ボーレート"),
1864: trmSettingsEnabled);
1865: trmDataBitsComboBox =
1866: ComponentFactory.setEnabled (
1867: Multilingual.mlnToolTipText (
1868: ComponentFactory.createComboBox (
1869: trmDataBitsIndex, "Data bits", listener, trmDataBitsArray),
1870: "ja", "データビット"),
1871: trmSettingsEnabled);
1872: trmParityComboBox =
1873: ComponentFactory.setEnabled (
1874: Multilingual.mlnToolTipText (
1875: ComponentFactory.createComboBox (
1876: trmParityIndex, "Parity", listener, trmParityArray),
1877: "ja", "パリティ"),
1878: trmSettingsEnabled);
1879: trmStopBitsComboBox =
1880: ComponentFactory.setEnabled (
1881: Multilingual.mlnToolTipText (
1882: ComponentFactory.createComboBox (
1883: trmStopBitsIndex, "Stop bits", listener, trmStopBitsArray),
1884: "ja", "ストップビット"),
1885: trmSettingsEnabled);
1886: trmFlowControlComboBox =
1887: ComponentFactory.setEnabled (
1888: Multilingual.mlnToolTipText (
1889: ComponentFactory.createComboBox (
1890: trmFlowControlIndex, "Flow control", listener, trmFlowControlArray),
1891: "ja", "フロー制御"),
1892: trmSettingsEnabled);
1893: trmSendButton =
1894: ComponentFactory.setEnabled (
1895: Multilingual.mlnText (
1896: ComponentFactory.createButton ("Send file", listener),
1897: "ja", "ファイル送信"),
1898: trmSendEnabled);
1899:
1900:
1901: trmFrame = Multilingual.mlnTitle (
1902: ComponentFactory.createRestorableSubFrame (
1903: Settings.SGS_TRM_FRAME_KEY,
1904: "RS-232C and terminal",
1905: null,
1906: ComponentFactory.createVerticalSplitPane (
1907: ComponentFactory.createVerticalBox (
1908: Multilingual.mlnTitledBorder (
1909: ComponentFactory.setTitledLineBorder (
1910: ComponentFactory.createHorizontalBox (
1911: Box.createHorizontalStrut (5),
1912: ComponentFactory.createVerticalBox (
1913: Box.createVerticalGlue (),
1914: trmRefreshButton,
1915: Box.createVerticalGlue ()
1916: ),
1917: Box.createHorizontalStrut (10),
1918: trmConnectionBox,
1919: Box.createHorizontalGlue ()
1920: ),
1921: "Connection"),
1922: "ja", "接続"),
1923: ComponentFactory.createHorizontalBox (
1924: Multilingual.mlnTitledBorder (
1925: ComponentFactory.setTitledLineBorder (
1926: ComponentFactory.createHorizontalBox (
1927: Box.createHorizontalStrut (5),
1928: trmBaudRateComboBox,
1929: trmDataBitsComboBox,
1930: trmParityComboBox,
1931: trmStopBitsComboBox,
1932: trmFlowControlComboBox,
1933: Box.createHorizontalStrut (5)
1934: ),
1935: "Communication Settings"),
1936: "ja", "通信設定"),
1937: Multilingual.mlnTitledBorder (
1938: ComponentFactory.setTitledLineBorder (
1939: ComponentFactory.createHorizontalBox (
1940: Box.createHorizontalStrut (5),
1941: trmSendButton,
1942: Box.createHorizontalStrut (5)
1943: ),
1944: "Transfer"),
1945: "ja", "転送"),
1946: Box.createHorizontalGlue (),
1947: Multilingual.mlnTitledBorder (
1948: ComponentFactory.setTitledLineBorder (
1949: ComponentFactory.createHorizontalBox (
1950: Box.createHorizontalStrut (5),
1951: ComponentFactory.createCheckBox (Z8530.sccFreq == 7372800.0, "7.3728MHz", listener),
1952: Box.createHorizontalStrut (5)
1953: ),
1954: "Modification"),
1955: "ja", "改造")
1956: )
1957: ),
1958: ComponentFactory.createVerticalBox (
1959: Multilingual.mlnTitledBorder (
1960: ComponentFactory.setTitledLineBorder (trmBoard, "Terminal"),
1961: "ja", "ターミナル")
1962: )
1963: )
1964: ),
1965: "ja", "RS-232C とターミナル");
1966:
1967: }
1968:
1969:
1970:
1971:
1972: public static void trmShowPopup (MouseEvent me) {
1973: if (me.isPopupTrigger ()) {
1974:
1975: boolean enableCutAndCopy = XEiJ.clpClipboard != null && trmBoard.getSelectionStart () != trmBoard.getSelectionEnd ();
1976: ComponentFactory.setEnabled (trmPopupCutMenuItem, enableCutAndCopy);
1977: ComponentFactory.setEnabled (trmPopupCopyMenuItem, enableCutAndCopy);
1978:
1979: ComponentFactory.setEnabled (trmPopupPasteMenuItem, XEiJ.clpClipboard != null && XEiJ.clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor));
1980:
1981: ComponentFactory.setEnabled (trmPopupSelectAllMenuItem, XEiJ.clpClipboard != null);
1982:
1983: ComponentFactory.setEnabled (trmPopupSendCtrlCMenuItem,
1984: trmRowToCol[0] == 1 ||
1985: 0 < trmColToRow[0]);
1986:
1987: trmPopupMenu.show (me.getComponent (), me.getX (), me.getY ());
1988: }
1989: }
1990:
1991:
1992:
1993: public static void trmCut () {
1994: if (XEiJ.clpClipboard != null) {
1995:
1996: XEiJ.clpClipboardString = trmBoard.getSelectedText ();
1997: try {
1998: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
1999: XEiJ.clpIsClipboardOwner = true;
2000: } catch (Exception e) {
2001: return;
2002: }
2003:
2004: trmBoard.replaceRange ("", trmBoard.getSelectionStart (), trmBoard.getSelectionEnd ());
2005: }
2006: }
2007:
2008:
2009:
2010: public static void trmCopy () {
2011: if (XEiJ.clpClipboard != null) {
2012:
2013: String selectedText = trmBoard.getSelectedText ();
2014: if (selectedText != null) {
2015: XEiJ.clpClipboardString = selectedText;
2016: try {
2017: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
2018: XEiJ.clpIsClipboardOwner = true;
2019: } catch (Exception e) {
2020: return;
2021: }
2022: }
2023: }
2024: }
2025:
2026:
2027:
2028: public static void trmPaste () {
2029: if (XEiJ.clpClipboard != null) {
2030:
2031: String string = null;
2032: try {
2033: string = (String) XEiJ.clpClipboard.getData (DataFlavor.stringFlavor);
2034: } catch (Exception e) {
2035: return;
2036: }
2037:
2038: trmBoard.replaceRange (string, trmBoard.getSelectionStart (), trmBoard.getSelectionEnd ());
2039: }
2040: }
2041:
2042:
2043:
2044: public static void trmSelectAll () {
2045: if (XEiJ.clpClipboard != null) {
2046:
2047: trmBoard.selectAll ();
2048: }
2049: }
2050:
2051:
2052: public static void trmStart () {
2053: if (RestorableFrame.rfmGetOpened (Settings.SGS_TRM_FRAME_KEY)) {
2054: trmOpen ();
2055: }
2056: }
2057:
2058:
2059:
2060: public static void trmOpen () {
2061: if (trmFrame == null) {
2062: trmMake ();
2063: }
2064: XEiJ.pnlExitFullScreen (false);
2065: trmFrame.setVisible (true);
2066: }
2067:
2068:
2069:
2070:
2071: public static void trmPrintSJIS (int d) {
2072: d &= 0xff;
2073: if (trmOutputSJIS1 != 0) {
2074: if (0x40 <= d && d != 0x7f && d <= 0xfc) {
2075: int c = CharacterCode.chrSJISToChar[trmOutputSJIS1 << 8 | d];
2076: if (c != 0) {
2077: trmPrintChar (c);
2078: } else {
2079:
2080: trmPrintChar ('[');
2081: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 >> 4));
2082: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 & 15));
2083: trmPrintChar (XEiJ.fmtHexc (d >> 4));
2084: trmPrintChar (XEiJ.fmtHexc (d & 15));
2085: trmPrintChar (']');
2086: }
2087: trmOutputSJIS1 = 0;
2088: return;
2089: }
2090:
2091:
2092: trmPrintChar ('[');
2093: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 >> 4));
2094: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 & 15));
2095: trmPrintChar (']');
2096: trmOutputSJIS1 = 0;
2097: }
2098: if (0x81 <= d && d <= 0x9f || 0xe0 <= d && d <= 0xef) {
2099: trmOutputSJIS1 = d;
2100: } else {
2101: int c = CharacterCode.chrSJISToChar[d];
2102: if (c != 0) {
2103: trmPrintChar (c);
2104: } else {
2105:
2106: trmPrintChar ('[');
2107: trmPrintChar (XEiJ.fmtHexc (d >> 4));
2108: trmPrintChar (XEiJ.fmtHexc (d & 15));
2109: trmPrintChar (']');
2110: }
2111: }
2112: }
2113:
2114:
2115:
2116: public static void trmPrintChar (int c) {
2117: if (c == 0x08) {
2118: if (trmOutputEnd > 0) {
2119: if (trmBoard != null) {
2120: trmBoard.replaceRange ("", trmOutputEnd - 1, trmOutputEnd);
2121: trmOutputEnd--;
2122: trmBoard.setCaretPosition (trmOutputEnd);
2123: } else {
2124: trmOutputBuilder.delete (trmOutputEnd - 1, trmOutputEnd);
2125: trmOutputEnd--;
2126: }
2127: }
2128: } else if (c >= 0x20 && c != 0x7f || c == 0x09 || c == 0x0a) {
2129: if (trmBoard != null) {
2130: trmBoard.insert (String.valueOf ((char) c), trmOutputEnd);
2131: trmOutputEnd++;
2132: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
2133: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
2134: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
2135: }
2136: trmBoard.setCaretPosition (trmOutputEnd);
2137: } else {
2138: trmOutputBuilder.append ((char) c);
2139: trmOutputEnd++;
2140: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
2141: trmOutputBuilder.delete (0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
2142: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
2143: }
2144: }
2145: }
2146: }
2147:
2148:
2149:
2150:
2151:
2152: public static void trmPrint (String s) {
2153: if (s == null) {
2154: return;
2155: }
2156: if (trmFrame != null) {
2157: trmBoard.insert (s, trmOutputEnd);
2158: trmOutputEnd += s.length ();
2159: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
2160: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
2161: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
2162: }
2163: trmBoard.setCaretPosition (trmOutputEnd);
2164: } else {
2165: trmOutputBuilder.append (s);
2166: trmOutputEnd += s.length ();
2167: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
2168: trmOutputBuilder.delete (0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
2169: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
2170: }
2171: }
2172: }
2173:
2174:
2175:
2176:
2177:
2178: public static void trmPrintln (String s) {
2179: trmPrint (s);
2180: trmPrintChar ('\n');
2181: }
2182:
2183:
2184:
2185: public static void trmEnter () {
2186: String text = trmBoard.getText ();
2187: int length = text.length ();
2188: int outputLineStart = text.lastIndexOf ('\n', trmOutputEnd - 1) + 1;
2189: int caretLineStart = text.lastIndexOf ('\n', trmBoard.getCaretPosition () - 1) + 1;
2190: if (outputLineStart <= caretLineStart) {
2191: trmBoard.replaceRange ("", trmOutputEnd, length);
2192: trmSendString (text.substring (trmOutputEnd, length) + "\r");
2193: } else if (outputLineStart < trmOutputEnd) {
2194: String prompt = text.substring (outputLineStart, trmOutputEnd);
2195: int caretLineEnd = text.indexOf ('\n', caretLineStart);
2196: if (caretLineEnd == -1) {
2197: caretLineEnd = length;
2198: }
2199: String line = text.substring (caretLineStart, caretLineEnd);
2200: int start = line.indexOf (prompt);
2201: if (start >= 0) {
2202: trmOutputEnd = length;
2203: if (text.charAt (trmOutputEnd - 1) != '\n') {
2204: trmBoard.insert ("\n", trmOutputEnd);
2205: trmOutputEnd++;
2206: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
2207: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
2208: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
2209: }
2210: }
2211: trmBoard.setCaretPosition (trmOutputEnd);
2212: trmSendString (line.substring (start + prompt.length ()) + "\r");
2213: }
2214: }
2215: }
2216:
2217:
2218:
2219: public static void trmSendString (String s) {
2220: int l = s.length ();
2221: if (l == 0) {
2222: return;
2223: }
2224: byte[] b = new byte[l * 2];
2225: int k = 0;
2226: for (int i = 0; i < l; i++) {
2227: int c = CharacterCode.chrCharToSJIS[s.charAt (i)];
2228: if (0x00ff < c) {
2229: b[k++] = (byte) (c >> 8);
2230: }
2231: b[k++] = (byte) c;
2232: }
2233: if (trmRowToCol[0] == 1) {
2234: int row = 0;
2235: int col = 1;
2236: trmConnectionArray[trmCols * row + col - 1].row2colQueue.write (b, 0, k);
2237: } else if (0 < trmColToRow[0]) {
2238: int row = trmColToRow[0];
2239: int col = 0;
2240: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (b, 0, k);
2241: }
2242: }
2243:
2244:
2245:
2246:
2247:
2248: public static void trmSendFile () {
2249: if (trmSendDialog == null) {
2250: ActionListener listener = new ActionListener () {
2251: @Override public void actionPerformed (ActionEvent ae) {
2252: switch (ae.getActionCommand ()) {
2253: case JFileChooser.APPROVE_SELECTION:
2254: case "Send":
2255: trmSendDialog.setVisible (false);
2256: File file = trmSendFileChooser.getSelectedFile ();
2257: if (file != null) {
2258: trmSendThread = new SendThread (file);
2259: trmSendThread.start ();
2260: }
2261: break;
2262: case JFileChooser.CANCEL_SELECTION:
2263: case "Cancel":
2264: trmSendDialog.setVisible (false);
2265: break;
2266: }
2267: }
2268: };
2269: trmSendFileChooser = new JFileChooser (new File ("a.txt"));
2270: trmSendFileChooser.setMultiSelectionEnabled (false);
2271: trmSendFileChooser.setControlButtonsAreShown (false);
2272: trmSendFileChooser.addActionListener (listener);
2273: trmSendDialog =
2274: Multilingual.mlnTitle (
2275: ComponentFactory.createModalDialog (
2276: trmFrame,
2277: "Send file",
2278: ComponentFactory.createBorderPanel (
2279: 0, 0,
2280: ComponentFactory.createVerticalBox (
2281: trmSendFileChooser,
2282: ComponentFactory.createHorizontalBox (
2283: Box.createHorizontalStrut (12),
2284: Box.createHorizontalGlue (),
2285: Multilingual.mlnText (
2286: ComponentFactory.createLabel (
2287: "Prepare COMMAND.X with CTTY AUX"),
2288: "ja", "COMMAND.X を CTTY AUX で準備して"),
2289: Box.createHorizontalStrut (12),
2290: Multilingual.mlnText (
2291: ComponentFactory.createButton ("Send", KeyEvent.VK_S, listener),
2292: "ja", "送信"),
2293: Box.createHorizontalStrut (12),
2294: Multilingual.mlnText (
2295: ComponentFactory.createButton ("Cancel", KeyEvent.VK_C, listener),
2296: "ja", "キャンセル"),
2297: Box.createHorizontalStrut (12)
2298: ),
2299: Box.createVerticalStrut (12)
2300: )
2301: )
2302: ),
2303: "ja", "ファイル送信");
2304: }
2305: XEiJ.pnlExitFullScreen (true);
2306: trmSendDialog.setVisible (true);
2307: }
2308:
2309:
2310:
2311:
2312:
2313:
2314:
2315: static class SendThread extends Thread {
2316: File file;
2317: SendThread (File file) {
2318: this.file = file;
2319: }
2320: @Override public void run () {
2321: trmSendProcess (file);
2322: }
2323: }
2324:
2325:
2326:
2327: static byte[] load (File file) {
2328: if (!file.isFile ()) {
2329: return null;
2330: }
2331: int len = (int) file.length ();
2332: if (len == 0) {
2333: return null;
2334: }
2335: byte[] buf = new byte[len];
2336: try (BufferedInputStream bis = new BufferedInputStream (new FileInputStream (file))) {
2337: if (bis.read (buf) != len) {
2338: return null;
2339: }
2340: } catch (IOException ioe) {
2341: return null;
2342: }
2343: return buf;
2344: }
2345:
2346:
2347:
2348: static class BitWriter {
2349:
2350: byte[] buffer;
2351: int byteIndex;
2352: int bitIndex;
2353: int bitCount;
2354:
2355:
2356:
2357: BitWriter () {
2358: buffer = new byte[16];
2359: byteIndex = 0;
2360: bitIndex = -1;
2361: bitCount = 0;
2362: }
2363:
2364:
2365:
2366:
2367: void writeByte (int data) {
2368: if (byteIndex == buffer.length) {
2369: byte[] temporary = new byte[byteIndex * 2];
2370: System.arraycopy (buffer, 0,
2371: temporary, 0,
2372: byteIndex);
2373: buffer = temporary;
2374: }
2375: buffer[byteIndex++] = (byte) data;
2376: }
2377:
2378:
2379:
2380:
2381:
2382: void writeBits (int width, int data) {
2383: while (width != 0) {
2384: if (bitCount == 0) {
2385: if (byteIndex == buffer.length) {
2386: byte[] temporary = new byte[byteIndex * 2];
2387: System.arraycopy (buffer, 0,
2388: temporary, 0,
2389: byteIndex);
2390: buffer = temporary;
2391: }
2392: bitIndex = byteIndex;
2393: bitCount = 8;
2394: buffer[byteIndex++] = 0;
2395: }
2396: data &= (1 << width) - 1;
2397: int n = Math.min (bitCount, width);
2398: bitCount -= n;
2399: width -= n;
2400: buffer[bitIndex] |= (byte) ((data >>> width) << bitCount);
2401: }
2402: }
2403:
2404:
2405:
2406: byte[] getBuffer () {
2407: return buffer;
2408: }
2409:
2410:
2411:
2412: int getLength () {
2413: return byteIndex;
2414: }
2415:
2416: }
2417:
2418: static class DIC {
2419: int ptr;
2420: int len;
2421: }
2422:
2423:
2424:
2425:
2426:
2427: static byte[] compress (byte[] inpbuf, int dicbit) {
2428: int dicsiz = 1 << dicbit;
2429:
2430: DIC[] dicbuf = new DIC[dicsiz];
2431: for (int pag = 0; pag < dicsiz; pag++) {
2432: dicbuf[pag] = new DIC ();
2433: dicbuf[pag].ptr = 0;
2434: dicbuf[pag].len = 0;
2435: }
2436: int dicent = 0;
2437:
2438: int inplen = inpbuf.length;
2439: BitWriter bw = new BitWriter ();
2440: bw.writeBits (24, inplen);
2441:
2442: bw.writeBits (4, dicbit);
2443:
2444: int inpptr = 0;
2445: while (inpptr < inplen) {
2446:
2447: int dicpag = -1;
2448: int dicptr = -1;
2449: int diclen = 0;
2450: int fstchr = inpbuf[inpptr] & 255;
2451: for (int pag = 0; pag < dicsiz; pag++) {
2452: int len = dicbuf[pag].len;
2453: if (diclen < len &&
2454: inpptr + len + 1 <= inplen) {
2455: int ptr = dicbuf[pag].ptr;
2456: cmp:
2457: if (fstchr == (inpbuf[ptr] & 255)) {
2458: for (int i = 1; i < len; i++) {
2459: if (inpbuf[inpptr + i] != inpbuf[ptr + i]) {
2460: break cmp;
2461: }
2462: }
2463: dicpag = pag;
2464: dicptr = ptr;
2465: diclen = len;
2466: }
2467: }
2468: }
2469: if (diclen == 0) {
2470: bw.writeBits (1, 0);
2471: } else {
2472: bw.writeBits (1, 1);
2473: bw.writeBits (dicbit, dicpag);
2474: }
2475: int chr = inpbuf[inpptr + diclen] & 255;
2476:
2477: bw.writeByte (chr);
2478:
2479: diclen++;
2480:
2481: dicbuf[dicent].ptr = inpptr;
2482: dicbuf[dicent].len = diclen;
2483: dicent++;
2484: if (dicent == dicsiz) {
2485: dicent = 0;
2486: }
2487:
2488: inpptr += diclen;
2489: }
2490:
2491: byte[] outbuf = bw.getBuffer ();
2492: int outlen = bw.getLength ();
2493: if (outbuf.length != outlen) {
2494: byte[] tmpbuf = new byte[outlen];
2495: System.arraycopy (outbuf, 0, tmpbuf, 0, outlen);
2496: outbuf = tmpbuf;
2497: }
2498: return outbuf;
2499: }
2500:
2501:
2502:
2503:
2504:
2505:
2506:
2507:
2508:
2509:
2510: public static byte[] encode (byte[] src) {
2511: int r = src.length;
2512: int q = r / 62;
2513: r -= 62 * q;
2514: if (r != 0) {
2515: r = ((r + 2 + 3) & -4) - 2;
2516: if (src.length < 62 * q + r) {
2517: byte[] tmp = new byte[62 * q + r];
2518: System.arraycopy (src, 0, tmp, 0, src.length);
2519: src = tmp;
2520: }
2521: }
2522: byte[] dst = new byte[64 * q + (r == 0 ? 0 : r + 2)];
2523: int[] w = new int[16];
2524: for (int i = 0; 64 * i < dst.length; i++) {
2525: int n = Math.min (64, dst.length - 64 * i) / 4;
2526:
2527: for (int k = 0; k < n - 1; k++) {
2528: w[k] = ((src[62 * i + 4 * k + 0] & 255) << 24 |
2529: (src[62 * i + 4 * k + 1] & 255) << 16 |
2530: (src[62 * i + 4 * k + 2] & 255) << 8 |
2531: (src[62 * i + 4 * k + 3] & 255));
2532: }
2533: w[n - 1] = ((src[62 * i + 4 * (n - 1) + 0] & 255) << 24 |
2534: (src[62 * i + 4 * (n - 1) + 1] & 255) << 16);
2535:
2536: for (int k = 0; k < n; k++) {
2537: if ((w[k] & 0x80000000) != 0) {
2538: w[k] &= 0x7fffffff;
2539: w[n - 1] |= 1 << (15 - k);
2540: }
2541: }
2542:
2543: for (int k = 0; k < n; k++) {
2544: int t3 = w[k];
2545: int t2 = t3 / 224;
2546: t3 -= 224 * t2;
2547: int t1 = t2 / 224;
2548: t2 -= 224 * t1;
2549: int t0 = t1 / 224;
2550: t1 -= 224 * t0;
2551: dst[64 * i + 4 * k + 0] = (byte) (32 + t0);
2552: dst[64 * i + 4 * k + 1] = (byte) (32 + t1);
2553: dst[64 * i + 4 * k + 2] = (byte) (32 + t2);
2554: dst[64 * i + 4 * k + 3] = (byte) (32 + t3);
2555: }
2556: }
2557: return dst;
2558: }
2559:
2560:
2561:
2562: public static void trmSendProcess (File file) {
2563:
2564: byte[] fileData = load (file);
2565: if (fileData == null) {
2566: return;
2567: }
2568: if (0x00ffff00 < fileData.length) {
2569: return;
2570: }
2571:
2572:
2573:
2574: byte[] step3Data = new byte[adotr3.length +
2575: 24 +
2576: 4 +
2577: 4 +
2578: 4 +
2579: fileData.length];
2580: int index3 = 0;
2581:
2582: System.arraycopy (adotr3, 0,
2583: step3Data, index3,
2584: adotr3.length);
2585: index3 += adotr3.length;
2586:
2587:
2588:
2589:
2590:
2591: String name = file.getName ();
2592: {
2593: byte[] b = new byte[2 * name.length ()];
2594: int k = 0;
2595: int p = -1;
2596: for (int i = 0; i < name.length (); i++) {
2597: int c = CharacterCode.chrCharToSJIS[name.charAt (i)];
2598: if (c == 0) {
2599: return;
2600: }
2601: if (c <= ' ' || c == ':' || c == '*' || c == '?' ||
2602: c == '\\' || c == '/' || (c == '-' && k == 0) ||
2603: c == '"' || c == '\'' || c == '+' || c == ';' ||
2604: c == '<' || c == '=' || c == '>' ||
2605: c == '[' || c == ']' || c == '|') {
2606: return;
2607: }
2608: if (c == '.') {
2609: if (p < 0) {
2610: p = k;
2611: } else {
2612: return;
2613: }
2614: }
2615: if (0x00ff < c) {
2616: b[k++] = (byte) (c >> 8);
2617: }
2618: b[k++] = (byte) c;
2619: if (p < 0 ? 18 < k : p + 1 + 3 < k) {
2620: return;
2621: }
2622: }
2623: for (int i = 0; i < k; i++) {
2624: step3Data[index3++] = b[i];
2625: }
2626: for (int i = k; i < 24; i++) {
2627: step3Data[index3++] = 0;
2628: }
2629: }
2630:
2631: {
2632: long dttm = DnT.dntDttmCmil (file.lastModified () + RP5C15.rtcCmilGap);
2633: int date = DnT.dntYearDttm (dttm) - 1980 << 9 | DnT.dntMontDttm (dttm) << 5 | DnT.dntMdayDttm (dttm);
2634: int time = DnT.dntHourDttm (dttm) << 11 | DnT.dntMinuDttm (dttm) << 5 | DnT.dntSecoDttm (dttm) >> 1;
2635: step3Data[index3++] = (byte) (date >> 8);
2636: step3Data[index3++] = (byte) date;
2637: step3Data[index3++] = (byte) (time >> 8);
2638: step3Data[index3++] = (byte) time;
2639: }
2640:
2641: {
2642: CRC32 crc32 = new CRC32 ();
2643: crc32.update (fileData, 0, fileData.length);
2644: int t = (int) crc32.getValue ();
2645: step3Data[index3++] = (byte) (t >> 24);
2646: step3Data[index3++] = (byte) (t >> 16);
2647: step3Data[index3++] = (byte) (t >> 8);
2648: step3Data[index3++] = (byte) (t);
2649: }
2650:
2651: {
2652: int t = fileData.length;
2653: step3Data[index3++] = (byte) (t >> 24);
2654: step3Data[index3++] = (byte) (t >> 16);
2655: step3Data[index3++] = (byte) (t >> 8);
2656: step3Data[index3++] = (byte) (t);
2657: }
2658:
2659: System.arraycopy (fileData, 0,
2660: step3Data, index3,
2661: fileData.length);
2662: index3 += fileData.length;
2663:
2664:
2665:
2666: byte[] step3DataCompressed = null;
2667: int dicbit = 0;
2668:
2669:
2670:
2671:
2672: for (int i = 8; i <= 10; i++) {
2673: byte[] t = compress (step3Data, i);
2674: if (step3DataCompressed == null ||
2675: t.length < step3DataCompressed.length) {
2676: step3DataCompressed = t;
2677: dicbit = i;
2678: }
2679: }
2680: byte[] step2Data = new byte[adotr2.length + step3DataCompressed.length];
2681: int index2 = 0;
2682:
2683: System.arraycopy (adotr2, 0,
2684: step2Data, index2,
2685: adotr2.length);
2686: index2 += adotr2.length;
2687:
2688: System.arraycopy (step3DataCompressed, 0,
2689: step2Data, index2,
2690: step3DataCompressed.length);
2691: index2 += step3DataCompressed.length;
2692:
2693:
2694:
2695: byte[] step3DataEncoded = encode (step3Data);
2696: byte[] step2DataEncoded = encode (step2Data);
2697: byte[] step1Data;
2698: if (step3DataEncoded.length <= step2DataEncoded.length) {
2699: step1Data = new byte[adotr1.length + step3DataEncoded.length + 1];
2700: int index1 = 0;
2701: System.arraycopy (adotr1, 0,
2702: step1Data, index1,
2703: adotr1.length);
2704: index1 += adotr1.length;
2705: System.arraycopy (step3DataEncoded, 0,
2706: step1Data, index1,
2707: step3DataEncoded.length);
2708: index1 += step3DataEncoded.length;
2709: step1Data[index1++] = 0x1a;
2710: if (false) {
2711: System.out.printf (" original: %d bytes (%.1f%%)\n",
2712: fileData.length,
2713: 100.0);
2714: System.out.printf (" generator concatenated: %d bytes (%.1f%%)\n",
2715: step3Data.length,
2716: 100.0 * (double) step3Data.length / (double) fileData.length);
2717: System.out.printf (" encoded: %d bytes (%.1f%%)\n",
2718: step3DataEncoded.length,
2719: 100.0 * (double) step3DataEncoded.length / (double) fileData.length);
2720: System.out.printf (" decoder concatenated: %d bytes (%.1f%%)\n",
2721: step1Data.length,
2722: 100.0 * (double) step1Data.length / (double) fileData.length);
2723: }
2724: } else {
2725: step1Data = new byte[adotr1.length + step2DataEncoded.length + 1];
2726: int index1 = 0;
2727: System.arraycopy (adotr1, 0,
2728: step1Data, index1,
2729: adotr1.length);
2730: index1 += adotr1.length;
2731: System.arraycopy (step2DataEncoded, 0,
2732: step1Data, index1,
2733: step2DataEncoded.length);
2734: index1 += step2DataEncoded.length;
2735: step1Data[index1++] = 0x1a;
2736: if (false) {
2737: System.out.printf (" original: %d bytes (%.1f%%)\n",
2738: fileData.length,
2739: 100.0);
2740: System.out.printf (" generator concatenated: %d bytes (%.1f%%)\n",
2741: step3Data.length,
2742: 100.0 * (double) step3Data.length / (double) fileData.length);
2743: System.out.printf (" compressed: %d bytes (%.1f%%) (%d bits dictionary)\n",
2744: step3DataCompressed.length,
2745: 100.0 * (double) step3DataCompressed.length / (double) fileData.length,
2746: dicbit);
2747: System.out.printf ("decompressor concatenated: %d bytes (%.1f%%)\n",
2748: step2Data.length,
2749: 100.0 * (double) step2Data.length / (double) fileData.length);
2750: System.out.printf (" encoded: %d bytes (%.1f%%)\n",
2751: step2DataEncoded.length,
2752: 100.0 * (double) step2DataEncoded.length / (double) fileData.length);
2753: System.out.printf (" decoder concatenated: %d bytes (%.1f%%)\n",
2754: step1Data.length,
2755: 100.0 * (double) step1Data.length / (double) fileData.length);
2756: }
2757: }
2758: if (false) {
2759: int l = step1Data.length;
2760: System.out.printf ("step1Data %d bytes\n", l);
2761: for (int i = 0; i < l; i++) {
2762: if ((i & 15) == 0) {
2763: System.out.printf ("%08x", i);
2764: }
2765: System.out.printf (" %02x", step1Data[i] & 255);
2766: if ((i & 15) == 15) {
2767: System.out.println ();
2768: }
2769: }
2770: if ((l & 15) != 0) {
2771: System.out.println ();
2772: }
2773: }
2774:
2775: trmSendString (String.format (
2776: "rem a.r/%s %d/%d %.1f%%\rcopy aux a.r\r",
2777: name, step1Data.length, fileData.length,
2778: 100.0 * (double) step1Data.length / (double) fileData.length));
2779: try {
2780: Thread.sleep (1000);
2781: } catch (InterruptedException ie) {
2782: }
2783: if (trmRowToCol[0] == 1) {
2784: int row = 0;
2785: int col = 1;
2786: trmConnectionArray[trmCols * row + col - 1].row2colQueue.write (step1Data, 0, step1Data.length);
2787: } else if (0 < trmColToRow[0]) {
2788: int row = trmColToRow[0];
2789: int col = 0;
2790: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (step1Data, 0, step1Data.length);
2791: }
2792: try {
2793: Thread.sleep (1000);
2794: } catch (InterruptedException ie) {
2795: }
2796: trmSendString ("a.r\r");
2797: }
2798:
2799:
2800: public static final byte[] adotr1 = "B\202G\373 h\324\211\304|\377\374(B\"Kx@\330\213B\200\320\214\220\204\223\201\300\201\330\200$I\"<\337\337\337\340\322\233B\200v( @\347\210\220\210\353\210\341\231\320\201Q\301\220\201\342Kd\354\"\300\267\304e\3322!B\200\322A\342\220\321\232\265\311e\364\267\314e\266A\372\377\370t\370N\360\" BAVAp\254NO".getBytes (XEiJ.ISO_8859_1);
2801:
2802: public static final byte[] adotr2 = "p\1\320\211\300|\377\376\"@|\0~\0E\372\0\372r\30a\0\0\322&\0\326\211p\1\320\203\300|\377\376*@r\4a\0\0\276g\0\0\246\30\0z\b\351\255\332\215\377\201\"\5\222\200/\1/\0\377JP\217J\200ktp\0 M \300 \300\261\305e\370(I,M\265\311dvr\1a\0\0\206f\b,\314p\1,\300`0\22\4av\347\210 u\b\0 5\b\4gVR\200\"\0\322\214\262\203bL,\314,\300U\200H@H@\30\330Q\310\377\374H@Q\310\377\364\30\332\275\305f\2,M\271\303e\260p\372N\373\2\16r\3p\254NO IN\320\377\t\377\0Hz\0\4`\366out of memory\r\n\0Hz\0\4`\340data error\r\n\0\0p\0J\7f\4\34\32P\7\24\1\264\7c\2\24\7\20\6\345\250\345.\236\2\222\2f\344\340\210Nu".getBytes (XEiJ.ISO_8859_1);
2803:
2804: public static final byte[] adotr3 = "E\372\1\2&*\0 G\352\0$ \13\320\203R\200\300|\377\376(@K\354\4\0\377\201\"\r\222\200/\1/\0\377JP\217J\200k\0\0\230 Lr\0 \1t\7\342\210d\6\n\200\355\270\203 Q\312\377\364 \300R\1d\350\"Lp\0\"\3 KF\200`\22HAt\0\24\30\261\2\340\210\345J$1(\0\265\200Q\311\377\356HAQ\311\377\346F\200\260\252\0\34f`?<\0 /\n\377<\\\217J\200kd/\3/\13?\0\377@\"\0/j\0\30\0\2\377\207\377>O\357\0\n\262\203g\b/\n\377AX\217`@/\n\377\tHz\0\6\377\t\377\0 created\r\n\0\0Hz\0\4`\352out of memory\r\n\0Hz\0\4`\324crc error\r\n\0Hz\0\4`\302cannot write\r\n\0\0".getBytes (XEiJ.ISO_8859_1);
2805:
2806: }