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