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