Rearrange settings, update sample config
Build and Test j3270 / Build JAR & Run Tests (Java 11) (push) Successful in 1m8s
Build and Test j3270 / Build JAR & Run Tests (Java 21) (push) Successful in 1m15s
Build and Test j3270 / Build JAR & Run Tests (Java 17) (push) Successful in 1m38s
Release j3270 / Build & Publish Release (push) Successful in 1m13s
Build and Test j3270 / Build JAR & Run Tests (Java 11) (push) Successful in 1m8s
Build and Test j3270 / Build JAR & Run Tests (Java 21) (push) Successful in 1m15s
Build and Test j3270 / Build JAR & Run Tests (Java 17) (push) Successful in 1m38s
Release j3270 / Build & Publish Release (push) Successful in 1m13s
This commit is contained in:
@@ -546,6 +546,29 @@ public class ECLPS implements ECLConstants {
|
||||
|
||||
private boolean enablePasteFromExcel = true;
|
||||
private boolean pasteStopAtProtectedLine = false;
|
||||
private boolean blockPaste = true;
|
||||
|
||||
public boolean isBlockPaste() {
|
||||
if (session != null && session.getProperties() != null) {
|
||||
String p = session.getProperties().getProperty(ECLSession.BLOCK_PASTE);
|
||||
if (p != null) return Boolean.parseBoolean(p);
|
||||
}
|
||||
return blockPaste;
|
||||
}
|
||||
|
||||
public boolean IsBlockPaste() { return isBlockPaste(); }
|
||||
|
||||
public void setBlockPaste(boolean val) {
|
||||
this.blockPaste = val;
|
||||
if (session != null && session.getProperties() != null) {
|
||||
session.getProperties().setProperty(ECLSession.BLOCK_PASTE, String.valueOf(val));
|
||||
}
|
||||
if (inputProcessor != null) {
|
||||
inputProcessor.setBlockPaste(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBlockPaste(boolean val) { setBlockPaste(val); }
|
||||
|
||||
public boolean isEnablePasteFromExcel() {
|
||||
if (session != null && session.getProperties() != null) {
|
||||
@@ -591,7 +614,7 @@ public class ECLPS implements ECLConstants {
|
||||
setCursorPos(row, col);
|
||||
}
|
||||
if (inputProcessor != null) {
|
||||
return inputProcessor.pasteText(text, true, isPasteStopAtProtectedLine());
|
||||
return inputProcessor.pasteText(text, true, isPasteStopAtProtectedLine(), isBlockPaste());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -605,9 +628,9 @@ public class ECLPS implements ECLConstants {
|
||||
*/
|
||||
public synchronized int pasteString(String text, int row, int col) {
|
||||
if (text == null || text.isEmpty() || screen == null) return 0;
|
||||
if (inputProcessor != null && (text.contains("\t") || isEnablePasteFromExcel() || isPasteStopAtProtectedLine())) {
|
||||
if (inputProcessor != null && (text.contains("\t") || isEnablePasteFromExcel() || isPasteStopAtProtectedLine() || isBlockPaste())) {
|
||||
setCursorPos(row, col);
|
||||
return inputProcessor.pasteText(text, isEnablePasteFromExcel(), isPasteStopAtProtectedLine());
|
||||
return inputProcessor.pasteText(text, isEnablePasteFromExcel(), isPasteStopAtProtectedLine(), isBlockPaste());
|
||||
}
|
||||
int rows = screen.getRows();
|
||||
int cols = screen.getCols();
|
||||
|
||||
@@ -38,6 +38,7 @@ public class ECLSession {
|
||||
public static final String ENABLE_PASTE_FROM_EXCEL = "enablePasteFromExcel";
|
||||
public static final String PASTE_TAB_OPTIONS = "pasteTabOptions";
|
||||
public static final String PASTE_STOP_AT_PROTECTED_LINE = "pasteStopAtProtectedLine";
|
||||
public static final String BLOCK_PASTE = "blockPaste";
|
||||
public static final String PASTE_FIELD_WRAP = "pasteFieldWrap";
|
||||
public static final String PASTE_LINE_WRAP = "pasteLineWrap";
|
||||
public static final String ENTRYASSIST_DOCMODE = "EntryAssist_DOCmode";
|
||||
|
||||
@@ -137,6 +137,10 @@ public class InputProcessor {
|
||||
private boolean aplKeyboardMode = false;
|
||||
private boolean numericFieldLock = true;
|
||||
private boolean autoSkipEnabled = true;
|
||||
private boolean blockPaste = true;
|
||||
|
||||
public boolean isBlockPaste() { return blockPaste; }
|
||||
public void setBlockPaste(boolean val) { this.blockPaste = val; }
|
||||
|
||||
public void setBellListener(BellListener listener) { this.bellListener = listener; }
|
||||
public BellListener getBellListener() { return bellListener; }
|
||||
@@ -446,6 +450,19 @@ public class InputProcessor {
|
||||
* @return number of characters pasted
|
||||
*/
|
||||
public int pasteText(String text, boolean enablePasteFromExcel, boolean pasteStopAtProtectedLine) {
|
||||
return pasteText(text, enablePasteFromExcel, pasteStopAtProtectedLine, this.blockPaste);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pastes text onto the screen with tabular, boundary, and block alignment controls.
|
||||
*
|
||||
* @param text text to paste
|
||||
* @param enablePasteFromExcel whether to parse tabs as field advances and newlines as row advances
|
||||
* @param pasteStopAtProtectedLine whether to halt paste when encountering protected boundaries
|
||||
* @param blockPaste whether newlines align each line with the initial starting cursor column
|
||||
* @return number of characters pasted
|
||||
*/
|
||||
public int pasteText(String text, boolean enablePasteFromExcel, boolean pasteStopAtProtectedLine, boolean blockPaste) {
|
||||
if (text == null || text.isEmpty() || screen == null || keyboardLocked) {
|
||||
return 0;
|
||||
}
|
||||
@@ -463,6 +480,7 @@ public class InputProcessor {
|
||||
int count = 0;
|
||||
int len = text.length();
|
||||
int i = 0;
|
||||
int startCol = screen.getCursorCol();
|
||||
|
||||
while (i < len && !keyboardLocked) {
|
||||
char ch = text.charAt(i);
|
||||
@@ -472,7 +490,34 @@ public class InputProcessor {
|
||||
if (ch == '\r' && (i + 1) < len && text.charAt(i + 1) == '\n') {
|
||||
i++; // skip \n of \r\n
|
||||
}
|
||||
if (enablePasteFromExcel) {
|
||||
if (blockPaste) {
|
||||
int curRow = screen.getCursorRow();
|
||||
int nextRow = (curRow + 1) % screen.getRows();
|
||||
if (pasteStopAtProtectedLine && isLineProtected(nextRow)) {
|
||||
break; // Stop paste when next line is protected
|
||||
}
|
||||
int cols = screen.getCols();
|
||||
int rows = screen.getRows();
|
||||
int targetAddr = nextRow * cols + startCol;
|
||||
if (screen.isFormatted()) {
|
||||
int size = rows * cols;
|
||||
ExtendedAttribute ea = screen.getCell(targetAddr);
|
||||
if (ea.isFieldAttribute()) {
|
||||
targetAddr = (targetAddr + 1) % size;
|
||||
}
|
||||
byte faVal = screen.getFieldAttributeAt(targetAddr);
|
||||
if (faIsProtected(faVal & 0xFF)) {
|
||||
if (pasteStopAtProtectedLine) {
|
||||
break;
|
||||
} else {
|
||||
targetAddr = screen.findNextUnprotected(targetAddr == 0 ? (size - 1) : (targetAddr - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
screen.setCursorAddress(targetAddr);
|
||||
screen.markAllChanged();
|
||||
screen.updateDisplaySnapshot();
|
||||
} else if (enablePasteFromExcel) {
|
||||
int curRow = screen.getCursorRow();
|
||||
int nextRow = (curRow + 1) % screen.getRows();
|
||||
if (pasteStopAtProtectedLine && isLineProtected(nextRow)) {
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package haus.nightmare.lib3270j.input;
|
||||
|
||||
import haus.nightmare.lib3270j.TerminalModel;
|
||||
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
|
||||
import haus.nightmare.lib3270j.ecl.ECLPS;
|
||||
import haus.nightmare.lib3270j.screen.ScreenBuffer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static haus.nightmare.lib3270j.protocol.DS3270Constants.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for the "Block paste" feature.
|
||||
* Ensures that multi-line pastes maintain column alignment with the initial start column
|
||||
* when blockPaste is active (the default), and revert to standard 3270 Newline field advance
|
||||
* when blockPaste is disabled.
|
||||
*/
|
||||
public class BlockPasteTest {
|
||||
|
||||
private ScreenBuffer screen;
|
||||
private EbcdicTranslator translator;
|
||||
private InputProcessor input;
|
||||
private ECLPS ps;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
translator = new EbcdicTranslator();
|
||||
screen = new ScreenBuffer(TerminalModel.IBM_3278_2, translator);
|
||||
input = new InputProcessor(screen, translator, null);
|
||||
ps = new ECLPS(screen, input, translator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockPasteDefaultsToTrue() {
|
||||
assertTrue(input.isBlockPaste(), "InputProcessor blockPaste should default to true");
|
||||
assertTrue(ps.isBlockPaste(), "ECLPS blockPaste should default to true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockPasteAlignsStartColumnInUnformattedScreen() {
|
||||
screen.erase(false);
|
||||
// Start cursor at row 0, column 15
|
||||
int startPos = screen.rowColToAddress(0, 15);
|
||||
screen.setCursorAddress(startPos);
|
||||
|
||||
String multilineText = "FIRST\nSECOND\nTHIRD";
|
||||
int pasted = input.pasteText(multilineText, true, false, true);
|
||||
assertEquals(16, pasted);
|
||||
|
||||
// Verify row 0, col 15-19 has "FIRST"
|
||||
assertEquals("FIRST", ps.getString(startPos, 5));
|
||||
|
||||
// Verify row 1, col 15-20 has "SECOND"
|
||||
int row1Col15 = screen.rowColToAddress(1, 15);
|
||||
assertEquals("SECOND", ps.getString(row1Col15, 6));
|
||||
|
||||
// Verify row 2, col 15-19 has "THIRD"
|
||||
int row2Col15 = screen.rowColToAddress(2, 15);
|
||||
assertEquals("THIRD", ps.getString(row2Col15, 5));
|
||||
|
||||
// Verify start of row 1 (cols 0-5) did NOT receive the paste
|
||||
int row1Col0 = screen.rowColToAddress(1, 0);
|
||||
assertNotEquals("SECOND", ps.getString(row1Col0, 6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockPasteAlignsStartColumnInFormattedScreen() {
|
||||
screen.erase(false);
|
||||
// Set up 3 rows each with an unprotected field starting at col 0 (FA at 0, 80, 160)
|
||||
screen.setFieldAttribute(0, (byte) FA_PRINTABLE);
|
||||
screen.setFieldAttribute(80, (byte) FA_PRINTABLE);
|
||||
screen.setFieldAttribute(160, (byte) FA_PRINTABLE);
|
||||
|
||||
// Start pasting at Row 0, Col 25
|
||||
int startPos = screen.rowColToAddress(0, 25);
|
||||
screen.setCursorAddress(startPos);
|
||||
|
||||
String multilineText = "ALPHA\r\nBETA\r\nGAMMA";
|
||||
int pasted = input.pasteText(multilineText, true, false, true);
|
||||
assertEquals(14, pasted);
|
||||
|
||||
assertEquals("ALPHA", ps.getString(screen.rowColToAddress(0, 25), 5));
|
||||
assertEquals("BETA", ps.getString(screen.rowColToAddress(1, 25), 4));
|
||||
assertEquals("GAMMA", ps.getString(screen.rowColToAddress(2, 25), 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisabledBlockPasteRevertsToFirstUnprotectedField() {
|
||||
screen.erase(false);
|
||||
// Row 0: FA at 0 (unprotected col 1-79)
|
||||
// Row 1: FA at 80 (unprotected col 1-79)
|
||||
screen.setFieldAttribute(0, (byte) FA_PRINTABLE);
|
||||
screen.setFieldAttribute(80, (byte) FA_PRINTABLE);
|
||||
|
||||
// Start pasting at Row 0, Col 25
|
||||
int startPos = screen.rowColToAddress(0, 25);
|
||||
screen.setCursorAddress(startPos);
|
||||
|
||||
// blockPaste = false: newline should advance to first unprotected field on next row (pos 81 / col 1)
|
||||
String multilineText = "LINE1\nLINE2";
|
||||
input.pasteText(multilineText, true, false, false);
|
||||
|
||||
assertEquals("LINE1", ps.getString(screen.rowColToAddress(0, 25), 5));
|
||||
// LINE2 must be at row 1, col 1 (pos 81) rather than col 25
|
||||
assertEquals("LINE2", ps.getString(81, 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockPasteStopAtProtectedBoundary() {
|
||||
screen.erase(false);
|
||||
// Row 0: unprotected field at pos 0
|
||||
screen.setFieldAttribute(0, (byte) FA_PRINTABLE);
|
||||
// Row 1: entirely protected row
|
||||
screen.setFieldAttribute(80, (byte) (FA_PRINTABLE | FA_PROTECT));
|
||||
|
||||
int startPos = screen.rowColToAddress(0, 10);
|
||||
screen.setCursorAddress(startPos);
|
||||
|
||||
// pasteStopAtProtectedLine = true
|
||||
String multilineText = "ROW0\nROW1";
|
||||
int pasted = input.pasteText(multilineText, true, true, true);
|
||||
|
||||
// Should paste "ROW0" (4 chars) and halt when row 1 is protected
|
||||
assertEquals(4, pasted);
|
||||
assertEquals("ROW0", ps.getString(startPos, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEclPsPasteStringHonorsBlockPaste() {
|
||||
screen.erase(false);
|
||||
screen.setFieldAttribute(0, (byte) FA_PRINTABLE);
|
||||
screen.setFieldAttribute(80, (byte) FA_PRINTABLE);
|
||||
|
||||
ps.setBlockPaste(true);
|
||||
assertTrue(ps.isBlockPaste());
|
||||
|
||||
int pasted = ps.pasteString("DATA1\nDATA2", 0, 12);
|
||||
assertEquals(10, pasted);
|
||||
|
||||
assertEquals("DATA1", ps.getString(screen.rowColToAddress(0, 12), 5));
|
||||
assertEquals("DATA2", ps.getString(screen.rowColToAddress(1, 12), 5));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user