From 30b1a77b6184fcee48c233a667e49380b0dfdb87 Mon Sep 17 00:00:00 2001 From: Rudi Date: Wed, 16 Sep 2026 21:08:22 +0000 Subject: [PATCH] Datastream bug fixes w/ not recognizing bytes --- .../datastream/DataStreamProcessor.java | 2 + .../datastream/DataStreamProcessorTest.java | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/lib3270j/src/main/java/haus/nightmare/lib3270j/datastream/DataStreamProcessor.java b/lib3270j/src/main/java/haus/nightmare/lib3270j/datastream/DataStreamProcessor.java index dcf28db..d25a790 100644 --- a/lib3270j/src/main/java/haus/nightmare/lib3270j/datastream/DataStreamProcessor.java +++ b/lib3270j/src/main/java/haus/nightmare/lib3270j/datastream/DataStreamProcessor.java @@ -548,6 +548,8 @@ public class DataStreamProcessor { applyExtendedAttribute(ea, attrType, attrValue); } } + baddr = (baddr + 1) % size; + screen.setBufferAddress(baddr); pos += 2 + nPairs * 2; lastWasOrder = true; break; diff --git a/lib3270j/src/test/java/haus/nightmare/lib3270j/datastream/DataStreamProcessorTest.java b/lib3270j/src/test/java/haus/nightmare/lib3270j/datastream/DataStreamProcessorTest.java index 7482ccb..9b8da4d 100644 --- a/lib3270j/src/test/java/haus/nightmare/lib3270j/datastream/DataStreamProcessorTest.java +++ b/lib3270j/src/test/java/haus/nightmare/lib3270j/datastream/DataStreamProcessorTest.java @@ -198,4 +198,77 @@ public class DataStreamProcessorTest { processor.processRecord(ewStream.toByteArray(), 0, ewStream.size(), true); assertEquals((byte) 0, screen.getCell(0).fg); } + + @Test + public void testModifyFieldAdvancesBufferAddressAndPreservesFieldAttributes() throws java.io.IOException { + // Step 1: Initialize screen with an Erase/Write defining two fields + java.io.ByteArrayOutputStream initStream = new java.io.ByteArrayOutputStream(); + initStream.write(CMD_EW); + initStream.write(0xC3); + // Field 1 at pos 0: SFE with FA_PRINTABLE, text "ABC" + initStream.write(ORDER_SBA); + initStream.write(0x40); initStream.write(0x40); // pos 0 + initStream.write(ORDER_SFE); + initStream.write(0x01); // 1 pair + initStream.write(XA_3270); + initStream.write(FA_PRINTABLE); + initStream.write(translator.stringToEbcdic("ABC")); + + // Field 2 at pos 10: SFE with FA_PRINTABLE, text "XYZ" + initStream.write(ORDER_SBA); + byte[] addr10 = encodeAddress(10, screen.getRows(), screen.getCols()); + initStream.write(addr10); + initStream.write(ORDER_SFE); + initStream.write(0x01); + initStream.write(XA_3270); + initStream.write(FA_PRINTABLE); + initStream.write(translator.stringToEbcdic("XYZ")); + + processor.processRecord(initStream.toByteArray(), 0, initStream.size(), true); + + assertTrue(screen.getCell(0).isFieldAttribute()); + assertEquals('A', screen.getCell(1).ucs4); + assertTrue(screen.getCell(10).isFieldAttribute()); + assertEquals('X', screen.getCell(11).ucs4); + + // Step 2: Issue a Write command that uses ORDER_MF on Field 1 and Field 2 + java.io.ByteArrayOutputStream updateStream = new java.io.ByteArrayOutputStream(); + updateStream.write(CMD_W); + updateStream.write(0xC1); + // SBA to pos 0 + updateStream.write(ORDER_SBA); + updateStream.write(0x40); updateStream.write(0x40); + // MF on pos 0: set foreground to green (0xF4) + updateStream.write(ORDER_MF); + updateStream.write(0x01); // 1 pair + updateStream.write(XA_FOREGROUND); + updateStream.write(0xF4); + // Data "123" following MF directly + updateStream.write(translator.stringToEbcdic("123")); + + // MF on pos 10 + updateStream.write(ORDER_SBA); + updateStream.write(addr10); + updateStream.write(ORDER_MF); + updateStream.write(0x01); + updateStream.write(XA_FOREGROUND); + updateStream.write(0xF5); // turquoise + updateStream.write(translator.stringToEbcdic("789")); + + processor.processRecord(updateStream.toByteArray(), 0, updateStream.size(), false); + + // Verify Field 1: pos 0 MUST still be a field attribute, NOT overwritten by '1' + assertTrue(screen.getCell(0).isFieldAttribute(), "Position 0 must remain a field attribute"); + assertEquals((byte) 0xF4, screen.getCell(0).fg, "Position 0 field attribute must have updated fg"); + assertEquals('1', screen.getCell(1).ucs4, "Data must start at pos 1, not overwrite pos 0"); + assertEquals('2', screen.getCell(2).ucs4); + assertEquals('3', screen.getCell(3).ucs4); + + // Verify Field 2: pos 10 MUST still be a field attribute, NOT overwritten by '7' + assertTrue(screen.getCell(10).isFieldAttribute(), "Position 10 must remain a field attribute"); + assertEquals((byte) 0xF5, screen.getCell(10).fg, "Position 10 field attribute must have updated fg"); + assertEquals('7', screen.getCell(11).ucs4, "Data must start at pos 11, not overwrite pos 10"); + assertEquals('8', screen.getCell(12).ucs4); + assertEquals('9', screen.getCell(13).ucs4); + } }