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