This commit is contained in:
@@ -662,8 +662,15 @@ public class DataStreamProcessor {
|
|||||||
|
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
|
||||||
|
int aid = (inputProcessor != null && inputProcessor.getLastAid() != 0)
|
||||||
|
? inputProcessor.getLastAid()
|
||||||
|
: AID_NO;
|
||||||
|
if (inputProcessor != null) {
|
||||||
|
inputProcessor.setLastAid(AID_NO);
|
||||||
|
}
|
||||||
|
|
||||||
// AID byte
|
// AID byte
|
||||||
outputWrite(AID_NO);
|
outputWrite(aid);
|
||||||
// Cursor address
|
// Cursor address
|
||||||
byte[] caddr = encodeAddress(screen.getCursorAddress(), screen.getRows(), screen.getCols());
|
byte[] caddr = encodeAddress(screen.getCursorAddress(), screen.getRows(), screen.getCols());
|
||||||
outputWrite(caddr[0] & 0xFF);
|
outputWrite(caddr[0] & 0xFF);
|
||||||
@@ -710,56 +717,36 @@ public class DataStreamProcessor {
|
|||||||
outputWrite(caddr[1] & 0xFF);
|
outputWrite(caddr[1] & 0xFF);
|
||||||
|
|
||||||
if (!screen.isFormatted()) {
|
if (!screen.isFormatted()) {
|
||||||
// Unformatted screen: send data up to last non-null
|
// Unformatted screen: send all non-null characters (null suppression)
|
||||||
int lastNonNull = -1;
|
for (int i = 0; i < size; i++) {
|
||||||
for (int i = size - 1; i >= 0; i--) {
|
int b = screen.getCell(i).ec & 0xFF;
|
||||||
if (screen.getCell(i).ec != 0) {
|
if (b != 0x00) {
|
||||||
lastNonNull = i;
|
outputWrite(b);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lastNonNull >= 0) {
|
|
||||||
for (int i = 0; i <= lastNonNull; i++) {
|
|
||||||
int b = screen.getCell(i).ec & 0xFF;
|
|
||||||
outputWrite(b != 0 ? b : 0x40);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Formatted screen: send modified fields with trailing NULLs stripped
|
// Formatted screen: send modified fields with null suppression per 3270 spec
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
ExtendedAttribute ea = screen.getCell(i);
|
ExtendedAttribute ea = screen.getCell(i);
|
||||||
if (ea.isFieldAttribute() && (all || faIsModified(ea.fa & 0xFF))) {
|
if (ea.isFieldAttribute() && (all || faIsModified(ea.fa & 0xFF))) {
|
||||||
int fieldStart = (i + 1) % size;
|
int fieldStart = (i + 1) % size;
|
||||||
|
|
||||||
// Collect field data and find last non-null byte
|
// Always send SBA and address of first character position in field
|
||||||
ByteArrayOutputStream fieldData = new ByteArrayOutputStream();
|
|
||||||
int pos = fieldStart;
|
|
||||||
int lastNonNull = -1;
|
|
||||||
int fieldLen = 0;
|
|
||||||
while (!screen.getCell(pos).isFieldAttribute()) {
|
|
||||||
int b = screen.getCell(pos).ec & 0xFF;
|
|
||||||
fieldData.write(b);
|
|
||||||
if (b != 0x00) {
|
|
||||||
lastNonNull = fieldLen;
|
|
||||||
}
|
|
||||||
fieldLen++;
|
|
||||||
pos = (pos + 1) % size;
|
|
||||||
if (pos == fieldStart)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always send SBA and address
|
|
||||||
outputWrite(ORDER_SBA);
|
outputWrite(ORDER_SBA);
|
||||||
byte[] addr = encodeAddress(fieldStart, screen.getRows(), screen.getCols());
|
byte[] addr = encodeAddress(fieldStart, screen.getRows(), screen.getCols());
|
||||||
outputWrite(addr[0] & 0xFF);
|
outputWrite(addr[0] & 0xFF);
|
||||||
outputWrite(addr[1] & 0xFF);
|
outputWrite(addr[1] & 0xFF);
|
||||||
|
|
||||||
// Send field data (strip trailing nulls)
|
// Send all non-null characters in field (suppressing 0x00)
|
||||||
if (lastNonNull >= 0) {
|
int pos = fieldStart;
|
||||||
byte[] allData = fieldData.toByteArray();
|
while (!screen.getCell(pos).isFieldAttribute()) {
|
||||||
for (int k = 0; k <= lastNonNull; k++) {
|
int b = screen.getCell(pos).ec & 0xFF;
|
||||||
outputWrite(allData[k] & 0xFF);
|
if (b != 0x00) {
|
||||||
|
outputWrite(b);
|
||||||
}
|
}
|
||||||
|
pos = (pos + 1) % size;
|
||||||
|
if (pos == fieldStart)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,8 +95,10 @@ public class InputProcessor {
|
|||||||
public void typeCharacter(char ch) {
|
public void typeCharacter(char ch) {
|
||||||
if (keyboardLocked) return;
|
if (keyboardLocked) return;
|
||||||
|
|
||||||
int baddr = screen.getCursorAddress();
|
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
if (size <= 0) return;
|
||||||
|
int baddr = screen.getCursorAddress();
|
||||||
|
baddr = ((baddr % size) + size) % size;
|
||||||
|
|
||||||
// Check if cursor is at a field attribute or in a protected field
|
// Check if cursor is at a field attribute or in a protected field
|
||||||
ExtendedAttribute ea = screen.getCell(baddr);
|
ExtendedAttribute ea = screen.getCell(baddr);
|
||||||
@@ -120,8 +122,10 @@ public class InputProcessor {
|
|||||||
// Insert mode: shift characters right from cursor to end of field
|
// Insert mode: shift characters right from cursor to end of field
|
||||||
// Find end of field
|
// Find end of field
|
||||||
int endAddr = baddr;
|
int endAddr = baddr;
|
||||||
while (!screen.getCell(screen.incrementAddress(endAddr)).isFieldAttribute()) {
|
int count = 0;
|
||||||
|
while (!screen.getCell(screen.incrementAddress(endAddr)).isFieldAttribute() && count < size) {
|
||||||
endAddr = screen.incrementAddress(endAddr);
|
endAddr = screen.incrementAddress(endAddr);
|
||||||
|
count++;
|
||||||
if (endAddr == baddr) break; // wrapped around (unformatted)
|
if (endAddr == baddr) break; // wrapped around (unformatted)
|
||||||
}
|
}
|
||||||
// Check if last position is non-null (field overflow)
|
// Check if last position is non-null (field overflow)
|
||||||
@@ -131,11 +135,13 @@ public class InputProcessor {
|
|||||||
}
|
}
|
||||||
// Shift right from endAddr-1 down to baddr
|
// Shift right from endAddr-1 down to baddr
|
||||||
int dst = endAddr;
|
int dst = endAddr;
|
||||||
while (dst != baddr) {
|
int shiftCount = 0;
|
||||||
|
while (dst != baddr && shiftCount < size) {
|
||||||
int src = screen.decrementAddress(dst);
|
int src = screen.decrementAddress(dst);
|
||||||
screen.getCell(dst).ec = screen.getCell(src).ec;
|
screen.getCell(dst).ec = screen.getCell(src).ec;
|
||||||
screen.getCell(dst).ucs4 = screen.getCell(src).ucs4;
|
screen.getCell(dst).ucs4 = screen.getCell(src).ucs4;
|
||||||
dst = src;
|
dst = src;
|
||||||
|
shiftCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +161,11 @@ public class InputProcessor {
|
|||||||
// Advance cursor
|
// Advance cursor
|
||||||
int startAdvance = baddr;
|
int startAdvance = baddr;
|
||||||
baddr = (baddr + 1) % size;
|
baddr = (baddr + 1) % size;
|
||||||
|
int advCount = 0;
|
||||||
// Skip over field attributes safely
|
// Skip over field attributes safely
|
||||||
while (screen.getCell(baddr).isFieldAttribute() && baddr != startAdvance) {
|
while (screen.getCell(baddr).isFieldAttribute() && baddr != startAdvance && advCount < size) {
|
||||||
baddr = (baddr + 1) % size;
|
baddr = (baddr + 1) % size;
|
||||||
|
advCount++;
|
||||||
}
|
}
|
||||||
screen.setCursorAddress(baddr);
|
screen.setCursorAddress(baddr);
|
||||||
screen.markAllChanged();
|
screen.markAllChanged();
|
||||||
@@ -247,39 +255,28 @@ public class InputProcessor {
|
|||||||
|
|
||||||
if (screen.isFormatted()) {
|
if (screen.isFormatted()) {
|
||||||
// Send modified fields with SBA
|
// Send modified fields with SBA
|
||||||
// Per 3270 Data Stream Architecture: strip trailing NULLs (0x00) from field data
|
// Per 3270 Data Stream Architecture: suppress NULLs (0x00) from field data
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
ExtendedAttribute ea = screen.getCell(i);
|
ExtendedAttribute ea = screen.getCell(i);
|
||||||
if (ea.isFieldAttribute() && faIsModified(ea.fa & 0xFF)) {
|
if (ea.isFieldAttribute() && faIsModified(ea.fa & 0xFF)) {
|
||||||
int fieldStart = (i + 1) % size;
|
int fieldStart = (i + 1) % size;
|
||||||
|
|
||||||
// First, collect field data and find last non-null byte
|
// Always send SBA and address of first character in field
|
||||||
ByteArrayOutputStream fieldData = new ByteArrayOutputStream();
|
|
||||||
int pos = fieldStart;
|
|
||||||
int lastNonNull = -1;
|
|
||||||
int fieldLen = 0;
|
|
||||||
while (!screen.getCell(pos).isFieldAttribute()) {
|
|
||||||
int b = screen.getCell(pos).ec & 0xFF;
|
|
||||||
fieldData.write(b);
|
|
||||||
if (b != 0x00) {
|
|
||||||
lastNonNull = fieldLen;
|
|
||||||
}
|
|
||||||
fieldLen++;
|
|
||||||
pos = (pos + 1) % size;
|
|
||||||
if (pos == fieldStart) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always send SBA and address
|
|
||||||
out.write(ORDER_SBA);
|
out.write(ORDER_SBA);
|
||||||
byte[] addr = encodeAddress(fieldStart, screen.getRows(), screen.getCols());
|
byte[] addr = encodeAddress(fieldStart, screen.getRows(), screen.getCols());
|
||||||
out.write(addr[0] & 0xFF);
|
out.write(addr[0] & 0xFF);
|
||||||
out.write(addr[1] & 0xFF);
|
out.write(addr[1] & 0xFF);
|
||||||
|
|
||||||
// Only send data if there is any (strip trailing nulls)
|
// Send all non-null characters in field (suppressing 0x00)
|
||||||
if (lastNonNull >= 0) {
|
int pos = fieldStart;
|
||||||
byte[] allData = fieldData.toByteArray();
|
while (!screen.getCell(pos).isFieldAttribute()) {
|
||||||
out.write(allData, 0, lastNonNull + 1);
|
int b = screen.getCell(pos).ec & 0xFF;
|
||||||
|
if (b != 0x00) {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
pos = (pos + 1) % size;
|
||||||
|
if (pos == fieldStart) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,6 +356,8 @@ public class InputProcessor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
if (size <= 0) return false;
|
||||||
|
address = ((address % size) + size) % size;
|
||||||
int faPos = screen.findFieldAttribute(address);
|
int faPos = screen.findFieldAttribute(address);
|
||||||
if (faPos < 0) {
|
if (faPos < 0) {
|
||||||
System.out.println("LP: no FA found for addr=" + address);
|
System.out.println("LP: no FA found for addr=" + address);
|
||||||
@@ -461,11 +460,14 @@ public class InputProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void backTab() {
|
public void backTab() {
|
||||||
// Find previous unprotected field
|
if (!screen.isFormatted()) return;
|
||||||
int addr = screen.getCursorAddress();
|
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
if (size <= 0) return;
|
||||||
|
int addr = screen.getCursorAddress();
|
||||||
|
addr = ((addr % size) + size) % size;
|
||||||
int start = screen.decrementAddress(addr);
|
int start = screen.decrementAddress(addr);
|
||||||
addr = start;
|
addr = start;
|
||||||
|
int count = 0;
|
||||||
do {
|
do {
|
||||||
addr = screen.decrementAddress(addr);
|
addr = screen.decrementAddress(addr);
|
||||||
if (screen.getCell(addr).isFieldAttribute()) {
|
if (screen.getCell(addr).isFieldAttribute()) {
|
||||||
@@ -475,7 +477,8 @@ public class InputProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (addr != start);
|
count++;
|
||||||
|
} while (addr != start && count < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eraseEof() {
|
public void eraseEof() {
|
||||||
@@ -493,15 +496,19 @@ public class InputProcessor {
|
|||||||
}
|
}
|
||||||
int addr = screen.getCursorAddress();
|
int addr = screen.getCursorAddress();
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
if (size <= 0) return;
|
||||||
|
addr = ((addr % size) + size) % size;
|
||||||
byte faVal = screen.getFieldAttributeAt(addr);
|
byte faVal = screen.getFieldAttributeAt(addr);
|
||||||
if (faIsProtected(faVal & 0xFF)) return;
|
if (faIsProtected(faVal & 0xFF)) return;
|
||||||
|
|
||||||
// Erase from cursor to end of field
|
// Erase from cursor to end of field
|
||||||
while (!screen.getCell(addr).isFieldAttribute()) {
|
int count = 0;
|
||||||
|
while (!screen.getCell(addr).isFieldAttribute() && count < size) {
|
||||||
ExtendedAttribute ea = screen.getCell(addr);
|
ExtendedAttribute ea = screen.getCell(addr);
|
||||||
ea.ec = 0;
|
ea.ec = 0;
|
||||||
ea.ucs4 = 0;
|
ea.ucs4 = 0;
|
||||||
addr = screen.incrementAddress(addr);
|
addr = screen.incrementAddress(addr);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set MDT
|
// Set MDT
|
||||||
@@ -516,13 +523,20 @@ public class InputProcessor {
|
|||||||
public void deleteChar() {
|
public void deleteChar() {
|
||||||
if (!screen.isFormatted()) return;
|
if (!screen.isFormatted()) return;
|
||||||
int addr = screen.getCursorAddress();
|
int addr = screen.getCursorAddress();
|
||||||
|
int size = screen.getRows() * screen.getCols();
|
||||||
|
if (size <= 0) return;
|
||||||
|
addr = ((addr % size) + size) % size;
|
||||||
|
|
||||||
|
// Cannot delete a field attribute
|
||||||
|
if (screen.getCell(addr).isFieldAttribute()) return;
|
||||||
|
|
||||||
byte faVal = screen.getFieldAttributeAt(addr);
|
byte faVal = screen.getFieldAttributeAt(addr);
|
||||||
if (faIsProtected(faVal & 0xFF)) return;
|
if (faIsProtected(faVal & 0xFF)) return;
|
||||||
|
|
||||||
// Shift characters left within the field
|
// Shift characters left within the field
|
||||||
int shiftAddr = addr;
|
int shiftAddr = addr;
|
||||||
int size = screen.getRows() * screen.getCols();
|
int count = 0;
|
||||||
while (true) {
|
while (count < size) {
|
||||||
int next = screen.incrementAddress(shiftAddr);
|
int next = screen.incrementAddress(shiftAddr);
|
||||||
if (screen.getCell(next).isFieldAttribute()) {
|
if (screen.getCell(next).isFieldAttribute()) {
|
||||||
screen.getCell(shiftAddr).ec = 0;
|
screen.getCell(shiftAddr).ec = 0;
|
||||||
@@ -532,6 +546,7 @@ public class InputProcessor {
|
|||||||
screen.getCell(shiftAddr).ec = screen.getCell(next).ec;
|
screen.getCell(shiftAddr).ec = screen.getCell(next).ec;
|
||||||
screen.getCell(shiftAddr).ucs4 = screen.getCell(next).ucs4;
|
screen.getCell(shiftAddr).ucs4 = screen.getCell(next).ucs4;
|
||||||
shiftAddr = next;
|
shiftAddr = next;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int faAddr = screen.findFieldAttribute(addr);
|
int faAddr = screen.findFieldAttribute(addr);
|
||||||
@@ -543,8 +558,19 @@ public class InputProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void backspace() {
|
public void backspace() {
|
||||||
if (screen.getCursorAddress() == 0) return;
|
int addr = screen.getCursorAddress();
|
||||||
cursorLeft();
|
int prev = screen.decrementAddress(addr);
|
||||||
|
if (screen.isFormatted()) {
|
||||||
|
// If previous position is a field attribute or in protected field, do not back up over it
|
||||||
|
if (screen.getCell(prev).isFieldAttribute()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte faVal = screen.getFieldAttributeAt(prev);
|
||||||
|
if (faIsProtected(faVal & 0xFF)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
screen.setCursorAddress(prev);
|
||||||
deleteChar();
|
deleteChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,11 +741,13 @@ public class InputProcessor {
|
|||||||
int fieldLen = 0;
|
int fieldLen = 0;
|
||||||
int pos = fieldStart;
|
int pos = fieldStart;
|
||||||
int size = screen.getRows() * screen.getCols();
|
int size = screen.getRows() * screen.getCols();
|
||||||
while (!screen.getCell(pos).isFieldAttribute()) {
|
int count = 0;
|
||||||
|
while (!screen.getCell(pos).isFieldAttribute() && count < size) {
|
||||||
screen.getCell(pos).ec = 0;
|
screen.getCell(pos).ec = 0;
|
||||||
screen.getCell(pos).ucs4 = 0;
|
screen.getCell(pos).ucs4 = 0;
|
||||||
fieldLen++;
|
fieldLen++;
|
||||||
pos = screen.incrementAddress(pos);
|
pos = screen.incrementAddress(pos);
|
||||||
|
count++;
|
||||||
if (pos == fieldStart) break;
|
if (pos == fieldStart) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,13 +272,17 @@ public class ScreenBuffer {
|
|||||||
public int findFieldAttribute(int baddr) {
|
public int findFieldAttribute(int baddr) {
|
||||||
if (!formatted) return -1;
|
if (!formatted) return -1;
|
||||||
int size = rows * cols;
|
int size = rows * cols;
|
||||||
|
if (size <= 0) return -1;
|
||||||
|
baddr = ((baddr % size) + size) % size;
|
||||||
int start = baddr;
|
int start = baddr;
|
||||||
|
int count = 0;
|
||||||
do {
|
do {
|
||||||
if (buffer[baddr].isFieldAttribute()) {
|
if (buffer[baddr].isFieldAttribute()) {
|
||||||
return baddr;
|
return baddr;
|
||||||
}
|
}
|
||||||
baddr = (baddr > 0) ? baddr - 1 : size - 1;
|
baddr = (baddr > 0) ? baddr - 1 : size - 1;
|
||||||
} while (baddr != start);
|
count++;
|
||||||
|
} while (baddr != start && count < size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,8 +300,12 @@ public class ScreenBuffer {
|
|||||||
* Returns 0 if none found.
|
* Returns 0 if none found.
|
||||||
*/
|
*/
|
||||||
public int findNextUnprotected(int baddr) {
|
public int findNextUnprotected(int baddr) {
|
||||||
|
if (!formatted) return 0;
|
||||||
int size = rows * cols;
|
int size = rows * cols;
|
||||||
|
if (size <= 0) return 0;
|
||||||
|
baddr = ((baddr % size) + size) % size;
|
||||||
int start = baddr;
|
int start = baddr;
|
||||||
|
int count = 0;
|
||||||
do {
|
do {
|
||||||
int next = (baddr + 1) % size;
|
int next = (baddr + 1) % size;
|
||||||
if (buffer[baddr].isFieldAttribute()
|
if (buffer[baddr].isFieldAttribute()
|
||||||
@@ -306,7 +314,8 @@ public class ScreenBuffer {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
baddr = next;
|
baddr = next;
|
||||||
} while (baddr != start);
|
count++;
|
||||||
|
} while (baddr != start && count < size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,12 +338,17 @@ public class ScreenBuffer {
|
|||||||
|
|
||||||
/** Increment buffer address (wrapping). */
|
/** Increment buffer address (wrapping). */
|
||||||
public int incrementAddress(int addr) {
|
public int incrementAddress(int addr) {
|
||||||
return (addr + 1) % (rows * cols);
|
int size = rows * cols;
|
||||||
|
if (size <= 0) return 0;
|
||||||
|
return ((addr % size) + size + 1) % size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decrement buffer address (wrapping). */
|
/** Decrement buffer address (wrapping). */
|
||||||
public int decrementAddress(int addr) {
|
public int decrementAddress(int addr) {
|
||||||
return (addr > 0) ? addr - 1 : (rows * cols) - 1;
|
int size = rows * cols;
|
||||||
|
if (size <= 0) return 0;
|
||||||
|
int norm = ((addr % size) + size) % size;
|
||||||
|
return (norm > 0) ? norm - 1 : size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert buffer address to row. */
|
/** Convert buffer address to row. */
|
||||||
|
|||||||
@@ -66,4 +66,20 @@ public class DataStreamProcessorTest {
|
|||||||
assertEquals('A', screen.getCell(i).ucs4, "Cell " + i + " should be 'A'");
|
assertEquals('A', screen.getCell(i).ucs4, "Cell " + i + " should be 'A'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadBufferPropagatesLastAid() {
|
||||||
|
org.lib3270j.input.InputProcessor input = new org.lib3270j.input.InputProcessor(screen, translator, null);
|
||||||
|
processor.setInputProcessor(input);
|
||||||
|
input.setLastAid(AID_ENTER);
|
||||||
|
|
||||||
|
java.util.concurrent.atomic.AtomicReference<byte[]> sentData = new java.util.concurrent.atomic.AtomicReference<>();
|
||||||
|
processor.setOutputCallback(sentData::set);
|
||||||
|
|
||||||
|
byte[] rbRecord = new byte[] { (byte) CMD_RB };
|
||||||
|
processor.processRecord(rbRecord, 0, rbRecord.length, true);
|
||||||
|
|
||||||
|
assertNotNull(sentData.get());
|
||||||
|
assertEquals((byte) AID_ENTER, sentData.get()[0], "ReadBuffer must transmit operator's stored AID");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,4 +153,50 @@ public class InputProcessorTest {
|
|||||||
assertEquals((byte) 0xFF, sf[34]);
|
assertEquals((byte) 0xFF, sf[34]);
|
||||||
assertEquals((byte) AID_ENTER, sf[35]);
|
assertEquals((byte) AID_ENTER, sf[35]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendAidSuppressesNullsInModifiedField() {
|
||||||
|
java.util.concurrent.atomic.AtomicReference<byte[]> sent = new java.util.concurrent.atomic.AtomicReference<>();
|
||||||
|
InputProcessor input = new InputProcessor(screen, translator, null) {
|
||||||
|
@Override
|
||||||
|
public void sendAid(int aidCode) {
|
||||||
|
// Call super logic by hooking via fake FSM or overriding sendAid
|
||||||
|
super.sendAid(aidCode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Setup screen: field attribute at 0 (unprotected, modified)
|
||||||
|
screen.erase(false);
|
||||||
|
screen.setCellFA(0, (byte) (FA_PRINTABLE | FA_MODIFY));
|
||||||
|
// Pos 1 = null (0x00)
|
||||||
|
screen.getCell(1).ec = 0x00;
|
||||||
|
// Pos 2 = 'Q' (0xD8)
|
||||||
|
screen.getCell(2).ec = (byte) 0xD8;
|
||||||
|
// Pos 3 = 'U' (0xE4)
|
||||||
|
screen.getCell(3).ec = (byte) 0xE4;
|
||||||
|
// Pos 4 = 'I' (0xC9)
|
||||||
|
screen.getCell(4).ec = (byte) 0xC9;
|
||||||
|
// Pos 5 = 'T' (0xE3)
|
||||||
|
screen.getCell(5).ec = (byte) 0xE3;
|
||||||
|
// Next field at 10 (protected)
|
||||||
|
screen.setCellFA(10, (byte) (FA_PRINTABLE | FA_PROTECT));
|
||||||
|
|
||||||
|
// Use custom callback or inspection
|
||||||
|
// Let's verify DataStreamProcessor ReadModified behavior with the same buffer
|
||||||
|
DataStreamProcessor dsp = new DataStreamProcessor(screen, translator);
|
||||||
|
dsp.setInputProcessor(input);
|
||||||
|
dsp.setOutputCallback(sent::set);
|
||||||
|
|
||||||
|
byte[] rmRecord = new byte[] { (byte) CMD_RM };
|
||||||
|
dsp.processRecord(rmRecord, 0, rmRecord.length, true);
|
||||||
|
|
||||||
|
byte[] result = sent.get();
|
||||||
|
assertNotNull(result);
|
||||||
|
// Result format: AID (1 byte), Cursor (2 bytes), SBA (1 byte), Addr (2 bytes), Data ('Q', 'U', 'I', 'T' - 4 bytes)
|
||||||
|
assertEquals(10, result.length, "Result should be AID(1) + Cursor(2) + SBA(1) + Addr(2) + Data(4)");
|
||||||
|
assertEquals((byte) ORDER_SBA, result[3]);
|
||||||
|
assertEquals((byte) 0xD8, result[6]); // 'Q'
|
||||||
|
assertEquals((byte) 0xE4, result[7]); // 'U'
|
||||||
|
assertEquals((byte) 0xC9, result[8]); // 'I'
|
||||||
|
assertEquals((byte) 0xE3, result[9]); // 'T'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user