Fix Read Modified Query from Moshix bug report
Build and Test j3270 / Build JAR & Run Tests (Java 21) (push) Successful in 42s
Build and Test j3270 / Build JAR & Run Tests (Java 11) (push) Successful in 52s
Build and Test j3270 / Build JAR & Run Tests (Java 17) (push) Successful in 1m42s
Release j3270 / Build & Publish Release (push) Failing after 1m24s
Build and Test j3270 / Build JAR & Run Tests (Java 21) (push) Successful in 42s
Build and Test j3270 / Build JAR & Run Tests (Java 11) (push) Successful in 52s
Build and Test j3270 / Build JAR & Run Tests (Java 17) (push) Successful in 1m42s
Release j3270 / Build & Publish Release (push) Failing after 1m24s
This commit is contained in:
@@ -257,6 +257,9 @@ public class DataStreamProcessor {
|
|||||||
case SNA_CMD_EAU:
|
case SNA_CMD_EAU:
|
||||||
qreplyPending = false;
|
qreplyPending = false;
|
||||||
programSymbolManager.commitStagedSymbols();
|
programSymbolManager.commitStagedSymbols();
|
||||||
|
if (inputProcessor != null) {
|
||||||
|
inputProcessor.setLastAid(AID_NO);
|
||||||
|
}
|
||||||
log.info(">>> EAU: erasing all unprotected fields");
|
log.info(">>> EAU: erasing all unprotected fields");
|
||||||
screen.eraseAllUnprotected();
|
screen.eraseAllUnprotected();
|
||||||
currentFg = 0;
|
currentFg = 0;
|
||||||
@@ -290,6 +293,7 @@ public class DataStreamProcessor {
|
|||||||
cmd == CMD_EWA || cmd == SNA_CMD_EWA);
|
cmd == CMD_EWA || cmd == SNA_CMD_EWA);
|
||||||
if (!isWriteCmd && keyboardRestore && inputProcessor != null && !contentionResolution) {
|
if (!isWriteCmd && keyboardRestore && inputProcessor != null && !contentionResolution) {
|
||||||
inputProcessor.setKeyboardLocked(false);
|
inputProcessor.setKeyboardLocked(false);
|
||||||
|
inputProcessor.setLastAid(AID_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug: dump non-empty screen lines
|
// Debug: dump non-empty screen lines
|
||||||
@@ -389,10 +393,14 @@ public class DataStreamProcessor {
|
|||||||
if (kbdRestore) {
|
if (kbdRestore) {
|
||||||
unlockPending = true;
|
unlockPending = true;
|
||||||
unlockSysPending = true;
|
unlockSysPending = true;
|
||||||
|
if (inputProcessor != null) {
|
||||||
|
inputProcessor.setLastAid(AID_NO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contentionResolution && kbdRestore && inputProcessor != null) {
|
if (!contentionResolution && kbdRestore && inputProcessor != null) {
|
||||||
inputProcessor.setKeyboardLocked(false);
|
inputProcessor.setKeyboardLocked(false);
|
||||||
|
inputProcessor.setLastAid(AID_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resetMdt) {
|
if (resetMdt) {
|
||||||
@@ -1053,7 +1061,7 @@ public class DataStreamProcessor {
|
|||||||
// ========== Read Modified ==========
|
// ========== Read Modified ==========
|
||||||
|
|
||||||
public void processReadModified(boolean all) {
|
public void processReadModified(boolean all) {
|
||||||
int aid = (inputProcessor != null && inputProcessor.getLastAid() != 0)
|
int aid = (inputProcessor != null && inputProcessor.isKeyboardLocked() && inputProcessor.getLastAid() != 0 && inputProcessor.getLastAid() != AID_NO)
|
||||||
? inputProcessor.getLastAid()
|
? inputProcessor.getLastAid()
|
||||||
: AID_NO;
|
: AID_NO;
|
||||||
processReadModified(aid, all);
|
processReadModified(aid, all);
|
||||||
|
|||||||
@@ -129,6 +129,9 @@ public class InputProcessor {
|
|||||||
lockStateListener.onLockStateChanged(locked);
|
lockStateListener.onLockStateChanged(locked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!locked) {
|
||||||
|
this.lastAid = AID_NO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public boolean isInsertMode() { return insertMode; }
|
public boolean isInsertMode() { return insertMode; }
|
||||||
public void setInsertMode(boolean insert) {
|
public void setInsertMode(boolean insert) {
|
||||||
@@ -756,7 +759,7 @@ public class InputProcessor {
|
|||||||
* Build inbound 3270 Read Modified data stream (AID + Cursor + SBA + Modified fields).
|
* Build inbound 3270 Read Modified data stream (AID + Cursor + SBA + Modified fields).
|
||||||
*/
|
*/
|
||||||
public byte[] buildReadModifiedInboundData() {
|
public byte[] buildReadModifiedInboundData() {
|
||||||
return buildReadModifiedInboundData(lastAid != 0 ? lastAid : AID_ENTER, false);
|
return buildReadModifiedInboundData(lastAid != 0 ? lastAid : AID_NO, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1659,6 +1662,7 @@ public class InputProcessor {
|
|||||||
/** Reset (unlock keyboard, cancel insert mode, clear OIA error states). */
|
/** Reset (unlock keyboard, cancel insert mode, clear OIA error states). */
|
||||||
public void reset() {
|
public void reset() {
|
||||||
setKeyboardLocked(false);
|
setKeyboardLocked(false);
|
||||||
|
lastAid = AID_NO;
|
||||||
insertMode = false;
|
insertMode = false;
|
||||||
if (oia != null) {
|
if (oia != null) {
|
||||||
oia.setInputInhibited(ECLConstants.INHIBIT_NOT_INHIBITED);
|
oia.setInputInhibited(ECLConstants.INHIBIT_NOT_INHIBITED);
|
||||||
|
|||||||
+65
@@ -358,4 +358,69 @@ public class DataStreamProcessorTest {
|
|||||||
assertEquals((byte) AID_SF, sent[0], "Query reply header AID must be AID_SF (0x88)");
|
assertEquals((byte) AID_SF, sent[0], "Query reply header AID must be AID_SF (0x88)");
|
||||||
assertFalse(processor.isQreplyPending(), "qreplyPending should be cleared after reply is sent");
|
assertFalse(processor.isQreplyPending(), "qreplyPending should be cleared after reply is sent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandaloneReadModifiedReturnsAidNo() {
|
||||||
|
haus.nightmare.lib3270j.input.InputProcessor input = new haus.nightmare.lib3270j.input.InputProcessor(screen, translator, null);
|
||||||
|
processor.setInputProcessor(input);
|
||||||
|
|
||||||
|
// Simulate operator previously pressing Enter
|
||||||
|
input.setLastAid(AID_ENTER);
|
||||||
|
input.setKeyboardLocked(true);
|
||||||
|
|
||||||
|
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
|
||||||
|
processor.setOutputSender(out::writeBytes);
|
||||||
|
|
||||||
|
// Host responds with Erase/Write Alternate (0x7E) with WCC 0xC3 (kbdRestore=true)
|
||||||
|
byte[] ewa = new byte[] { (byte) SNA_CMD_EWA, (byte) 0xC3 };
|
||||||
|
processor.processRecord(ewa, 0, ewa.length, true);
|
||||||
|
|
||||||
|
assertFalse(input.isKeyboardLocked(), "Keyboard should be restored by WCC");
|
||||||
|
assertEquals(AID_NO, input.getLastAid(), "lastAid should be reset to AID_NO on keyboard restore");
|
||||||
|
|
||||||
|
// Host subsequently polls terminal with standalone Read Modified (0xF6)
|
||||||
|
byte[] rm = new byte[] { (byte) SNA_CMD_RM };
|
||||||
|
out.reset();
|
||||||
|
processor.processRecord(rm, 0, rm.length, true);
|
||||||
|
|
||||||
|
byte[] sent = out.toByteArray();
|
||||||
|
assertTrue(sent.length >= 3, "Read Modified response must contain at least AID and 2-byte cursor address");
|
||||||
|
assertEquals((byte) AID_NO, sent[0], "Standalone Read Modified from host must respond with AID_NO (0x60)");
|
||||||
|
assertFalse(input.isKeyboardLocked(), "Keyboard must remain unlocked after host Read Modified poll");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandaloneReadModifiedWithModifiedFieldSendsDataAndAidNo() {
|
||||||
|
haus.nightmare.lib3270j.input.InputProcessor input = new haus.nightmare.lib3270j.input.InputProcessor(screen, translator, null);
|
||||||
|
processor.setInputProcessor(input);
|
||||||
|
|
||||||
|
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
|
||||||
|
processor.setOutputSender(out::writeBytes);
|
||||||
|
|
||||||
|
// Write a screen with an unprotected field at pos 10, WCC kbdRestore
|
||||||
|
byte[] initStream = new byte[] {
|
||||||
|
(byte) CMD_EW, (byte) 0xC3,
|
||||||
|
(byte) ORDER_SBA, 0x00, 0x0A, // SBA 10
|
||||||
|
(byte) ORDER_SF, (byte) FA_PRINTABLE, // unprotected
|
||||||
|
(byte) 0xC1, (byte) 0xC2 // EBCDIC 'A', 'B'
|
||||||
|
};
|
||||||
|
processor.processRecord(initStream, 0, initStream.length, true);
|
||||||
|
|
||||||
|
// Modify the field by setting MDT (e.g. user typed into it)
|
||||||
|
screen.getCell(10).fa = (byte) (screen.getCell(10).fa | FA_MODIFY);
|
||||||
|
|
||||||
|
// Host polls with 0xF6 (SNA_CMD_RM)
|
||||||
|
out.reset();
|
||||||
|
byte[] rm = new byte[] { (byte) SNA_CMD_RM };
|
||||||
|
processor.processRecord(rm, 0, rm.length, true);
|
||||||
|
|
||||||
|
byte[] sent = out.toByteArray();
|
||||||
|
assertTrue(sent.length > 3, "Should include SBA and field contents for modified field");
|
||||||
|
assertEquals((byte) AID_NO, sent[0], "AID must be AID_NO (0x60)");
|
||||||
|
assertEquals((byte) ORDER_SBA, sent[3], "Order must be SBA");
|
||||||
|
assertEquals((byte) 0xC1, sent[6], "First char should be 'A'");
|
||||||
|
assertEquals((byte) 0xC2, sent[7], "Second char should be 'B'");
|
||||||
|
assertTrue((screen.getCell(10).fa & FA_MODIFY) != 0, "MDT must not be cleared by Read Modified command");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user