From e18d2f436f56dba60b1b96cc75427b44445790f1 Mon Sep 17 00:00:00 2001 From: Rudi Date: Mon, 31 Aug 2026 00:00:13 +0000 Subject: [PATCH] Adjust clearing --- .../lib3270j/graphics/GocaDecoder.java | 114 ++++-------------- .../graphics/GocaDecoderPhase5Test.java | 12 +- 2 files changed, 28 insertions(+), 98 deletions(-) diff --git a/lib3270j/src/main/java/haus/nightmare/lib3270j/graphics/GocaDecoder.java b/lib3270j/src/main/java/haus/nightmare/lib3270j/graphics/GocaDecoder.java index 55d6b06..6390641 100644 --- a/lib3270j/src/main/java/haus/nightmare/lib3270j/graphics/GocaDecoder.java +++ b/lib3270j/src/main/java/haus/nightmare/lib3270j/graphics/GocaDecoder.java @@ -63,9 +63,6 @@ public class GocaDecoder { // Segment Store for retained graphics / segment calling (G_GCALL 0x2A) private final java.util.Map segmentStore = new java.util.HashMap<>(); - private final java.util.Map segmentChainMap = new java.util.HashMap<>(); - private final java.util.List segmentOrderList = new java.util.ArrayList<>(); - private final java.util.Set chainedTargets = new java.util.HashSet<>(); private int callDepth = 0; /** @@ -208,9 +205,6 @@ public class GocaDecoder { graphicCursorX = 0; graphicCursorY = 0; segmentStore.clear(); - segmentChainMap.clear(); - segmentOrderList.clear(); - chainedTargets.clear(); segmentBoundsMap.clear(); activeSegmentsInOrder.clear(); currentSegId = 0; @@ -294,61 +288,6 @@ public class GocaDecoder { return (data[idx + 1] & 0xFF) + 2; } - private void indexSegments(byte[] data, int offset, int length) { - int idx = offset; - int end = offset + length; - while (idx < end) { - int order = data[idx] & 0xFF; - if (order == GocaConstants.G_BEGSEGM) { - int segStart = idx; - int segLen = getOrderLength(data, idx, end); - if (segLen <= 0 || idx + 5 >= end) { - break; - } - int segId = ((data[idx + 2] & 0xFF) << 24) | - ((data[idx + 3] & 0xFF) << 16) | - ((data[idx + 4] & 0xFF) << 8) | - (data[idx + 5] & 0xFF); - - int nextId = 0; - if (segLen >= 14 && (data[idx + 1] & 0xFF) >= 12) { - nextId = ((data[idx + 10] & 0xFF) << 24) | - ((data[idx + 11] & 0xFF) << 16) | - ((data[idx + 12] & 0xFF) << 8) | - (data[idx + 13] & 0xFF); - } - - int searchIdx = idx + segLen; - while (searchIdx < end) { - int o = data[searchIdx] & 0xFF; - int oLen = getOrderLength(data, searchIdx, end); - if (oLen <= 0) break; - if (o == GocaConstants.G_ENDSEGM) { - searchIdx += oLen; - break; - } - searchIdx += oLen; - } - int fullSegLen = searchIdx - segStart; - if (fullSegLen > 0 && segStart + fullSegLen <= end) { - byte[] segBytes = new byte[fullSegLen]; - System.arraycopy(data, segStart, segBytes, 0, fullSegLen); - segmentStore.put(segId, segBytes); - segmentOrderList.add(segId); - if (nextId != 0) { - segmentChainMap.put(segId, nextId); - chainedTargets.add(nextId); - } - } - idx = searchIdx; - } else { - int oLen = getOrderLength(data, idx, end); - if (oLen <= 0) break; - idx += oLen; - } - } - } - /** * Decodes a stream of GOCA drawing orders (matching IBM Host On-Demand HODDecoder.decodeGOCA). */ @@ -386,7 +325,7 @@ public class GocaDecoder { } /** - * Executes a stored procedure segment by segment ID, traversing chained next segments. + * Executes a stored procedure segment by segment ID. */ public synchronized void procedureSegment(int segId) { if (segId == 0) return; @@ -401,12 +340,6 @@ public class GocaDecoder { decodeStreamDirect(segData, 0, segData.length); callDepth--; currentSegId = savedSeg; - - // Execute chained segments - Integer nextId = segmentChainMap.get(segId); - if (nextId != null && nextId != 0 && callDepth < 16) { - procedureSegment(nextId); - } } else { logger.warning("procedureSegment: Segment not found in store: " + segId); } @@ -444,10 +377,6 @@ public class GocaDecoder { end = offset + length; } - if (callDepth == 0) { - indexSegments(inputData, idx, end - idx); - } - decodeStreamDirect(inputData, idx, end - idx); } @@ -495,6 +424,27 @@ public class GocaDecoder { SegmentBounds sb = segmentBoundsMap.computeIfAbsent(segId, SegmentBounds::new); activeSegmentsInOrder.remove(sb); activeSegmentsInOrder.add(sb); + + if (segId != 0 && callDepth == 0) { + int segStart = idx; + int searchIdx = idx + orderLen; + while (searchIdx < end) { + int o = inputData[searchIdx] & 0xFF; + int oLen = getOrderLength(inputData, searchIdx, end); + if (oLen <= 0) break; + if (o == GocaConstants.G_ENDSEGM) { + searchIdx += oLen; + break; + } + searchIdx += oLen; + } + int fullSegLen = searchIdx - segStart; + if (fullSegLen > 0 && segStart + fullSegLen <= end) { + byte[] segBytes = new byte[fullSegLen]; + System.arraycopy(inputData, segStart, segBytes, 0, fullSegLen); + segmentStore.put(segId, segBytes); + } + } } if (idx + 6 < end) flag0 = inputData[idx + 6] & 0xFF; if (idx + 7 < end) flag1 = inputData[idx + 7] & 0xFF; @@ -507,7 +457,6 @@ public class GocaDecoder { } case GocaConstants.G_ENDSEGM: { // End Segment (0x71) logger.info(String.format("GOCA ENDSEGM: segId=%d", currentSegId)); - int finishedSegId = currentSegId; if (currentSegId != 0) { SegmentBounds sb = segmentBoundsMap.get(currentSegId); if (sb != null) { @@ -519,23 +468,6 @@ public class GocaDecoder { } currentSegId = 0; idx += orderLen; - if (finishedSegId != 0 && callDepth < 16) { - Integer nextId = segmentChainMap.get(finishedSegId); - if (nextId != null && nextId != 0) { - byte[] nextSeg = segmentStore.get(nextId); - if (nextSeg != null) { - logger.info("Executing chained segment nextId=" + nextId); - currentSegId = nextId; - SegmentBounds targetSb = segmentBoundsMap.computeIfAbsent(nextId, SegmentBounds::new); - activeSegmentsInOrder.remove(targetSb); - activeSegmentsInOrder.add(targetSb); - callDepth++; - decodeStreamDirect(nextSeg, 0, nextSeg.length); - callDepth--; - currentSegId = 0; - } - } - } break; } @@ -901,8 +833,6 @@ public class GocaDecoder { activeSegmentsInOrder.clear(); segmentBoundsMap.clear(); segmentStore.clear(); - segmentOrderList.clear(); - chainedTargets.clear(); logger.info("GOCA P_ERASE: erased graphics presentation space and cleared segment stores"); idx += 2; break; diff --git a/lib3270j/src/test/java/haus/nightmare/lib3270j/graphics/GocaDecoderPhase5Test.java b/lib3270j/src/test/java/haus/nightmare/lib3270j/graphics/GocaDecoderPhase5Test.java index 53cff95..e0b2ba4 100644 --- a/lib3270j/src/test/java/haus/nightmare/lib3270j/graphics/GocaDecoderPhase5Test.java +++ b/lib3270j/src/test/java/haus/nightmare/lib3270j/graphics/GocaDecoderPhase5Test.java @@ -71,14 +71,14 @@ public class GocaDecoderPhase5Test { GraphicsPlane plane = new GraphicsPlane(400, 300); GocaDecoder decoder = new GocaDecoder(plane); - // Segment 10 chains to Segment 11 + // Segment 10 has bytes indicating nextId = 11 ByteArrayOutputStream s10 = new ByteArrayOutputStream(); s10.write(GocaConstants.G_BEGSEGM); s10.write(0x0C); s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0A); // Seg 10 s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x00); // flags - s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0B); // Next Seg ID = 11! + s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0B); // Next Seg ID = 11 s10.write(GocaConstants.G_GSCOL); s10.write(0x01); // Blue s10.write(GocaConstants.G_GLINE); s10.write(0x08); s10.write(0x00); s10.write(10); s10.write(0x00); s10.write(10); @@ -99,16 +99,16 @@ public class GocaDecoderPhase5Test { s11.write(0x00); s11.write(70); s11.write(0x00); s11.write(70); s11.write(GocaConstants.G_ENDSEGM); s11.write(0x00); - // Store Segment 11 first + // Decode Segment 11 first, then clear decoder.decodeGoca(s11.toByteArray(), 0, s11.toByteArray().length); plane.clear(); assertFalse(plane.hasContent()); - // Execute Segment 10; upon ENDSEGM, Segment 11 should be automatically chained! + // Execute Segment 10; per HOD architecture, ENDSEGM must NOT automatically execute Segment 11! decoder.decodeGoca(s10.toByteArray(), 0, s10.toByteArray().length); assertTrue(plane.hasContent()); - // Verify both Blue (Seg 10) and Yellow (Seg 11) pixels exist + // Verify Blue (Seg 10) exists, and Yellow (Seg 11) is NOT drawn int blueArgb = GocaConstants.GOCA_COLORS[1]; int yellowArgb = GocaConstants.GOCA_COLORS[6]; boolean foundBlue = false; @@ -118,7 +118,7 @@ public class GocaDecoderPhase5Test { if (p == yellowArgb) foundYellow = true; } assertTrue(foundBlue, "Expected Blue pixel from Segment 10"); - assertTrue(foundYellow, "Expected Yellow pixel from chained Segment 11"); + assertFalse(foundYellow, "Per HOD architecture, Segment 11 must NOT be automatically chained on ENDSEGM"); } @Test