Add missing menus back
This commit is contained in:
@@ -48,7 +48,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
|
||||
public J3270App() {
|
||||
super("j3270 — Java TN3270 Terminal Emulator");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setBackground(new Color(10, 10, 10));
|
||||
setBackground(Color.BLACK);
|
||||
|
||||
buildUI();
|
||||
buildMenuBar();
|
||||
@@ -92,7 +92,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
|
||||
statusBar = new StatusBar();
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().setBackground(new Color(10, 10, 10));
|
||||
getContentPane().setBackground(Color.BLACK);
|
||||
getContentPane().add(terminalPanel, BorderLayout.CENTER);
|
||||
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);
|
||||
|
||||
// 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() {
|
||||
setupColors();
|
||||
|
||||
@@ -18,9 +18,9 @@ public class QueryReplyBuilder {
|
||||
private static final int SW_3279_2 = 0x09;
|
||||
private static final int SH_3279_2 = 0x0c;
|
||||
|
||||
// Usable Area physical dimensions matching IBM Host On-Demand QR_USEAREA_STRING (Inches)
|
||||
private static final int Xr_HOD = 0x00020089;
|
||||
private static final int Yr_HOD = 0x00020085;
|
||||
// Usable Area physical dimensions matching IBM Host On-Demand DS3270.java (Inches, 96 dpi: 0x00010060)
|
||||
private static final int Xr_HOD = 0x00010060;
|
||||
private static final int Yr_HOD = 0x00010060;
|
||||
|
||||
private final ScreenBuffer screen;
|
||||
private GraphicsMode graphicsMode = GraphicsMode.BOTH;
|
||||
@@ -309,7 +309,7 @@ public class QueryReplyBuilder {
|
||||
|
||||
private byte[] buildUsableArea(int maxCols, int maxRows, int bufferSize) {
|
||||
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((maxCols >> 8) & 0xFF); // usable width high
|
||||
out.write(maxCols & 0xFF); // usable width low
|
||||
@@ -380,8 +380,8 @@ public class QueryReplyBuilder {
|
||||
cpgid = screen.getTranslator().getCpgid();
|
||||
}
|
||||
|
||||
if (graphicsMode.isProgrammedSymbolsEnabled()) {
|
||||
// Programmed Symbols mode (3279 PS with LoadPS 0x0A, flags1 = 0xA2 for GE + PS + CGCSGID)
|
||||
if (graphicsMode == GraphicsMode.PROGRAMMED_SYMBOLS) {
|
||||
// Programmed Symbols only mode (3279 PS with LoadPS 0x0A, flags1 = 0xA2 for GE + PS + CGCSGID)
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(65);
|
||||
out.write(0xa2); // flags: GE (0x80), PS/Loadable Charsets (0x20), CGCSGID present (0x02)
|
||||
out.write(0x00); // more flags
|
||||
@@ -615,11 +615,10 @@ public class QueryReplyBuilder {
|
||||
cgcsgid = screen.getTranslator().getCgcsgid();
|
||||
cpgid = screen.getTranslator().getCpgid();
|
||||
}
|
||||
// HOD QueryReply3270Constants.java QR_GRSYMBOLSET_S_STRING ("\u0000!\u0081\u00b6...")
|
||||
return new byte[]{
|
||||
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,
|
||||
(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_GSMCEL = 0x37; // Set Marker Cell
|
||||
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_GSETAG = 0x39; // Set Pick Identifier / Tag
|
||||
public static final int G_GSCC = 0x39; // Set Character Precision
|
||||
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_ENDPROLOGUE = 0x3E; // End Prologue
|
||||
public static final int G_GPOP = 0x3F; // Pop Attribute
|
||||
|
||||
@@ -27,6 +27,7 @@ public class GocaDecoder {
|
||||
private int markerType = GocaConstants.MK_PLUS;
|
||||
private int markerSize = 5;
|
||||
private int markerColor = GocaConstants.GOCA_COLORS[0];
|
||||
private int markerPrecision = 0;
|
||||
private int pattern = GocaConstants.PT_SOLID;
|
||||
private int patternSet = 0;
|
||||
private int fillColor = GocaConstants.GOCA_COLORS[0];
|
||||
@@ -225,6 +226,7 @@ public class GocaDecoder {
|
||||
markerType = GocaConstants.MK_PLUS;
|
||||
markerSize = 5;
|
||||
markerColor = curColor;
|
||||
markerPrecision = 0;
|
||||
pattern = GocaConstants.PT_SOLID;
|
||||
patternSet = 0;
|
||||
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)
|
||||
if (order == GocaConstants.G_GSPT || order == GocaConstants.G_GSMT ||
|
||||
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) {
|
||||
return (data[idx + 1] == 0x01 && idx + 2 < end) ? 3 : 2;
|
||||
}
|
||||
@@ -536,17 +538,7 @@ public class GocaDecoder {
|
||||
}
|
||||
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)
|
||||
idx += orderLen;
|
||||
break;
|
||||
@@ -706,16 +698,22 @@ public class GocaDecoder {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
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);
|
||||
if (charPrecision == 0) charPrecision = GocaConstants.CP_STRING;
|
||||
idx += orderLen;
|
||||
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_GSMS_SET:
|
||||
case GocaConstants.G_GPOP: {
|
||||
@@ -1393,7 +1391,15 @@ public class GocaDecoder {
|
||||
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++) {
|
||||
int code = data[pos + i] & 0xFF;
|
||||
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);
|
||||
}
|
||||
curX = startX;
|
||||
curY = startY;
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
char[] chars = new char[textLen];
|
||||
for (int i = 0; i < textLen; i++) {
|
||||
chars[i] = EbcdicTranslator.ebcdicToAscii(data[pos + i]);
|
||||
}
|
||||
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,
|
||||
curColor, cw, ch, charDir, charAngle);
|
||||
}
|
||||
|
||||
+24
-13
@@ -81,21 +81,19 @@ public class QueryReplyBuilderTest {
|
||||
byte[] replies = qrBuilder.buildCompleteQueryReplies(80, 43, 80 * 43);
|
||||
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 hasCharsetsWithLoadPs = false;
|
||||
boolean hasCharsets = false;
|
||||
for (int i = 0; i < replies.length - 3; i++) {
|
||||
if ((replies[i] & 0xFF) == 0x81 && (replies[i + 1] & 0xFF) == QR_SEGMENT) {
|
||||
hasB0 = true;
|
||||
}
|
||||
if ((replies[i] & 0xFF) == 0x81 && (completeReplyIsCharsets(replies, i))) {
|
||||
if (i + 6 < replies.length && (replies[i + 6] & 0xFF) == 0x0A) {
|
||||
hasCharsetsWithLoadPs = true;
|
||||
}
|
||||
hasCharsets = true;
|
||||
}
|
||||
}
|
||||
assertTrue(hasB0);
|
||||
assertTrue(hasCharsetsWithLoadPs);
|
||||
assertTrue(hasCharsets);
|
||||
}
|
||||
|
||||
private boolean completeReplyIsCharsets(byte[] replies, int i) {
|
||||
@@ -283,24 +281,24 @@ public class QueryReplyBuilderTest {
|
||||
assertEquals(0x81, replies[3] & 0xFF);
|
||||
assertEquals(QR_USABLE_AREA, replies[4] & 0xFF);
|
||||
|
||||
// Flags: 12/14 bit addressing (0x01), 0x00
|
||||
assertEquals(0x01, replies[5] & 0xFF);
|
||||
// Flags: 12/14 bit addressing | Graphics (0x03), 0x00
|
||||
assertEquals(0x03, replies[5] & 0xFF);
|
||||
assertEquals(0x00, replies[6] & 0xFF);
|
||||
|
||||
// Usable width and height: 80, 43
|
||||
assertEquals(80, ((replies[7] & 0xFF) << 8) | (replies[8] & 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);
|
||||
|
||||
// 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);
|
||||
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);
|
||||
assertEquals(0x00020085, yr);
|
||||
assertEquals(0x00010060, yr);
|
||||
|
||||
// AW and AH: 9 and 16
|
||||
assertEquals(9, replies[20] & 0xFF);
|
||||
@@ -309,4 +307,17 @@ public class QueryReplyBuilderTest {
|
||||
// Buffer size: 80 * 43 = 3440
|
||||
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