Overnight churnings
This commit is contained in:
@@ -40,6 +40,8 @@ public interface ECLConstants {
|
||||
// Search directions
|
||||
int SEARCH_FORWARD = 1;
|
||||
int SEARCH_BACKWARD = 2;
|
||||
int DIR_FORWARD = 1;
|
||||
int DIR_BACKWARD = 2;
|
||||
|
||||
// OIA Input Inhibited Reason Codes
|
||||
int INHIBIT_NOT_INHIBITED = 0;
|
||||
|
||||
@@ -28,35 +28,43 @@ public class ECLField {
|
||||
|
||||
/** Buffer address of the field attribute character. */
|
||||
public int getStart() { return startPos; }
|
||||
public int GetStart() { return getStart(); }
|
||||
|
||||
/** First buffer address of the field data (start + 1). */
|
||||
public int getDataStart() { return dataStart; }
|
||||
public int GetDataStart() { return getDataStart(); }
|
||||
|
||||
/** Last buffer address of the field data inclusive. */
|
||||
public int getEnd() { return endPos; }
|
||||
public int GetEnd() { return getEnd(); }
|
||||
|
||||
/** Number of data characters in the field. */
|
||||
public int getLength() { return length; }
|
||||
public int GetLength() { return getLength(); }
|
||||
|
||||
public int getStartRow() {
|
||||
int cols = ps.getCols();
|
||||
return cols > 0 ? startPos / cols : 0;
|
||||
}
|
||||
public int GetStartRow() { return getStartRow(); }
|
||||
|
||||
public int getStartCol() {
|
||||
int cols = ps.getCols();
|
||||
return cols > 0 ? startPos % cols : 0;
|
||||
}
|
||||
public int GetStartCol() { return getStartCol(); }
|
||||
|
||||
public int getEndRow() {
|
||||
int cols = ps.getCols();
|
||||
return cols > 0 ? endPos / cols : 0;
|
||||
}
|
||||
public int GetEndRow() { return getEndRow(); }
|
||||
|
||||
public int getEndCol() {
|
||||
int cols = ps.getCols();
|
||||
return cols > 0 ? endPos % cols : 0;
|
||||
}
|
||||
public int GetEndCol() { return getEndCol(); }
|
||||
|
||||
private byte getLiveAttribute() {
|
||||
if (ps != null && ps.getScreenBuffer() != null) {
|
||||
@@ -71,34 +79,42 @@ public class ECLField {
|
||||
public boolean isModified() {
|
||||
return faIsModified(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsModified() { return isModified(); }
|
||||
|
||||
public boolean isProtected() {
|
||||
return faIsProtected(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsProtected() { return isProtected(); }
|
||||
|
||||
public boolean isNumeric() {
|
||||
return faIsNumeric(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsNumeric() { return isNumeric(); }
|
||||
|
||||
public boolean isHighIntensity() {
|
||||
return faIsHigh(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsHighIntensity() { return isHighIntensity(); }
|
||||
|
||||
public boolean isHidden() {
|
||||
return faIsZero(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsHidden() { return isHidden(); }
|
||||
|
||||
public boolean isDisplay() {
|
||||
return !isHidden();
|
||||
}
|
||||
public boolean IsDisplay() { return isDisplay(); }
|
||||
|
||||
public boolean isPenSelectable() {
|
||||
return faIsSelectable(getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public boolean IsPenSelectable() { return isPenSelectable(); }
|
||||
|
||||
public short getAttribute() {
|
||||
return (short) (getLiveAttribute() & 0xFF);
|
||||
}
|
||||
public short GetAttribute() { return getAttribute(); }
|
||||
|
||||
/**
|
||||
* Get the text contents of this field as a String.
|
||||
@@ -107,6 +123,7 @@ public class ECLField {
|
||||
if (length <= 0) return "";
|
||||
return ps.getString(dataStart, length);
|
||||
}
|
||||
public String GetText() { return getText(); }
|
||||
|
||||
/**
|
||||
* Set the text contents of this field.
|
||||
@@ -115,6 +132,7 @@ public class ECLField {
|
||||
if (isProtected() || length <= 0) return;
|
||||
ps.setText(text, dataStart);
|
||||
}
|
||||
public void SetText(String text) { setText(text); }
|
||||
|
||||
/**
|
||||
* Get selector light pen type.
|
||||
@@ -129,6 +147,7 @@ public class ECLField {
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
public char GetSelectorPenType() { return getSelectorPenType(); }
|
||||
|
||||
/**
|
||||
* Actuate lightpen selection on this field ('?' -> '>').
|
||||
@@ -140,6 +159,7 @@ public class ECLField {
|
||||
setText(">" + (t.length() > 1 ? t.substring(1) : ""));
|
||||
}
|
||||
}
|
||||
public void SelectField() { selectField(); }
|
||||
|
||||
/**
|
||||
* Deselect lightpen selection on this field ('>' -> '?').
|
||||
@@ -151,16 +171,19 @@ public class ECLField {
|
||||
setText("?" + (t.length() > 1 ? t.substring(1) : ""));
|
||||
}
|
||||
}
|
||||
public void DeSelectField() { deSelectField(); }
|
||||
|
||||
/** Return true if this field wraps from bottom of screen to top. */
|
||||
public boolean isWrapped() {
|
||||
return startPos > endPos;
|
||||
}
|
||||
public boolean IsWrapped() { return isWrapped(); }
|
||||
|
||||
/** Last data buffer address (same as getEnd). */
|
||||
public int getDataEnd() {
|
||||
return endPos;
|
||||
}
|
||||
public int GetDataEnd() { return getDataEnd(); }
|
||||
|
||||
/**
|
||||
* Check if the specified buffer address is contained within this field (including its FA).
|
||||
@@ -178,6 +201,7 @@ public class ECLField {
|
||||
return pos >= startPos || pos <= endPos;
|
||||
}
|
||||
}
|
||||
public boolean Contains(int pos) { return contains(pos); }
|
||||
|
||||
/**
|
||||
* Check if the specified row and column is contained within this field.
|
||||
@@ -187,6 +211,7 @@ public class ECLField {
|
||||
int cols = ps.getCols();
|
||||
return contains(row * cols + col);
|
||||
}
|
||||
public boolean Contains(int row, int col) { return contains(row, col); }
|
||||
|
||||
/**
|
||||
* Set the Modified Data Tag (MDT) for this field.
|
||||
@@ -205,6 +230,7 @@ public class ECLField {
|
||||
}
|
||||
}
|
||||
}
|
||||
public void SetModified(boolean modified) { setModified(modified); }
|
||||
|
||||
/**
|
||||
* Erase all character data within this field to nulls.
|
||||
@@ -225,6 +251,20 @@ public class ECLField {
|
||||
sb.markAllChanged();
|
||||
sb.updateDisplaySnapshot();
|
||||
}
|
||||
public void Erase() { erase(); }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ECLField)) return false;
|
||||
ECLField other = (ECLField) o;
|
||||
return this.startPos == other.startPos && this.endPos == other.endPos && this.length == other.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return java.util.Objects.hash(startPos, endPos, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -70,27 +70,38 @@ public class ECLFieldList {
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh() { refresh(); }
|
||||
|
||||
public synchronized int getFieldCount() {
|
||||
return fields.size();
|
||||
}
|
||||
public int GetFieldCount() { return getFieldCount(); }
|
||||
|
||||
public synchronized List<ECLField> getFields() {
|
||||
return Collections.unmodifiableList(new ArrayList<>(fields));
|
||||
}
|
||||
public List<ECLField> GetFields() { return getFields(); }
|
||||
|
||||
public synchronized ECLField getFirstField() {
|
||||
if (fields.isEmpty()) return null;
|
||||
return fields.get(0);
|
||||
}
|
||||
public ECLField GetFirstField() { return getFirstField(); }
|
||||
|
||||
public synchronized ECLField getNextField(ECLField prev) {
|
||||
if (prev == null || fields.isEmpty()) return getFirstField();
|
||||
int idx = fields.indexOf(prev);
|
||||
if (idx >= 0 && idx + 1 < fields.size()) {
|
||||
return fields.get(idx + 1);
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
ECLField f = fields.get(i);
|
||||
if (f.equals(prev) || f.getStart() == prev.getStart()) {
|
||||
if (i + 1 < fields.size()) {
|
||||
return fields.get(i + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ECLField GetNextField(ECLField prev) { return getNextField(prev); }
|
||||
|
||||
/**
|
||||
* Find the field that contains the specified buffer position.
|
||||
@@ -113,6 +124,7 @@ public class ECLFieldList {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ECLField FindField(int pos) { return findField(pos); }
|
||||
|
||||
/**
|
||||
* Find the field at the specified 0-indexed row and column.
|
||||
@@ -122,20 +134,26 @@ public class ECLFieldList {
|
||||
int cols = screen.getCols();
|
||||
return findField(row * cols + col);
|
||||
}
|
||||
public ECLField FindField(int row, int col) { return findField(row, col); }
|
||||
|
||||
/**
|
||||
* Get the field preceding the given field in the field list.
|
||||
*/
|
||||
public synchronized ECLField getPreviousField(ECLField next) {
|
||||
if (next == null || fields.isEmpty()) return null;
|
||||
int idx = fields.indexOf(next);
|
||||
if (idx > 0) {
|
||||
return fields.get(idx - 1);
|
||||
} else if (idx == 0) {
|
||||
return fields.get(fields.size() - 1);
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
ECLField f = fields.get(i);
|
||||
if (f.equals(next) || f.getStart() == next.getStart()) {
|
||||
if (i > 0) {
|
||||
return fields.get(i - 1);
|
||||
} else {
|
||||
return fields.get(fields.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ECLField GetPreviousField(ECLField next) { return getPreviousField(next); }
|
||||
|
||||
/**
|
||||
* Find the field at the given buffer position (alias for findField).
|
||||
@@ -143,6 +161,7 @@ public class ECLFieldList {
|
||||
public ECLField findFieldAt(int pos) {
|
||||
return findField(pos);
|
||||
}
|
||||
public ECLField FindFieldAt(int pos) { return findFieldAt(pos); }
|
||||
|
||||
/**
|
||||
* Find the field at the given row and column.
|
||||
@@ -150,6 +169,7 @@ public class ECLFieldList {
|
||||
public ECLField findFieldAt(int row, int col) {
|
||||
return findField(row, col);
|
||||
}
|
||||
public ECLField FindFieldAt(int row, int col) { return findFieldAt(row, col); }
|
||||
|
||||
/**
|
||||
* Find the field preceding the one at the given buffer position.
|
||||
@@ -159,6 +179,7 @@ public class ECLFieldList {
|
||||
if (curr == null) return null;
|
||||
return getPreviousField(curr);
|
||||
}
|
||||
public ECLField FindPrevField(int pos) { return findPrevField(pos); }
|
||||
|
||||
/**
|
||||
* Find the field succeeding the one at the given buffer position.
|
||||
@@ -168,6 +189,7 @@ public class ECLFieldList {
|
||||
if (curr == null) return null;
|
||||
return getNextField(curr);
|
||||
}
|
||||
public ECLField FindNextField(int pos) { return findNextField(pos); }
|
||||
|
||||
/**
|
||||
* Find field containing the given text string.
|
||||
@@ -202,4 +224,5 @@ public class ECLFieldList {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ECLField FindField(String text, int startPos) { return findField(text, startPos); }
|
||||
}
|
||||
|
||||
@@ -85,24 +85,52 @@ public class ECLOIA implements ECLConstants {
|
||||
return inputProcessor != null && inputProcessor.isInsertMode();
|
||||
}
|
||||
|
||||
public boolean IsInsertMode() {
|
||||
return isInsertMode();
|
||||
}
|
||||
|
||||
public boolean isNumeric() {
|
||||
if (screen == null || !screen.isFormatted()) return false;
|
||||
byte fa = screen.getFieldAttributeAt(screen.getCursorAddress());
|
||||
return faIsNumeric(fa & 0xFF);
|
||||
}
|
||||
|
||||
public boolean IsNumeric() {
|
||||
return isNumeric();
|
||||
}
|
||||
|
||||
public boolean isAlphanumeric() {
|
||||
return !isNumeric();
|
||||
}
|
||||
|
||||
public boolean IsAlphanumeric() {
|
||||
return isAlphanumeric();
|
||||
}
|
||||
|
||||
public boolean isDBCS() {
|
||||
return getAlphanumericType() == TYPE_DBCS;
|
||||
}
|
||||
|
||||
public boolean IsDBCS() {
|
||||
return isDBCS();
|
||||
}
|
||||
|
||||
public boolean isMessageWaiting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean IsMessageWaiting() {
|
||||
return isMessageWaiting();
|
||||
}
|
||||
|
||||
public boolean isCommError() {
|
||||
return fsm != null && fsm.getConnectionState() != null && !fsm.getConnectionState().isConnected();
|
||||
}
|
||||
|
||||
public boolean IsCommError() {
|
||||
return isCommError();
|
||||
}
|
||||
|
||||
private int inhibitOverride = -1;
|
||||
|
||||
public void setInputInhibited(int reason) {
|
||||
@@ -112,6 +140,10 @@ public class ECLOIA implements ECLConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public void SetInputInhibited(int reason) {
|
||||
setInputInhibited(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alphanumeric character entry type allowed at current cursor position.
|
||||
* Returns TYPE_ALPHANUMERIC (0), TYPE_NUMERIC (1), or TYPE_DBCS (2).
|
||||
@@ -132,6 +164,10 @@ public class ECLOIA implements ECLConstants {
|
||||
return TYPE_ALPHANUMERIC;
|
||||
}
|
||||
|
||||
public int GetAlphanumericType() {
|
||||
return getAlphanumericType();
|
||||
}
|
||||
|
||||
public String getAlphanumericTypeString() {
|
||||
switch (getAlphanumericType()) {
|
||||
case TYPE_NUMERIC: return "N";
|
||||
@@ -141,38 +177,74 @@ public class ECLOIA implements ECLConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public String GetAlphanumericTypeString() {
|
||||
return getAlphanumericTypeString();
|
||||
}
|
||||
|
||||
public boolean isXSystem() {
|
||||
return getInputInhibited() == INHIBIT_SYSTEM_LOCK;
|
||||
}
|
||||
|
||||
public boolean IsXSystem() {
|
||||
return isXSystem();
|
||||
}
|
||||
|
||||
public boolean isXProt() {
|
||||
return getInputInhibited() == INHIBIT_PROTECTED_FIELD;
|
||||
}
|
||||
|
||||
public boolean IsXProt() {
|
||||
return isXProt();
|
||||
}
|
||||
|
||||
public boolean isXNum() {
|
||||
return getInputInhibited() == INHIBIT_NUMERIC_ONLY;
|
||||
}
|
||||
|
||||
public boolean IsXNum() {
|
||||
return isXNum();
|
||||
}
|
||||
|
||||
public boolean isXWait() {
|
||||
return isXSystem();
|
||||
}
|
||||
|
||||
public boolean IsXWait() {
|
||||
return isXWait();
|
||||
}
|
||||
|
||||
public boolean isXInsert() {
|
||||
return isInsertMode();
|
||||
}
|
||||
|
||||
public boolean IsXInsert() {
|
||||
return isXInsert();
|
||||
}
|
||||
|
||||
public boolean isXComm() {
|
||||
return isCommError() || getInputInhibited() == INHIBIT_COMM_CHECK;
|
||||
}
|
||||
|
||||
public boolean IsXComm() {
|
||||
return isXComm();
|
||||
}
|
||||
|
||||
public boolean isXOverflow() {
|
||||
return getInputInhibited() == INHIBIT_OVERFLOW;
|
||||
}
|
||||
|
||||
public boolean IsXOverflow() {
|
||||
return isXOverflow();
|
||||
}
|
||||
|
||||
public boolean isXOperatorDue() {
|
||||
return getInputInhibited() == INHIBIT_OPERATOR_DUE;
|
||||
}
|
||||
|
||||
public boolean IsXOperatorDue() {
|
||||
return isXOperatorDue();
|
||||
}
|
||||
|
||||
public String getStatusString() {
|
||||
int inhibit = getInputInhibited();
|
||||
switch (inhibit) {
|
||||
@@ -188,6 +260,10 @@ public class ECLOIA implements ECLConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public String GetStatusString() {
|
||||
return getStatusString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current Input Inhibited code.
|
||||
* Returns one of INHIBIT_* constants from ECLConstants.
|
||||
@@ -205,6 +281,18 @@ public class ECLOIA implements ECLConstants {
|
||||
return INHIBIT_NOT_INHIBITED;
|
||||
}
|
||||
|
||||
public int GetInputInhibited() {
|
||||
return getInputInhibited();
|
||||
}
|
||||
|
||||
public int getInputInhibitedType() {
|
||||
return getInputInhibited();
|
||||
}
|
||||
|
||||
public int GetInputInhibitedType() {
|
||||
return getInputInhibited();
|
||||
}
|
||||
|
||||
/**
|
||||
* Block until the keyboard becomes unlocked and ready for user input, or timeout expires.
|
||||
* @return true if keyboard unlocked, false if timeout occurred.
|
||||
|
||||
@@ -205,21 +205,75 @@ public class ECLPS implements ECLConstants {
|
||||
return SearchPSExt(text, 1, getSize(), SEARCH_FORWARD, false, true);
|
||||
}
|
||||
|
||||
public int searchPS(String text) {
|
||||
return SearchPS(text);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startPos) {
|
||||
return SearchPSExt(text, startPos, getSize(), SEARCH_FORWARD, false, true);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startPos) {
|
||||
return SearchPS(text, startPos);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol) {
|
||||
int pos = (startRow - 1) * getCols() + startCol;
|
||||
return SearchPSExt(text, pos, getSize(), SEARCH_FORWARD, false, true);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol) {
|
||||
return SearchPS(text, startRow, startCol);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol, int dir) {
|
||||
int pos = (startRow - 1) * getCols() + startCol;
|
||||
return SearchPSExt(text, pos, getSize(), dir, false, true);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol, int dir) {
|
||||
return SearchPS(text, startRow, startCol, dir);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol, int dir, boolean ignoreCase) {
|
||||
int pos = (startRow - 1) * getCols() + startCol;
|
||||
return SearchPSExt(text, pos, getSize(), dir, ignoreCase, true);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol, int dir, boolean ignoreCase) {
|
||||
return SearchPS(text, startRow, startCol, dir, ignoreCase);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol, int endRow, int endCol) {
|
||||
int sPos = (startRow - 1) * getCols() + startCol;
|
||||
int ePos = (endRow - 1) * getCols() + endCol;
|
||||
return SearchPSExt(text, sPos, ePos, SEARCH_FORWARD, false, false);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol, int endRow, int endCol) {
|
||||
return SearchPS(text, startRow, startCol, endRow, endCol);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol, int endRow, int endCol, int dir) {
|
||||
int sPos = (startRow - 1) * getCols() + startCol;
|
||||
int ePos = (endRow - 1) * getCols() + endCol;
|
||||
return SearchPSExt(text, sPos, ePos, dir, false, false);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol, int endRow, int endCol, int dir) {
|
||||
return SearchPS(text, startRow, startCol, endRow, endCol, dir);
|
||||
}
|
||||
|
||||
public int SearchPS(String text, int startRow, int startCol, int endRow, int endCol, int dir, boolean ignoreCase) {
|
||||
int sPos = (startRow - 1) * getCols() + startCol;
|
||||
int ePos = (endRow - 1) * getCols() + endCol;
|
||||
return SearchPSExt(text, sPos, ePos, dir, ignoreCase, false);
|
||||
}
|
||||
|
||||
public int searchPS(String text, int startRow, int startCol, int endRow, int endCol, int dir, boolean ignoreCase) {
|
||||
return SearchPS(text, startRow, startCol, endRow, endCol, dir, ignoreCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* SearchPS extended method conforming to IBM ECL specification.
|
||||
* Uses 1-based positions and returns 1-based index (or 0 if not found).
|
||||
@@ -263,6 +317,21 @@ public class ECLPS implements ECLConstants {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int searchPSExt(String text, int startPos, int endPos, int dir, boolean ignoreCase, boolean wrap) {
|
||||
return SearchPSExt(text, startPos, endPos, dir, ignoreCase, wrap);
|
||||
}
|
||||
|
||||
public int SearchPSExt(String text, int startRow, int startCol, int endRow, int endCol, int dir, boolean ignoreCase, boolean wrap) {
|
||||
int cols = getCols();
|
||||
int sPos = (startRow - 1) * cols + startCol;
|
||||
int ePos = (endRow - 1) * cols + endCol;
|
||||
return SearchPSExt(text, sPos, ePos, dir, ignoreCase, wrap);
|
||||
}
|
||||
|
||||
public int searchPSExt(String text, int startRow, int startCol, int endRow, int endCol, int dir, boolean ignoreCase, boolean wrap) {
|
||||
return SearchPSExt(text, startRow, startCol, endRow, endCol, dir, ignoreCase, wrap);
|
||||
}
|
||||
|
||||
private boolean matchesAt(String screenText, String target, int pos, int size) {
|
||||
int len = target.length();
|
||||
for (int j = 0; j < len; j++) {
|
||||
@@ -303,6 +372,10 @@ public class ECLPS implements ECLConstants {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String CopyString(int sRow, int sCol, int eRow, int eCol) {
|
||||
return copyString(sRow, sCol, eRow, eCol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste a multi-line rectangular block of text starting at (row, col).
|
||||
*/
|
||||
@@ -320,6 +393,12 @@ public class ECLPS implements ECLConstants {
|
||||
String line = lines[i];
|
||||
for (int c = 0; c < line.length() && (col + c) < cols; c++) {
|
||||
int pos = targetRow * cols + (col + c);
|
||||
if (screen.isFormatted()) {
|
||||
byte fa = screen.getFieldAttributeAt(pos);
|
||||
if (faIsProtected(fa & 0xFF) || screen.getCell(pos).isFieldAttribute()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
setCursorPos(pos);
|
||||
if (inputProcessor != null) {
|
||||
inputProcessor.typeCharacter(line.charAt(c));
|
||||
@@ -330,6 +409,18 @@ public class ECLPS implements ECLConstants {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int PasteString(String text, int row, int col) {
|
||||
return pasteString(text, row, col);
|
||||
}
|
||||
|
||||
public int pasteRectangular(String text, int row, int col) {
|
||||
return pasteString(text, row, col);
|
||||
}
|
||||
|
||||
public int PasteRectangular(String text, int row, int col) {
|
||||
return pasteString(text, row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste text with line wrapping across unprotected fields.
|
||||
*/
|
||||
@@ -365,6 +456,108 @@ public class ECLPS implements ECLConstants {
|
||||
return charsPasted;
|
||||
}
|
||||
|
||||
public int PasteLineWrap(String text, int startPos, int endCol, boolean wordWrap) {
|
||||
return pasteLineWrap(text, startPos, endCol, wordWrap);
|
||||
}
|
||||
|
||||
// ========== Entry Assist & DOC Mode Operations ==========
|
||||
|
||||
public boolean isEntryAssistDOCmode() { return screen != null && screen.isEntryAssistDOCmode(); }
|
||||
public boolean IsEntryAssistDOCmode() { return isEntryAssistDOCmode(); }
|
||||
public void setEntryAssistDOCmode(boolean bl) { if (screen != null) screen.setEntryAssistDOCmode(bl); }
|
||||
public void SetEntryAssistDOCmode(boolean bl) { setEntryAssistDOCmode(bl); }
|
||||
|
||||
public boolean isEntryAssistWordWrap() { return screen != null && screen.isEntryAssistWordWrap(); }
|
||||
public boolean IsEntryAssistWordWrap() { return isEntryAssistWordWrap(); }
|
||||
public void setEntryAssistWordWrap(boolean bl) { if (screen != null) screen.setEntryAssistWordWrap(bl); }
|
||||
public void SetEntryAssistWordWrap(boolean bl) { setEntryAssistWordWrap(bl); }
|
||||
|
||||
public int getEntryAssistStartColumn() { return screen != null ? screen.getEntryAssistStartColumn() : 0; }
|
||||
public int GetEntryAssistStartColumn() { return getEntryAssistStartColumn(); }
|
||||
public void setEntryAssistStartColumn(int n) { if (screen != null) screen.setEntryAssistStartColumn(n); }
|
||||
public void SetEntryAssistStartColumn(int n) { setEntryAssistStartColumn(n); }
|
||||
|
||||
public int getEntryAssistEndColumn() { return screen != null ? screen.getEntryAssistEndColumn() : 0; }
|
||||
public int GetEntryAssistEndColumn() { return getEntryAssistEndColumn(); }
|
||||
public void setEntryAssistEndColumn(int n) { if (screen != null) screen.setEntryAssistEndColumn(n); }
|
||||
public void SetEntryAssistEndColumn(int n) { setEntryAssistEndColumn(n); }
|
||||
|
||||
public int[] getEntryAssistTabStops() { return screen != null ? screen.getEntryAssistTabStops() : null; }
|
||||
public int[] GetEntryAssistTabStops() { return getEntryAssistTabStops(); }
|
||||
public void setEntryAssistTabStops(int[] stops) { if (screen != null) screen.setEntryAssistTabStops(stops); }
|
||||
public void SetEntryAssistTabStops(int[] stops) { setEntryAssistTabStops(stops); }
|
||||
|
||||
public void processWordTab(boolean forward) { if (inputProcessor != null) inputProcessor.processWordTab(forward); else if (screen != null) screen.processWordTab(forward); }
|
||||
public void ProcessWordTab(boolean forward) { processWordTab(forward); }
|
||||
public void wordTab(boolean forward) { processWordTab(forward); }
|
||||
public void WordTab(boolean forward) { processWordTab(forward); }
|
||||
|
||||
public void processDeleteWord() { if (inputProcessor != null) inputProcessor.processDeleteWord(); else if (screen != null) screen.processDeleteWord(); }
|
||||
public void ProcessDeleteWord() { processDeleteWord(); }
|
||||
public void deleteWord() { processDeleteWord(); }
|
||||
public void DeleteWord() { processDeleteWord(); }
|
||||
|
||||
public void processWordLeft() { if (inputProcessor != null) inputProcessor.processWordLeft(); }
|
||||
public void ProcessWordLeft() { processWordLeft(); }
|
||||
public void wordLeft() { processWordLeft(); }
|
||||
public void WordLeft() { processWordLeft(); }
|
||||
|
||||
public void processWordRight() { if (inputProcessor != null) inputProcessor.processWordRight(); }
|
||||
public void ProcessWordRight() { processWordRight(); }
|
||||
public void wordRight() { processWordRight(); }
|
||||
public void WordRight() { processWordRight(); }
|
||||
|
||||
public void processFieldEnd() { if (inputProcessor != null) inputProcessor.processFieldEnd(); }
|
||||
public void ProcessFieldEnd() { processFieldEnd(); }
|
||||
public void fieldEnd() { processFieldEnd(); }
|
||||
public void FieldEnd() { processFieldEnd(); }
|
||||
|
||||
// ========== Field Management Accessors ==========
|
||||
|
||||
public ECLField getField(int pos) {
|
||||
return getFieldList().findField(pos);
|
||||
}
|
||||
|
||||
public ECLField GetField(int pos) {
|
||||
return getField(pos);
|
||||
}
|
||||
|
||||
public ECLField getField(int row, int col) {
|
||||
return getFieldList().findField(row, col);
|
||||
}
|
||||
|
||||
public ECLField GetField(int row, int col) {
|
||||
return getField(row, col);
|
||||
}
|
||||
|
||||
public ECLField getFirstField() {
|
||||
return getFieldList().getFirstField();
|
||||
}
|
||||
|
||||
public ECLField GetFirstField() {
|
||||
return getFirstField();
|
||||
}
|
||||
|
||||
public ECLField getNextField(ECLField prev) {
|
||||
return getFieldList().getNextField(prev);
|
||||
}
|
||||
|
||||
public ECLField GetNextField(ECLField prev) {
|
||||
return getNextField(prev);
|
||||
}
|
||||
|
||||
public ECLField getPreviousField(ECLField next) {
|
||||
return getFieldList().getPreviousField(next);
|
||||
}
|
||||
|
||||
public ECLField GetPreviousField(ECLField next) {
|
||||
return getPreviousField(next);
|
||||
}
|
||||
|
||||
public ECLFieldList GetFieldList() {
|
||||
return getFieldList();
|
||||
}
|
||||
|
||||
// ========== ECLPS Event Listener Management ==========
|
||||
|
||||
private final java.util.List<ECLPSListener> psListeners = new java.util.concurrent.CopyOnWriteArrayList<>();
|
||||
@@ -455,6 +648,29 @@ public class ECLPS implements ECLConstants {
|
||||
/**
|
||||
* Send keystrokes with configurable inter-character or inter-mnemonic delay.
|
||||
*/
|
||||
public void sendCharacters(String keys) {
|
||||
sendCharacters(keys, 0);
|
||||
}
|
||||
|
||||
public void SendCharacters(String keys) {
|
||||
sendCharacters(keys, 0);
|
||||
}
|
||||
|
||||
public void SendCharacters(String keys, int delayMs) {
|
||||
sendCharacters(keys, delayMs);
|
||||
}
|
||||
|
||||
public void sendCharacters(String keys, int row, int col, int delayMs) {
|
||||
if (row > 0 && col > 0) {
|
||||
setCursorPos(row - 1, col - 1);
|
||||
}
|
||||
sendCharacters(keys, delayMs);
|
||||
}
|
||||
|
||||
public void SendCharacters(String keys, int row, int col, int delayMs) {
|
||||
sendCharacters(keys, row, col, delayMs);
|
||||
}
|
||||
|
||||
public void sendCharacters(String keys, int delayMs) {
|
||||
if (keys == null || keys.isEmpty()) return;
|
||||
if (delayMs <= 0) {
|
||||
@@ -466,14 +682,20 @@ public class ECLPS implements ECLConstants {
|
||||
int len = keys.length();
|
||||
while (i < len) {
|
||||
if (keys.charAt(i) == '[') {
|
||||
int close = keys.indexOf(']', i);
|
||||
if (close > i) {
|
||||
String mnemonic = keys.substring(i, close + 1);
|
||||
sendKeys(mnemonic);
|
||||
i = close + 1;
|
||||
if (i + 1 < len && keys.charAt(i + 1) == '[') {
|
||||
// Escaped bracket "[["
|
||||
sendKeys("[");
|
||||
i += 2;
|
||||
} else {
|
||||
sendKeys(keys.substring(i, i + 1));
|
||||
i++;
|
||||
int close = keys.indexOf(']', i);
|
||||
if (close > i) {
|
||||
String mnemonic = keys.substring(i, close + 1);
|
||||
sendKeys(mnemonic);
|
||||
i = close + 1;
|
||||
} else {
|
||||
sendKeys(keys.substring(i, i + 1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendKeys(keys.substring(i, i + 1));
|
||||
|
||||
@@ -131,6 +131,22 @@ public class InputProcessor {
|
||||
int baddr = screen.getCursorAddress();
|
||||
baddr = ((baddr % size) + size) % size;
|
||||
|
||||
// Entry Assist DOC mode / Word Wrap handling
|
||||
if ((screen.isEntryAssistDOCmode() || screen.isEntryAssistWordWrap()) && !isNvtMode()) {
|
||||
int curCol = baddr % screen.getCols();
|
||||
int endCol = screen.getEntryAssistEndColumn();
|
||||
int startCol = screen.getEntryAssistStartColumn();
|
||||
if (curCol >= endCol) {
|
||||
screen.handleWordWrap(baddr, ch);
|
||||
baddr = screen.getCursorAddress();
|
||||
if (ch == ' ' && (baddr % screen.getCols()) == startCol) {
|
||||
screen.markAllChanged();
|
||||
screen.updateDisplaySnapshot();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (screen.isFormatted()) {
|
||||
// Check if cursor is at a field attribute
|
||||
ExtendedAttribute ea = screen.getCell(baddr);
|
||||
|
||||
@@ -909,19 +909,108 @@ public class ScreenBuffer {
|
||||
// ========== Entry Assist & DOC Mode Operations ==========
|
||||
|
||||
public boolean isEntryAssistDOCmode() { return docMode; }
|
||||
public boolean IsEntryAssistDOCmode() { return isEntryAssistDOCmode(); }
|
||||
public void setEntryAssistDOCmode(boolean bl) { this.docMode = bl; }
|
||||
public void SetEntryAssistDOCmode(boolean bl) { setEntryAssistDOCmode(bl); }
|
||||
|
||||
public boolean isEntryAssistWordWrap() { return wordWrap; }
|
||||
public boolean IsEntryAssistWordWrap() { return isEntryAssistWordWrap(); }
|
||||
public void setEntryAssistWordWrap(boolean bl) { this.wordWrap = bl; }
|
||||
public void SetEntryAssistWordWrap(boolean bl) { setEntryAssistWordWrap(bl); }
|
||||
|
||||
public int getEntryAssistStartColumn() { return docStartCol; }
|
||||
public int GetEntryAssistStartColumn() { return getEntryAssistStartColumn(); }
|
||||
public void setEntryAssistStartColumn(int n) { this.docStartCol = Math.max(0, n); }
|
||||
public void SetEntryAssistStartColumn(int n) { setEntryAssistStartColumn(n); }
|
||||
|
||||
public int getEntryAssistEndColumn() { return docEndCol >= 0 ? docEndCol : (cols - 1); }
|
||||
public int GetEntryAssistEndColumn() { return getEntryAssistEndColumn(); }
|
||||
public void setEntryAssistEndColumn(int n) { this.docEndCol = n; }
|
||||
public void SetEntryAssistEndColumn(int n) { setEntryAssistEndColumn(n); }
|
||||
|
||||
public int[] getEntryAssistTabStops() { return tabStops; }
|
||||
public int[] GetEntryAssistTabStops() { return getEntryAssistTabStops(); }
|
||||
public void setEntryAssistTabStops(int[] stops) { this.tabStops = stops; }
|
||||
public void SetEntryAssistTabStops(int[] stops) { setEntryAssistTabStops(stops); }
|
||||
|
||||
/**
|
||||
* Perform Entry Assist word wrap if typing near/past end margin.
|
||||
* Moves any partial word typed on the current line to the beginning of the next line (docStartCol).
|
||||
*/
|
||||
public synchronized boolean handleWordWrap(int curAddr, char typedChar) {
|
||||
if (!docMode && !wordWrap) return false;
|
||||
int size = rows * cols;
|
||||
if (size <= 0) return false;
|
||||
curAddr = ((curAddr % size) + size) % size;
|
||||
|
||||
int curRow = curAddr / cols;
|
||||
int curCol = curAddr % cols;
|
||||
int endCol = getEntryAssistEndColumn();
|
||||
int startCol = getEntryAssistStartColumn();
|
||||
|
||||
if (curCol < endCol) return false;
|
||||
|
||||
if (typedChar == ' ') {
|
||||
int nextRow = (curRow + 1) % rows;
|
||||
setCursorPosition(nextRow, startCol);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Scan backwards to find the start of the current word on this row
|
||||
int rowStartAddr = curRow * cols + startCol;
|
||||
int scan = curAddr - 1;
|
||||
while (scan >= rowStartAddr) {
|
||||
ExtendedAttribute ea = getCell(scan);
|
||||
if (ea.isFieldAttribute()) break;
|
||||
int ec = ea.ec & 0xFF;
|
||||
if (ec == 0 || ec == 0x40 || ea.ucs4 == ' ' || ea.ucs4 == 0) {
|
||||
break;
|
||||
}
|
||||
scan--;
|
||||
}
|
||||
|
||||
int wordStartAddr = scan + 1;
|
||||
int wordStartCol = wordStartAddr % cols;
|
||||
|
||||
if (wordStartCol > startCol && wordStartAddr < curAddr) {
|
||||
int wordLen = curAddr - wordStartAddr;
|
||||
ExtendedAttribute[] wordCells = new ExtendedAttribute[wordLen];
|
||||
for (int i = 0; i < wordLen; i++) {
|
||||
wordCells[i] = new ExtendedAttribute();
|
||||
wordCells[i].copyFrom(getCell(wordStartAddr + i));
|
||||
getCell(wordStartAddr + i).clear();
|
||||
}
|
||||
|
||||
int nextRow = (curRow + 1) % rows;
|
||||
int targetAddr = nextRow * cols + startCol;
|
||||
if (formatted) {
|
||||
targetAddr = findNextUnprotected(targetAddr - 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < wordLen; i++) {
|
||||
int dst = (targetAddr + i) % size;
|
||||
if (!getCell(dst).isFieldAttribute()) {
|
||||
getCell(dst).copyFrom(wordCells[i]);
|
||||
}
|
||||
}
|
||||
|
||||
setCursorAddress((targetAddr + wordLen) % size);
|
||||
screenChanged = true;
|
||||
updateDisplaySnapshot();
|
||||
return true;
|
||||
} else {
|
||||
// Word spans entire line or starts at startCol, wrap to next line
|
||||
int nextRow = (curRow + 1) % rows;
|
||||
int targetAddr = nextRow * cols + startCol;
|
||||
if (formatted) {
|
||||
targetAddr = findNextUnprotected(targetAddr - 1);
|
||||
}
|
||||
setCursorAddress(targetAddr);
|
||||
screenChanged = true;
|
||||
updateDisplaySnapshot();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void processWordTab(boolean forward) {
|
||||
int size = rows * cols;
|
||||
@@ -1060,4 +1149,12 @@ public class ScreenBuffer {
|
||||
screenChanged = true;
|
||||
updateDisplaySnapshot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect and balance Shift-Out (0x0E) and Shift-In (0x0F) markers, ensuring DBCS integrity.
|
||||
*/
|
||||
public synchronized void balanceSOSI() {
|
||||
cleanAdjacentSISO(0);
|
||||
processSOSI();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,41 @@ public class TelnetConnection {
|
||||
*/
|
||||
public void connect() throws IOException {
|
||||
ConnectionConfig.ProxyType proxyType = config.getProxyType();
|
||||
boolean hasProxy = proxyType != null && proxyType != ConnectionConfig.ProxyType.NONE &&
|
||||
config.getProxyHost() != null && !config.getProxyHost().trim().isEmpty();
|
||||
String proxyHost = config.getProxyHost();
|
||||
int proxyPort = config.getProxyPort();
|
||||
String proxyUser = config.getProxyUsername();
|
||||
String proxyPass = config.getProxyPassword();
|
||||
|
||||
String connectHost = hasProxy ? config.getProxyHost().trim() : config.getHost();
|
||||
int connectPort = hasProxy ? (config.getProxyPort() > 0 ? config.getProxyPort() : (proxyType == ConnectionConfig.ProxyType.HTTP ? 8080 : 1080)) : config.getPort();
|
||||
if ((proxyType == null || proxyType == ConnectionConfig.ProxyType.NONE) && (proxyHost == null || proxyHost.trim().isEmpty())) {
|
||||
// Check JVM system properties (matching IBM HoD browser/system default fallback)
|
||||
String sysSocks = System.getProperty("socksProxyHost");
|
||||
String sysHttp = System.getProperty("http.proxyHost");
|
||||
if (sysSocks != null && !sysSocks.trim().isEmpty()) {
|
||||
proxyType = ConnectionConfig.ProxyType.SOCKS5;
|
||||
proxyHost = sysSocks.trim();
|
||||
String portStr = System.getProperty("socksProxyPort");
|
||||
if (portStr != null) {
|
||||
try { proxyPort = Integer.parseInt(portStr.trim()); } catch (NumberFormatException ignored) {}
|
||||
}
|
||||
proxyUser = System.getProperty("java.net.socks.username");
|
||||
proxyPass = System.getProperty("java.net.socks.password");
|
||||
} else if (sysHttp != null && !sysHttp.trim().isEmpty()) {
|
||||
proxyType = ConnectionConfig.ProxyType.HTTP;
|
||||
proxyHost = sysHttp.trim();
|
||||
String portStr = System.getProperty("http.proxyPort");
|
||||
if (portStr != null) {
|
||||
try { proxyPort = Integer.parseInt(portStr.trim()); } catch (NumberFormatException ignored) {}
|
||||
}
|
||||
proxyUser = System.getProperty("http.proxyUser");
|
||||
proxyPass = System.getProperty("http.proxyPassword");
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasProxy = proxyType != null && proxyType != ConnectionConfig.ProxyType.NONE &&
|
||||
proxyHost != null && !proxyHost.trim().isEmpty();
|
||||
|
||||
String connectHost = hasProxy ? proxyHost.trim() : config.getHost();
|
||||
int connectPort = hasProxy ? (proxyPort > 0 ? proxyPort : (proxyType == ConnectionConfig.ProxyType.HTTP ? 8080 : 1080)) : config.getPort();
|
||||
|
||||
log.info("Connecting TCP socket to " + connectHost + ":" + connectPort +
|
||||
(hasProxy ? " (via " + proxyType + " proxy for " + config.getHost() + ":" + config.getPort() + ")" : "") +
|
||||
@@ -67,13 +97,13 @@ public class TelnetConnection {
|
||||
if (hasProxy) {
|
||||
switch (proxyType) {
|
||||
case HTTP:
|
||||
establishHttpProxy(rawSocket, config.getHost(), config.getPort(), config.getProxyUsername(), config.getProxyPassword());
|
||||
establishHttpProxy(rawSocket, config.getHost(), config.getPort(), proxyUser, proxyPass);
|
||||
break;
|
||||
case SOCKS4:
|
||||
establishSocks4Proxy(rawSocket, config.getHost(), config.getPort(), config.getProxyUsername());
|
||||
establishSocks4Proxy(rawSocket, config.getHost(), config.getPort(), proxyUser);
|
||||
break;
|
||||
case SOCKS5:
|
||||
establishSocks5Proxy(rawSocket, config.getHost(), config.getPort(), config.getProxyUsername(), config.getProxyPassword());
|
||||
establishSocks5Proxy(rawSocket, config.getHost(), config.getPort(), proxyUser, proxyPass);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user