How had I not tested on Linux before
Build and Test j3270 / Build JAR & Run Tests (push) Successful in 45s

This commit is contained in:
2026-08-21 21:00:10 -04:00
parent 09600260b5
commit b57d8f960d
10 changed files with 125 additions and 6 deletions
@@ -152,6 +152,7 @@ public class InputProcessor {
}
screen.setCursorAddress(baddr);
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
/**
@@ -206,6 +207,7 @@ public class InputProcessor {
int nextRowAddr = ((row + 1) % screen.getRows()) * cols;
screen.setCursorAddress(nextRowAddr);
screen.markAllChanged();
screen.updateDisplaySnapshot();
setKeyboardLocked(false);
return;
}
@@ -309,6 +311,7 @@ public class InputProcessor {
addr -= screen.getCols();
if (addr < 0) addr += screen.getRows() * screen.getCols();
screen.setCursorAddress(addr);
screen.updateDisplaySnapshot();
}
public void cursorDown() {
@@ -316,18 +319,21 @@ public class InputProcessor {
addr += screen.getCols();
if (addr >= screen.getRows() * screen.getCols()) addr -= screen.getRows() * screen.getCols();
screen.setCursorAddress(addr);
screen.updateDisplaySnapshot();
}
public void cursorLeft() {
int addr = screen.getCursorAddress();
addr = screen.decrementAddress(addr);
screen.setCursorAddress(addr);
screen.updateDisplaySnapshot();
}
public void cursorRight() {
int addr = screen.getCursorAddress();
addr = screen.incrementAddress(addr);
screen.setCursorAddress(addr);
screen.updateDisplaySnapshot();
}
public void cursorHome() {
@@ -336,11 +342,13 @@ public class InputProcessor {
} else {
screen.setCursorAddress(0);
}
screen.updateDisplaySnapshot();
}
public void tab() {
int addr = screen.findNextUnprotected(screen.getCursorAddress());
screen.setCursorAddress(addr);
screen.updateDisplaySnapshot();
}
public int getLastAid() { return lastAid; }
@@ -348,6 +356,7 @@ public class InputProcessor {
public void setCursorAddress(int baddr) {
screen.setCursorAddress(baddr);
screen.updateDisplaySnapshot();
}
public void backTab() {
@@ -361,6 +370,7 @@ public class InputProcessor {
if (screen.getCell(addr).isFieldAttribute()) {
if (!faIsProtected(screen.getCell(addr).fa & 0xFF)) {
screen.setCursorAddress(screen.incrementAddress(addr));
screen.updateDisplaySnapshot();
return;
}
}
@@ -377,6 +387,7 @@ public class InputProcessor {
ea.ucs4 = 0;
}
screen.markAllChanged();
screen.updateDisplaySnapshot();
return;
}
int addr = screen.getCursorAddress();
@@ -398,6 +409,7 @@ public class InputProcessor {
screen.getCell(faAddr).fa = (byte) (screen.getCell(faAddr).fa | FA_MODIFY);
}
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
public void deleteChar() {
@@ -426,6 +438,7 @@ public class InputProcessor {
screen.getCell(faAddr).fa = (byte) (screen.getCell(faAddr).fa | FA_MODIFY);
}
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
public void backspace() {
@@ -439,6 +452,7 @@ public class InputProcessor {
if (keyboardLocked) return;
screen.eraseAllUnprotected();
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
/** Move cursor to first unprotected field on next line (Newline key in 3270). */
@@ -455,6 +469,7 @@ public class InputProcessor {
}
screen.setCursorAddress(target);
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
/** Insert Duplicate (DUP) code and advance to next field. */
@@ -472,6 +487,8 @@ public class InputProcessor {
screen.getCell(faAddr).fa = (byte) (screen.getCell(faAddr).fa | FA_MODIFY);
}
tab();
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
/** Insert Field Mark (FM) code. */
@@ -495,6 +512,7 @@ public class InputProcessor {
}
screen.setCursorAddress(baddr);
screen.markAllChanged();
screen.updateDisplaySnapshot();
}
/** Attention key (sends Telnet IP). */
@@ -571,6 +589,7 @@ public class InputProcessor {
screen.getCell(i).ucs4 = 0;
}
screen.markAllChanged();
screen.updateDisplaySnapshot();
return size;
}
@@ -608,6 +627,7 @@ public class InputProcessor {
screen.getCell(faAddr).fa = (byte) (screen.getCell(faAddr).fa | FA_MODIFY);
}
screen.markAllChanged();
screen.updateDisplaySnapshot();
return fieldLen;
}
@@ -60,6 +60,7 @@ public class ScreenBuffer {
defaultFA.ic = 1;
allocateBuffers();
updateDisplaySnapshot();
}
private void allocateBuffers() {
@@ -139,7 +140,7 @@ public class ScreenBuffer {
public boolean isScreenAlt() { return screenAlt; }
/** Update alternate dimensions from BIND image. Re-allocates buffers if needed. */
public void setAlternateDimensions(int newAltRows, int newAltCols) {
public synchronized void setAlternateDimensions(int newAltRows, int newAltCols) {
if (newAltRows == altRows && newAltCols == altCols) return;
this.altRows = newAltRows;
this.altCols = newAltCols;
@@ -149,11 +150,15 @@ public class ScreenBuffer {
this.maxCols = Math.max(maxCols, newAltCols);
allocateBuffers();
}
updateDisplaySnapshot();
}
// ========== Cursor ==========
public int getCursorAddress() { return cursorAddress; }
public void setCursorAddress(int addr) { this.cursorAddress = addr; }
public synchronized void setCursorAddress(int addr) {
this.cursorAddress = addr;
this.displayCursorAddress = addr;
}
public int getCursorRow() { return cursorAddress / cols; }
public int getCursorCol() { return cursorAddress % cols; }
@@ -168,20 +173,22 @@ public class ScreenBuffer {
/**
* Perform an erase, optionally using the alternate screen size.
*/
public void erase(boolean alt) {
public synchronized void erase(boolean alt) {
clear();
int newRows = alt ? altRows : defRows;
int newCols = alt ? altCols : defCols;
if (alt == screenAlt && rows == newRows && cols == newCols) {
updateDisplaySnapshot();
return;
}
rows = newRows;
cols = newCols;
screenAlt = alt;
updateDisplaySnapshot();
}
/** Clear the entire buffer. */
public void clear() {
public synchronized void clear() {
for (ExtendedAttribute ea : buffer) {
ea.clear();
}
@@ -196,12 +203,13 @@ public class ScreenBuffer {
defaultCs = 0x00;
defaultIc = 0x00;
replyMode = SF_SRM_FIELD;
updateDisplaySnapshot();
}
/**
* Erase all unprotected fields.
*/
public void eraseAllUnprotected() {
public synchronized void eraseAllUnprotected() {
int size = rows * cols;
boolean inUnprotected = false;
@@ -229,6 +237,7 @@ public class ScreenBuffer {
// Move cursor to first unprotected field
cursorAddress = findNextUnprotected(0);
screenChanged = true;
updateDisplaySnapshot();
}
// ========== Field attribute navigation ==========
@@ -322,7 +331,7 @@ public class ScreenBuffer {
// ========== Setters for model reconfiguration ==========
public void setDimensions(int maxRows, int maxCols, int defRows, int defCols,
public synchronized void setDimensions(int maxRows, int maxCols, int defRows, int defCols,
int altRows, int altCols) {
this.maxRows = maxRows;
this.maxCols = maxCols;
@@ -333,6 +342,7 @@ public class ScreenBuffer {
this.rows = defRows;
this.cols = defCols;
allocateBuffers();
updateDisplaySnapshot();
}
public void translateToUnicode() {
@@ -44,10 +44,91 @@ public class InputProcessorTest {
assertEquals('A', screen.getCell(1).ucs4);
assertEquals('B', screen.getCell(2).ucs4);
assertEquals('A', screen.getDisplayCell(1).ucs4);
assertEquals('B', screen.getDisplayCell(2).ucs4);
input.eraseInput();
assertEquals(0, screen.getCell(1).ec);
assertEquals(0, screen.getCell(2).ec);
assertEquals(0, screen.getDisplayCell(1).ec);
assertEquals(0, screen.getDisplayCell(2).ec);
}
@Test
public void testTypeCharacterUpdatesDisplaySnapshot() {
InputProcessor input = new InputProcessor(screen, translator, null);
screen.erase(false);
screen.setCellFA(0, (byte) FA_PRINTABLE); // Unprotected field starting at 1
screen.setCursorAddress(1);
screen.updateDisplaySnapshot(); // Initial snapshot
// Type "logon"
input.typeCharacter('l');
input.typeCharacter('o');
input.typeCharacter('g');
input.typeCharacter('o');
input.typeCharacter('n');
// Verify underlying buffer
assertEquals('l', screen.getCell(1).ucs4);
assertEquals('o', screen.getCell(2).ucs4);
assertEquals('g', screen.getCell(3).ucs4);
assertEquals('o', screen.getCell(4).ucs4);
assertEquals('n', screen.getCell(5).ucs4);
// Verify display snapshot (what TerminalPanel renders)
assertEquals('l', screen.getDisplayCell(1).ucs4);
assertEquals('o', screen.getDisplayCell(2).ucs4);
assertEquals('g', screen.getDisplayCell(3).ucs4);
assertEquals('o', screen.getDisplayCell(4).ucs4);
assertEquals('n', screen.getDisplayCell(5).ucs4);
assertEquals(6, screen.getDisplayCursorAddress());
assertEquals(6, screen.getCursorAddress());
}
@Test
public void testCursorMovementUpdatesDisplayCursorAddress() {
InputProcessor input = new InputProcessor(screen, translator, null);
screen.erase(false);
screen.setCursorAddress(10);
assertEquals(10, screen.getDisplayCursorAddress());
input.cursorRight();
assertEquals(11, screen.getDisplayCursorAddress());
input.cursorLeft();
assertEquals(10, screen.getDisplayCursorAddress());
screen.setCursorAddress(45);
assertEquals(45, screen.getDisplayCursorAddress());
}
@Test
public void testDeleteAndEraseEofUpdateDisplaySnapshot() {
InputProcessor input = new InputProcessor(screen, translator, null);
screen.erase(false);
screen.setCellFA(0, (byte) FA_PRINTABLE);
screen.setCellFA(10, (byte) (FA_PRINTABLE | FA_PROTECT));
screen.setCursorAddress(1);
input.typeCharacter('A');
input.typeCharacter('B');
input.typeCharacter('C');
assertEquals('A', screen.getDisplayCell(1).ucs4);
assertEquals('B', screen.getDisplayCell(2).ucs4);
assertEquals('C', screen.getDisplayCell(3).ucs4);
// Backspace over 'C'
input.backspace();
assertEquals(3, screen.getCursorAddress());
assertEquals(3, screen.getDisplayCursorAddress());
assertEquals(0, screen.getDisplayCell(3).ucs4);
// Erase EOF from position 2 ('B')
screen.setCursorAddress(2);
input.eraseEof();
assertEquals(0, screen.getDisplayCell(2).ucs4);
assertEquals('A', screen.getDisplayCell(1).ucs4);
}
}