Add missing menus back
This commit is contained in:
@@ -48,7 +48,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
|
|||||||
public J3270App() {
|
public J3270App() {
|
||||||
super("j3270 — Java TN3270 Terminal Emulator");
|
super("j3270 — Java TN3270 Terminal Emulator");
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
setBackground(new Color(10, 10, 10));
|
setBackground(Color.BLACK);
|
||||||
|
|
||||||
buildUI();
|
buildUI();
|
||||||
buildMenuBar();
|
buildMenuBar();
|
||||||
@@ -92,7 +92,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
|
|||||||
statusBar = new StatusBar();
|
statusBar = new StatusBar();
|
||||||
|
|
||||||
getContentPane().setLayout(new BorderLayout());
|
getContentPane().setLayout(new BorderLayout());
|
||||||
getContentPane().setBackground(new Color(10, 10, 10));
|
getContentPane().setBackground(Color.BLACK);
|
||||||
getContentPane().add(terminalPanel, BorderLayout.CENTER);
|
getContentPane().add(terminalPanel, BorderLayout.CENTER);
|
||||||
getContentPane().add(statusBar, BorderLayout.SOUTH);
|
getContentPane().add(statusBar, BorderLayout.SOUTH);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
|||||||
public static final Color DEFAULT_MONO_PROTECTED_HIGH = new Color(255, 255, 255);
|
public static final Color DEFAULT_MONO_PROTECTED_HIGH = new Color(255, 255, 255);
|
||||||
|
|
||||||
// Default Background
|
// Default Background
|
||||||
public static final Color DEFAULT_BG_COLOR = new Color(10, 10, 10);
|
public static final Color DEFAULT_BG_COLOR = Color.BLACK;
|
||||||
|
|
||||||
public TerminalPanel() {
|
public TerminalPanel() {
|
||||||
setupColors();
|
setupColors();
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ public class QueryReplyBuilder {
|
|||||||
private static final int SW_3279_2 = 0x09;
|
private static final int SW_3279_2 = 0x09;
|
||||||
private static final int SH_3279_2 = 0x0c;
|
private static final int SH_3279_2 = 0x0c;
|
||||||
|
|
||||||
// Usable Area physical dimensions matching IBM Host On-Demand QR_USEAREA_STRING (Inches)
|
// Usable Area physical dimensions matching IBM Host On-Demand DS3270.java (Inches, 96 dpi: 0x00010060)
|
||||||
private static final int Xr_HOD = 0x00020089;
|
private static final int Xr_HOD = 0x00010060;
|
||||||
private static final int Yr_HOD = 0x00020085;
|
private static final int Yr_HOD = 0x00010060;
|
||||||
|
|
||||||
private final ScreenBuffer screen;
|
private final ScreenBuffer screen;
|
||||||
private GraphicsMode graphicsMode = GraphicsMode.BOTH;
|
private GraphicsMode graphicsMode = GraphicsMode.BOTH;
|
||||||
@@ -309,7 +309,7 @@ public class QueryReplyBuilder {
|
|||||||
|
|
||||||
private byte[] buildUsableArea(int maxCols, int maxRows, int bufferSize) {
|
private byte[] buildUsableArea(int maxCols, int maxRows, int bufferSize) {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(19);
|
ByteArrayOutputStream out = new ByteArrayOutputStream(19);
|
||||||
out.write(0x01); // 12/14-bit addressing
|
out.write(graphicsMode.isVectorGraphicsEnabled() ? 0x03 : 0x01); // 12/14-bit addressing + graphics flag (matching HOD DS3270.java)
|
||||||
out.write(0x00); // no special character features
|
out.write(0x00); // no special character features
|
||||||
out.write((maxCols >> 8) & 0xFF); // usable width high
|
out.write((maxCols >> 8) & 0xFF); // usable width high
|
||||||
out.write(maxCols & 0xFF); // usable width low
|
out.write(maxCols & 0xFF); // usable width low
|
||||||
@@ -380,8 +380,8 @@ public class QueryReplyBuilder {
|
|||||||
cpgid = screen.getTranslator().getCpgid();
|
cpgid = screen.getTranslator().getCpgid();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graphicsMode.isProgrammedSymbolsEnabled()) {
|
if (graphicsMode == GraphicsMode.PROGRAMMED_SYMBOLS) {
|
||||||
// Programmed Symbols mode (3279 PS with LoadPS 0x0A, flags1 = 0xA2 for GE + PS + CGCSGID)
|
// Programmed Symbols only mode (3279 PS with LoadPS 0x0A, flags1 = 0xA2 for GE + PS + CGCSGID)
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(65);
|
ByteArrayOutputStream out = new ByteArrayOutputStream(65);
|
||||||
out.write(0xa2); // flags: GE (0x80), PS/Loadable Charsets (0x20), CGCSGID present (0x02)
|
out.write(0xa2); // flags: GE (0x80), PS/Loadable Charsets (0x20), CGCSGID present (0x02)
|
||||||
out.write(0x00); // more flags
|
out.write(0x00); // more flags
|
||||||
@@ -615,11 +615,10 @@ public class QueryReplyBuilder {
|
|||||||
cgcsgid = screen.getTranslator().getCgcsgid();
|
cgcsgid = screen.getTranslator().getCgcsgid();
|
||||||
cpgid = screen.getTranslator().getCpgid();
|
cpgid = screen.getTranslator().getCpgid();
|
||||||
}
|
}
|
||||||
// HOD QueryReply3270Constants.java QR_GRSYMBOLSET_S_STRING ("\u0000!\u0081\u00b6...")
|
|
||||||
return new byte[]{
|
return new byte[]{
|
||||||
0x00, 0x00, (byte) charW, (byte) charH, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12,
|
0x00, 0x00, (byte) charW, (byte) charH, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12,
|
||||||
0x01, 0x00, 0x00, (byte) 0xF0, (byte) ((cgcsgid >> 8) & 0xFF), (byte) (cgcsgid & 0xFF), 0x00, 0x00,
|
0x01, 0x00, 0x00, (byte) 0xF0, (byte) ((cgcsgid >> 8) & 0xFF), (byte) (cgcsgid & 0xFF), 0x00, 0x00,
|
||||||
(byte) charW, (byte) charH, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
(byte) charW, (byte) charH, 0x00, 0x00, (byte) 0xF0, (byte) ((cgcsgid >> 8) & 0xFF), (byte) (cgcsgid & 0xFF), 0x00, 0x00
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,10 +60,9 @@ public final class GocaConstants {
|
|||||||
public static final int G_GSCR = 0x35; // Set Character Shear
|
public static final int G_GSCR = 0x35; // Set Character Shear
|
||||||
public static final int G_GSMCEL = 0x37; // Set Marker Cell
|
public static final int G_GSMCEL = 0x37; // Set Marker Cell
|
||||||
public static final int G_GSCS = 0x38; // Set Character Set
|
public static final int G_GSCS = 0x38; // Set Character Set
|
||||||
public static final int G_GSMP = 0x39; // Set Marker Precision
|
public static final int G_GSCC = 0x39; // Set Character Precision
|
||||||
public static final int G_GSETAG = 0x39; // Set Pick Identifier / Tag
|
|
||||||
public static final int G_GSCD = 0x3A; // Set Character Direction
|
public static final int G_GSCD = 0x3A; // Set Character Direction
|
||||||
public static final int G_GSCC = 0x3B; // Set Character Precision
|
public static final int G_GSMP = 0x3B; // Set Marker Precision
|
||||||
public static final int G_GSMS_SET = 0x3C; // Set Marker Set
|
public static final int G_GSMS_SET = 0x3C; // Set Marker Set
|
||||||
public static final int G_ENDPROLOGUE = 0x3E; // End Prologue
|
public static final int G_ENDPROLOGUE = 0x3E; // End Prologue
|
||||||
public static final int G_GPOP = 0x3F; // Pop Attribute
|
public static final int G_GPOP = 0x3F; // Pop Attribute
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class GocaDecoder {
|
|||||||
private int markerType = GocaConstants.MK_PLUS;
|
private int markerType = GocaConstants.MK_PLUS;
|
||||||
private int markerSize = 5;
|
private int markerSize = 5;
|
||||||
private int markerColor = GocaConstants.GOCA_COLORS[0];
|
private int markerColor = GocaConstants.GOCA_COLORS[0];
|
||||||
|
private int markerPrecision = 0;
|
||||||
private int pattern = GocaConstants.PT_SOLID;
|
private int pattern = GocaConstants.PT_SOLID;
|
||||||
private int patternSet = 0;
|
private int patternSet = 0;
|
||||||
private int fillColor = GocaConstants.GOCA_COLORS[0];
|
private int fillColor = GocaConstants.GOCA_COLORS[0];
|
||||||
@@ -225,6 +226,7 @@ public class GocaDecoder {
|
|||||||
markerType = GocaConstants.MK_PLUS;
|
markerType = GocaConstants.MK_PLUS;
|
||||||
markerSize = 5;
|
markerSize = 5;
|
||||||
markerColor = curColor;
|
markerColor = curColor;
|
||||||
|
markerPrecision = 0;
|
||||||
pattern = GocaConstants.PT_SOLID;
|
pattern = GocaConstants.PT_SOLID;
|
||||||
patternSet = 0;
|
patternSet = 0;
|
||||||
fillColor = curColor;
|
fillColor = curColor;
|
||||||
@@ -281,7 +283,7 @@ public class GocaDecoder {
|
|||||||
// Flexible 1-byte attribute orders (support both short 2-byte or long 3-byte if len byte == 1)
|
// Flexible 1-byte attribute orders (support both short 2-byte or long 3-byte if len byte == 1)
|
||||||
if (order == GocaConstants.G_GSPT || order == GocaConstants.G_GSMT ||
|
if (order == GocaConstants.G_GSPT || order == GocaConstants.G_GSMT ||
|
||||||
order == GocaConstants.G_GSCS || order == GocaConstants.G_GSCD ||
|
order == GocaConstants.G_GSCS || order == GocaConstants.G_GSCD ||
|
||||||
order == GocaConstants.G_GSCC ||
|
order == GocaConstants.G_GSCC || order == GocaConstants.G_GSMP ||
|
||||||
order == GocaConstants.G_GSMS_SET || order == GocaConstants.G_GBAR) {
|
order == GocaConstants.G_GSMS_SET || order == GocaConstants.G_GBAR) {
|
||||||
return (data[idx + 1] == 0x01 && idx + 2 < end) ? 3 : 2;
|
return (data[idx + 1] == 0x01 && idx + 2 < end) ? 3 : 2;
|
||||||
}
|
}
|
||||||
@@ -536,17 +538,7 @@ public class GocaDecoder {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GocaConstants.G_GSETAG: { // Set Pick Identifier / Tag (0x39)
|
|
||||||
if (currentSegId != 0 && payloadLen >= 2 && idx + 3 < end) {
|
|
||||||
int tag = ((inputData[idx + 2] & 0xFF) << 8) | (inputData[idx + 3] & 0xFF);
|
|
||||||
SegmentBounds sb = segmentBoundsMap.get(currentSegId);
|
|
||||||
if (sb != null) {
|
|
||||||
sb.tag = tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
idx += orderLen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GocaConstants.G_ENDPROLOGUE: { // End Prologue (0x3E)
|
case GocaConstants.G_ENDPROLOGUE: { // End Prologue (0x3E)
|
||||||
idx += orderLen;
|
idx += orderLen;
|
||||||
break;
|
break;
|
||||||
@@ -706,16 +698,22 @@ public class GocaDecoder {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GocaConstants.G_GSCS: { // Set Character Set (0x38)
|
case GocaConstants.G_GSCS: { // Set Character Set (0x38)
|
||||||
charSet = (orderLen == 3) ? (inputData[idx + 2] & 0xFF) : (inputData[idx + 1] & 0xFF);
|
int cs = (orderLen == 3) ? (inputData[idx + 2] & 0xFF) : (inputData[idx + 1] & 0xFF);
|
||||||
|
charSet = (cs == 0xF0) ? 0 : cs;
|
||||||
idx += orderLen;
|
idx += orderLen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GocaConstants.G_GSCC: { // Set Character Precision (0x3B)
|
case GocaConstants.G_GSCC: { // Set Character Precision (0x39)
|
||||||
charPrecision = (orderLen == 3) ? (inputData[idx + 2] & 0xFF) : (inputData[idx + 1] & 0xFF);
|
charPrecision = (orderLen == 3) ? (inputData[idx + 2] & 0xFF) : (inputData[idx + 1] & 0xFF);
|
||||||
if (charPrecision == 0) charPrecision = GocaConstants.CP_STRING;
|
if (charPrecision == 0) charPrecision = GocaConstants.CP_STRING;
|
||||||
idx += orderLen;
|
idx += orderLen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GocaConstants.G_GSMP: { // Set Marker Precision (0x3B)
|
||||||
|
markerPrecision = (orderLen == 3) ? (inputData[idx + 2] & 0xFF) : (inputData[idx + 1] & 0xFF);
|
||||||
|
idx += orderLen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GocaConstants.G_GSMX:
|
case GocaConstants.G_GSMX:
|
||||||
case GocaConstants.G_GSMS_SET:
|
case GocaConstants.G_GSMS_SET:
|
||||||
case GocaConstants.G_GPOP: {
|
case GocaConstants.G_GPOP: {
|
||||||
@@ -1393,7 +1391,15 @@ public class GocaDecoder {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charSet != 0 && programSymbolManager != null) {
|
if (charSet == 0xF8 || charPrecision == GocaConstants.CP_STROKE) {
|
||||||
|
char[] chars = new char[textLen];
|
||||||
|
for (int i = 0; i < textLen; i++) {
|
||||||
|
chars[i] = EbcdicTranslator.ebcdicToAscii(data[pos + i]);
|
||||||
|
}
|
||||||
|
String text = new String(chars);
|
||||||
|
plane.drawVectorText(plane.mapXDouble(startX), plane.mapYDouble(startY), text,
|
||||||
|
curColor, cw, ch, charDir, charAngle);
|
||||||
|
} else if (charSet != 0 && programSymbolManager != null) {
|
||||||
for (int i = 0; i < textLen; i++) {
|
for (int i = 0; i < textLen; i++) {
|
||||||
int code = data[pos + i] & 0xFF;
|
int code = data[pos + i] & 0xFF;
|
||||||
double px = plane.mapXDouble(startX);
|
double px = plane.mapXDouble(startX);
|
||||||
@@ -1417,27 +1423,18 @@ public class GocaDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
char c = EbcdicTranslator.ebcdicToAscii(data[pos + i]);
|
|
||||||
plane.drawVectorText(px, py, String.valueOf(c), curColor, cw, ch, charDir, charAngle);
|
|
||||||
}
|
}
|
||||||
startX += (charWidth > 0 ? charWidth : 9);
|
startX += (charWidth > 0 ? charWidth : 9);
|
||||||
}
|
}
|
||||||
curX = startX;
|
curX = startX;
|
||||||
curY = startY;
|
curY = startY;
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
char[] chars = new char[textLen];
|
char[] chars = new char[textLen];
|
||||||
for (int i = 0; i < textLen; i++) {
|
for (int i = 0; i < textLen; i++) {
|
||||||
chars[i] = EbcdicTranslator.ebcdicToAscii(data[pos + i]);
|
chars[i] = EbcdicTranslator.ebcdicToAscii(data[pos + i]);
|
||||||
}
|
}
|
||||||
String text = new String(chars);
|
String text = new String(chars);
|
||||||
|
|
||||||
if (charPrecision == GocaConstants.CP_STROKE) {
|
|
||||||
plane.drawVectorText(plane.mapXDouble(startX), plane.mapYDouble(startY), text,
|
|
||||||
curColor, cw, ch, charDir, charAngle);
|
|
||||||
} else {
|
|
||||||
plane.drawText(plane.mapXDouble(startX), plane.mapYDouble(startY), text,
|
plane.drawText(plane.mapXDouble(startX), plane.mapYDouble(startY), text,
|
||||||
curColor, cw, ch, charDir, charAngle);
|
curColor, cw, ch, charDir, charAngle);
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-13
@@ -81,21 +81,19 @@ public class QueryReplyBuilderTest {
|
|||||||
byte[] replies = qrBuilder.buildCompleteQueryReplies(80, 43, 80 * 43);
|
byte[] replies = qrBuilder.buildCompleteQueryReplies(80, 43, 80 * 43);
|
||||||
assertNotNull(replies);
|
assertNotNull(replies);
|
||||||
|
|
||||||
// Vector Graphics (0xB0) must be present and Charsets must have LoadPS (0x0A)
|
// Vector Graphics (0xB0) must be present and Charsets must be present (0x85)
|
||||||
boolean hasB0 = false;
|
boolean hasB0 = false;
|
||||||
boolean hasCharsetsWithLoadPs = false;
|
boolean hasCharsets = false;
|
||||||
for (int i = 0; i < replies.length - 3; i++) {
|
for (int i = 0; i < replies.length - 3; i++) {
|
||||||
if ((replies[i] & 0xFF) == 0x81 && (replies[i + 1] & 0xFF) == QR_SEGMENT) {
|
if ((replies[i] & 0xFF) == 0x81 && (replies[i + 1] & 0xFF) == QR_SEGMENT) {
|
||||||
hasB0 = true;
|
hasB0 = true;
|
||||||
}
|
}
|
||||||
if ((replies[i] & 0xFF) == 0x81 && (completeReplyIsCharsets(replies, i))) {
|
if ((replies[i] & 0xFF) == 0x81 && (completeReplyIsCharsets(replies, i))) {
|
||||||
if (i + 6 < replies.length && (replies[i + 6] & 0xFF) == 0x0A) {
|
hasCharsets = true;
|
||||||
hasCharsetsWithLoadPs = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue(hasB0);
|
assertTrue(hasB0);
|
||||||
assertTrue(hasCharsetsWithLoadPs);
|
assertTrue(hasCharsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean completeReplyIsCharsets(byte[] replies, int i) {
|
private boolean completeReplyIsCharsets(byte[] replies, int i) {
|
||||||
@@ -283,24 +281,24 @@ public class QueryReplyBuilderTest {
|
|||||||
assertEquals(0x81, replies[3] & 0xFF);
|
assertEquals(0x81, replies[3] & 0xFF);
|
||||||
assertEquals(QR_USABLE_AREA, replies[4] & 0xFF);
|
assertEquals(QR_USABLE_AREA, replies[4] & 0xFF);
|
||||||
|
|
||||||
// Flags: 12/14 bit addressing (0x01), 0x00
|
// Flags: 12/14 bit addressing | Graphics (0x03), 0x00
|
||||||
assertEquals(0x01, replies[5] & 0xFF);
|
assertEquals(0x03, replies[5] & 0xFF);
|
||||||
assertEquals(0x00, replies[6] & 0xFF);
|
assertEquals(0x00, replies[6] & 0xFF);
|
||||||
|
|
||||||
// Usable width and height: 80, 43
|
// Usable width and height: 80, 43
|
||||||
assertEquals(80, ((replies[7] & 0xFF) << 8) | (replies[8] & 0xFF));
|
assertEquals(80, ((replies[7] & 0xFF) << 8) | (replies[8] & 0xFF));
|
||||||
assertEquals(43, ((replies[9] & 0xFF) << 8) | (replies[10] & 0xFF));
|
assertEquals(43, ((replies[9] & 0xFF) << 8) | (replies[10] & 0xFF));
|
||||||
|
|
||||||
// Units: 0x00 (Inches, matching IBM Host On-Demand QR_USEAREA_STRING)
|
// Units: 0x00 (Inches, matching IBM Host On-Demand DS3270.java)
|
||||||
assertEquals(0x00, replies[11] & 0xFF);
|
assertEquals(0x00, replies[11] & 0xFF);
|
||||||
|
|
||||||
// Xr (4 bytes): 0x00020089 (matching HOD)
|
// Xr (4 bytes): 0x00010060 (96 dpi matching HOD)
|
||||||
int xr = ((replies[12] & 0xFF) << 24) | ((replies[13] & 0xFF) << 16) | ((replies[14] & 0xFF) << 8) | (replies[15] & 0xFF);
|
int xr = ((replies[12] & 0xFF) << 24) | ((replies[13] & 0xFF) << 16) | ((replies[14] & 0xFF) << 8) | (replies[15] & 0xFF);
|
||||||
assertEquals(0x00020089, xr);
|
assertEquals(0x00010060, xr);
|
||||||
|
|
||||||
// Yr (4 bytes): 0x00020085 (matching HOD)
|
// Yr (4 bytes): 0x00010060 (96 dpi matching HOD)
|
||||||
int yr = ((replies[16] & 0xFF) << 24) | ((replies[17] & 0xFF) << 16) | ((replies[18] & 0xFF) << 8) | (replies[19] & 0xFF);
|
int yr = ((replies[16] & 0xFF) << 24) | ((replies[17] & 0xFF) << 16) | ((replies[18] & 0xFF) << 8) | (replies[19] & 0xFF);
|
||||||
assertEquals(0x00020085, yr);
|
assertEquals(0x00010060, yr);
|
||||||
|
|
||||||
// AW and AH: 9 and 16
|
// AW and AH: 9 and 16
|
||||||
assertEquals(9, replies[20] & 0xFF);
|
assertEquals(9, replies[20] & 0xFF);
|
||||||
@@ -309,4 +307,17 @@ public class QueryReplyBuilderTest {
|
|||||||
// Buffer size: 80 * 43 = 3440
|
// Buffer size: 80 * 43 = 3440
|
||||||
assertEquals(80 * 43, ((replies[22] & 0xFF) << 8) | (replies[23] & 0xFF));
|
assertEquals(80 * 43, ((replies[22] & 0xFF) << 8) | (replies[23] & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGrSymbolSetMatchesHOD() {
|
||||||
|
qrBuilder.setGraphicsMode(GraphicsMode.VECTOR_GRAPHICS);
|
||||||
|
byte[] requested = new byte[] { (byte) QR_GRSYMBOLSET };
|
||||||
|
byte[] replies = qrBuilder.buildQueryReplies(requested, 80, 43, 80 * 43);
|
||||||
|
|
||||||
|
assertNotNull(replies);
|
||||||
|
assertEquals((byte) AID_SF, replies[0]);
|
||||||
|
assertEquals(33, ((replies[1] & 0xFF) << 8) | (replies[2] & 0xFF));
|
||||||
|
assertEquals(0x81, replies[3] & 0xFF);
|
||||||
|
assertEquals(QR_GRSYMBOLSET, replies[4] & 0xFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user