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.charset.*;
20: import java.util.*;
21: import java.util.zip.*;
22: import javax.swing.*;
23: import javax.swing.event.*;
24:
25: import com.fazecast.jSerialComm.*;
26:
27: public class RS232CTerminal {
28:
29: public static final int TRM_MAX_OUTPUT_LENGTH = 1024 * 256;
30: public static final int TRM_CUT_OUTPUT_LENGTH = TRM_MAX_OUTPUT_LENGTH + 1024 * 16;
31:
32:
33: public static JFrame trmFrame;
34: public static ScrollTextArea trmBoard;
35: public static JPopupMenu trmPopupMenu;
36: public static JMenuItem trmPopupCutMenuItem;
37: public static JMenuItem trmPopupCopyMenuItem;
38: public static JMenuItem trmPopupPasteMenuItem;
39: public static JMenuItem trmPopupSelectAllMenuItem;
40: public static StringBuilder trmOutputBuilder;
41: public static int trmOutputEnd;
42: public static int trmOutputSJIS1;
43:
44:
45: public static SerialPort[] trmPortArray;
46: public static int trmNumberOfPorts;
47:
48:
49: public static int trmRows;
50: public static String[] trmRowName;
51: public static int[] trmRowToCol;
52:
53: public static int trmNumberOfAUXs;
54:
55:
56: public static int trmCols;
57: public static String[] trmColName;
58: public static int[] trmColToRow;
59:
60:
61:
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: static class Connection implements SerialPortDataListener {
89: int row;
90: int col;
91: int index;
92: String text;
93: boolean connected;
94: JCheckBox checkBox;
95: Box box;
96:
97:
98: ByteQueue row2colQueue;
99: ByteQueue col2rowQueue;
100: boolean row2colReset;
101: boolean col2rowReset;
102:
103:
104: @Override public int getListeningEvents () {
105: return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
106: }
107: @Override public void serialEvent (SerialPortEvent spe) {
108: if (spe.getEventType () != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
109: return;
110: }
111: SerialPort port = spe.getSerialPort ();
112: for (;;) {
113: int k = Math.min (port.bytesAvailable (),
114: row2colQueue.unused ());
115: if (k == 0) {
116: break;
117: }
118: byte[] b = new byte[k];
119: port.readBytes (b, k);
120: row2colQueue.write (b, 0, k);
121: }
122: }
123:
124:
125: boolean polling;
126: Thread row2colThread;
127: Thread col2rowThread;
128:
129:
130: class TerminalThread extends Thread {
131: @Override public void run () {
132: ByteQueue queue = (col == 0 ? row2colQueue : col2rowQueue);
133: while (polling) {
134: if (col == 0 ? row2colReset : col2rowReset) {
135: if (col == 0) {
136: row2colReset = false;
137: } else {
138: col2rowReset = false;
139: }
140: queue.clear ();
141: } else {
142: for (int k = queue.used (); k != 0; k = queue.used ()) {
143: byte[] b = new byte[k];
144: queue.read (b, 0, k);
145: for (int i = 0; i < k; i++) {
146: trmPrintSJIS (b[i] & 0xff);
147: }
148: }
149: }
150: try {
151: Thread.sleep (100);
152: } catch (InterruptedException ie) {
153: }
154: }
155: }
156: }
157:
158:
159: class SerialPortThread extends Thread {
160: @Override public void run () {
161: SerialPort port = trmPortArray[row - 1];
162: ByteQueue queue = col2rowQueue;
163: while (polling) {
164: if (col2rowReset) {
165: col2rowReset = false;
166: queue.clear ();
167: port.flushIOBuffers ();
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: port.writeBytes (b, k);
173: }
174: }
175: try {
176: Thread.sleep (10);
177: } catch (InterruptedException ie) {
178: }
179: }
180: }
181: }
182:
183: }
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197: public static boolean trmAUXFlowControlRTS;
198: public static boolean trmAUXFlowControlXON;
199: public static boolean trmAUXNotReceiving;
200:
201:
202: public static int trmAUXDataBuffer;
203: public static boolean trmAUXDataAvailable;
204:
205:
206:
207: public static int trmAUXReadData () {
208: trmAUXDataAvailable = false;
209: return trmAUXDataBuffer;
210: }
211:
212:
213:
214: public static void trmAUXWriteData (int data) {
215: int col = 1;
216: int row = trmColToRow[col];
217: if (row < 0) {
218: return;
219: }
220: data &= 0xff;
221: if (trmAUXFlowControlXON) {
222: if (data == 0x11) {
223: trmAUXNotReceiving = false;
224: return;
225: } else if (data == 0x13) {
226: trmAUXNotReceiving = true;
227: return;
228: }
229: }
230: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (data);
231: }
232:
233:
234:
235:
236: public static void trmAUXSetNotReceiving (boolean notReceiving) {
237: trmAUXNotReceiving = notReceiving;
238: }
239:
240:
241:
242:
243:
244:
245:
246: public static int trmAUXReadCommand () {
247: return (trmAUXConnection == null ?
248: (0 << 5 |
249: 0 << 3 |
250: 0 << 2 |
251: 0 << 0) :
252: (1 << 5 |
253: 1 << 3 |
254: 1 << 2 |
255: (trmAUXDataAvailable ? 1 << 0 : 0 << 0)));
256: }
257:
258:
259: public static Connection trmAUXConnection;
260: public static final TickerQueue.Ticker trmAUXTicker = new TickerQueue.Ticker () {
261: @Override protected void tick () {
262: long interval = XEiJ.TMR_FREQ / 1000 * 1;
263: ByteQueue queue = trmAUXConnection.row2colQueue;
264: if (trmAUXConnection.row2colReset) {
265: trmAUXConnection.row2colReset = false;
266: queue.clear ();
267: } else if (!trmAUXNotReceiving &&
268: queue.used () != 0) {
269: trmAUXDataBuffer = queue.read ();
270: trmAUXDataAvailable = true;
271: if (Z8530.scc1aReceiveMask != 0 &&
272: Z8530.scc1aReceiveRR3 == 0) {
273: Z8530.scc1aReceiveRR3 = Z8530.SCC_1A_RECEIVE_MASK;
274: Z8530.scc1aReceiveRequest = Z8530.SCC_1A_RECEIVE_MASK;
275: XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
276: }
277: interval = Z8530.scc1aInterval;
278: }
279: TickerQueue.tkqAdd (trmAUXTicker, XEiJ.mpuClockTime + interval);
280: }
281: };
282:
283: public static int trmRSDRV202Head;
284: public static int trmTMSIO031Head;
285: public static int trmBSIO021Head;
286:
287:
288:
289:
290:
291:
292:
293:
294: public static final TickerQueue.Ticker trmAUXFlowControlTicker = new TickerQueue.Ticker () {
295: @Override protected void tick () {
296: int set232c = MC68060.mmuPeekLongData (0x04c0, 1);
297: int modeAddress = (0x00fc0000 <= set232c && set232c < 0x01000000 ? 0x0926 :
298: set232c == trmRSDRV202Head + 0x03ba ? trmRSDRV202Head + 0x0ab2 :
299: set232c == trmTMSIO031Head + 0x0210 ? trmTMSIO031Head + 0x0a42 :
300: set232c == trmBSIO021Head + 0x013A ? trmBSIO021Head + 0x074a :
301: 0);
302: if (modeAddress == 0) {
303: return;
304: }
305: int mode = MC68060.mmuPeekWordZeroData (modeAddress, 1);
306: if (mode == 0x0000 || mode == 0xffff) {
307: return;
308: }
309: boolean rts = (mode & 0x0080) != 0;
310: boolean xon = !rts && (mode & 0x0200) != 0;
311: if (trmAUXFlowControlRTS == rts &&
312: trmAUXFlowControlXON == xon) {
313: return;
314: }
315: trmAUXFlowControlRTS = rts;
316: trmAUXFlowControlXON = xon;
317: if (false) {
318: System.out.printf ("flowcontrol=%s\n", rts ? "rts" : xon ? "xon" : "none");
319: }
320: int row = trmColToRow[1];
321: SerialPort port = row < 1 ? null : trmPortArray[row - 1];
322: if (port != null) {
323: port.setFlowControl (rts ? (SerialPort.FLOW_CONTROL_RTS_ENABLED |
324: SerialPort.FLOW_CONTROL_CTS_ENABLED) :
325: xon ? (SerialPort.FLOW_CONTROL_XONXOFF_IN_ENABLED |
326: SerialPort.FLOW_CONTROL_XONXOFF_OUT_ENABLED) :
327: SerialPort.FLOW_CONTROL_DISABLED);
328: }
329: }
330: };
331:
332:
333:
334: public static void trmAUXReset () {
335: if (trmAUXConnection != null) {
336: TickerQueue.tkqRemove (trmAUXFlowControlTicker);
337:
338: trmAUXConnection.row2colReset = true;
339: trmAUXConnection.col2rowReset = true;
340: }
341: }
342:
343:
344: public static Connection[] trmConnectionArray;
345: public static Box trmConnectionBox;
346: public static ActionListener trmConnectionListener;
347: public static boolean trmRefreshEnabled;
348: public static JButton trmRefreshButton;
349:
350: public static boolean trmSettingsEnabled;
351: public static String[] trmBaudRateArray;
352: public static int trmBaudRateIndex;
353: public static String[] trmDataBitsArray;
354: public static int trmDataBitsIndex;
355: public static String[] trmParityArray;
356: public static int trmParityIndex;
357: public static String[] trmStopBitsArray;
358: public static int trmStopBitsIndex;
359: public static String[] trmFlowControlArray;
360: public static int trmFlowControlIndex;
361: public static JComboBox<String> trmBaudRateComboBox;
362: public static JComboBox<String> trmDataBitsComboBox;
363: public static JComboBox<String> trmParityComboBox;
364: public static JComboBox<String> trmStopBitsComboBox;
365: public static JComboBox<String> trmFlowControlComboBox;
366:
367: public static boolean trmSendEnabled;
368: public static JButton trmSendButton;
369: public static JFileChooser trmSendFileChooser;
370: public static JDialog trmSendDialog;
371: public static SendThread trmSendThread;
372:
373:
374:
375: public static void trmInitConnection () {
376:
377: trmBaudRateArray = new String[] { "75", "150", "300", "600", "1200", "2400", "4800", "9600", "19200", "31250", "38400", "57600", "76800", "115200" };
378: trmBaudRateIndex = 10;
379: trmDataBitsArray = new String[] { "B5", "B6", "B7", "B8" };
380: trmDataBitsIndex = 3;
381: trmParityArray = new String[] { "PN", "PO", "PE" };
382: trmParityIndex = 0;
383: trmStopBitsArray = new String[] { "S1", "S1.5", "S2" };
384: trmStopBitsIndex = 0;
385: trmFlowControlArray = new String[] { "NONE", "XON", "RTS" };
386: trmFlowControlIndex = 2;
387: trmBaudRateComboBox = null;
388: trmDataBitsComboBox = null;
389: trmParityComboBox = null;
390: trmStopBitsComboBox = null;
391: trmFlowControlComboBox = null;
392:
393: for (String keyword : Settings.sgsGetString ("terminalsettings").split ("/")) {
394: for (int i = 0; i < trmBaudRateArray.length; i++) {
395: if (trmBaudRateArray[i].equals (keyword)) {
396: trmBaudRateIndex = i;
397: break;
398: }
399: }
400: for (int i = 0; i < trmDataBitsArray.length; i++) {
401: if (trmDataBitsArray[i].equals (keyword)) {
402: trmDataBitsIndex = i;
403: break;
404: }
405: }
406: for (int i = 0; i < trmParityArray.length; i++) {
407: if (trmParityArray[i].equals (keyword)) {
408: trmParityIndex = i;
409: break;
410: }
411: }
412: for (int i = 0; i < trmStopBitsArray.length; i++) {
413: if (trmStopBitsArray[i].equals (keyword)) {
414: trmStopBitsIndex = i;
415: break;
416: }
417: }
418: for (int i = 0; i < trmFlowControlArray.length; i++) {
419: if (trmFlowControlArray[i].equals (keyword)) {
420: trmFlowControlIndex = i;
421: break;
422: }
423: }
424: }
425:
426: trmSendButton = null;
427: trmSendFileChooser = null;
428: trmSendDialog = null;
429: trmSendThread = null;
430:
431: trmPortArray = new SerialPort[0];
432: trmNumberOfPorts = 0;
433:
434: trmRows = 1;
435: trmRowName = new String[1];
436: trmRowName[0] = "Terminal";
437: trmRowToCol = new int[1];
438: Arrays.fill (trmRowToCol, -1);
439:
440: trmNumberOfAUXs = 0;
441:
442: trmCols = 1;
443: trmColName = new String[1];
444: trmColName[0] = "Terminal";
445: trmColToRow = new int[1];
446: Arrays.fill (trmColToRow, -1);
447:
448: trmConnectionArray = new Connection[0];
449: trmConnectionBox = ComponentFactory.createVerticalBox (Box.createVerticalGlue ());
450: trmConnectionListener = new ActionListener () {
451: @Override public void actionPerformed (ActionEvent ae) {
452: String command = ae.getActionCommand ();
453: for (Connection connection : trmConnectionArray) {
454: if (connection.text.equals (command)) {
455: if (connection.connected) {
456: trmDisconnect (connection);
457: } else {
458: trmConnect (connection);
459: }
460: break;
461: }
462: }
463: }
464: };
465: trmRefreshEnabled = false;
466: trmRefreshButton = null;
467: trmSettingsEnabled = false;
468: trmSendEnabled = false;
469:
470: trmUpdateConnection ();
471:
472: HashSet<String> map = new HashSet<String> ();
473: for (String encodedText : Settings.sgsGetString ("rs232cconnection").split ("/")) {
474: try {
475: map.add (URLDecoder.decode (encodedText, "UTF-8"));
476: } catch (UnsupportedEncodingException uee) {
477: }
478: }
479: for (Connection connection : trmConnectionArray) {
480: if (map.contains (connection.text)) {
481: trmConnect (connection);
482: }
483: }
484: }
485:
486:
487:
488: public static void trmTiniConnection () {
489:
490: {
491: StringBuilder sb = new StringBuilder ();
492: for (Connection connection : trmConnectionArray) {
493: if (connection.connected) {
494: if (sb.length () != 0) {
495: sb.append ('/');
496: }
497: try {
498: sb.append (URLEncoder.encode (connection.text, "UTF-8"));
499: } catch (UnsupportedEncodingException uee) {
500: }
501: }
502: }
503: Settings.sgsPutString ("rs232cconnection", sb.toString ());
504: }
505:
506: {
507: StringBuilder sb = new StringBuilder ();
508: sb.append (trmBaudRateArray[trmBaudRateIndex]);
509: sb.append ('/');
510: sb.append (trmDataBitsArray[trmDataBitsIndex]);
511: sb.append ('/');
512: sb.append (trmParityArray[trmParityIndex]);
513: sb.append ('/');
514: sb.append (trmStopBitsArray[trmStopBitsIndex]);
515: sb.append ('/');
516: sb.append (trmFlowControlArray[trmFlowControlIndex]);
517: Settings.sgsPutString ("terminalsettings", sb.toString ());
518: }
519:
520: for (Connection connection : trmConnectionArray) {
521: trmDisconnect (connection);
522: }
523: }
524:
525:
526:
527: public static boolean trmIsConnectionUpdatable () {
528: for (Connection connection : trmConnectionArray) {
529: if (connection.row != 0 &&
530: connection.connected) {
531: return false;
532: }
533: }
534: return true;
535: }
536:
537:
538:
539: public static void trmUpdateConnection () {
540:
541: if (!trmIsConnectionUpdatable ()) {
542: return;
543: }
544:
545: SerialPort[] portArray = SerialPort.getCommPorts ();
546: int ukun = -1;
547: for (int i = 0; i < portArray.length; i++) {
548: if (portArray[i].getPortDescription ().startsWith (PPI.PPI_UKUN_DESCRIPTION)) {
549: ukun = i;
550: break;
551: }
552: }
553: if (ukun < 0) {
554: trmPortArray = portArray;
555: } else {
556: trmPortArray = new SerialPort[portArray.length - 1];
557: for (int i = 0; i < ukun; i++) {
558: trmPortArray[i] = portArray[i];
559: }
560: for (int i = ukun + 1; i < portArray.length; i++) {
561: trmPortArray[i - 1] = portArray[i];
562: }
563: }
564: trmNumberOfPorts = trmPortArray.length;
565:
566: trmRows = 1 + trmNumberOfPorts;
567: trmRowName = new String[trmRows];
568: trmRowName[0] = "Terminal";
569: for (int row = 1; row < trmRows; row++) {
570: SerialPort port = trmPortArray[row - 1];
571: trmRowName[row] = port.getSystemPortName () + "(" + port.getPortDescription () + ")";
572: }
573: trmRowToCol = new int[trmRows];
574: Arrays.fill (trmRowToCol, -1);
575:
576: trmNumberOfAUXs = 1;
577:
578: trmCols = 1 + trmNumberOfAUXs;
579: trmColName = new String[trmCols];
580: trmColName[0] = "Terminal";
581: for (int col = 1; col < trmCols; col++) {
582: trmColName[col] = col == 1 ? "AUX" : "AUX" + col;
583: }
584: trmColToRow = new int[trmCols];
585: Arrays.fill (trmColToRow, -1);
586:
587: for (int index = trmConnectionArray.length - 1; 0 <= index; index--) {
588: trmConnectionBox.remove (index);
589: }
590: trmConnectionArray = new Connection[trmCols * trmRows - 1];
591: for (int row = 0; row < trmRows; row++) {
592: for (int col = 0; col < trmCols; col++) {
593: if (col == 0 && row == 0) {
594: continue;
595: }
596: Connection connection = new Connection ();
597: connection.row = row;
598: connection.col = col;
599: connection.index = trmCols * row + col - 1;
600: connection.text = trmRowName[row] + " ⇔ " + trmColName[col];
601: connection.connected = false;
602: connection.checkBox =
603: ComponentFactory.createCheckBox (connection.connected, connection.text, trmConnectionListener);
604: connection.box =
605: ComponentFactory.createHorizontalBox (
606: connection.checkBox,
607: Box.createHorizontalGlue ());
608: trmConnectionArray[connection.index] = connection;
609: trmConnectionBox.add (connection.box, connection.index);
610: }
611: }
612: trmUpdateComponents ();
613: trmConnectionBox.validate ();
614: }
615:
616:
617:
618:
619:
620: public static void trmUpdateComponents () {
621: boolean updatable = true;
622: boolean configurable = false;
623: boolean transferable = false;
624: for (Connection connection : trmConnectionArray) {
625: if (connection.connected) {
626: connection.checkBox.setEnabled (true);
627: if (0 < connection.row) {
628: updatable = false;
629: if (connection.col == 0) {
630: configurable = true;
631: }
632: }
633: if (connection.row == 0 ||
634: connection.col == 0) {
635: transferable = true;
636: }
637: } else {
638: connection.checkBox.setEnabled (trmIsConnectable (connection));
639: }
640: }
641: trmRefreshEnabled = updatable;
642: if (trmRefreshButton != null) {
643: trmRefreshButton.setEnabled (updatable);
644: }
645: trmSettingsEnabled = configurable;
646: trmSendEnabled = transferable;
647: if (trmBaudRateComboBox != null) {
648: trmBaudRateComboBox.setEnabled (configurable);
649: trmDataBitsComboBox.setEnabled (configurable);
650: trmParityComboBox.setEnabled (configurable);
651: trmStopBitsComboBox.setEnabled (configurable);
652: trmFlowControlComboBox.setEnabled (configurable);
653: trmSendButton.setEnabled (transferable);
654: }
655: }
656:
657:
658:
659: public static boolean trmIsConnectable (Connection connection) {
660: if (!connection.connected) {
661: for (Connection connection2 : trmConnectionArray) {
662: if (connection != connection2 &&
663: connection2.connected &&
664: (((connection.row == 0 || connection.col == 0) &&
665: (connection2.row == 0 || connection2.col == 0)) ||
666: connection.row == connection2.row ||
667: connection.col == connection2.col)) {
668: return false;
669: }
670: }
671: }
672: return true;
673: }
674:
675:
676:
677: public static void trmConnect (Connection connection) {
678:
679: if (connection.connected ||
680: !trmIsConnectable (connection)) {
681: return;
682: }
683:
684: connection.connected = true;
685: connection.checkBox.setSelected (true);
686: trmRowToCol[connection.row] = connection.col;
687: trmColToRow[connection.col] = connection.row;
688: trmUpdateComponents ();
689:
690: connection.row2colQueue = new ByteQueue ();
691: connection.col2rowQueue = new ByteQueue ();
692: if (0 < connection.row) {
693:
694: SerialPort port = trmPortArray[connection.row - 1];
695: port.openPort ();
696: System.out.println (Multilingual.mlnJapanese ?
697: connection.text + " を開きました" :
698: connection.text + " opened");
699: port.setComPortTimeouts (SerialPort.TIMEOUT_WRITE_BLOCKING | SerialPort.TIMEOUT_READ_BLOCKING, 0, 0);
700: port.setFlowControl (SerialPort.FLOW_CONTROL_DISABLED);
701:
702: trmReflectSettings (connection.col);
703:
704: port.addDataListener (connection);
705: }
706:
707: connection.polling = true;
708: connection.row2colThread = (connection.col == 0 ? connection.new TerminalThread () :
709: null);
710: connection.col2rowThread = (connection.row == 0 ? connection.new TerminalThread () :
711: connection.new SerialPortThread ());
712: for (int i = 0; i < 2; i++) {
713: Thread thread = (i == 0 ? connection.row2colThread : connection.col2rowThread);
714: if (thread != null) {
715: thread.start ();
716: }
717: }
718:
719: if (connection.col == 1) {
720: trmAUXNotReceiving = false;
721: trmAUXDataBuffer = 0;
722: trmAUXDataAvailable = false;
723: trmAUXConnection = connection;
724: TickerQueue.tkqAdd (trmAUXTicker, XEiJ.mpuClockTime + XEiJ.TMR_FREQ / 1000 * 1);
725: }
726: }
727:
728:
729:
730: public static void trmDisconnect (Connection connection) {
731:
732: if (!connection.connected) {
733: return;
734: }
735:
736: connection.connected = false;
737: connection.checkBox.setSelected (connection.connected);
738: trmRowToCol[connection.row] = -1;
739: trmColToRow[connection.col] = -1;
740: trmUpdateComponents ();
741:
742: if (trmAUXConnection != null) {
743: TickerQueue.tkqRemove (trmAUXTicker);
744: trmAUXConnection = null;
745: }
746:
747: connection.polling = false;
748: for (int i = 0; i < 2; i++) {
749: Thread thread = (i == 0 ? connection.row2colThread : connection.col2rowThread);
750: if (thread != null) {
751: connection.row2colThread = null;
752: if (thread.isAlive ()) {
753: thread.interrupt ();
754: try {
755: thread.join ();
756: } catch (InterruptedException ie) {
757: }
758: }
759: }
760: }
761: if (0 < connection.row) {
762: SerialPort port = trmPortArray[connection.row - 1];
763:
764: port.removeDataListener ();
765:
766: port.closePort ();
767: System.out.println (Multilingual.mlnJapanese ?
768: connection.text + " を閉じました" :
769: connection.text + " closed");
770: }
771:
772: connection.row2colQueue.clear ();
773: connection.col2rowQueue.clear ();
774: connection.row2colQueue = null;
775: connection.col2rowQueue = null;
776: }
777:
778:
779:
780: public static void trmSetBaudRate (int index) {
781: if (0 <= index && index < trmBaudRateArray.length) {
782: trmBaudRateIndex = index;
783: trmReflectSettings (0);
784: }
785: }
786:
787:
788:
789: public static void trmSetDataBits (int index) {
790: if (0 <= index && index < trmDataBitsArray.length) {
791: trmDataBitsIndex = index;
792: trmReflectSettings (0);
793: }
794: }
795:
796:
797:
798: public static void trmSetParity (int index) {
799: if (0 <= index && index < trmParityArray.length) {
800: trmParityIndex = index;
801: trmReflectSettings (0);
802: }
803: }
804:
805:
806:
807: public static void trmSetStopBits (int index) {
808: if (0 <= index && index < trmStopBitsArray.length) {
809: trmStopBitsIndex = index;
810: trmReflectSettings (0);
811: }
812: }
813:
814:
815:
816: public static void trmSetFlowControl (int index) {
817: if (0 <= index && index < trmFlowControlArray.length) {
818: trmFlowControlIndex = index;
819: trmReflectSettings (0);
820: }
821: }
822:
823:
824:
825: public static void trmReflectSettings (int col) {
826: int row = trmColToRow[col];
827: SerialPort port = row <= 0 ? null : trmPortArray[row - 1];
828: if (col == 0) {
829: String baudRate = trmBaudRateArray[trmBaudRateIndex];
830: String dataBits = trmDataBitsArray[trmDataBitsIndex];
831: String stopBits = trmStopBitsArray[trmStopBitsIndex];
832: String parity = trmParityArray[trmParityIndex];
833: if (port != null) {
834: port.setComPortParameters (Integer.parseInt (baudRate, 10),
835: Integer.parseInt (dataBits.substring (1), 10),
836: stopBits.equals ("S1.5") ? SerialPort.ONE_POINT_FIVE_STOP_BITS :
837: stopBits.equals ("S2") ? SerialPort.TWO_STOP_BITS : SerialPort.ONE_STOP_BIT,
838: parity.equals ("PO") ? SerialPort.ODD_PARITY :
839: parity.equals ("PE") ? SerialPort.EVEN_PARITY : SerialPort.NO_PARITY);
840: }
841: } else if (col == 1) {
842: double rate = Z8530.sccFreq / (double) ((Z8530.scc1aBaudRateGen + 2) << (Z8530.scc1aClockModeShift + 1));
843: double bits = (1.0 +
844: (Z8530.scc1aRxBits == 0 ? 5.0 :
845: Z8530.scc1aRxBits == 1 ? 7.0 :
846: Z8530.scc1aRxBits == 2 ? 6.0 : 8.0) +
847: ((Z8530.scc1aParity & 1) == 0 ? 0.0 : 1.0) +
848: (Z8530.scc1aStop == 0 ? 0.0 :
849: Z8530.scc1aStop == 1 ? 1.0 :
850: Z8530.scc1aStop == 2 ? 1.5 : 2.0));
851: double interval = bits / rate;
852: if (false) {
853: System.out.printf ("%08x baudrate=%.3fbps interval=%.3fus\n", XEiJ.regPC0, rate, interval * 1e+6);
854: }
855: Z8530.scc1aInterval = Math.round (interval * (double) XEiJ.TMR_FREQ);
856:
857: if (port != null) {
858: port.setComPortParameters ((int) Math.round (rate),
859: Z8530.scc1aRxBits == 0b00 ? 5 :
860: Z8530.scc1aRxBits == 0b01 ? 7 :
861: Z8530.scc1aRxBits == 0b10 ? 6 : 8,
862: Z8530.scc1aStop == 0b10 ? SerialPort.ONE_POINT_FIVE_STOP_BITS :
863: Z8530.scc1aStop == 0b11 ? SerialPort.TWO_STOP_BITS : SerialPort.ONE_STOP_BIT,
864: Z8530.scc1aParity == 0b01 ? SerialPort.ODD_PARITY :
865: Z8530.scc1aParity == 0b11 ? SerialPort.EVEN_PARITY : SerialPort.NO_PARITY);
866: }
867:
868:
869: TickerQueue.tkqAdd (trmAUXFlowControlTicker, XEiJ.mpuClockTime + XEiJ.TMR_FREQ * 500 / 1000000);
870: } else {
871:
872: }
873: }
874:
875:
876:
877:
878: public static void trmInit () {
879: trmFrame = null;
880: trmBoard = null;
881: trmPopupMenu = null;
882: trmPopupCutMenuItem = null;
883: trmPopupCopyMenuItem = null;
884: trmPopupPasteMenuItem = null;
885: trmPopupSelectAllMenuItem = null;
886: trmOutputBuilder = new StringBuilder ();
887: trmOutputEnd = 0;
888: trmOutputSJIS1 = 0;
889:
890: trmInitConnection ();
891: trmReset ();
892: }
893:
894: public static void trmReset () {
895: trmRSDRV202Head = 0;
896: trmTMSIO031Head = 0;
897: trmBSIO021Head = 0;
898: trmAUXFlowControlXON = false;
899: trmAUXFlowControlRTS = false;
900: }
901:
902:
903:
904: public static void trmTini () {
905: trmTiniConnection ();
906: }
907:
908:
909:
910:
911: public static void trmMake () {
912:
913:
914: trmBoard = ComponentFactory.createScrollTextArea (
915: trmOutputBuilder.toString (),
916: 650, 350,
917: true);
918: trmOutputBuilder = null;
919: trmBoard.setUnderlineCursorOn (true);
920: trmBoard.setLineWrap (true);
921: trmBoard.addDocumentListener (new DocumentListener () {
922: @Override public void changedUpdate (DocumentEvent de) {
923: }
924: @Override public void insertUpdate (DocumentEvent de) {
925: if (de.getOffset () < trmOutputEnd) {
926: trmOutputEnd += de.getLength ();
927: }
928: }
929: @Override public void removeUpdate (DocumentEvent de) {
930: if (de.getOffset () < trmOutputEnd) {
931: trmOutputEnd -= Math.min (de.getLength (), trmOutputEnd - de.getOffset ());
932: }
933: }
934: });
935: trmBoard.addKeyListener (new KeyAdapter () {
936: @Override public void keyPressed (KeyEvent ke) {
937: if (ke.getKeyCode () == KeyEvent.VK_ENTER) {
938: ke.consume ();
939: trmEnter ();
940: }
941: }
942: });
943:
944:
945: ActionListener popupActionListener = new ActionListener () {
946: @Override public void actionPerformed (ActionEvent ae) {
947: switch (ae.getActionCommand ()) {
948: case "Cut":
949: trmCut ();
950: break;
951: case "Copy":
952: trmCopy ();
953: break;
954: case "Paste":
955: trmPaste ();
956: break;
957: case "Select All":
958: trmSelectAll ();
959: break;
960: }
961: }
962: };
963: trmPopupMenu = ComponentFactory.createPopupMenu (
964: trmPopupCutMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Cut", 'T', popupActionListener), "ja", "切り取り"),
965: trmPopupCopyMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Copy", 'C', popupActionListener), "ja", "コピー"),
966: trmPopupPasteMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Paste", 'P', popupActionListener), "ja", "貼り付け"),
967: ComponentFactory.createHorizontalSeparator (),
968: trmPopupSelectAllMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Select All", 'A', popupActionListener), "ja", "すべて選択")
969: );
970: trmBoard.addMouseListener (new MouseAdapter () {
971: @Override public void mousePressed (MouseEvent me) {
972: trmShowPopup (me);
973: }
974: @Override public void mouseReleased (MouseEvent me) {
975: trmShowPopup (me);
976: }
977: });
978:
979:
980: ActionListener listener = new ActionListener () {
981: @Override public void actionPerformed (ActionEvent ae) {
982: Object source = ae.getSource ();
983: String command = ae.getActionCommand ();
984: switch (command) {
985: case "Refresh":
986: trmUpdateConnection ();
987: break;
988: case "Baud rate":
989: trmSetBaudRate (((JComboBox) source).getSelectedIndex ());
990: break;
991: case "Data bits":
992: trmSetDataBits (((JComboBox) source).getSelectedIndex ());
993: break;
994: case "Parity":
995: trmSetParity (((JComboBox) source).getSelectedIndex ());
996: break;
997: case "Stop bits":
998: trmSetStopBits (((JComboBox) source).getSelectedIndex ());
999: break;
1000: case "Flow control":
1001: trmSetFlowControl (((JComboBox) source).getSelectedIndex ());
1002: break;
1003: case "Send file":
1004: trmSendFile ();
1005: break;
1006: case "7.5MHz":
1007: Z8530.sccFreq = ((JCheckBox) source).isSelected () ? 7500000 : 5000000;
1008: break;
1009: default:
1010: System.out.println ("unknown action command " + command);
1011: }
1012: }
1013: };
1014:
1015:
1016: trmRefreshButton =
1017: ComponentFactory.setEnabled (
1018: Multilingual.mlnText (
1019: ComponentFactory.createButton ("Refresh", listener),
1020: "ja", "更新"),
1021: trmRefreshEnabled);
1022: trmBaudRateComboBox =
1023: ComponentFactory.setEnabled (
1024: Multilingual.mlnToolTipText (
1025: ComponentFactory.createComboBox (
1026: trmBaudRateIndex, "Baud rate", listener, trmBaudRateArray),
1027: "ja", "ボーレート"),
1028: trmSettingsEnabled);
1029: trmDataBitsComboBox =
1030: ComponentFactory.setEnabled (
1031: Multilingual.mlnToolTipText (
1032: ComponentFactory.createComboBox (
1033: trmDataBitsIndex, "Data bits", listener, trmDataBitsArray),
1034: "ja", "データビット"),
1035: trmSettingsEnabled);
1036: trmParityComboBox =
1037: ComponentFactory.setEnabled (
1038: Multilingual.mlnToolTipText (
1039: ComponentFactory.createComboBox (
1040: trmParityIndex, "Parity", listener, trmParityArray),
1041: "ja", "パリティ"),
1042: trmSettingsEnabled);
1043: trmStopBitsComboBox =
1044: ComponentFactory.setEnabled (
1045: Multilingual.mlnToolTipText (
1046: ComponentFactory.createComboBox (
1047: trmStopBitsIndex, "Stop bits", listener, trmStopBitsArray),
1048: "ja", "ストップビット"),
1049: trmSettingsEnabled);
1050: trmFlowControlComboBox =
1051: ComponentFactory.setEnabled (
1052: Multilingual.mlnToolTipText (
1053: ComponentFactory.createComboBox (
1054: trmFlowControlIndex, "Flow control", listener, trmFlowControlArray),
1055: "ja", "フロー制御"),
1056: trmSettingsEnabled);
1057: trmSendButton =
1058: ComponentFactory.setEnabled (
1059: Multilingual.mlnText (
1060: ComponentFactory.createButton ("Send file", listener),
1061: "ja", "ファイル送信"),
1062: trmSendEnabled);
1063:
1064:
1065: trmFrame = Multilingual.mlnTitle (
1066: ComponentFactory.createRestorableSubFrame (
1067: Settings.SGS_TRM_FRAME_KEY,
1068: "RS-232C and terminal",
1069: null,
1070: ComponentFactory.createVerticalSplitPane (
1071: ComponentFactory.createVerticalBox (
1072: Multilingual.mlnTitledBorder (
1073: ComponentFactory.setTitledLineBorder (
1074: ComponentFactory.createHorizontalBox (
1075: Box.createHorizontalStrut (5),
1076: ComponentFactory.createVerticalBox (
1077: Box.createVerticalGlue (),
1078: trmRefreshButton,
1079: Box.createVerticalGlue ()
1080: ),
1081: Box.createHorizontalStrut (10),
1082: trmConnectionBox,
1083: Box.createHorizontalGlue ()
1084: ),
1085: "Connection"),
1086: "ja", "接続"),
1087: ComponentFactory.createHorizontalBox (
1088: Multilingual.mlnTitledBorder (
1089: ComponentFactory.setTitledLineBorder (
1090: ComponentFactory.createHorizontalBox (
1091: Box.createHorizontalStrut (5),
1092: trmBaudRateComboBox,
1093: trmDataBitsComboBox,
1094: trmParityComboBox,
1095: trmStopBitsComboBox,
1096: trmFlowControlComboBox,
1097: Box.createHorizontalStrut (5)
1098: ),
1099: "Communication Settings"),
1100: "ja", "通信設定"),
1101: Multilingual.mlnTitledBorder (
1102: ComponentFactory.setTitledLineBorder (
1103: ComponentFactory.createHorizontalBox (
1104: Box.createHorizontalStrut (5),
1105: trmSendButton,
1106: Box.createHorizontalStrut (5)
1107: ),
1108: "Transfer"),
1109: "ja", "転送"),
1110: Box.createHorizontalGlue (),
1111: Multilingual.mlnTitledBorder (
1112: ComponentFactory.setTitledLineBorder (
1113: ComponentFactory.createHorizontalBox (
1114: Box.createHorizontalStrut (5),
1115: ComponentFactory.createCheckBox (Z8530.sccFreq == 7500000, "7.5MHz", listener),
1116: Box.createHorizontalStrut (5)
1117: ),
1118: "Modification"),
1119: "ja", "改造")
1120: )
1121: ),
1122: ComponentFactory.createVerticalBox (
1123: Multilingual.mlnTitledBorder (
1124: ComponentFactory.setTitledLineBorder (trmBoard, "Terminal"),
1125: "ja", "ターミナル")
1126: )
1127: )
1128: ),
1129: "ja", "RS-232C とターミナル");
1130:
1131: }
1132:
1133:
1134:
1135:
1136: public static void trmShowPopup (MouseEvent me) {
1137: if (me.isPopupTrigger ()) {
1138:
1139: boolean enableCutAndCopy = XEiJ.clpClipboard != null && trmBoard.getSelectionStart () != trmBoard.getSelectionEnd ();
1140: ComponentFactory.setEnabled (trmPopupCutMenuItem, enableCutAndCopy);
1141: ComponentFactory.setEnabled (trmPopupCopyMenuItem, enableCutAndCopy);
1142:
1143: ComponentFactory.setEnabled (trmPopupPasteMenuItem, XEiJ.clpClipboard != null && XEiJ.clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor));
1144:
1145: ComponentFactory.setEnabled (trmPopupSelectAllMenuItem, XEiJ.clpClipboard != null);
1146:
1147: trmPopupMenu.show (me.getComponent (), me.getX (), me.getY ());
1148: }
1149: }
1150:
1151:
1152:
1153: public static void trmCut () {
1154: if (XEiJ.clpClipboard != null) {
1155:
1156: XEiJ.clpClipboardString = trmBoard.getSelectedText ();
1157: try {
1158: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
1159: XEiJ.clpIsClipboardOwner = true;
1160: } catch (Exception e) {
1161: return;
1162: }
1163:
1164: trmBoard.replaceRange ("", trmBoard.getSelectionStart (), trmBoard.getSelectionEnd ());
1165: }
1166: }
1167:
1168:
1169:
1170: public static void trmCopy () {
1171: if (XEiJ.clpClipboard != null) {
1172:
1173: String selectedText = trmBoard.getSelectedText ();
1174: if (selectedText != null) {
1175: XEiJ.clpClipboardString = selectedText;
1176: try {
1177: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
1178: XEiJ.clpIsClipboardOwner = true;
1179: } catch (Exception e) {
1180: return;
1181: }
1182: }
1183: }
1184: }
1185:
1186:
1187:
1188: public static void trmPaste () {
1189: if (XEiJ.clpClipboard != null) {
1190:
1191: String string = null;
1192: try {
1193: string = (String) XEiJ.clpClipboard.getData (DataFlavor.stringFlavor);
1194: } catch (Exception e) {
1195: return;
1196: }
1197:
1198: trmBoard.replaceRange (string, trmBoard.getSelectionStart (), trmBoard.getSelectionEnd ());
1199: }
1200: }
1201:
1202:
1203:
1204: public static void trmSelectAll () {
1205: if (XEiJ.clpClipboard != null) {
1206:
1207: trmBoard.selectAll ();
1208: }
1209: }
1210:
1211:
1212: public static void trmStart () {
1213: if (RestorableFrame.rfmGetOpened (Settings.SGS_TRM_FRAME_KEY)) {
1214: trmOpen ();
1215: }
1216: }
1217:
1218:
1219:
1220: public static void trmOpen () {
1221: if (trmFrame == null) {
1222: trmMake ();
1223: }
1224: trmFrame.setVisible (true);
1225: }
1226:
1227:
1228:
1229:
1230: public static void trmPrintSJIS (int d) {
1231: d &= 0xff;
1232: if (trmOutputSJIS1 != 0) {
1233: if (0x40 <= d && d != 0x7f && d <= 0xfc) {
1234: int c = CharacterCode.chrSJISToChar[trmOutputSJIS1 << 8 | d];
1235: if (c != 0) {
1236: trmPrintChar (c);
1237: } else {
1238:
1239: trmPrintChar ('[');
1240: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 >> 4));
1241: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 & 15));
1242: trmPrintChar (XEiJ.fmtHexc (d >> 4));
1243: trmPrintChar (XEiJ.fmtHexc (d & 15));
1244: trmPrintChar (']');
1245: }
1246: trmOutputSJIS1 = 0;
1247: return;
1248: }
1249:
1250:
1251: trmPrintChar ('[');
1252: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 >> 4));
1253: trmPrintChar (XEiJ.fmtHexc (trmOutputSJIS1 & 15));
1254: trmPrintChar (']');
1255: trmOutputSJIS1 = 0;
1256: }
1257: if (0x81 <= d && d <= 0x9f || 0xe0 <= d && d <= 0xef) {
1258: trmOutputSJIS1 = d;
1259: } else {
1260: int c = CharacterCode.chrSJISToChar[d];
1261: if (c != 0) {
1262: trmPrintChar (c);
1263: } else {
1264:
1265: trmPrintChar ('[');
1266: trmPrintChar (XEiJ.fmtHexc (d >> 4));
1267: trmPrintChar (XEiJ.fmtHexc (d & 15));
1268: trmPrintChar (']');
1269: }
1270: }
1271: }
1272:
1273:
1274:
1275: public static void trmPrintChar (int c) {
1276: if (c == 0x08) {
1277: if (trmOutputEnd > 0) {
1278: if (trmBoard != null) {
1279: trmBoard.replaceRange ("", trmOutputEnd - 1, trmOutputEnd);
1280: trmOutputEnd--;
1281: trmBoard.setCaretPosition (trmOutputEnd);
1282: } else {
1283: trmOutputBuilder.delete (trmOutputEnd - 1, trmOutputEnd);
1284: trmOutputEnd--;
1285: }
1286: }
1287: } else if (c >= 0x20 && c != 0x7f || c == 0x09 || c == 0x0a) {
1288: if (trmBoard != null) {
1289: trmBoard.insert (String.valueOf ((char) c), trmOutputEnd);
1290: trmOutputEnd++;
1291: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
1292: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
1293: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
1294: }
1295: trmBoard.setCaretPosition (trmOutputEnd);
1296: } else {
1297: trmOutputBuilder.append ((char) c);
1298: trmOutputEnd++;
1299: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
1300: trmOutputBuilder.delete (0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
1301: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
1302: }
1303: }
1304: }
1305: }
1306:
1307:
1308:
1309:
1310:
1311: public static void trmPrint (String s) {
1312: if (s == null) {
1313: return;
1314: }
1315: if (trmFrame != null) {
1316: trmBoard.insert (s, trmOutputEnd);
1317: trmOutputEnd += s.length ();
1318: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
1319: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
1320: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
1321: }
1322: trmBoard.setCaretPosition (trmOutputEnd);
1323: } else {
1324: trmOutputBuilder.append (s);
1325: trmOutputEnd += s.length ();
1326: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
1327: trmOutputBuilder.delete (0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
1328: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
1329: }
1330: }
1331: }
1332:
1333:
1334:
1335:
1336:
1337: public static void trmPrintln (String s) {
1338: trmPrint (s);
1339: trmPrintChar ('\n');
1340: }
1341:
1342:
1343:
1344: public static void trmEnter () {
1345: String text = trmBoard.getText ();
1346: int length = text.length ();
1347: int outputLineStart = text.lastIndexOf ('\n', trmOutputEnd - 1) + 1;
1348: int caretLineStart = text.lastIndexOf ('\n', trmBoard.getCaretPosition () - 1) + 1;
1349: if (outputLineStart <= caretLineStart) {
1350: trmBoard.replaceRange ("", trmOutputEnd, length);
1351: trmSendString (text.substring (trmOutputEnd, length) + "\r");
1352: } else if (outputLineStart < trmOutputEnd) {
1353: String prompt = text.substring (outputLineStart, trmOutputEnd);
1354: int caretLineEnd = text.indexOf ('\n', caretLineStart);
1355: if (caretLineEnd == -1) {
1356: caretLineEnd = length;
1357: }
1358: String line = text.substring (caretLineStart, caretLineEnd);
1359: int start = line.indexOf (prompt);
1360: if (start >= 0) {
1361: trmOutputEnd = length;
1362: if (text.charAt (trmOutputEnd - 1) != '\n') {
1363: trmBoard.insert ("\n", trmOutputEnd);
1364: trmOutputEnd++;
1365: if (trmOutputEnd >= TRM_CUT_OUTPUT_LENGTH) {
1366: trmBoard.replaceRange ("", 0, trmOutputEnd - TRM_MAX_OUTPUT_LENGTH);
1367: trmOutputEnd = TRM_MAX_OUTPUT_LENGTH;
1368: }
1369: }
1370: trmBoard.setCaretPosition (trmOutputEnd);
1371: trmSendString (line.substring (start + prompt.length ()) + "\r");
1372: }
1373: }
1374: }
1375:
1376:
1377:
1378: public static void trmSendString (String s) {
1379: int l = s.length ();
1380: if (l == 0) {
1381: return;
1382: }
1383: byte[] b = new byte[l * 2];
1384: int k = 0;
1385: for (int i = 0; i < l; i++) {
1386: int c = CharacterCode.chrCharToSJIS[s.charAt (i)];
1387: if (0x00ff < c) {
1388: b[k++] = (byte) (c >> 8);
1389: }
1390: b[k++] = (byte) c;
1391: }
1392: if (trmRowToCol[0] == 1) {
1393: int row = 0;
1394: int col = 1;
1395: trmConnectionArray[trmCols * row + col - 1].row2colQueue.write (b, 0, k);
1396: } else if (0 < trmColToRow[0]) {
1397: int row = trmColToRow[0];
1398: int col = 0;
1399: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (b, 0, k);
1400: }
1401: }
1402:
1403:
1404:
1405:
1406:
1407: public static void trmSendFile () {
1408: if (trmSendDialog == null) {
1409: ActionListener listener = new ActionListener () {
1410: @Override public void actionPerformed (ActionEvent ae) {
1411: switch (ae.getActionCommand ()) {
1412: case JFileChooser.APPROVE_SELECTION:
1413: case "Send":
1414: trmSendDialog.setVisible (false);
1415: trmSendThread = new SendThread (trmSendFileChooser.getSelectedFile ());
1416: trmSendThread.start ();
1417: break;
1418: case JFileChooser.CANCEL_SELECTION:
1419: case "Cancel":
1420: trmSendDialog.setVisible (false);
1421: break;
1422: }
1423: }
1424: };
1425: trmSendFileChooser = new JFileChooser (new File ("a.txt"));
1426: trmSendFileChooser.setMultiSelectionEnabled (false);
1427: trmSendFileChooser.setControlButtonsAreShown (false);
1428: trmSendFileChooser.addActionListener (listener);
1429: trmSendDialog =
1430: Multilingual.mlnTitle (
1431: ComponentFactory.createModalDialog (
1432: trmFrame,
1433: "Send file",
1434: ComponentFactory.createBorderPanel (
1435: 0, 0,
1436: ComponentFactory.createVerticalBox (
1437: trmSendFileChooser,
1438: ComponentFactory.createHorizontalBox (
1439: Box.createHorizontalStrut (12),
1440: Box.createHorizontalGlue (),
1441: Multilingual.mlnText (
1442: ComponentFactory.createLabel (
1443: "Prepare COMMAND.X with CTTY AUX"),
1444: "ja", "COMMAND.X を CTTY AUX で準備して"),
1445: Box.createHorizontalStrut (12),
1446: Multilingual.mlnText (
1447: ComponentFactory.createButton ("Send", KeyEvent.VK_S, listener),
1448: "ja", "送信"),
1449: Box.createHorizontalStrut (12),
1450: Multilingual.mlnText (
1451: ComponentFactory.createButton ("Cancel", KeyEvent.VK_C, listener),
1452: "ja", "キャンセル"),
1453: Box.createHorizontalStrut (12)
1454: ),
1455: Box.createVerticalStrut (12)
1456: )
1457: )
1458: ),
1459: "ja", "ファイル送信");
1460: }
1461: trmSendDialog.setVisible (true);
1462: }
1463:
1464:
1465:
1466:
1467:
1468:
1469:
1470: static class SendThread extends Thread {
1471: File file;
1472: SendThread (File file) {
1473: this.file = file;
1474: }
1475: @Override public void run () {
1476: trmSendProcess (file);
1477: }
1478: }
1479:
1480:
1481:
1482: static byte[] load (File file) {
1483: if (!file.isFile ()) {
1484: return null;
1485: }
1486: int len = (int) file.length ();
1487: if (len == 0) {
1488: return null;
1489: }
1490: byte[] buf = new byte[len];
1491: try (BufferedInputStream bis = new BufferedInputStream (new FileInputStream (file))) {
1492: if (bis.read (buf) != len) {
1493: return null;
1494: }
1495: } catch (IOException ioe) {
1496: return null;
1497: }
1498: return buf;
1499: }
1500:
1501:
1502:
1503: static class BitWriter {
1504:
1505: byte[] buffer;
1506: int byteIndex;
1507: int bitIndex;
1508: int bitCount;
1509:
1510:
1511:
1512: BitWriter () {
1513: buffer = new byte[16];
1514: byteIndex = 0;
1515: bitIndex = -1;
1516: bitCount = 0;
1517: }
1518:
1519:
1520:
1521:
1522: void writeByte (int data) {
1523: if (byteIndex == buffer.length) {
1524: byte[] temporary = new byte[byteIndex * 2];
1525: System.arraycopy (buffer, 0,
1526: temporary, 0,
1527: byteIndex);
1528: buffer = temporary;
1529: }
1530: buffer[byteIndex++] = (byte) data;
1531: }
1532:
1533:
1534:
1535:
1536:
1537: void writeBits (int width, int data) {
1538: while (width != 0) {
1539: if (bitCount == 0) {
1540: if (byteIndex == buffer.length) {
1541: byte[] temporary = new byte[byteIndex * 2];
1542: System.arraycopy (buffer, 0,
1543: temporary, 0,
1544: byteIndex);
1545: buffer = temporary;
1546: }
1547: bitIndex = byteIndex;
1548: bitCount = 8;
1549: buffer[byteIndex++] = 0;
1550: }
1551: data &= (1 << width) - 1;
1552: int n = Math.min (bitCount, width);
1553: bitCount -= n;
1554: width -= n;
1555: buffer[bitIndex] |= (byte) ((data >>> width) << bitCount);
1556: }
1557: }
1558:
1559:
1560:
1561: byte[] getBuffer () {
1562: return buffer;
1563: }
1564:
1565:
1566:
1567: int getLength () {
1568: return byteIndex;
1569: }
1570:
1571: }
1572:
1573: static class DIC {
1574: int ptr;
1575: int len;
1576: }
1577:
1578:
1579:
1580:
1581:
1582: static byte[] compress (byte[] inpbuf, int dicbit) {
1583: int dicsiz = 1 << dicbit;
1584:
1585: DIC[] dicbuf = new DIC[dicsiz];
1586: for (int pag = 0; pag < dicsiz; pag++) {
1587: dicbuf[pag] = new DIC ();
1588: dicbuf[pag].ptr = 0;
1589: dicbuf[pag].len = 0;
1590: }
1591: int dicent = 0;
1592:
1593: int inplen = inpbuf.length;
1594: BitWriter bw = new BitWriter ();
1595: bw.writeBits (24, inplen);
1596:
1597: bw.writeBits (4, dicbit);
1598:
1599: int inpptr = 0;
1600: while (inpptr < inplen) {
1601:
1602: int dicpag = -1;
1603: int dicptr = -1;
1604: int diclen = 0;
1605: int fstchr = inpbuf[inpptr] & 255;
1606: for (int pag = 0; pag < dicsiz; pag++) {
1607: int len = dicbuf[pag].len;
1608: if (diclen < len &&
1609: inpptr + len + 1 <= inplen) {
1610: int ptr = dicbuf[pag].ptr;
1611: cmp:
1612: if (fstchr == (inpbuf[ptr] & 255)) {
1613: for (int i = 1; i < len; i++) {
1614: if (inpbuf[inpptr + i] != inpbuf[ptr + i]) {
1615: break cmp;
1616: }
1617: }
1618: dicpag = pag;
1619: dicptr = ptr;
1620: diclen = len;
1621: }
1622: }
1623: }
1624: if (diclen == 0) {
1625: bw.writeBits (1, 0);
1626: } else {
1627: bw.writeBits (1, 1);
1628: bw.writeBits (dicbit, dicpag);
1629: }
1630: int chr = inpbuf[inpptr + diclen] & 255;
1631:
1632: bw.writeByte (chr);
1633:
1634: diclen++;
1635:
1636: dicbuf[dicent].ptr = inpptr;
1637: dicbuf[dicent].len = diclen;
1638: dicent++;
1639: if (dicent == dicsiz) {
1640: dicent = 0;
1641: }
1642:
1643: inpptr += diclen;
1644: }
1645:
1646: byte[] outbuf = bw.getBuffer ();
1647: int outlen = bw.getLength ();
1648: if (outbuf.length != outlen) {
1649: byte[] tmpbuf = new byte[outlen];
1650: System.arraycopy (outbuf, 0, tmpbuf, 0, outlen);
1651: outbuf = tmpbuf;
1652: }
1653: return outbuf;
1654: }
1655:
1656:
1657:
1658:
1659:
1660:
1661:
1662:
1663:
1664:
1665: public static byte[] encode (byte[] src) {
1666: int r = src.length;
1667: int q = r / 62;
1668: r -= 62 * q;
1669: if (r != 0) {
1670: r = ((r + 2 + 3) & -4) - 2;
1671: if (src.length < 62 * q + r) {
1672: byte[] tmp = new byte[62 * q + r];
1673: System.arraycopy (src, 0, tmp, 0, src.length);
1674: src = tmp;
1675: }
1676: }
1677: byte[] dst = new byte[64 * q + (r == 0 ? 0 : r + 2)];
1678: int[] w = new int[16];
1679: for (int i = 0; 64 * i < dst.length; i++) {
1680: int n = Math.min (64, dst.length - 64 * i) / 4;
1681:
1682: for (int k = 0; k < n - 1; k++) {
1683: w[k] = ((src[62 * i + 4 * k + 0] & 255) << 24 |
1684: (src[62 * i + 4 * k + 1] & 255) << 16 |
1685: (src[62 * i + 4 * k + 2] & 255) << 8 |
1686: (src[62 * i + 4 * k + 3] & 255));
1687: }
1688: w[n - 1] = ((src[62 * i + 4 * (n - 1) + 0] & 255) << 24 |
1689: (src[62 * i + 4 * (n - 1) + 1] & 255) << 16);
1690:
1691: for (int k = 0; k < n; k++) {
1692: if ((w[k] & 0x80000000) != 0) {
1693: w[k] &= 0x7fffffff;
1694: w[n - 1] |= 1 << (15 - k);
1695: }
1696: }
1697:
1698: for (int k = 0; k < n; k++) {
1699: int t3 = w[k];
1700: int t2 = t3 / 224;
1701: t3 -= 224 * t2;
1702: int t1 = t2 / 224;
1703: t2 -= 224 * t1;
1704: int t0 = t1 / 224;
1705: t1 -= 224 * t0;
1706: dst[64 * i + 4 * k + 0] = (byte) (32 + t0);
1707: dst[64 * i + 4 * k + 1] = (byte) (32 + t1);
1708: dst[64 * i + 4 * k + 2] = (byte) (32 + t2);
1709: dst[64 * i + 4 * k + 3] = (byte) (32 + t3);
1710: }
1711: }
1712: return dst;
1713: }
1714:
1715:
1716:
1717: public static void trmSendProcess (File file) {
1718:
1719: byte[] fileData = load (file);
1720: if (fileData == null) {
1721: return;
1722: }
1723: if (0x00ffff00 < fileData.length) {
1724: return;
1725: }
1726:
1727:
1728:
1729: byte[] step3Data = new byte[adotr3.length +
1730: 24 +
1731: 4 +
1732: 4 +
1733: 4 +
1734: fileData.length];
1735: int index3 = 0;
1736:
1737: System.arraycopy (adotr3, 0,
1738: step3Data, index3,
1739: adotr3.length);
1740: index3 += adotr3.length;
1741:
1742:
1743:
1744:
1745:
1746: String name = file.getName ();
1747: {
1748: byte[] b = new byte[2 * name.length ()];
1749: int k = 0;
1750: int p = -1;
1751: for (int i = 0; i < name.length (); i++) {
1752: int c = CharacterCode.chrCharToSJIS[name.charAt (i)];
1753: if (c == 0) {
1754: return;
1755: }
1756: if (c <= ' ' || c == ':' || c == '*' || c == '?' ||
1757: c == '\\' || c == '/' || (c == '-' && k == 0) ||
1758: c == '"' || c == '\'' || c == '+' || c == ';' ||
1759: c == '<' || c == '=' || c == '>' ||
1760: c == '[' || c == ']' || c == '|') {
1761: return;
1762: }
1763: if (c == '.') {
1764: if (p < 0) {
1765: p = k;
1766: } else {
1767: return;
1768: }
1769: }
1770: if (0x00ff < c) {
1771: b[k++] = (byte) (c >> 8);
1772: }
1773: b[k++] = (byte) c;
1774: if (p < 0 ? 18 < k : p + 1 + 3 < k) {
1775: return;
1776: }
1777: }
1778: for (int i = 0; i < k; i++) {
1779: step3Data[index3++] = b[i];
1780: }
1781: for (int i = k; i < 24; i++) {
1782: step3Data[index3++] = 0;
1783: }
1784: }
1785:
1786: {
1787: long dttm = DnT.dntDttmCmil (file.lastModified () + RP5C15.rtcCmilGap);
1788: int date = DnT.dntYearDttm (dttm) - 1980 << 9 | DnT.dntMontDttm (dttm) << 5 | DnT.dntMdayDttm (dttm);
1789: int time = DnT.dntHourDttm (dttm) << 11 | DnT.dntMinuDttm (dttm) << 5 | DnT.dntSecoDttm (dttm) >> 1;
1790: step3Data[index3++] = (byte) (date >> 8);
1791: step3Data[index3++] = (byte) date;
1792: step3Data[index3++] = (byte) (time >> 8);
1793: step3Data[index3++] = (byte) time;
1794: }
1795:
1796: {
1797: CRC32 crc32 = new CRC32 ();
1798: crc32.update (fileData, 0, fileData.length);
1799: int t = (int) crc32.getValue ();
1800: step3Data[index3++] = (byte) (t >> 24);
1801: step3Data[index3++] = (byte) (t >> 16);
1802: step3Data[index3++] = (byte) (t >> 8);
1803: step3Data[index3++] = (byte) (t);
1804: }
1805:
1806: {
1807: int t = fileData.length;
1808: step3Data[index3++] = (byte) (t >> 24);
1809: step3Data[index3++] = (byte) (t >> 16);
1810: step3Data[index3++] = (byte) (t >> 8);
1811: step3Data[index3++] = (byte) (t);
1812: }
1813:
1814: System.arraycopy (fileData, 0,
1815: step3Data, index3,
1816: fileData.length);
1817: index3 += fileData.length;
1818:
1819:
1820:
1821: byte[] step3DataCompressed = null;
1822: int dicbit = 0;
1823:
1824:
1825:
1826:
1827: for (int i = 8; i <= 10; i++) {
1828: byte[] t = compress (step3Data, i);
1829: if (step3DataCompressed == null ||
1830: t.length < step3DataCompressed.length) {
1831: step3DataCompressed = t;
1832: dicbit = i;
1833: }
1834: }
1835: byte[] step2Data = new byte[adotr2.length + step3DataCompressed.length];
1836: int index2 = 0;
1837:
1838: System.arraycopy (adotr2, 0,
1839: step2Data, index2,
1840: adotr2.length);
1841: index2 += adotr2.length;
1842:
1843: System.arraycopy (step3DataCompressed, 0,
1844: step2Data, index2,
1845: step3DataCompressed.length);
1846: index2 += step3DataCompressed.length;
1847:
1848:
1849:
1850: byte[] step3DataEncoded = encode (step3Data);
1851: byte[] step2DataEncoded = encode (step2Data);
1852: byte[] step1Data;
1853: if (step3DataEncoded.length <= step2DataEncoded.length) {
1854: step1Data = new byte[adotr1.length + step3DataEncoded.length + 1];
1855: int index1 = 0;
1856: System.arraycopy (adotr1, 0,
1857: step1Data, index1,
1858: adotr1.length);
1859: index1 += adotr1.length;
1860: System.arraycopy (step3DataEncoded, 0,
1861: step1Data, index1,
1862: step3DataEncoded.length);
1863: index1 += step3DataEncoded.length;
1864: step1Data[index1++] = 0x1a;
1865: if (false) {
1866: System.out.printf (" original: %d bytes (%.1f%%)\n",
1867: fileData.length,
1868: 100.0);
1869: System.out.printf (" generator concatenated: %d bytes (%.1f%%)\n",
1870: step3Data.length,
1871: 100.0 * (double) step3Data.length / (double) fileData.length);
1872: System.out.printf (" encoded: %d bytes (%.1f%%)\n",
1873: step3DataEncoded.length,
1874: 100.0 * (double) step3DataEncoded.length / (double) fileData.length);
1875: System.out.printf (" decoder concatenated: %d bytes (%.1f%%)\n",
1876: step1Data.length,
1877: 100.0 * (double) step1Data.length / (double) fileData.length);
1878: }
1879: } else {
1880: step1Data = new byte[adotr1.length + step2DataEncoded.length + 1];
1881: int index1 = 0;
1882: System.arraycopy (adotr1, 0,
1883: step1Data, index1,
1884: adotr1.length);
1885: index1 += adotr1.length;
1886: System.arraycopy (step2DataEncoded, 0,
1887: step1Data, index1,
1888: step2DataEncoded.length);
1889: index1 += step2DataEncoded.length;
1890: step1Data[index1++] = 0x1a;
1891: if (false) {
1892: System.out.printf (" original: %d bytes (%.1f%%)\n",
1893: fileData.length,
1894: 100.0);
1895: System.out.printf (" generator concatenated: %d bytes (%.1f%%)\n",
1896: step3Data.length,
1897: 100.0 * (double) step3Data.length / (double) fileData.length);
1898: System.out.printf (" compressed: %d bytes (%.1f%%) (%d bits dictionary)\n",
1899: step3DataCompressed.length,
1900: 100.0 * (double) step3DataCompressed.length / (double) fileData.length,
1901: dicbit);
1902: System.out.printf ("decompressor concatenated: %d bytes (%.1f%%)\n",
1903: step2Data.length,
1904: 100.0 * (double) step2Data.length / (double) fileData.length);
1905: System.out.printf (" encoded: %d bytes (%.1f%%)\n",
1906: step2DataEncoded.length,
1907: 100.0 * (double) step2DataEncoded.length / (double) fileData.length);
1908: System.out.printf (" decoder concatenated: %d bytes (%.1f%%)\n",
1909: step1Data.length,
1910: 100.0 * (double) step1Data.length / (double) fileData.length);
1911: }
1912: }
1913:
1914: trmSendString (String.format (
1915: "rem a.r/%s %d/%d %.1f%%\rcopy aux a.r\r",
1916: name, step1Data.length, fileData.length,
1917: 100.0 * (double) step1Data.length / (double) fileData.length));
1918: try {
1919: Thread.sleep (1000);
1920: } catch (InterruptedException ie) {
1921: }
1922: if (trmRowToCol[0] == 1) {
1923: int row = 0;
1924: int col = 1;
1925: trmConnectionArray[trmCols * row + col - 1].row2colQueue.write (step1Data, 0, step1Data.length);
1926: } else if (0 < trmColToRow[0]) {
1927: int row = trmColToRow[0];
1928: int col = 0;
1929: trmConnectionArray[trmCols * row + col - 1].col2rowQueue.write (step1Data, 0, step1Data.length);
1930: }
1931: try {
1932: Thread.sleep (1000);
1933: } catch (InterruptedException ie) {
1934: }
1935: trmSendString ("a.r\r");
1936: }
1937:
1938:
1939: 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);
1940:
1941: 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);
1942:
1943: 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);
1944:
1945: }