Admdraw appears
This commit is contained in:
@@ -251,26 +251,26 @@ public class GocaDecoder {
|
||||
*/
|
||||
private int getOrderLength(byte[] data, int idx, int end) {
|
||||
int order = data[idx] & 0xFF;
|
||||
if (order == GocaConstants.G_NOP1 || order == 0xFF || order == 0x00 ||
|
||||
order == GocaConstants.G_GEAR || order == GocaConstants.G_ENDSEGM ||
|
||||
order == GocaConstants.G_ENDPROLOGUE || order == GocaConstants.G_GEIMG ||
|
||||
order == GocaConstants.G_GPOP || order == GocaConstants.G_GERASE) {
|
||||
if (order == GocaConstants.G_NOP1 || order == 0xFF || order == 0x00 || order == GocaConstants.G_COMT) {
|
||||
return 1;
|
||||
}
|
||||
// Orders with optional 0x00 trailing length/qualifier byte (e.g. 3E 00, 71 00, 60 00, 7E 00, 3F 00, 91 00)
|
||||
if (order == GocaConstants.G_ENDPROLOGUE || order == GocaConstants.G_ENDSEGM ||
|
||||
order == GocaConstants.G_GEAR || order == GocaConstants.G_GERASE ||
|
||||
order == GocaConstants.G_GPOP || order == GocaConstants.G_GEIMG) {
|
||||
return (idx + 1 < end && data[idx + 1] == 0x00) ? 2 : 1;
|
||||
}
|
||||
if (idx + 1 >= end) {
|
||||
return -1;
|
||||
}
|
||||
// Fixed 2-byte orders: 1-byte opcode + 1-byte operand
|
||||
if (order == 0x04 || order == GocaConstants.G_GSMC || order == GocaConstants.G_GSPS ||
|
||||
order == GocaConstants.G_GSCOL || order == GocaConstants.G_GSMX ||
|
||||
order == GocaConstants.G_GSBMX || order == GocaConstants.G_GSLT ||
|
||||
order == GocaConstants.G_GSLW || order == GocaConstants.G_GSMS) {
|
||||
// All 1-byte operand short orders in 0x02..0x1F range (GSCOL, GSLT, GSLW, GSMS, GSMC, GSPS, GSMX, GSBMX, etc.)
|
||||
if (order < 0x20) {
|
||||
return 2;
|
||||
}
|
||||
// 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_GSMP ||
|
||||
order == GocaConstants.G_GSCC ||
|
||||
order == GocaConstants.G_GSMS_SET || order == GocaConstants.G_GBAR) {
|
||||
return (data[idx + 1] == 0x01 && idx + 2 < end) ? 3 : 2;
|
||||
}
|
||||
@@ -558,11 +558,16 @@ public class GocaDecoder {
|
||||
idx += orderLen;
|
||||
break;
|
||||
}
|
||||
case 0x06:
|
||||
case 0x11:
|
||||
case GocaConstants.G_GSLT: { // Set Line Type (0x18)
|
||||
lineType = inputData[idx + 1] & 0xFF;
|
||||
idx += orderLen;
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x12:
|
||||
case GocaConstants.G_GSLW: { // Set Line Width (0x19)
|
||||
lineWidth = inputData[idx + 1] & 0xFF;
|
||||
idx += orderLen;
|
||||
@@ -612,9 +617,7 @@ public class GocaDecoder {
|
||||
idx += orderLen;
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
case GocaConstants.G_GSMX:
|
||||
case GocaConstants.G_GSFLW:
|
||||
case GocaConstants.G_GSMS_SET:
|
||||
case GocaConstants.G_GPOP: {
|
||||
idx += orderLen;
|
||||
@@ -804,6 +807,31 @@ public class GocaDecoder {
|
||||
break;
|
||||
}
|
||||
case GocaConstants.P_SCUDEF: { // 0x21: Drawing Process Control / Segment Execute
|
||||
if (idx + 5 < end) {
|
||||
int pLen = data[idx + 1] & 0xFF;
|
||||
if (pLen >= 6) {
|
||||
int flags0 = data[idx + 2] & 0xFF;
|
||||
int flags1 = data[idx + 3] & 0xFF;
|
||||
int startSeg = ((data[idx + 4] & 0xFF) << 8) | (data[idx + 5] & 0xFF);
|
||||
int endSeg = (idx + 7 < end) ? (((data[idx + 6] & 0xFF) << 8) | (data[idx + 7] & 0xFF)) : startSeg;
|
||||
logger.info(String.format("GOCA P_SCUDEF: flags0=0x%02x flags1=0x%02x startSeg=%d endSeg=%d",
|
||||
flags0, flags1, startSeg, endSeg));
|
||||
for (int s = startSeg; s <= endSeg; s++) {
|
||||
byte[] segBytes = segmentStore.get(s);
|
||||
if (segBytes != null) {
|
||||
int savedSegId = currentSegId;
|
||||
currentSegId = s;
|
||||
SegmentBounds sb = segmentBoundsMap.computeIfAbsent(s, SegmentBounds::new);
|
||||
activeSegmentsInOrder.remove(sb);
|
||||
activeSegmentsInOrder.add(sb);
|
||||
callDepth++;
|
||||
decodeStreamDirect(segBytes, 0, segBytes.length);
|
||||
callDepth--;
|
||||
currentSegId = savedSegId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx + 1 < end) {
|
||||
int len = (data[idx + 1] & 0xFF) + 2;
|
||||
idx += len;
|
||||
@@ -1164,6 +1192,7 @@ public class GocaDecoder {
|
||||
List<Double> ptsY = new ArrayList<>();
|
||||
|
||||
if (fromCurPos) {
|
||||
trackPoint(curX, curY);
|
||||
ptsX.add(plane.mapXDouble(curX));
|
||||
ptsY.add(plane.mapYDouble(curY));
|
||||
if (inArea) {
|
||||
@@ -1178,6 +1207,7 @@ public class GocaDecoder {
|
||||
while (pos + 4 <= end) {
|
||||
int x = readCoord(data, pos);
|
||||
int y = readCoord(data, pos + 2);
|
||||
trackPoint(x, y);
|
||||
ptsX.add(plane.mapXDouble(x));
|
||||
ptsY.add(plane.mapYDouble(y));
|
||||
if (inArea) {
|
||||
|
||||
@@ -8,11 +8,11 @@ public class GraphicInputBuilder {
|
||||
|
||||
// 56-byte template mask from IBM Host On-Demand (HODInput.java)
|
||||
private static final byte[] MASK = new byte[] {
|
||||
0x00, 0x34, 0x0F, 0x0F, 0x00, (byte) 0xC0, 0x00, 0x40,
|
||||
0x00, 0x38, 0x0F, 0x0F, 0x00, (byte) 0xC0, 0x00, 0x40,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x23, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1F, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x80, 0x00
|
||||
};
|
||||
@@ -22,15 +22,15 @@ public class GraphicInputBuilder {
|
||||
*
|
||||
* @param gocaX GOCA signed X coordinate (-xMax..+xMax)
|
||||
* @param gocaY GOCA signed Y coordinate (-yMax..+yMax)
|
||||
* @param aidCode The 3270 AID code (e.g. 0x7D for ENTER, 0xF3 for PF3)
|
||||
* @param buttonOrAidCode The mouse button number (1=Pick, 2=Action) or 3270 AID code for keyboard
|
||||
* @param isMouseAction true if triggered directly by mouse button press, false for keyboard AID
|
||||
* @param isShift true if shift key was down
|
||||
* @param isCtrl true if ctrl key was down
|
||||
* @return 56-byte payload
|
||||
*/
|
||||
public static byte[] buildGraphicInput(int gocaX, int gocaY, int aidCode,
|
||||
public static byte[] buildGraphicInput(int gocaX, int gocaY, int buttonOrAidCode,
|
||||
boolean isMouseAction, boolean isShift, boolean isCtrl) {
|
||||
return buildGraphicInput(gocaX, gocaY, aidCode, isMouseAction, isShift, isCtrl, 0, 0);
|
||||
return buildGraphicInput(gocaX, gocaY, buttonOrAidCode, isMouseAction, isShift, isCtrl, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,16 +38,18 @@ public class GraphicInputBuilder {
|
||||
*
|
||||
* IMPORTANT ARCHITECTURE NOTE:
|
||||
* Per IBM GA23-0059 / GDDM specifications:
|
||||
* - Bytes 0-1: Total structured field length (0x0038 = 56 bytes).
|
||||
* - Bytes 24-27: (gocaX, gocaY) cursor coordinates.
|
||||
* - Bytes 28-31: Picked Segment Identifier (32-bit big-endian). When clicking on a menu item or
|
||||
* interactive element (e.g. DRAW button = Segment 2, EXIT button = Segment 5), GDDM requires
|
||||
* the exact segment ID in bytes 28-31. If hardcoded or mismatched, GDDM rejects the click
|
||||
* with a WCC 0xF7 alarm beep.
|
||||
* the exact segment ID in bytes 28-31. If mismatched, GDDM rejects the click with a WCC 0xF7 alarm beep.
|
||||
* - Bytes 32-33: Pick Correlation Tag (16-bit big-endian) set by G_GSETAG (0x39).
|
||||
* - Byte 34: Modifier flags (Shift = 0x80, Ctrl = 0x40, 0xFF for keyboard AID).
|
||||
* - Byte 35: Button ID (0x01 = Button 1 / Pick, 0x02 = Button 2 / Action) or 3270 AID code.
|
||||
*
|
||||
* @param gocaX GOCA signed X coordinate (-xMax..+xMax)
|
||||
* @param gocaY GOCA signed Y coordinate (-yMax..+yMax)
|
||||
* @param aidCode The 3270 AID code (e.g. 0x7D for ENTER, 0xF3 for PF3)
|
||||
* @param buttonOrAidCode The mouse button number (1=Pick, 2=Action) or 3270 AID code for keyboard
|
||||
* @param isMouseAction true if triggered directly by mouse button press, false for keyboard AID
|
||||
* @param isShift true if shift key was down
|
||||
* @param isCtrl true if ctrl key was down
|
||||
@@ -55,12 +57,16 @@ public class GraphicInputBuilder {
|
||||
* @param pickTag Pick correlation tag
|
||||
* @return 56-byte payload
|
||||
*/
|
||||
public static byte[] buildGraphicInput(int gocaX, int gocaY, int aidCode,
|
||||
public static byte[] buildGraphicInput(int gocaX, int gocaY, int buttonOrAidCode,
|
||||
boolean isMouseAction, boolean isShift, boolean isCtrl,
|
||||
int pickedSegId, int pickTag) {
|
||||
byte[] sf = new byte[MASK.length];
|
||||
System.arraycopy(MASK, 0, sf, 0, MASK.length);
|
||||
|
||||
// Byte 0-1: Structured Field Length (56 bytes)
|
||||
sf[0] = (byte) ((MASK.length >> 8) & 0xFF);
|
||||
sf[1] = (byte) (MASK.length & 0xFF);
|
||||
|
||||
// Byte 24-25: GOCA X coordinate (signed 16-bit big-endian)
|
||||
sf[24] = (byte) ((gocaX >> 8) & 0xFF);
|
||||
sf[25] = (byte) (gocaX & 0xFF);
|
||||
@@ -69,28 +75,29 @@ public class GraphicInputBuilder {
|
||||
sf[26] = (byte) ((gocaY >> 8) & 0xFF);
|
||||
sf[27] = (byte) (gocaY & 0xFF);
|
||||
|
||||
if (pickedSegId != 0) {
|
||||
if (isMouseAction) {
|
||||
// Byte 28-31: Picked Segment ID (4 bytes big-endian)
|
||||
sf[28] = (byte) ((pickedSegId >> 24) & 0xFF);
|
||||
sf[29] = (byte) ((pickedSegId >> 16) & 0xFF);
|
||||
sf[30] = (byte) ((pickedSegId >> 8) & 0xFF);
|
||||
sf[31] = (byte) (pickedSegId & 0xFF);
|
||||
}
|
||||
|
||||
if (isMouseAction) {
|
||||
if (pickTag != 0) {
|
||||
// Byte 32-33: Pick Tag / Correlation (2 bytes big-endian)
|
||||
sf[32] = (byte) ((pickTag >> 8) & 0xFF);
|
||||
sf[33] = (byte) (pickTag & 0xFF);
|
||||
}
|
||||
// Byte 32-33: Pick Tag / Correlation (2 bytes big-endian)
|
||||
sf[32] = (byte) ((pickTag >> 8) & 0xFF);
|
||||
sf[33] = (byte) (pickTag & 0xFF);
|
||||
|
||||
sf[34] = isShift ? (byte) 0x80 : (isCtrl ? (byte) 0x40 : 0x00);
|
||||
sf[35] = (byte) (aidCode == 2 ? 0x02 : 0x01); // Button 1 = Pick, Button 2 = Action
|
||||
sf[35] = (byte) (buttonOrAidCode == 2 ? 0x02 : 0x01); // Button 1 = Pick, Button 2 = Action
|
||||
} else {
|
||||
// Keyboard AID (Enter, PF keys)
|
||||
sf[28] = 0x00;
|
||||
sf[29] = 0x00;
|
||||
sf[30] = 0x00;
|
||||
sf[31] = 0x07;
|
||||
sf[32] = 0x00;
|
||||
sf[33] = 0x07;
|
||||
sf[34] = (byte) 0xFF;
|
||||
sf[35] = (byte) (aidCode & 0xFF);
|
||||
sf[35] = (byte) (buttonOrAidCode & 0xFF);
|
||||
}
|
||||
|
||||
return sf;
|
||||
|
||||
@@ -325,7 +325,7 @@ public class InputProcessor {
|
||||
int pickedSeg = gocaDecoder.findPickedSegment(gx, gy);
|
||||
int pickTag = gocaDecoder.getSegmentTag(pickedSeg);
|
||||
byte[] sf = haus.nightmare.lib3270j.graphics.GraphicInputBuilder.buildGraphicInput(
|
||||
gx, gy, aidCode, true, isShift, isCtrl, pickedSeg, pickTag
|
||||
gx, gy, button, true, isShift, isCtrl, pickedSeg, pickTag
|
||||
);
|
||||
System.err.println(String.format(
|
||||
"sendGraphicMouseAid: goca=(%d, %d) pickedSeg=%d pickTag=%d btn=%d shift=%b ctrl=%b",
|
||||
|
||||
Reference in New Issue
Block a user