IBM-DYNAMIC

This commit is contained in:
2026-09-03 16:27:01 -04:00
parent db6043cb39
commit 1feb7c093e
210 changed files with 16655 additions and 299 deletions
+1 -3
View File
@@ -131,9 +131,7 @@ public class TestRunner {
summary.printTo(new PrintWriter(System.out));
summary.printFailuresTo(new PrintWriter(System.err));
if (summary.getTotalFailureCount() > 0) {
System.exit(1);
}
System.exit(summary.getTotalFailureCount() > 0 ? 1 : 0);
}
}
EOF
@@ -178,6 +178,38 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
viewMenu.add(themeMenu);
viewMenu.addSeparator();
JCheckBoxMenuItem rulerItem = new JCheckBoxMenuItem("Crosshair Ruler", terminalPanel.isCrosshairRulerEnabled());
ThemeManager.styleMenuItem(rulerItem);
rulerItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
rulerItem.addActionListener(e -> {
boolean en = rulerItem.isSelected();
terminalPanel.setCrosshairRulerEnabled(en);
haus.nightmare.j3270.config.Settings.setCrosshairRuler(en);
});
viewMenu.add(rulerItem);
JMenu cursorMenu = createMenu("Cursor Style");
ButtonGroup cursorGroup = new ButtonGroup();
JRadioButtonMenuItem blockCursorItem = new JRadioButtonMenuItem("Block Cursor", terminalPanel.getCursorStyle() == TerminalPanel.CursorStyle.BLOCK);
ThemeManager.styleMenuItem(blockCursorItem);
blockCursorItem.addActionListener(e -> {
terminalPanel.setCursorStyle(TerminalPanel.CursorStyle.BLOCK);
haus.nightmare.j3270.config.Settings.setCursorStyle("BLOCK");
});
cursorGroup.add(blockCursorItem);
cursorMenu.add(blockCursorItem);
JRadioButtonMenuItem underlineCursorItem = new JRadioButtonMenuItem("Underline Cursor", terminalPanel.getCursorStyle() == TerminalPanel.CursorStyle.UNDERLINE);
ThemeManager.styleMenuItem(underlineCursorItem);
underlineCursorItem.addActionListener(e -> {
terminalPanel.setCursorStyle(TerminalPanel.CursorStyle.UNDERLINE);
haus.nightmare.j3270.config.Settings.setCursorStyle("UNDERLINE");
});
cursorGroup.add(underlineCursorItem);
cursorMenu.add(underlineCursorItem);
viewMenu.add(cursorMenu);
viewMenu.addSeparator();
// CodePage Submenu
JMenu cpMenu = createMenu("Code Page");
String[] codePages = {
@@ -704,7 +736,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
"Delete — Delete character\n" +
"Backspace — Backspace\n" +
"Insert — Toggle insert mode\n" +
"Escape — Reset\n" +
"Escape / Alt+R — Reset\n" +
"PageUp/Down — PF7/PF8\n" +
"Alt+C / Alt+K — Clear\n" +
"Alt+E — Erase Input\n" +
@@ -713,6 +745,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
"Alt+Q — Cursor Select\n" +
"Alt+L — Toggle Light Pen\n" +
"Alt+T — File Transfer\n" +
"Alt+Shift+R — Crosshair Ruler\n" +
"Alt+=/-/0 — Font size +/-/reset\n" +
"Cmd/Ctrl+F — Find on Screen\n" +
"Cmd/Ctrl+G / F3— Find Next\n" +
@@ -893,10 +926,15 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate
}
TerminalModel model = TerminalModel.IBM_3279_4;
if (remainingArgs.size() >= 3) {
try {
int modelNum = Integer.parseInt(remainingArgs.get(2));
model = TerminalModel.forModel(modelNum, true);
} catch (Exception ignored) {}
String mArg = remainingArgs.get(2).trim();
if (mArg.equalsIgnoreCase("dynamic") || mArg.equals("0")) {
model = TerminalModel.IBM_DYNAMIC;
} else {
try {
int modelNum = Integer.parseInt(mArg);
model = TerminalModel.forModel(modelNum, true);
} catch (Exception ignored) {}
}
}
ConnectionConfig config = ConnectionConfig.parseHostString(hostArg, port, model);
if (finalTls) {
@@ -113,6 +113,22 @@ public class Settings {
prefs.put("codePage", (codePage != null && !codePage.trim().isEmpty()) ? codePage.trim() : "037");
}
public static int getDynamicRows() {
return prefs.getInt("dynamicRows", 62);
}
public static void setDynamicRows(int rows) {
prefs.putInt("dynamicRows", Math.max(1, rows));
}
public static int getDynamicCols() {
return prefs.getInt("dynamicCols", 160);
}
public static void setDynamicCols(int cols) {
prefs.putInt("dynamicCols", Math.max(1, cols));
}
public static Color getColorOverride(int index, Color defaultColor) {
String hex = prefs.get("color_" + index, null);
try {
@@ -233,6 +249,26 @@ public class Settings {
prefs.putBoolean("blockSelectMode", block);
}
// ========== Crosshair Ruler ==========
public static boolean getCrosshairRuler() {
return prefs.getBoolean("crosshairRuler", false);
}
public static void setCrosshairRuler(boolean enabled) {
prefs.putBoolean("crosshairRuler", enabled);
}
// ========== Cursor Style ==========
public static String getCursorStyle() {
return prefs.get("cursorStyle", "BLOCK");
}
public static void setCursorStyle(String style) {
prefs.put("cursorStyle", style != null ? style.toUpperCase() : "BLOCK");
}
private static void applyConfigEntry(String section, String key, String value) {
switch (section) {
case "appearance":
@@ -244,6 +280,13 @@ public class Settings {
case "uiTheme":
setJavaUiTheme(UITheme.fromString(value));
break;
case "crosshairRuler":
case "ruler":
setCrosshairRuler(Boolean.parseBoolean(value));
break;
case "cursorStyle":
setCursorStyle(value);
break;
default:
log.warning("Unknown appearance key: " + key);
}
@@ -284,6 +327,14 @@ public class Settings {
case "charset":
setCodePage(value);
break;
case "dynamicRows":
case "dynamic_rows":
setDynamicRows(Integer.parseInt(value));
break;
case "dynamicCols":
case "dynamic_cols":
setDynamicCols(Integer.parseInt(value));
break;
case "blockSelectMode": setBlockSelectMode(Boolean.parseBoolean(value)); break;
default:
log.warning("Unknown behavior/connection key: " + key);
@@ -340,6 +391,8 @@ public class Settings {
w.println("javaUiTheme = " + getJavaUiTheme().name());
w.println("fontFamily = " + getFontFamily());
w.println("fontSize = " + getFontSize());
w.println("crosshairRuler = " + getCrosshairRuler());
w.println("cursorStyle = " + getCursorStyle());
w.println();
// [behavior]
@@ -354,6 +407,8 @@ public class Settings {
w.println("autoConnectTn3270e = " + getAutoConnectTn3270e());
}
w.println("codePage = " + getCodePage());
w.println("dynamicRows = " + getDynamicRows());
w.println("dynamicCols = " + getDynamicCols());
w.println("blockSelectMode = " + getBlockSelectMode());
w.println();
@@ -14,6 +14,10 @@ public class ConnectDialog extends JDialog {
private JTextField hostField;
private JTextField portField;
private JComboBox<TerminalModel> modelCombo;
private JLabel dynamicDimLabel;
private JPanel dynamicDimPanel;
private JSpinner dynamicRowsSpinner;
private JSpinner dynamicColsSpinner;
private JComboBox<haus.nightmare.lib3270j.graphics.GraphicsMode> graphicsCombo;
private JComboBox<String> codePageCombo;
private JTextField luField;
@@ -79,10 +83,49 @@ public class ConnectDialog extends JDialog {
ThemeManager.styleComboBox(modelCombo);
mainPanel.add(modelCombo, gbc);
// LU Name
// Dynamic Dimensions (shown when IBM-DYNAMIC is selected)
gbc.gridx = 0;
gbc.gridy = 3;
gbc.weightx = 0;
dynamicDimLabel = new JLabel("Screen Size:");
dynamicDimLabel.setFont(labelFont);
mainPanel.add(dynamicDimLabel, gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
dynamicDimPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 0));
dynamicDimPanel.setOpaque(false);
JLabel rowsLabel = new JLabel("Rows:");
rowsLabel.setFont(labelFont);
dynamicRowsSpinner = new JSpinner(new SpinnerNumberModel(haus.nightmare.j3270.config.Settings.getDynamicRows(), 24, 255, 1));
ThemeManager.styleSpinner(dynamicRowsSpinner);
JLabel colsLabel = new JLabel("Cols:");
colsLabel.setFont(labelFont);
dynamicColsSpinner = new JSpinner(new SpinnerNumberModel(haus.nightmare.j3270.config.Settings.getDynamicCols(), 80, 255, 1));
ThemeManager.styleSpinner(dynamicColsSpinner);
dynamicDimPanel.add(rowsLabel);
dynamicDimPanel.add(dynamicRowsSpinner);
dynamicDimPanel.add(colsLabel);
dynamicDimPanel.add(dynamicColsSpinner);
mainPanel.add(dynamicDimPanel, gbc);
Runnable updateDynamicVisibility = () -> {
TerminalModel m = (TerminalModel) modelCombo.getSelectedItem();
boolean isDyn = (m != null && m.isDynamic());
dynamicDimLabel.setVisible(isDyn);
dynamicDimPanel.setVisible(isDyn);
pack();
};
modelCombo.addActionListener(e -> updateDynamicVisibility.run());
updateDynamicVisibility.run();
// LU Name
gbc.gridx = 0;
gbc.gridy = 4;
gbc.weightx = 0;
JLabel luLabel = new JLabel("LU Name:");
luLabel.setFont(labelFont);
mainPanel.add(luLabel, gbc);
@@ -93,7 +136,7 @@ public class ConnectDialog extends JDialog {
// Graphics Mode
gbc.gridx = 0;
gbc.gridy = 4;
gbc.gridy = 5;
gbc.weightx = 0;
JLabel graphicsLabel = new JLabel("Graphics:");
graphicsLabel.setFont(labelFont);
@@ -108,7 +151,7 @@ public class ConnectDialog extends JDialog {
// Code Page
gbc.gridx = 0;
gbc.gridy = 5;
gbc.gridy = 6;
gbc.weightx = 0;
JLabel cpLabel = new JLabel("Code Page:");
cpLabel.setFont(labelFont);
@@ -167,7 +210,7 @@ public class ConnectDialog extends JDialog {
// TLS / SSL Checkbox
gbc.gridx = 1;
gbc.gridy = 6;
gbc.gridy = 7;
gbc.weightx = 1.0;
tlsCheckBox = new JCheckBox("Enable TLS/SSL");
ThemeManager.styleCheckBox(tlsCheckBox);
@@ -186,7 +229,7 @@ public class ConnectDialog extends JDialog {
// Verify Certificate Checkbox
gbc.gridx = 1;
gbc.gridy = 7;
gbc.gridy = 8;
verifyCertCheckBox = new JCheckBox("Verify Server Certificate");
ThemeManager.styleCheckBox(verifyCertCheckBox);
verifyCertCheckBox.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 13));
@@ -196,7 +239,7 @@ public class ConnectDialog extends JDialog {
// TN3270E Checkbox
gbc.gridx = 1;
gbc.gridy = 8;
gbc.gridy = 9;
tn3270eCheckBox = new JCheckBox("Enable TN3270E (Extended 3270)");
ThemeManager.styleCheckBox(tn3270eCheckBox);
tn3270eCheckBox.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 13));
@@ -223,7 +266,7 @@ public class ConnectDialog extends JDialog {
buttonPanel.add(connectBtn);
gbc.gridx = 0;
gbc.gridy = 9;
gbc.gridy = 10;
gbc.gridwidth = 2;
mainPanel.add(buttonPanel, gbc);
@@ -256,7 +299,15 @@ public class ConnectDialog extends JDialog {
return;
}
result = new ConnectionConfig(host, port, (TerminalModel) modelCombo.getSelectedItem());
TerminalModel selectedModel = (TerminalModel) modelCombo.getSelectedItem();
result = new ConnectionConfig(host, port, selectedModel);
if (selectedModel != null && selectedModel.isDynamic()) {
int dRows = (Integer) dynamicRowsSpinner.getValue();
int dCols = (Integer) dynamicColsSpinner.getValue();
result.setDynamicDimensions(dRows, dCols);
haus.nightmare.j3270.config.Settings.setDynamicRows(dRows);
haus.nightmare.j3270.config.Settings.setDynamicCols(dCols);
}
String lu = luField.getText().trim();
if (!lu.isEmpty()) {
result.setLuName(lu);
@@ -98,19 +98,21 @@ public class ScreenExporter {
writer.write("<style>\n");
writer.write("body { background-color: #0a0a0a; color: #32cd32; font-family: 'Courier New', Courier, monospace; font-size: 14px; margin: 20px; }\n");
writer.write(".screen { background-color: #000; padding: 15px; border-radius: 4px; display: inline-block; box-shadow: 0 0 10px rgba(0,0,0,0.8); line-height: 1.2; }\n");
writer.write(".c-blue { color: #5078ff; }\n");
writer.write(".c-red { color: #ff3232; }\n");
writer.write(".c-pink { color: #ff82b4; }\n");
writer.write(".c-green { color: #32cd32; }\n");
writer.write(".c-turq { color: #40e0d0; }\n");
writer.write(".c-yellow { color: #ffff50; }\n");
writer.write(".c-blue { color: #7890f0; }\n");
writer.write(".c-red { color: #ff0000; }\n");
writer.write(".c-pink { color: #ff00ff; }\n");
writer.write(".c-green { color: #00ff00; }\n");
writer.write(".c-turq { color: #00ffff; }\n");
writer.write(".c-yellow { color: #ffff00; }\n");
writer.write(".c-white { color: #ffffff; }\n");
writer.write(".c-black { color: #000000; }\n");
writer.write(".c-orange { color: #ffa500; }\n");
writer.write(".c-purple { color: #b482ff; }\n");
writer.write(".c-palegreen { color: #90ee90; }\n");
writer.write(".c-paleturq { color: #afeeee; }\n");
writer.write(".c-grey { color: #aaaaaa; }\n");
writer.write(".c-deepblue { color: #000080; }\n");
writer.write(".c-orange { color: #ffa200; }\n");
writer.write(".c-purple { color: #800080; }\n");
writer.write(".c-palegreen { color: #008000; }\n");
writer.write(".c-paleturq { color: #008080; }\n");
writer.write(".c-mustard { color: #a0a000; }\n");
writer.write(".c-grey { color: #c0c0c0; }\n");
writer.write(".bold { font-weight: bold; }\n");
writer.write(".underline { text-decoration: underline; }\n");
writer.write("</style>\n</head>\n<body>\n<div class=\"screen\"><pre>");
@@ -209,17 +211,17 @@ public class ScreenExporter {
case 6: return "c-yellow";
case 7: return "c-white";
case 8: return "c-black";
case 9: return "c-blue";
case 9: return "c-deepblue";
case 10: return "c-orange";
case 11: return "c-purple";
case 12: return "c-palegreen";
case 13: return "c-paleturq";
case 14: return "c-grey";
case 15: return "c-white";
case 14: return "c-mustard";
case 15: return "c-grey";
}
}
if (faIsProtected(currentFA & 0xFF)) {
return faIsHigh(currentFA & 0xFF) ? "c-white" : "c-blue";
return faIsHigh(currentFA & 0xFF) ? "c-white" : "c-turq";
}
return faIsHigh(currentFA & 0xFF) ? "c-red" : "c-green";
}
@@ -31,6 +31,8 @@ public class SettingsDialog extends JDialog {
private JTextField hostField;
private JTextField portField;
private JCheckBox blockSelectCheck;
private JSpinner dynamicRowsSpinner;
private JSpinner dynamicColsSpinner;
// Advanced tab state tracking
private final Color[] tempHostColors = new Color[16];
@@ -235,8 +237,30 @@ public class SettingsDialog extends JDialog {
blockSelectCheck = new JCheckBox("Block selection mode (rectangular select)", Settings.getBlockSelectMode());
panel.add(blockSelectCheck, gbc);
// Placeholder for potentially more behavior options below
// Default Dynamic Screen Size
gbc.gridy = 3;
gbc.gridwidth = 1;
gbc.gridx = 0;
panel.add(new JLabel("Default Dynamic Screen:"), gbc);
JPanel dynDimPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 0));
dynDimPanel.setOpaque(false);
dynDimPanel.add(new JLabel("Rows:"));
dynamicRowsSpinner = new JSpinner(new SpinnerNumberModel(Settings.getDynamicRows(), 24, 255, 1));
ThemeManager.styleSpinner(dynamicRowsSpinner);
dynDimPanel.add(dynamicRowsSpinner);
dynDimPanel.add(new JLabel("Cols:"));
dynamicColsSpinner = new JSpinner(new SpinnerNumberModel(Settings.getDynamicCols(), 80, 255, 1));
ThemeManager.styleSpinner(dynamicColsSpinner);
dynDimPanel.add(dynamicColsSpinner);
gbc.gridx = 1;
panel.add(dynDimPanel, gbc);
// Placeholder for potentially more behavior options below
gbc.gridx = 0;
gbc.gridy = 4;
gbc.gridwidth = 2;
gbc.weighty = 1.0;
panel.add(Box.createGlue(), gbc);
@@ -555,6 +579,12 @@ public class SettingsDialog extends JDialog {
// Block select mode
Settings.setBlockSelectMode(blockSelectCheck.isSelected());
// Default Dynamic screen dimensions
if (dynamicRowsSpinner != null && dynamicColsSpinner != null) {
Settings.setDynamicRows((Integer) dynamicRowsSpinner.getValue());
Settings.setDynamicCols((Integer) dynamicColsSpinner.getValue());
}
// Propagate visual changes to the app
// Save Colors
for (int i=0; i<16; i++) {
@@ -110,25 +110,25 @@ public class StatusBar extends JPanel {
break;
case CONNECTED_3270:
connectionStatus.setText("TN3270");
connectionStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
connectionStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
break;
case CONNECTED_TN3270E:
connectionStatus.setText("TN3270E");
connectionStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
connectionStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
break;
case CONNECTED_SSCP:
connectionStatus.setText("SSCP-LU");
connectionStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
connectionStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
break;
case CONNECTED_NVT:
case CONNECTED_NVT_CHAR:
case CONNECTED_E_NVT:
connectionStatus.setText("NVT");
connectionStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
connectionStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
break;
case CONNECTED_UNBOUND:
connectionStatus.setText("Unbound");
connectionStatus.setForeground(ThemeManager.getOiaFgWarn(theme));
connectionStatus.setForeground(ThemeManager.getOiaAttention());
break;
default:
connectionStatus.setText(state.name());
@@ -144,11 +144,11 @@ public class StatusBar extends JPanel {
String protocol = session != null ? session.getProtocol() : "TLS";
if (verified) {
tlsStatus.setText("🔒 TLS");
tlsStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
tlsStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
tlsStatus.setToolTipText(protocol + " / " + cipher + " (Verified)");
} else {
tlsStatus.setText("🔓 TLS (Unverified)");
tlsStatus.setForeground(ThemeManager.getOiaFgWarn(theme));
tlsStatus.setForeground(ThemeManager.getOiaAttention());
tlsStatus.setToolTipText(protocol + " / " + cipher + " (Verification Bypassed)");
}
} else {
@@ -164,38 +164,46 @@ public class StatusBar extends JPanel {
lu = "LU:" + client.getConfig().getLuName();
}
luName.setText(lu);
luName.setForeground(ThemeManager.getOiaFgNormal(theme));
luName.setForeground(ThemeManager.getOiaStatusSysAvail());
// Lock / Inhibit status
int inhibit = client.getOIA().getInputInhibited();
if (inhibit != ECLConstants.INHIBIT_NOT_INHIBITED) {
Color lockFg = ThemeManager.getOiaInputInhibited(); // White (oII)
switch (inhibit) {
case ECLConstants.INHIBIT_SYSTEM_LOCK:
lockStatus.setText("X SYSTEM");
lockFg = ThemeManager.getOiaInputInhibited(); // White (oII)
break;
case ECLConstants.INHIBIT_COMM_CHECK:
lockStatus.setText("X COMM");
lockFg = ThemeManager.getOiaCommCheck(); // Red (oEI)
break;
case ECLConstants.INHIBIT_NUMERIC_ONLY:
lockStatus.setText("X NUM");
lockFg = ThemeManager.getOiaAttention(); // Yellow (oAI)
break;
case ECLConstants.INHIBIT_PROTECTED_FIELD:
lockStatus.setText("X PROT");
lockFg = ThemeManager.getOiaInputInhibited(); // White (oII)
break;
case ECLConstants.INHIBIT_OVERFLOW:
lockStatus.setText("X >");
lockFg = ThemeManager.getOiaAttention(); // Yellow (oAI)
break;
case ECLConstants.INHIBIT_OPERATOR_DUE:
lockStatus.setText("X OP");
lockFg = ThemeManager.getOiaAttention(); // Yellow (oAI)
break;
default:
lockStatus.setText("X LOCKED");
lockFg = ThemeManager.getOiaInputInhibited(); // White (oII)
break;
}
lockStatus.setForeground(ThemeManager.getOiaFgAlert(theme));
lockStatus.setForeground(lockFg);
} else if (client.getInputProcessor().isInsertMode()) {
lockStatus.setText("INSERT");
lockStatus.setForeground(ThemeManager.getOiaFgNormal(theme));
lockStatus.setForeground(ThemeManager.getOiaStatusSysAvail());
} else {
lockStatus.setText("");
}
@@ -223,7 +231,13 @@ public class StatusBar extends JPanel {
ScreenBuffer sb = client.getScreenBuffer();
int rows = sb.getDisplayRows();
int cols = sb.getDisplayCols();
modelInfo.setText(client.getConfig().getModel().name().replace('_', '-') + " [" + rows + "x" + cols + "]");
String modelName;
if (client.getConfig().isDynamicModel() || (client.getConfig().getModel() != null && client.getConfig().getModel().isDynamic())) {
modelName = "IBM-DYNAMIC [" + rows + "x" + cols + "]";
} else {
modelName = client.getConfig().getModel().name().replace('_', '-') + " [" + rows + "x" + cols + "]";
}
modelInfo.setText(modelName);
modelInfo.setForeground(ThemeManager.getOiaFgDim(theme));
// Cursor position and buffer address
@@ -57,11 +57,22 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
CHAR_STRINGS[i] = String.valueOf((char) i);
}
}
public enum CursorStyle {
BLOCK,
UNDERLINE
}
private CursorStyle cursorStyle = CursorStyle.BLOCK;
private static final Color CURSOR_COLOR = new Color(255, 255, 255, 180);
private boolean crosshairRulerEnabled = false;
private static final Color CROSSHAIR_RULER_COLOR = new Color(0, 255, 0, 102); // 40% alpha (cRC)
private boolean textBlinkVisible = true;
private Image wallpaperImage = null;
private haus.nightmare.lib3270j.graphics.HODWallpaper hodWallpaper = null;
private int selectionStartRow = -1, selectionStartCol = -1;
private int selectionEndRow = -1, selectionEndCol = -1;
private boolean isDragging = false;
private static final Color SELECTION_COLOR = new Color(75, 110, 175, 100);
private static final Color SELECTION_COLOR = new Color(75, 110, 175, 102); // 40% alpha blend
// ========== Search Highlight state ==========
private int searchHighlightAddr = -1;
@@ -96,31 +107,31 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
return Math.max(padding, extra / 2);
}
// Default Host color mapping
// Default Host color mapping aligned 1:1 with IBM Host On-Demand ColorRemapModel3270
public static final Color[] DEFAULT_HOST_COLORS = {
new Color(0, 0, 0), // 0: Neutral Black
new Color(80, 120, 255), // 1: Blue
new Color(255, 50, 50), // 2: Red
new Color(255, 130, 180), // 3: Pink
new Color(50, 205, 50), // 4: Green
new Color(64, 224, 208), // 5: Turquoise
new Color(255, 255, 80), // 6: Yellow
new Color(120, 144, 240), // 1: Blue (0x7890F0 CUSTOMBLUE)
new Color(255, 0, 0), // 2: Red
new Color(255, 0, 255), // 3: Pink
new Color(0, 255, 0), // 4: Green
new Color(0, 255, 255), // 5: Turquoise / Cyan
new Color(255, 255, 0), // 6: Yellow
new Color(255, 255, 255), // 7: Neutral White
new Color(0, 0, 0), // 8: Black
new Color(30, 60, 180), // 9: Deep Blue
new Color(255, 165, 0), // 10: Orange
new Color(180, 130, 255), // 11: Purple
new Color(144, 238, 144), // 12: Pale Green
new Color(175, 238, 238), // 13: Pale Turquoise
new Color(170, 170, 170), // 14: Grey
new Color(255, 255, 255), // 15: White
new Color(0, 0, 128), // 9: Deep Blue
new Color(255, 162, 0), // 10: Orange (0xFFFFA200)
new Color(128, 0, 128), // 11: Purple
new Color(0, 128, 0), // 12: Pale Green
new Color(0, 128, 128), // 13: Pale Turquoise
new Color(160, 160, 0), // 14: Mustard (0xFFA0A000)
new Color(192, 192, 192), // 15: Grey (0xFFC0C0C0)
};
// Default 3278 monochrome colors
public static final Color DEFAULT_MONO_NORMAL = new Color(50, 205, 50);
public static final Color DEFAULT_MONO_INTENSIFY = new Color(255, 255, 255);
public static final Color DEFAULT_MONO_PROTECTED = new Color(80, 120, 255);
public static final Color DEFAULT_MONO_PROTECTED_HIGH = new Color(255, 255, 255);
// Default 3278 / base monochrome colors aligned with HoD
public static final Color DEFAULT_MONO_NORMAL = new Color(0, 255, 0); // Green
public static final Color DEFAULT_MONO_INTENSIFY = new Color(255, 0, 0); // Red
public static final Color DEFAULT_MONO_PROTECTED = new Color(0, 255, 255); // Cyan / Turquoise
public static final Color DEFAULT_MONO_PROTECTED_HIGH = new Color(255, 255, 255); // White
// Default Background
public static final Color DEFAULT_BG_COLOR = Color.BLACK;
@@ -138,6 +149,9 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
setupCursorBlink();
blockSelectMode = haus.nightmare.j3270.config.Settings.getBlockSelectMode();
crosshairRulerEnabled = haus.nightmare.j3270.config.Settings.getCrosshairRuler();
String cStyle = haus.nightmare.j3270.config.Settings.getCursorStyle();
cursorStyle = "UNDERLINE".equalsIgnoreCase(cStyle) ? CursorStyle.UNDERLINE : CursorStyle.BLOCK;
// Handle mouse clicks to position cursor, selection, and grab focus
MouseAdapter mouseHandler = new MouseAdapter() {
@@ -1075,6 +1089,9 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
setupKeyBindings();
setupFont();
blockSelectMode = haus.nightmare.j3270.config.Settings.getBlockSelectMode();
crosshairRulerEnabled = haus.nightmare.j3270.config.Settings.getCrosshairRuler();
String cStyle = haus.nightmare.j3270.config.Settings.getCursorStyle();
cursorStyle = "UNDERLINE".equalsIgnoreCase(cStyle) ? CursorStyle.UNDERLINE : CursorStyle.BLOCK;
revalidate();
repaint();
}
@@ -1103,13 +1120,18 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
}
private void setupCursorBlink() {
blinkTimer = new Timer(530, e -> {
blinkTimer = new Timer(500, e -> {
cursorVisible = !cursorVisible;
textBlinkVisible = !textBlinkVisible;
repaint();
});
blinkTimer.start();
}
public Telnet3270Client getClient() {
return client;
}
public void setClient(Telnet3270Client client) {
this.client = client;
if (client != null) {
@@ -1247,7 +1269,18 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
int cols = sb.getDisplayCols();
boolean isColorModel = client.getConfig().getModel().isColor();
// Draw Vector Graphics Plane under text if present
// Layer 0: Optional Wallpaper / Background Image
if (hodWallpaper != null) {
int gridW = cols * cellWidth;
int gridH = rows * cellHeight;
hodWallpaper.paint(this, g2, ox, oy, gridW, gridH);
} else if (wallpaperImage != null) {
int gridW = cols * cellWidth;
int gridH = rows * cellHeight;
g2.drawImage(wallpaperImage, ox, oy, gridW, gridH, null);
}
// Layer 1: Draw Vector Graphics Plane under text if present
if (client.getGraphicsPlane() != null && client.getGraphicsPlane().hasContent()) {
int gridW = cols * cellWidth;
int gridH = rows * cellHeight;
@@ -1269,6 +1302,22 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
}
}
// Layer 2: Optional Crosshair Ruler under character glyphs
if (crosshairRulerEnabled && client.getConnectionState().isFullSession()) {
int curAddr = sb.getDisplayCursorAddress();
int curRow = curAddr / cols;
int curCol = curAddr % cols;
int cx = ox + curCol * cellWidth;
int cy = oy + curRow * cellHeight;
int gridW = cols * cellWidth;
int gridH = rows * cellHeight;
g2.setColor(CROSSHAIR_RULER_COLOR);
g2.fillRect(ox, cy, gridW, cellHeight);
g2.fillRect(cx, oy, cellWidth, gridH);
}
// Layer 3: Character / Text Plane
byte currentFA = 0;
ExtendedAttribute currentFieldEa = null;
@@ -1296,7 +1345,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
continue;
}
// Determine foreground color
// Determine foreground and background colors
if (isColorModel) {
fgColor = getColorForAttribute(ea, currentFieldEa, currentFA);
bgColor = getBackgroundForAttribute(ea, currentFieldEa);
@@ -1305,6 +1354,9 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
bgColor = this.bgColor;
}
int rawBg = ea.bg != 0 ? (ea.bg & 0xFF) : (currentFieldEa != null ? (currentFieldEa.bg & 0xFF) : 0);
boolean bgIsExplicit = (rawBg >= 0xF0 && rawBg <= 0xFF && rawBg != HOST_COLOR_NEUTRAL_BLACK && rawBg != HOST_COLOR_BLACK);
// Graphics rendition
byte gr = ea.gr != 0 ? ea.gr : (currentFieldEa != null ? currentFieldEa.gr : 0);
if (gr != 0) {
@@ -1334,22 +1386,26 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
if (reverse) {
Color tmp = fgColor;
fgColor = bgColor;
fgColor = (rawBg == 0) ? this.bgColor : bgColor;
bgColor = tmp;
}
if (!bgColor.equals(this.bgColor) || reverse) {
g2.setColor(bgColor);
g2.fillRect(x, y, cellWidth, cellHeight);
} else if (bgIsExplicit || !bgColor.equals(this.bgColor)) {
g2.setColor(bgColor);
g2.fillRect(x, y, cellWidth, cellHeight);
}
// Check text blink (500ms cycle)
boolean blink = (gr & GR_BLINK) != 0;
boolean suppressGlyph = blink && !textBlinkVisible;
// Draw character or Programmed Symbol
int cs = (ea.cs != 0) ? (ea.cs & 0xFF) : (currentFieldEa != null ? (currentFieldEa.cs & 0xFF) : 0);
boolean drawnAsPs = false;
if (cs >= 0x40 && client.getProgramSymbolManager() != null) {
if (cs >= 0x40 && client.getProgramSymbolManager() != null && !suppressGlyph) {
haus.nightmare.lib3270j.graphics.ProgramSymbolSet.SymbolSlot slot = client.getProgramSymbolManager().getSymbol(cs, ea.ec & 0xFF);
if (slot != null) {
int symBg = (!bgColor.equals(this.bgColor) || reverse) ? bgColor.getRGB() : 0;
int symBg = (bgIsExplicit || reverse) ? bgColor.getRGB() : 0;
java.awt.image.BufferedImage img = slot.getScaledImage(cellWidth, cellHeight, fgColor.getRGB(), symBg);
if (img != null) {
g2.drawImage(img, x, y, null);
@@ -1358,7 +1414,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
}
}
if (!drawnAsPs) {
if (!drawnAsPs && !suppressGlyph) {
char ch = ea.ucs4;
if (ch > 0x20 && ch != 0xFF) {
Font f = bold ? boldTerminalFont : terminalFont;
@@ -1385,7 +1441,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
g2.fillRect(x, y, cellWidth, cellHeight);
}
// Draw selection highlight
// Draw selection highlight (40% alpha blend over cell)
if (isCellSelected(row, col)) {
g2.setColor(SELECTION_COLOR);
g2.fillRect(x, y, cellWidth, cellHeight);
@@ -1394,9 +1450,15 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
}
// Draw Graphic Cursor if active
if (client.getGocaDecoder() != null && client.getGocaDecoder().isGraphicsCursorActive() && client.getGraphicsPlane() != null) {
int gocaX = client.getGocaDecoder().getGraphicCursorX();
int gocaY = client.getGocaDecoder().getGraphicCursorY();
boolean isGraphicCursor = (client.getGocaDecoder() != null && client.getGocaDecoder().isGraphicsCursorActive())
|| (client.getGraphicsPlane() != null && client.getGraphicsPlane().isGraphicCursorAttached());
if (isGraphicCursor && client.getGraphicsPlane() != null) {
int gocaX = (client.getGocaDecoder() != null && client.getGocaDecoder().isGraphicsCursorActive())
? client.getGocaDecoder().getGraphicCursorX()
: client.getGraphicsPlane().getGraphicCursorX();
int gocaY = (client.getGocaDecoder() != null && client.getGocaDecoder().isGraphicsCursorActive())
? client.getGocaDecoder().getGraphicCursorY()
: client.getGraphicsPlane().getGraphicCursorY();
int canvasPx = client.getGraphicsPlane().mapX(gocaX);
int canvasPy = client.getGraphicsPlane().mapY(gocaY);
int gridW = cols * cellWidth;
@@ -1408,12 +1470,19 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
g2.setColor(Color.WHITE);
g2.setXORMode(Color.BLACK);
g2.drawLine(px - 6, py, px + 6, py);
g2.drawLine(px, py - 6, px, py + 6);
int shape = client.getGraphicsPlane().getHodCursorShape();
if (shape == 2) {
// Shape 2: Box cursor per HoD
g2.drawRect(px - 3, py - 3, 6, 6);
} else {
// Shape 1 (default): Crosshair per HoD
g2.drawLine(px - 8, py, px + 8, py);
g2.drawLine(px, py - 8, px, py + 8);
}
g2.setPaintMode();
}
// Draw 3270 text cursor
// Draw 3270 text cursor with alpha blending (Block / Underline)
if (cursorVisible && client.getConnectionState().isFullSession()) {
int curAddr = sb.getDisplayCursorAddress();
int curRow = curAddr / cols;
@@ -1421,13 +1490,79 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
int cx = ox + curCol * cellWidth;
int cy = oy + curRow * cellHeight;
boolean isUnderline = (cursorStyle == CursorStyle.UNDERLINE) ||
(client.getInputProcessor() != null && client.getInputProcessor().isInsertMode());
g2.setColor(CURSOR_COLOR);
g2.setXORMode(bgColor);
g2.fillRect(cx, cy, cellWidth, cellHeight);
g2.setPaintMode();
if (isUnderline) {
int ulH = Math.max(2, cellHeight / 6);
g2.fillRect(cx, cy + cellHeight - ulH, cellWidth, ulH);
} else {
g2.fillRect(cx, cy, cellWidth, cellHeight);
}
}
}
public boolean isCrosshairRulerEnabled() {
return crosshairRulerEnabled;
}
public void setCrosshairRulerEnabled(boolean enabled) {
this.crosshairRulerEnabled = enabled;
repaint();
}
public void toggleCrosshairRuler() {
setCrosshairRulerEnabled(!crosshairRulerEnabled);
}
public CursorStyle getCursorStyle() {
return cursorStyle;
}
public void setCursorStyle(CursorStyle style) {
this.cursorStyle = (style != null) ? style : CursorStyle.BLOCK;
repaint();
}
public Image getWallpaperImage() {
return wallpaperImage;
}
public void setWallpaperImage(Image wallpaperImage) {
this.wallpaperImage = wallpaperImage;
if (wallpaperImage != null) {
if (this.hodWallpaper == null) {
this.hodWallpaper = new haus.nightmare.lib3270j.graphics.HODWallpaper(wallpaperImage, haus.nightmare.lib3270j.graphics.HODWallpaper.HOD_STRETCH);
} else {
this.hodWallpaper.setImage(wallpaperImage);
}
} else {
this.hodWallpaper = null;
}
repaint();
}
public haus.nightmare.lib3270j.graphics.HODWallpaper getHodWallpaper() {
return hodWallpaper;
}
public void setHodWallpaper(haus.nightmare.lib3270j.graphics.HODWallpaper wallpaper) {
this.hodWallpaper = wallpaper;
if (wallpaper != null) {
this.wallpaperImage = wallpaper.getHODImage();
}
repaint();
}
public void setWallpaperMode(int displayMode) {
if (this.hodWallpaper == null && this.wallpaperImage != null) {
this.hodWallpaper = new haus.nightmare.lib3270j.graphics.HODWallpaper(this.wallpaperImage, displayMode);
} else if (this.hodWallpaper != null) {
this.hodWallpaper.setDisplay(displayMode);
}
repaint();
}
private Color getColorForAttribute(ExtendedAttribute ea, ExtendedAttribute currentFieldEa, byte currentFA) {
int fg = ea.fg != 0 ? (ea.fg & 0xFF)
: (currentFieldEa != null && currentFieldEa.fg != 0 ? (currentFieldEa.fg & 0xFF) : 0);
@@ -1435,7 +1570,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
return hostColors[fg - 0xf0];
}
if (faIsProtected(currentFA & 0xFF)) {
return faIsHigh(currentFA & 0xFF) ? hostColors[HOST_COLOR_WHITE] : hostColors[HOST_COLOR_BLUE];
return faIsHigh(currentFA & 0xFF) ? hostColors[HOST_COLOR_WHITE] : hostColors[HOST_COLOR_TURQUOISE];
}
return faIsHigh(currentFA & 0xFF) ? hostColors[HOST_COLOR_RED] : hostColors[HOST_COLOR_GREEN];
}
@@ -244,6 +244,19 @@ public final class ThemeManager {
return t == UITheme.DARK ? new Color(255, 190, 70) : new Color(180, 100, 0);
}
// Host On-Demand OIA Category Colors (oSI, oII, oAI, oEI, oOB)
public static final Color HOD_OIA_STATUS_SYS_AVAIL = new Color(120, 144, 240); // oSI: CUSTOMBLUE
public static final Color HOD_OIA_INPUT_INHIBITED = new Color(255, 255, 255); // oII: White
public static final Color HOD_OIA_ATTENTION_WARN = new Color(255, 255, 0); // oAI: Yellow
public static final Color HOD_OIA_COMM_CHECK_ERROR = new Color(255, 0, 0); // oEI: Red
public static final Color HOD_OIA_BG_BLACK = new Color(0, 0, 0); // oOB: Black
public static Color getOiaStatusSysAvail() { return HOD_OIA_STATUS_SYS_AVAIL; }
public static Color getOiaInputInhibited() { return HOD_OIA_INPUT_INHIBITED; }
public static Color getOiaAttention() { return HOD_OIA_ATTENTION_WARN; }
public static Color getOiaCommCheck() { return HOD_OIA_COMM_CHECK_ERROR; }
public static Color getOiaBackground() { return HOD_OIA_BG_BLACK; }
// =========================================================================
// Button Variants & Color helpers
// =========================================================================
@@ -58,12 +58,26 @@ public class MenuBarShortcutsTest {
assertNotNull(fileMenu, "File menu should exist");
assertNotNull(editMenu, "Edit menu should exist");
// Verify View Menu items use ALT_DOWN_MASK
// Verify View Menu items
Map<String, JMenuItem> viewItems = collectMenuItems(viewMenu);
assertAcceleratorUsesAlt(viewItems.get("Font Size +"), KeyEvent.VK_EQUALS);
assertAcceleratorUsesAlt(viewItems.get("Font Size -"), KeyEvent.VK_MINUS);
assertAcceleratorUsesAlt(viewItems.get("Reset Font"), KeyEvent.VK_0);
// Crosshair Ruler must use Alt+Shift+R
JMenuItem rulerItem = viewItems.get("Crosshair Ruler");
assertNotNull(rulerItem, "Crosshair Ruler menu item must exist");
KeyStroke rulerKs = rulerItem.getAccelerator();
assertNotNull(rulerKs, "Crosshair Ruler should have an accelerator");
assertEquals(KeyEvent.VK_R, rulerKs.getKeyCode(), "Key code mismatch for Crosshair Ruler");
int rulerMods = rulerKs.getModifiers();
assertTrue((rulerMods & (KeyEvent.ALT_DOWN_MASK | KeyEvent.ALT_MASK)) != 0,
"Crosshair Ruler accelerator must have ALT modifier");
assertTrue((rulerMods & (KeyEvent.SHIFT_DOWN_MASK | KeyEvent.SHIFT_MASK)) != 0,
"Crosshair Ruler accelerator must have SHIFT modifier");
assertEquals(0, rulerMods & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK | KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK),
"Crosshair Ruler accelerator must NOT have CTRL or META modifiers");
// Verify Actions Menu items use ALT_DOWN_MASK
Map<String, JMenuItem> actionItems = collectMenuItems(actionsMenu);
assertAcceleratorUsesAlt(actionItems.get("Send Enter"), KeyEvent.VK_ENTER);
@@ -75,6 +89,10 @@ public class MenuBarShortcutsTest {
assertAcceleratorUsesAlt(actionItems.get("Cursor Select"), KeyEvent.VK_Q);
assertAcceleratorUsesAlt(actionItems.get("Toggle Light Pen (Alt+L)"), KeyEvent.VK_L);
assertAcceleratorUsesAlt(actionItems.get("File Transfer..."), KeyEvent.VK_T);
// Ensure Crosshair Ruler and Reset do not collide
assertNotEquals(rulerKs, actionItems.get("Reset").getAccelerator(),
"Crosshair Ruler and Reset accelerators must not collide");
} finally {
// Dispose frame
app.dispose();
@@ -89,6 +107,8 @@ public class MenuBarShortcutsTest {
int mods = ks.getModifiers();
assertTrue((mods & (KeyEvent.ALT_DOWN_MASK | KeyEvent.ALT_MASK)) != 0,
"Menu item " + item.getText() + " accelerator must have ALT modifier");
assertEquals(0, mods & (KeyEvent.SHIFT_DOWN_MASK | KeyEvent.SHIFT_MASK),
"Menu item " + item.getText() + " accelerator must NOT have SHIFT modifier");
assertEquals(0, mods & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK | KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK),
"Menu item " + item.getText() + " accelerator must NOT have CTRL or META modifiers");
}
@@ -0,0 +1,104 @@
package haus.nightmare.j3270.ui;
import haus.nightmare.j3270.config.Settings;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.awt.Color;
import java.awt.HeadlessException;
import static org.junit.jupiter.api.Assertions.*;
/**
* Verification test suite for Phase 1 UI Overlays and Color Alignment.
* Covers items 1.1, 1.2, and 1.5 of the PhasedUpdates specification.
*/
public class Phase1UiOverlayTest {
@Test
@DisplayName("Item 1.1 & 1.2: TerminalPanel host and mono colors match IBM Host On-Demand specs")
public void testTerminalPanelColorAlignment() {
// Index 10: Orange (255, 162, 0)
assertEquals(new Color(255, 162, 0), TerminalPanel.DEFAULT_HOST_COLORS[10]);
// Index 14: Mustard (160, 160, 0)
assertEquals(new Color(160, 160, 0), TerminalPanel.DEFAULT_HOST_COLORS[14]);
// Index 1: Blue (120, 144, 240)
assertEquals(new Color(120, 144, 240), TerminalPanel.DEFAULT_HOST_COLORS[1]);
// Base 4-Color mono defaults
assertEquals(new Color(0, 255, 0), TerminalPanel.DEFAULT_MONO_NORMAL);
assertEquals(new Color(255, 0, 0), TerminalPanel.DEFAULT_MONO_INTENSIFY);
assertEquals(new Color(0, 255, 255), TerminalPanel.DEFAULT_MONO_PROTECTED);
assertEquals(new Color(255, 255, 255), TerminalPanel.DEFAULT_MONO_PROTECTED_HIGH);
}
@Test
@DisplayName("Item 1.5: ThemeManager HoD OIA category colors match specification")
public void testThemeManagerOiaColors() {
// oSI: Status / System Available -> CUSTOMBLUE (120, 144, 240)
assertEquals(new Color(120, 144, 240), ThemeManager.getOiaStatusSysAvail());
// oII: Input Inhibited / X SYSTEM -> White (255, 255, 255)
assertEquals(new Color(255, 255, 255), ThemeManager.getOiaInputInhibited());
// oAI: Attention / Reminders / Message Waiting -> Yellow (255, 255, 0)
assertEquals(new Color(255, 255, 0), ThemeManager.getOiaAttention());
// oEI: Error Checks / Comm Check -> Red (255, 0, 0)
assertEquals(new Color(255, 0, 0), ThemeManager.getOiaCommCheck());
// oOB: OIA Separator / Background -> Black (0, 0, 0)
assertEquals(new Color(0, 0, 0), ThemeManager.getOiaBackground());
}
@Test
@DisplayName("Item 1.5: TerminalPanel Crosshair Ruler and Cursor Style controls")
public void testTerminalPanelRulerAndCursorStyle() {
try {
TerminalPanel panel = new TerminalPanel();
// Default cursor style is BLOCK
assertEquals(TerminalPanel.CursorStyle.BLOCK, panel.getCursorStyle());
panel.setCursorStyle(TerminalPanel.CursorStyle.UNDERLINE);
assertEquals(TerminalPanel.CursorStyle.UNDERLINE, panel.getCursorStyle());
// Crosshair ruler toggling
assertFalse(panel.isCrosshairRulerEnabled());
panel.setCrosshairRulerEnabled(true);
assertTrue(panel.isCrosshairRulerEnabled());
panel.toggleCrosshairRuler();
assertFalse(panel.isCrosshairRulerEnabled());
// Wallpaper image setter
assertNull(panel.getWallpaperImage());
} catch (HeadlessException e) {
// Handled gracefully in headless CI environments
}
}
@Test
@DisplayName("Settings persistence for Crosshair Ruler and Cursor Style")
public void testSettingsPersistence() {
boolean originalRuler = Settings.getCrosshairRuler();
String originalCursor = Settings.getCursorStyle();
try {
Settings.setCrosshairRuler(true);
assertTrue(Settings.getCrosshairRuler());
Settings.setCrosshairRuler(false);
assertFalse(Settings.getCrosshairRuler());
Settings.setCursorStyle("UNDERLINE");
assertEquals("UNDERLINE", Settings.getCursorStyle());
Settings.setCursorStyle("BLOCK");
assertEquals("BLOCK", Settings.getCursorStyle());
} finally {
Settings.setCrosshairRuler(originalRuler);
Settings.setCursorStyle(originalCursor);
}
}
}
@@ -0,0 +1,95 @@
package haus.nightmare.j3270.ui;
import haus.nightmare.lib3270j.graphics.GocaConstants;
import haus.nightmare.lib3270j.graphics.GraphicsPlane;
import haus.nightmare.lib3270j.graphics.HODWallpaper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.image.BufferedImage;
import static org.junit.jupiter.api.Assertions.*;
/**
* Verification test suite for Phase 2 UI Vector Graphics, Wallpaper, and Cursor Overlays.
*/
public class Phase2UiGraphicsTest {
@Test
@DisplayName("Test TerminalPanel Wallpaper Integration (Tile, Center, Stretch)")
public void testTerminalPanelWallpaperModes() {
try {
TerminalPanel panel = new TerminalPanel();
assertNull(panel.getHodWallpaper());
assertNull(panel.getWallpaperImage());
BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
panel.setWallpaperImage(img);
assertNotNull(panel.getWallpaperImage());
assertNotNull(panel.getHodWallpaper());
assertEquals(HODWallpaper.HOD_STRETCH, panel.getHodWallpaper().getDisplay());
panel.setWallpaperMode(HODWallpaper.HOD_TILE);
assertEquals(HODWallpaper.HOD_TILE, panel.getHodWallpaper().getDisplay());
panel.setWallpaperMode(HODWallpaper.HOD_CENTER);
assertEquals(HODWallpaper.HOD_CENTER, panel.getHodWallpaper().getDisplay());
HODWallpaper customWp = new HODWallpaper(img, HODWallpaper.HOD_TILE);
panel.setHodWallpaper(customWp);
assertSame(customWp, panel.getHodWallpaper());
// Clear wallpaper
panel.setWallpaperImage(null);
assertNull(panel.getHodWallpaper());
assertNull(panel.getWallpaperImage());
} catch (HeadlessException e) {
// Handled gracefully in headless environments
}
}
@Test
@DisplayName("Test Graphics Plane Cursor Synchronization and Rendering")
public void testGraphicsCursorOverlay() {
try {
TerminalPanel panel = new TerminalPanel();
panel.setSize(new Dimension(800, 600));
panel.setClient(new haus.nightmare.lib3270j.Telnet3270Client(new haus.nightmare.lib3270j.ConnectionConfig("localhost", 23)));
GraphicsPlane plane = panel.getClient() != null ? panel.getClient().getGraphicsPlane() : null;
if (plane != null) {
// Attach graphics cursor
plane.attachGraphicCursor(100, 100);
plane.setHodCursorShape(GocaConstants.GCURSOR_SHAPE_CROSSHAIR);
assertTrue(plane.isGraphicCursorAttached());
assertEquals(100, plane.getGraphicCursorX());
assertEquals(100, plane.getGraphicCursorY());
assertEquals(1, plane.getHodCursorShape());
// Paint component to verify no exceptions during rendering
BufferedImage offscreen = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = offscreen.createGraphics();
panel.paint(g2);
g2.dispose();
// Change cursor shape to box
plane.setHodCursorShape(GocaConstants.GCURSOR_SHAPE_BOX);
assertEquals(2, plane.getHodCursorShape());
offscreen = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
g2 = offscreen.createGraphics();
panel.paint(g2);
g2.dispose();
// Detach graphics cursor
plane.detachGraphicCursor();
assertFalse(plane.isGraphicCursorAttached());
}
} catch (HeadlessException e) {
// Handled gracefully in headless environments
}
}
}
@@ -18,6 +18,16 @@ public class ConnectionConfig {
private boolean tlsVerifyCert = true;
private haus.nightmare.lib3270j.tls.TlsCertificateVerifier certificateVerifier = null;
private String sslProtocol = "TLS";
private String keyStorePath = null;
private String keyStorePassword = null;
private String keyStoreType = null;
private String keyStoreAlias = null;
private String trustStorePath = null;
private String trustStorePassword = null;
private String trustStoreType = null;
private ClassLoader customizedCAsClassLoader = null;
private java.util.List<String> enabledProtocols = new java.util.ArrayList<>();
private java.util.List<String> enabledCipherSuites = new java.util.ArrayList<>();
private int connectTimeoutMs = 15000;
private int nopIntervalSeconds = 0;
private String terminalName = null; // override terminal type string
@@ -27,8 +37,8 @@ public class ConnectionConfig {
private int soTimeoutMs = 0;
private java.util.List<String> luNames = new java.util.ArrayList<>();
private boolean dynamicModel = false;
private int dynamicRows = 24;
private int dynamicCols = 80;
private int dynamicRows = 62;
private int dynamicCols = 160;
private haus.nightmare.lib3270j.graphics.GraphicsMode graphicsMode = haus.nightmare.lib3270j.graphics.GraphicsMode.BOTH;
private String codePage = "037";
private String associatedPrinterLu = null;
@@ -81,7 +91,12 @@ public class ConnectionConfig {
public void setPort(int port) { this.port = port; }
public TerminalModel getModel() { return model; }
public void setModel(TerminalModel model) { this.model = model; }
public void setModel(TerminalModel model) {
this.model = model;
if (model != null && model.isDynamic()) {
this.dynamicModel = true;
}
}
public String getLuName() { return luName; }
public void setLuName(String luName) { this.luName = luName; }
@@ -104,6 +119,52 @@ public class ConnectionConfig {
public String getSslProtocol() { return sslProtocol; }
public void setSslProtocol(String protocol) { this.sslProtocol = protocol; }
public String getKeyStorePath() { return keyStorePath; }
public void setKeyStorePath(String path) { this.keyStorePath = path; }
public String getKeyStorePassword() { return keyStorePassword; }
public void setKeyStorePassword(String password) { this.keyStorePassword = password; }
public String getKeyStoreType() { return keyStoreType; }
public void setKeyStoreType(String type) { this.keyStoreType = type; }
public String getKeyStoreAlias() { return keyStoreAlias; }
public void setKeyStoreAlias(String alias) { this.keyStoreAlias = alias; }
public String getTrustStorePath() { return trustStorePath; }
public void setTrustStorePath(String path) { this.trustStorePath = path; }
public String getTrustStorePassword() { return trustStorePassword; }
public void setTrustStorePassword(String password) { this.trustStorePassword = password; }
public String getTrustStoreType() { return trustStoreType; }
public void setTrustStoreType(String type) { this.trustStoreType = type; }
public ClassLoader getCustomizedCAsClassLoader() { return customizedCAsClassLoader; }
public void setCustomizedCAsClassLoader(ClassLoader cl) { this.customizedCAsClassLoader = cl; }
public java.util.List<String> getEnabledProtocols() { return enabledProtocols; }
public void setEnabledProtocols(java.util.List<String> protocols) {
this.enabledProtocols = protocols != null ? new java.util.ArrayList<>(protocols) : new java.util.ArrayList<>();
}
public void setEnabledProtocols(String... protocols) {
this.enabledProtocols = new java.util.ArrayList<>();
if (protocols != null) {
for (String p : protocols) if (p != null) this.enabledProtocols.add(p);
}
}
public java.util.List<String> getEnabledCipherSuites() { return enabledCipherSuites; }
public void setEnabledCipherSuites(java.util.List<String> cipherSuites) {
this.enabledCipherSuites = cipherSuites != null ? new java.util.ArrayList<>(cipherSuites) : new java.util.ArrayList<>();
}
public void setEnabledCipherSuites(String... cipherSuites) {
this.enabledCipherSuites = new java.util.ArrayList<>();
if (cipherSuites != null) {
for (String c : cipherSuites) if (c != null) this.enabledCipherSuites.add(c);
}
}
public int getConnectTimeoutMs() { return connectTimeoutMs; }
public void setConnectTimeoutMs(int ms) { this.connectTimeoutMs = ms; }
@@ -145,15 +206,30 @@ public class ConnectionConfig {
}
}
public boolean isDynamicModel() { return dynamicModel; }
public void setDynamicModel(boolean dynamicModel) { this.dynamicModel = dynamicModel; }
public boolean isDynamicModel() {
return dynamicModel || (model != null && model.isDynamic());
}
public void setDynamicModel(boolean dynamicModel) {
this.dynamicModel = dynamicModel;
if (dynamicModel && (model == null || !model.isDynamic())) {
this.model = TerminalModel.IBM_DYNAMIC;
} else if (!dynamicModel && model != null && model.isDynamic()) {
this.model = TerminalModel.IBM_3279_4;
}
}
public void setDynamic(boolean dynamic) {
setDynamicModel(dynamic);
}
public int getDynamicRows() { return dynamicRows; }
public int getDynamicCols() { return dynamicCols; }
public void setDynamicDimensions(int rows, int cols) {
this.dynamicModel = true;
this.dynamicRows = rows;
this.dynamicCols = cols;
this.dynamicRows = Math.max(1, rows);
this.dynamicCols = Math.max(1, cols);
this.model = TerminalModel.IBM_DYNAMIC;
}
public ProxyType getProxyType() { return proxyType; }
@@ -216,6 +292,9 @@ public class ConnectionConfig {
String s = hostStr.trim();
boolean tls = false;
boolean tn3270e = true;
boolean dynamic = false;
int dynRows = 62;
int dynCols = 160;
// Parse --proxy=<url> or -proxy=<url> flags
ProxyType pType = ProxyType.NONE;
@@ -287,6 +366,29 @@ public class ConnectionConfig {
int colon = s.indexOf(':');
s = s.substring(colon + 1);
prefixFound = true;
} else if (s.startsWith("D:") || s.startsWith("d:")) {
dynamic = true;
s = s.substring(2);
prefixFound = true;
} else if (s.toLowerCase().startsWith("dyn:") || s.toLowerCase().startsWith("dynamic:") ||
s.toLowerCase().startsWith("dyn[") || s.toLowerCase().startsWith("dynamic[")) {
int colon = s.indexOf(':');
if (colon > 0) {
String prefix = s.substring(0, colon);
s = s.substring(colon + 1);
prefixFound = true;
dynamic = true;
if (prefix.contains("[") && prefix.contains("]")) {
String dim = prefix.substring(prefix.indexOf('[') + 1, prefix.indexOf(']'));
String[] parts = dim.toLowerCase().split("x");
if (parts.length == 2) {
try {
dynRows = Integer.parseInt(parts[0].trim());
dynCols = Integer.parseInt(parts[1].trim());
} catch (NumberFormatException ignored) {}
}
}
}
}
}
@@ -315,6 +417,9 @@ public class ConnectionConfig {
ConnectionConfig config = new ConnectionConfig(host, port, defaultModel != null ? defaultModel : TerminalModel.IBM_3279_4);
config.setUseTls(tls);
config.setTn3270eEnabled(tn3270e);
if (dynamic) {
config.setDynamicDimensions(dynRows, dynCols);
}
if (pType != ProxyType.NONE && pHost != null) {
config.setProxy(pType, pHost, pPort, pUser, pPass);
}
@@ -328,7 +433,7 @@ public class ConnectionConfig {
if (terminalName != null) {
return terminalName;
}
if (dynamicModel) {
if (isDynamicModel()) {
return extendedDataStream ? "IBM-DYNAMIC-E" : "IBM-DYNAMIC";
}
return extendedDataStream ? model.getTerminalType() : model.getBaseTerminalType();
@@ -47,7 +47,16 @@ public class Telnet3270Client {
public Telnet3270Client(ConnectionConfig config) {
this.config = config;
this.translator = new EbcdicTranslator(config.getCodePage());
this.screenBuffer = new ScreenBuffer(config.getModel(), translator);
if (config.isDynamicModel() || (config.getModel() != null && config.getModel().isDynamic())) {
this.screenBuffer = new ScreenBuffer(
haus.nightmare.lib3270j.protocol.DS3270Constants.MODEL_2_ROWS,
haus.nightmare.lib3270j.protocol.DS3270Constants.MODEL_2_COLS,
config.getDynamicRows(),
config.getDynamicCols(),
translator);
} else {
this.screenBuffer = new ScreenBuffer(config.getModel(), translator);
}
this.dsProcessor = new DataStreamProcessor(screenBuffer, translator);
this.dsProcessor.getQueryReplyBuilder().setGraphicsMode(config.getGraphicsMode());
this.fsm = new TelnetFSM(config, screenBuffer, dsProcessor);
@@ -244,6 +253,9 @@ public class Telnet3270Client {
/** Get the data stream processor. */
public DataStreamProcessor getDataStreamProcessor() { return dsProcessor; }
/** Get the underlying telnet connection. */
public TelnetConnection getConnection() { return connection; }
/** Get the connection config. */
public ConnectionConfig getConfig() { return config; }
@@ -14,7 +14,8 @@ public enum TerminalModel {
IBM_3279_2(2, true, MODEL_2_ROWS, MODEL_2_COLS, MODEL_2_ROWS, MODEL_2_COLS),
IBM_3279_3(3, true, MODEL_2_ROWS, MODEL_2_COLS, MODEL_3_ROWS, MODEL_3_COLS),
IBM_3279_4(4, true, MODEL_2_ROWS, MODEL_2_COLS, MODEL_4_ROWS, MODEL_4_COLS),
IBM_3279_5(5, true, MODEL_2_ROWS, MODEL_2_COLS, MODEL_5_ROWS, MODEL_5_COLS);
IBM_3279_5(5, true, MODEL_2_ROWS, MODEL_2_COLS, MODEL_5_ROWS, MODEL_5_COLS),
IBM_DYNAMIC(0, true, MODEL_2_ROWS, MODEL_2_COLS, 62, 160);
private final int modelNumber;
private final boolean color;
@@ -40,12 +41,17 @@ public enum TerminalModel {
public int getDefaultCols() { return defaultCols; }
public int getAlternateRows() { return alternateRows; }
public int getAlternateCols() { return alternateCols; }
public boolean isDynamic() { return modelNumber == 0; }
/**
* Returns the terminal type string for TN3270E negotiation.
* e.g., "IBM-3279-4-E" for a color model 4 with extended data stream.
* e.g., "IBM-3279-4-E" for a color model 4 with extended data stream,
* or "IBM-DYNAMIC-E" for dynamic model.
*/
public String getTerminalType() {
if (modelNumber == 0) {
return "IBM-DYNAMIC-E";
}
return String.format("IBM-327%c-%d-E", color ? '9' : '8', modelNumber);
}
@@ -53,6 +59,9 @@ public enum TerminalModel {
* Returns the base terminal type without "-E" suffix (for non-extended mode).
*/
public String getBaseTerminalType() {
if (modelNumber == 0) {
return "IBM-DYNAMIC";
}
return String.format("IBM-327%c-%d", color ? '9' : '8', modelNumber);
}
@@ -60,6 +69,9 @@ public enum TerminalModel {
* Look up a model by number and color mode.
*/
public static TerminalModel forModel(int number, boolean isColor) {
if (number == 0) {
return IBM_DYNAMIC;
}
for (TerminalModel m : values()) {
if (m.modelNumber == number && m.color == isColor) {
return m;
@@ -69,4 +69,88 @@ public interface CodePage {
* Returns -1 if unmappable.
*/
int unicodeToDbcs(char unicode);
/**
* Convert an EBCDIC byte buffer to a char array matching IBM HoD conversion.
*/
default char[] convBuffByte2Char(byte[] buf, int offset, int length) {
if (buf == null || length <= 0) return new char[0];
char[] out = new char[length];
for (int i = 0; i < length; i++) {
out[i] = ebcdicToUnicode(buf[offset + i] & 0xFF);
}
return out;
}
/**
* Convert a char array to an EBCDIC byte array matching IBM HoD conversion.
*/
default byte[] convBuffChar2Byte(char[] buf, int offset, int length) {
if (buf == null || length <= 0) return new byte[0];
byte[] out = new byte[length];
for (int i = 0; i < length; i++) {
out[i] = unicodeToEbcdicSafe(buf[offset + i]);
}
return out;
}
/**
* Get a HODByteToCharConverter instance backed by this CodePage.
*/
default haus.nightmare.lib3270j.converters.HODByteToCharConverter getByteToCharConverter() {
if (isDBCS()) {
return new haus.nightmare.lib3270j.converters.ByteToCharDBCS_EBCDIC(this);
} else {
return new haus.nightmare.lib3270j.converters.ByteToCharSingleByte(this);
}
}
/**
* Get a HODCharToByteConverter instance backed by this CodePage.
*/
default haus.nightmare.lib3270j.converters.HODCharToByteConverter getCharToByteConverter() {
if (isDBCS()) {
return new haus.nightmare.lib3270j.converters.CharToByteDBCS_EBCDIC(this);
} else {
return new haus.nightmare.lib3270j.converters.CharToByteSingleByte(this);
}
}
/**
* Helper to test if a pair of characters forms a Unicode surrogate pair.
*/
static boolean isSurrogate(char high, char low) {
return Character.isSurrogatePair(high, low);
}
/**
* Helper to test if a character is a high surrogate.
*/
static boolean isHighSurrogate(char c) {
return Character.isHighSurrogate(c);
}
/**
* Helper to test if a character is a low surrogate.
*/
static boolean isLowSurrogate(char c) {
return Character.isLowSurrogate(c);
}
/**
* Helper matching IBM HoD CodePage.ComposeChar to combine characters.
*/
static boolean ComposeChar(char[] chars) {
if (chars == null || chars.length < 2) return false;
if (chars[1] >= '\u0300' && chars[1] <= '\u036F') {
String decomposed = new String(chars, 0, 2);
String normalized = java.text.Normalizer.normalize(decomposed, java.text.Normalizer.Form.NFC);
if (normalized.length() == 1) {
chars[0] = normalized.charAt(0);
return true;
}
}
return false;
}
}
@@ -157,7 +157,25 @@ public class CodePageRegistry {
public static String normalizeKey(String name) {
if (name == null) return "";
String s = name.trim().toLowerCase();
String s = name.trim();
// Strip package qualifiers if present (e.g. com.ibm.eNetwork.HOD.converters.onea.ByteToCharCp273)
int lastDot = Math.max(s.lastIndexOf('.'), s.lastIndexOf('/'));
if (lastDot >= 0 && lastDot < s.length() - 1) {
s = s.substring(lastDot + 1);
}
// Strip HoD converter class prefixes
for (String pfx : new String[]{
"HODByteToChar", "HODCharToByte", "ByteToChar", "CharToByte",
"ConverterBIDIPrinter", "ConverterFT", "ConverterJDK", "ConverterVT", "PrtConverter"
}) {
if (s.startsWith(pfx)) {
s = s.substring(pfx.length());
break;
}
}
s = s.toLowerCase();
s = s.replace("_", "").replace("-", "");
if (s.startsWith("ebcdiccp")) {
s = s.substring(8);
@@ -174,13 +192,12 @@ public class CodePageRegistry {
}
/**
* Look up a code page by ID or alias.
* If not found in built-ins, attempts to load via java.nio.charset.Charset.
* Falls back to CP037 if completely unresolvable.
* Look up a code page by ID, alias, or converter name without fallback to CP037.
* Returns null if unresolvable.
*/
public static CodePage getCodePage(String name) {
public static CodePage resolveCodePage(String name) {
if (name == null || name.trim().isEmpty()) {
return CODE_PAGES.get("037");
return null;
}
String raw = name.trim();
@@ -198,6 +215,9 @@ public class CodePageRegistry {
if (targetId != null) {
cp = CODE_PAGES.get(targetId);
if (cp != null) return cp;
String normTarget = normalizeKey(targetId);
cp = CODE_PAGES.get(normTarget);
if (cp != null) return cp;
}
// Try standard NIO Charset dynamic adapter
@@ -205,18 +225,55 @@ public class CodePageRegistry {
if (Charset.isSupported(raw)) {
return new NioCodePageAdapter(raw);
}
if (Charset.isSupported(norm)) {
return new NioCodePageAdapter(norm);
}
String ibmName = "IBM" + norm;
if (Charset.isSupported(ibmName)) {
return new NioCodePageAdapter(ibmName);
}
String ibmDashName = "IBM-" + norm;
if (Charset.isSupported(ibmDashName)) {
return new NioCodePageAdapter(ibmDashName);
}
String cpName = "Cp" + norm;
if (Charset.isSupported(cpName)) {
return new NioCodePageAdapter(cpName);
}
String isoName = "ISO-8859-" + norm.replace("8859", "");
if (Charset.isSupported(isoName)) {
return new NioCodePageAdapter(isoName);
}
String winName = "windows-" + norm;
if (Charset.isSupported(winName)) {
return new NioCodePageAdapter(winName);
}
} catch (Exception e) {
log.fine("Dynamic charset loading failed for " + name + ": " + e.getMessage());
}
return null;
}
/**
* Look up a code page by ID or alias.
* If not found in built-ins, attempts to load via java.nio.charset.Charset.
* Falls back to CP037 if completely unresolvable.
*/
public static CodePage get(String name) {
return getCodePage(name);
}
public static CodePage getDefault() {
return getCodePage("037");
}
public static CodePage getCodePage(String name) {
CodePage cp = resolveCodePage(name);
if (cp != null) {
return cp;
}
log.warning("CodePage not recognized: '" + name + "'; falling back to CP037");
return CODE_PAGES.get("037");
}
@@ -301,18 +358,82 @@ public class CodePageRegistry {
addAlias("chinese-ext-traditional", "1371");
addAlias("zh-traditional-ext", "1371");
addAlias("zh-tw-ext", "1371");
// HoD Converter aliases mapping all HoD converter names to CodePage / Charset
addAlias("1390", "930");
addAlias("1390jis2004", "930");
addAlias("1399", "939");
addAlias("1399jis2004", "939");
addAlias("937macau", "937");
addAlias("1364", "933");
addAlias("1379", "937");
addAlias("274", "500");
addAlias("275", "037");
addAlias("924", "1047");
addAlias("1153", "870");
addAlias("1156", "1025");
addAlias("1157", "1025");
addAlias("1158", "1025");
addAlias("1166", "1025");
addAlias("1112", "1025");
addAlias("1122", "1025");
addAlias("1137", "037");
addAlias("1008", "420");
addAlias("449", "420");
addAlias("1089", "420");
addAlias("1134", "424");
addAlias("1349", "424");
addAlias("8585", "875");
addAlias("8586", "875");
addAlias("220", "284");
addAlias("big5550", "937");
addAlias("cns", "937");
addAlias("tca", "937");
addAlias("ks25550", "933");
addAlias("jis", "930");
addAlias("euc", "937");
addAlias("singlebyte", "037");
addAlias("dbcsebcdic", "930");
addAlias("dbcsebcdicnibm", "930");
addAlias("dbcsebcdicibm", "930");
addAlias("dbcsascii", "930");
addAlias("encodings", "037");
addAlias("1011", "037");
addAlias("1012", "037");
addAlias("1020", "037");
addAlias("1021", "037");
addAlias("1023", "037");
addAlias("1090", "037");
addAlias("1101", "037");
addAlias("1102", "037");
addAlias("1103", "037");
addAlias("1104", "037");
addAlias("1105", "037");
addAlias("1106", "037");
}
/**
* Check if a code page is registered.
* Check if a code page or converter is registered or resolvable.
*/
public static boolean hasCodePage(String name) {
if (name == null || name.trim().isEmpty()) return false;
String raw = name.trim();
if (CODE_PAGES.containsKey(raw)) return true;
String norm = normalizeKey(raw);
if (CODE_PAGES.containsKey(norm)) return true;
return ALIASES.containsKey(norm);
return resolveCodePage(name) != null;
}
/**
* Convenience factory method to get a HODByteToCharConverter by name or alias.
*/
public static haus.nightmare.lib3270j.converters.HODByteToCharConverter getByteToCharConverter(String name)
throws haus.nightmare.lib3270j.converters.HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODByteToCharConverter.getHODConverter(name);
}
/**
* Convenience factory method to get a HODCharToByteConverter by name or alias.
*/
public static haus.nightmare.lib3270j.converters.HODCharToByteConverter getCharToByteConverter(String name)
throws haus.nightmare.lib3270j.converters.HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODCharToByteConverter.getHODConverter(name);
}
/**
@@ -0,0 +1,178 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
/**
* Concrete converter implementing mixed SBCS/DBCS byte-to-char conversion with transparent
* Shift-Out (0x0E) and Shift-In (0x0F) state management.
* Conforms to com.ibm.eNetwork.HOD.converters.ByteToCharDBCS_EBCDIC.
*/
public class ByteToCharDBCS_EBCDIC extends HODByteToCharConverter {
public ByteToCharDBCS_EBCDIC() {
this(CodePageRegistry.getCodePage("930"));
}
public ByteToCharDBCS_EBCDIC(CodePage codePage) {
super(codePage != null ? codePage : CodePageRegistry.getCodePage("930"));
}
@Override
public int convert(byte[] in, int inOff, int inEnd, char[] out, int outOff, int outEnd)
throws HODCharConversionException {
if (in == null || inEnd <= inOff) {
return 0;
}
if (out == null) {
throw new HODCharConversionException("Output buffer cannot be null");
}
this.byteOff = inOff;
this.charOff = outOff;
while (this.byteOff < inEnd || this.savedBytePresent) {
int b;
boolean isSaved = false;
if (this.savedBytePresent) {
b = this.savedByte & 0xFF;
this.savedBytePresent = false;
isSaved = true;
} else {
b = in[this.byteOff] & 0xFF;
}
// Handle Shift-Out (0x0E) -> DBCS mode
if (b == SO) {
this.currentState = 1;
if (this.preserveSOSI) {
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow writing SO at " + this.charOff);
}
out[this.charOff++] = (char) SO;
}
if (!isSaved) this.byteOff++;
continue;
}
// Handle Shift-In (0x0F) -> SBCS mode
if (b == SI) {
this.currentState = 0;
if (this.preserveSOSI) {
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow writing SI at " + this.charOff);
}
out[this.charOff++] = (char) SI;
}
if (!isSaved) this.byteOff++;
continue;
}
// SBCS mode conversion
if (this.currentState == 0) {
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow at position " + this.charOff);
}
char c = this.codePage.ebcdicToUnicode(b);
if (c == '\uFFFD') {
if (this.subMode) {
c = this.subChars[0];
} else {
this.badInputLength = 1;
throw new HODCharConversionException("Unmappable byte 0x" + Integer.toHexString(b) + " at index " + this.byteOff);
}
}
out[this.charOff++] = c;
if (!isSaved) this.byteOff++;
} else {
// DBCS mode conversion (requires 2 bytes)
int b2;
if (isSaved) {
if (this.byteOff >= inEnd) {
// Incomplete DBCS pair at end of buffer
this.savedByte = (byte) b;
this.savedBytePresent = true;
break;
}
b2 = in[this.byteOff++] & 0xFF;
} else {
if (this.byteOff + 1 >= inEnd) {
// Trailing single byte inside DBCS shift
this.savedByte = (byte) b;
this.savedBytePresent = true;
this.byteOff++;
break;
}
b2 = in[this.byteOff + 1] & 0xFF;
this.byteOff += 2;
}
// Check for premature Shift-In
if (b2 == SI) {
this.currentState = 0;
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow at position " + this.charOff);
}
out[this.charOff++] = this.codePage.ebcdicToUnicode(b);
if (this.preserveSOSI) {
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow at position " + this.charOff);
}
out[this.charOff++] = (char) SI;
}
continue;
}
char c = this.codePage.dbcsToUnicode(b, b2);
if (c == '?' || c == '\uFFFD') {
if (this.subMode) {
c = this.subChars[0];
} else {
this.badInputLength = 2;
throw new HODCharConversionException("Unmappable DBCS pair 0x" + Integer.toHexString(b) + ", 0x" + Integer.toHexString(b2));
}
}
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow at position " + this.charOff);
}
out[this.charOff++] = c;
}
}
return this.charOff - outOff;
}
@Override
public int flush(char[] out, int outOff, int outEnd) throws HODCharConversionException {
int count = 0;
if (this.savedBytePresent) {
if (!this.subMode) {
reset();
this.badInputLength = 1;
throw new HODCharConversionException("Unclosed trailing DBCS byte at end of input");
}
if (outOff < outEnd) {
out[outOff] = this.subChars[0];
count = 1;
}
}
reset();
return count;
}
@Override
public void reset() {
this.byteOff = 0;
this.charOff = 0;
this.currentState = 0;
this.savedBytePresent = false;
this.savedByte = 0;
this.badInputLength = 0;
}
@Override
public String getCharacterEncoding() {
return this.codePage != null ? "Cp" + this.codePage.getCodePageId() : "DBCS_EBCDIC";
}
}
@@ -0,0 +1,74 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
/**
* Concrete converter implementing single-byte character set (SBCS) byte-to-char conversion.
* Conforms to com.ibm.eNetwork.HOD.converters.ByteToCharSingleByte.
*/
public class ByteToCharSingleByte extends HODByteToCharConverter {
public ByteToCharSingleByte() {
this(CodePageRegistry.getDefault());
}
public ByteToCharSingleByte(CodePage codePage) {
super(codePage != null ? codePage : CodePageRegistry.getDefault());
}
@Override
public int convert(byte[] in, int inOff, int inEnd, char[] out, int outOff, int outEnd)
throws HODCharConversionException {
if (in == null || inEnd <= inOff) {
return 0;
}
if (out == null) {
throw new HODCharConversionException("Output buffer cannot be null");
}
this.byteOff = inOff;
this.charOff = outOff;
while (this.byteOff < inEnd) {
if (this.charOff >= outEnd) {
throw new HODCharConversionException("Output char buffer overflow at position " + this.charOff);
}
int b = in[this.byteOff] & 0xFF;
char c = this.codePage.ebcdicToUnicode(b);
if (c == '\uFFFD') {
if (this.subMode) {
c = this.subChars[0];
} else {
this.badInputLength = 1;
throw new HODCharConversionException("Unmappable byte 0x" + Integer.toHexString(b) + " at input index " + this.byteOff);
}
}
out[this.charOff++] = c;
this.byteOff++;
}
return this.charOff - outOff;
}
@Override
public int flush(char[] out, int outOff, int outEnd) {
reset();
return 0;
}
@Override
public void reset() {
this.byteOff = 0;
this.charOff = 0;
this.badInputLength = 0;
}
@Override
public String getCharacterEncoding() {
return this.codePage != null ? "Cp" + this.codePage.getCodePageId() : "SingleByte";
}
}
@@ -0,0 +1,137 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
/**
* Concrete converter implementing mixed SBCS/DBCS char-to-byte conversion with transparent
* Shift-Out (0x0E) and Shift-In (0x0F) state generation.
* Conforms to com.ibm.eNetwork.HOD.converters.CharToByteDBCS_EBCDIC.
*/
public class CharToByteDBCS_EBCDIC extends HODCharToByteConverter {
public CharToByteDBCS_EBCDIC() {
this(CodePageRegistry.getCodePage("930"));
}
public CharToByteDBCS_EBCDIC(CodePage codePage) {
super(codePage != null ? codePage : CodePageRegistry.getCodePage("930"));
}
@Override
public int convert(char[] in, int inOff, int inEnd, byte[] out, int outOff, int outEnd)
throws HODCharConversionException {
if (in == null || inEnd <= inOff) {
return 0;
}
if (out == null) {
throw new HODCharConversionException("Output buffer cannot be null");
}
this.charOff = inOff;
this.byteOff = outOff;
while (this.charOff < inEnd) {
char c = in[this.charOff];
// Explicit Shift-Out control character handling
if (c == (char) SO) {
if (this.currentState == 0) {
if (this.byteOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow writing SO at " + this.byteOff);
}
out[this.byteOff++] = SO;
this.currentState = 1;
}
this.charOff++;
continue;
}
// Explicit Shift-In control character handling
if (c == (char) SI) {
if (this.currentState == 1) {
if (this.byteOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow writing SI at " + this.byteOff);
}
out[this.byteOff++] = SI;
this.currentState = 0;
}
this.charOff++;
continue;
}
int dbcs = this.codePage.unicodeToDbcs(c);
if (dbcs >= 0) {
// Character is DBCS: ensure in DBCS mode
int needed = (this.currentState == 0) ? 3 : 2;
if (this.byteOff + needed > outEnd) {
throw new HODCharConversionException("Output buffer overflow writing DBCS character at " + this.byteOff);
}
if (this.currentState == 0) {
out[this.byteOff++] = SO;
this.currentState = 1;
}
out[this.byteOff++] = (byte) ((dbcs >> 8) & 0xFF);
out[this.byteOff++] = (byte) (dbcs & 0xFF);
} else {
// Character is SBCS: ensure in SBCS mode
int needed = (this.currentState == 1) ? 2 : 1;
if (this.byteOff + needed > outEnd) {
throw new HODCharConversionException("Output buffer overflow writing SBCS character at " + this.byteOff);
}
if (this.currentState == 1) {
out[this.byteOff++] = SI;
this.currentState = 0;
}
int ebc = this.codePage.unicodeToEbcdic(c);
if (ebc < 0) {
if (this.subMode) {
out[this.byteOff++] = this.subBytes[0];
} else {
this.badInputLength = 1;
throw new HODCharConversionException("Unmappable character '\\u" + Integer.toHexString(c) + "' at input index " + this.charOff);
}
} else {
out[this.byteOff++] = (byte) (ebc & 0xFF);
}
}
this.charOff++;
}
return this.byteOff - outOff;
}
@Override
public int flush(byte[] out, int outOff, int outEnd) throws HODCharConversionException {
int flushed = 0;
if (this.currentState == 1) {
if (outOff >= outEnd) {
throw new HODCharConversionException("Output buffer overflow during flush at " + outOff);
}
out[outOff] = SI;
flushed = 1;
this.currentState = 0;
}
reset();
return flushed;
}
@Override
public void reset() {
this.charOff = 0;
this.byteOff = 0;
this.currentState = 0;
this.badInputLength = 0;
}
@Override
public String getCharacterEncoding() {
return this.codePage != null ? "Cp" + this.codePage.getCodePageId() : "DBCS_EBCDIC";
}
}
@@ -0,0 +1,75 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
/**
* Concrete converter implementing single-byte character set (SBCS) char-to-byte conversion.
* Conforms to com.ibm.eNetwork.HOD.converters.CharToByteSingleByte.
*/
public class CharToByteSingleByte extends HODCharToByteConverter {
public CharToByteSingleByte() {
this(CodePageRegistry.getDefault());
}
public CharToByteSingleByte(CodePage codePage) {
super(codePage != null ? codePage : CodePageRegistry.getDefault());
}
@Override
public int convert(char[] in, int inOff, int inEnd, byte[] out, int outOff, int outEnd)
throws HODCharConversionException {
if (in == null || inEnd <= inOff) {
return 0;
}
if (out == null) {
throw new HODCharConversionException("Output buffer cannot be null");
}
this.charOff = inOff;
this.byteOff = outOff;
while (this.charOff < inEnd) {
if (this.byteOff >= outEnd) {
throw new HODCharConversionException("Output byte buffer overflow at position " + this.byteOff);
}
char c = in[this.charOff];
int ebc = this.codePage.unicodeToEbcdic(c);
if (ebc < 0) {
if (this.subMode) {
out[this.byteOff++] = this.subBytes[0];
} else {
this.badInputLength = 1;
throw new HODCharConversionException("Unmappable character '\\u" + Integer.toHexString(c) + "' at input index " + this.charOff);
}
} else {
out[this.byteOff++] = (byte) (ebc & 0xFF);
}
this.charOff++;
}
return this.byteOff - outOff;
}
@Override
public int flush(byte[] out, int outOff, int outEnd) {
reset();
return 0;
}
@Override
public void reset() {
this.charOff = 0;
this.byteOff = 0;
this.badInputLength = 0;
}
@Override
public String getCharacterEncoding() {
return this.codePage != null ? "Cp" + this.codePage.getCodePageId() : "SingleByte";
}
}
@@ -0,0 +1,184 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
import java.util.Objects;
/**
* High-performance adapter and bridge converting byte streams (EBCDIC, ASCII, ISO, UTF)
* to Unicode characters conforming to IBM Host On-Demand (HoD) converter specifications.
* <p>
* Supports dynamic factory resolution for all 275 HoD converter class names and transparent
* Shift-In (0x0F) / Shift-Out (0x0E) DBCS transitions.
*/
public abstract class HODByteToCharConverter {
public static final int SO = 0x0E;
public static final int SI = 0x0F;
protected int byteOff = 0;
protected int charOff = 0;
protected int badInputLength = 0;
protected boolean subMode = true;
protected char[] subChars = new char[]{'\uFFFD'};
protected CodePage codePage;
// DBCS State
protected int currentState = 0; // 0 = SBCS, 1 = DBCS
protected boolean savedBytePresent = false;
protected byte savedByte = 0;
protected boolean preserveSOSI = false;
public HODByteToCharConverter() {
}
public HODByteToCharConverter(CodePage codePage) {
this.codePage = Objects.requireNonNull(codePage, "codePage cannot be null");
}
/**
* Look up and instantiate a ByteToChar converter matching the given encoding,
* codepage ID, alias, or HoD converter class name (e.g. "Cp037", "037", "ByteToCharCp1047", "ConverterFT1047").
*
* @param encoding encoding identifier or class name
* @return initialized HODByteToCharConverter instance
* @throws HODUnsupportedCodepageException if the codepage cannot be resolved
*/
public static HODByteToCharConverter getHODConverter(String encoding) throws HODUnsupportedCodepageException {
if (encoding == null || encoding.trim().isEmpty()) {
throw new HODUnsupportedCodepageException("Encoding name cannot be null or empty");
}
CodePage cp = CodePageRegistry.resolveCodePage(encoding);
if (cp == null) {
throw new HODUnsupportedCodepageException("Unsupported codepage / converter: " + encoding);
}
if (cp.isDBCS()) {
return new ByteToCharDBCS_EBCDIC(cp);
} else {
return new ByteToCharSingleByte(cp);
}
}
/**
* Standard converter lookup alias conforming to Java/HoD converter factory patterns.
*/
public static HODByteToCharConverter getConverter(String encoding) throws HODUnsupportedCodepageException {
return getHODConverter(encoding);
}
/**
* Convert an array of bytes into an array of characters.
*
* @param in source byte buffer
* @param inOff start offset in input buffer
* @param inEnd end offset in input buffer (exclusive)
* @param out destination char buffer
* @param outOff start offset in output buffer
* @param outEnd end offset in output buffer (exclusive)
* @return number of characters converted and written into out
* @throws HODCharConversionException if an unmappable byte is encountered with substitution disabled,
* or if the output buffer overflows
*/
public abstract int convert(byte[] in, int inOff, int inEnd, char[] out, int outOff, int outEnd)
throws HODCharConversionException;
/**
* Overload supporting an extra boolean flag matching HoD CFR decompiled signature.
*/
public int convert(byte[] in, int inOff, int inEnd, char[] out, int outOff, int outEnd, boolean bl)
throws HODCharConversionException {
return convert(in, inOff, inEnd, out, outOff, outEnd);
}
/**
* Flush any buffered / trailing state into the output char buffer.
*
* @param out destination char buffer
* @param outOff start offset
* @param outEnd end offset
* @return number of characters flushed
* @throws HODCharConversionException if flush fails or trailing incomplete sequence cannot be converted
*/
public abstract int flush(char[] out, int outOff, int outEnd) throws HODCharConversionException;
/**
* Reset converter state and offsets to defaults.
*/
public abstract void reset();
/**
* Get the canonical character encoding name (e.g. "Cp037", "Cp930").
*/
public abstract String getCharacterEncoding();
/**
* Convert an entire byte array to a char array matching IBM HoD's hodConvertAll API.
*/
public char[] hodConvertAll(byte[] in) throws HODCharConversionException {
if (in == null) return new char[0];
reset();
char[] buf = new char[Math.max(16, in.length * 2 + 16)];
int converted = convert(in, 0, in.length, buf, 0, buf.length);
int flushed = flush(buf, converted, buf.length);
int total = converted + flushed;
char[] result = new char[total];
System.arraycopy(buf, 0, result, 0, total);
return result;
}
/**
* Convenience alias for hodConvertAll.
*/
public char[] convertAll(byte[] in) throws HODCharConversionException {
return hodConvertAll(in);
}
public void setSubstitutionMode(boolean mode) {
this.subMode = mode;
}
public boolean getSubstitutionMode() {
return this.subMode;
}
public void setSubstitutionChars(char[] subChars) {
if (subChars != null && subChars.length > 0) {
this.subChars = subChars;
}
}
public char[] getSubstitutionChars() {
return this.subChars;
}
public int getBadInputLength() {
return this.badInputLength;
}
public int nextByteIndex() {
return this.byteOff;
}
public int nextCharIndex() {
return this.charOff;
}
public CodePage getCodePage() {
return this.codePage;
}
public void setPreserveSOSI(boolean preserve) {
this.preserveSOSI = preserve;
}
public boolean isPreserveSOSI() {
return this.preserveSOSI;
}
public int getCurrentState() {
return this.currentState;
}
}
@@ -0,0 +1,20 @@
package haus.nightmare.lib3270j.converters;
import java.io.CharConversionException;
/**
* Exception thrown when character conversion fails during Host On-Demand converter processing.
* Conforms to com.ibm.eNetwork.HOD.common.HODCharConversionException.
*/
public class HODCharConversionException extends CharConversionException {
private static final long serialVersionUID = 1L;
public HODCharConversionException() {
super();
}
public HODCharConversionException(String message) {
super(message);
}
}
@@ -0,0 +1,169 @@
package haus.nightmare.lib3270j.converters;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.charset.CodePageRegistry;
import java.util.Objects;
/**
* High-performance adapter and bridge converting Unicode characters to byte streams
* (EBCDIC, ASCII, ISO, UTF) conforming to IBM Host On-Demand (HoD) converter specifications.
* <p>
* Supports dynamic factory resolution for all 275 HoD converter class names and transparent
* Shift-In (0x0F) / Shift-Out (0x0E) DBCS transitions.
*/
public abstract class HODCharToByteConverter {
public static final byte SO = 0x0E;
public static final byte SI = 0x0F;
protected int byteOff = 0;
protected int charOff = 0;
protected int badInputLength = 0;
protected boolean subMode = true;
protected byte[] subBytes = new byte[]{(byte) 0x6F}; // 0x6F '?' in EBCDIC (or safe fallback)
protected CodePage codePage;
// DBCS State
protected int currentState = 0; // 0 = SBCS, 1 = DBCS
public HODCharToByteConverter() {
}
public HODCharToByteConverter(CodePage codePage) {
this.codePage = Objects.requireNonNull(codePage, "codePage cannot be null");
}
/**
* Look up and instantiate a CharToByte converter matching the given encoding,
* codepage ID, alias, or HoD converter class name (e.g. "Cp037", "037", "CharToByteCp1047", "ConverterFT1047").
*
* @param encoding encoding identifier or class name
* @return initialized HODCharToByteConverter instance
* @throws HODUnsupportedCodepageException if the codepage cannot be resolved
*/
public static HODCharToByteConverter getHODConverter(String encoding) throws HODUnsupportedCodepageException {
if (encoding == null || encoding.trim().isEmpty()) {
throw new HODUnsupportedCodepageException("Encoding name cannot be null or empty");
}
CodePage cp = CodePageRegistry.resolveCodePage(encoding);
if (cp == null) {
throw new HODUnsupportedCodepageException("Unsupported codepage / converter: " + encoding);
}
if (cp.isDBCS()) {
return new CharToByteDBCS_EBCDIC(cp);
} else {
return new CharToByteSingleByte(cp);
}
}
/**
* Standard converter lookup alias conforming to Java/HoD converter factory patterns.
*/
public static HODCharToByteConverter getConverter(String encoding) throws HODUnsupportedCodepageException {
return getHODConverter(encoding);
}
/**
* Convert an array of characters into an array of bytes.
*
* @param in source char buffer
* @param inOff start offset in input buffer
* @param inEnd end offset in input buffer (exclusive)
* @param out destination byte buffer
* @param outOff start offset in output buffer
* @param outEnd end offset in output buffer (exclusive)
* @return number of bytes converted and written into out
* @throws HODCharConversionException if an unmappable char is encountered with substitution disabled,
* or if the output buffer overflows
*/
public abstract int convert(char[] in, int inOff, int inEnd, byte[] out, int outOff, int outEnd)
throws HODCharConversionException;
/**
* Flush any buffered / trailing shift state into the output byte buffer.
*
* @param out destination byte buffer
* @param outOff start offset
* @param outEnd end offset
* @return number of bytes flushed
* @throws HODCharConversionException if output buffer overflows
*/
public abstract int flush(byte[] out, int outOff, int outEnd) throws HODCharConversionException;
/**
* Reset converter state and offsets to defaults.
*/
public abstract void reset();
/**
* Get the canonical character encoding name (e.g. "Cp037", "Cp930").
*/
public abstract String getCharacterEncoding();
/**
* Convert an entire char array to a byte array matching IBM HoD's hodConvertAll API.
*/
public byte[] hodConvertAll(char[] in) throws HODCharConversionException {
if (in == null) return new byte[0];
reset();
byte[] buf = new byte[Math.max(16, in.length * 3 + 16)];
int converted = convert(in, 0, in.length, buf, 0, buf.length);
int flushed = flush(buf, converted, buf.length);
int total = converted + flushed;
byte[] result = new byte[total];
System.arraycopy(buf, 0, result, 0, total);
return result;
}
/**
* Convenience alias for hodConvertAll.
*/
public byte[] convertAll(char[] in) throws HODCharConversionException {
return hodConvertAll(in);
}
public void setSubstitutionMode(boolean mode) {
this.subMode = mode;
}
public boolean getSubstitutionMode() {
return this.subMode;
}
public void setSubstitutionBytes(byte[] subBytes) {
if (subBytes != null && subBytes.length > 0) {
this.subBytes = subBytes;
}
}
public byte[] getSubstitutionBytes() {
return this.subBytes;
}
public int getBadInputLength() {
return this.badInputLength;
}
public int nextByteIndex() {
return this.byteOff;
}
public int nextCharIndex() {
return this.charOff;
}
public int getMaxBytesPerChar() {
return (codePage != null && codePage.isDBCS()) ? 3 : 1; // At most 3 bytes (SO + 2-byte DBCS)
}
public CodePage getCodePage() {
return this.codePage;
}
public int getCurrentState() {
return this.currentState;
}
}
@@ -0,0 +1,20 @@
package haus.nightmare.lib3270j.converters;
import java.io.UnsupportedEncodingException;
/**
* Exception thrown when a requested character encoding or codepage identifier cannot be resolved.
* Conforms to com.ibm.eNetwork.HOD.common.HODUnsupportedCodepageException.
*/
public class HODUnsupportedCodepageException extends UnsupportedEncodingException {
private static final long serialVersionUID = 1L;
public HODUnsupportedCodepageException() {
super();
}
public HODUnsupportedCodepageException(String encoding) {
super(encoding);
}
}
@@ -63,6 +63,14 @@ public class DataStreamProcessor {
this.graphicsPlane.setProgramSymbolManager(programSymbolManager);
}
public ScreenBuffer getScreen() {
return screen;
}
public ScreenBuffer getScreenBuffer() {
return screen;
}
public QueryReplyBuilder getQueryReplyBuilder() {
return qrBuilder;
}
@@ -81,6 +89,13 @@ public class DataStreamProcessor {
public void setOutputSender(OutputSender sender) {
this.outputSender = sender;
if (inputProcessor != null) {
inputProcessor.setOutputSender(sender);
}
}
public OutputSender getOutputSender() {
return outputSender;
}
public void setFTDft(haus.nightmare.lib3270j.ft.FTDft ftDft) {
@@ -99,6 +114,9 @@ public class DataStreamProcessor {
public void setInputProcessor(haus.nightmare.lib3270j.input.InputProcessor inputProcessor) {
this.inputProcessor = inputProcessor;
if (inputProcessor != null && outputSender != null) {
inputProcessor.setOutputSender(outputSender);
}
}
public haus.nightmare.lib3270j.input.InputProcessor getInputProcessor() {
@@ -1516,4 +1534,233 @@ public class DataStreamProcessor {
public void processNullStructuredField() {
log.fine("Processed null structured field");
}
// ========== Phase 3: HoD DS3270 Order & Data Stream Functions ==========
/** Process Write Control Character (WCC). */
public void processWCC(int wcc) {
boolean alarm = wccSoundAlarm(wcc);
boolean kbdRestore = wccKeyboardRestore(wcc);
boolean resetMdt = wccResetMDT(wcc);
log.fine("processWCC: " + String.format("0x%02x", wcc) +
" reset=" + wccReset(wcc) + " alarm=" + alarm + " kbdRestore=" + kbdRestore + " resetMdt=" + resetMdt);
if (kbdRestore && inputProcessor != null) {
inputProcessor.setKeyboardLocked(false);
}
if (resetMdt) {
resetAllMDT();
}
if (wccReset(wcc)) {
log.fine("WCC reset: clearing default attributes");
}
}
public void processWCC(short wcc) {
processWCC(wcc & 0xFFFF);
}
/** Process Set Buffer Address (SBA) order. */
public void processSBA(int baddr) {
int size = screen.getRows() * screen.getCols();
if (size > 0) {
screen.setBufferAddress(baddr % size);
}
}
public void processSBA(int b1, int b2) {
processSBA(decodeAddress(b1, b2));
}
public void processSBA() {
// No-op or maintains current buffer address
}
/** Process Start Field (SF) order. */
public void processSF(byte fa) {
int size = screen.getRows() * screen.getCols();
if (size <= 0) return;
int baddr = screen.getBufferAddress();
ExtendedAttribute ea = screen.getCell(baddr);
ea.clear();
ea.fa = (byte) (fa & FA_MASK);
ea.ec = 0;
ea.ucs4 = ' ';
screen.setFormatted(true);
screen.setBufferAddress((baddr + 1) % size);
}
public void processSF() {
processSF((byte) FA_PRINTABLE);
}
/** Process Start Field Extended (SFE) order. */
public void processSFE(byte[] pairs) {
int size = screen.getRows() * screen.getCols();
if (size <= 0) return;
int baddr = screen.getBufferAddress();
ExtendedAttribute ea = screen.getCell(baddr);
ea.clear();
ea.ec = 0;
ea.ucs4 = ' ';
if (pairs != null) {
for (int i = 0; i + 1 < pairs.length; i += 2) {
int attrType = pairs[i] & 0xFF;
int attrValue = pairs[i + 1] & 0xFF;
applyExtendedAttribute(ea, attrType, attrValue);
}
}
if (ea.fa == 0) {
ea.fa = (byte) FA_PRINTABLE;
}
screen.setFormatted(true);
screen.setBufferAddress((baddr + 1) % size);
}
public void processSFE() {
processSFE(new byte[0]);
}
/** Process Set Attribute (SA) order. */
public void processSA(int attrType, int attrValue) {
int baddr = screen.getBufferAddress();
ExtendedAttribute ea = screen.getCell(baddr);
applyExtendedAttribute(ea, attrType, attrValue);
}
public void processSA() {
// Default attributes
}
/** Process Modify Field (MF) order. */
public void processMF(byte[] pairs) {
int baddr = screen.getBufferAddress();
int faAddr = screen.findFieldAttribute(baddr);
if (faAddr >= 0 && pairs != null) {
ExtendedAttribute ea = screen.getCell(faAddr);
for (int i = 0; i + 1 < pairs.length; i += 2) {
int attrType = pairs[i] & 0xFF;
int attrValue = pairs[i + 1] & 0xFF;
applyExtendedAttribute(ea, attrType, attrValue);
}
}
}
public void processMF() {
processMF(new byte[0]);
}
/** Process Insert Cursor (IC) order. */
public void processIC() {
screen.setCursorAddress(screen.getBufferAddress());
}
/** Process Program Tab (PT) order. */
public void processPT() {
int baddr = screen.findNextUnprotected(screen.getBufferAddress());
screen.setBufferAddress(baddr);
}
/** Process Repeat to Address (RA) order. */
public void processRA(int toAddr, int fillChar) {
int size = screen.getRows() * screen.getCols();
if (size <= 0) return;
toAddr = ((toAddr % size) + size) % size;
int baddr = screen.getBufferAddress();
char ucs4 = (translator != null) ? translator.ebcdicToUnicode(fillChar & 0xFF) : (char) fillChar;
do {
ExtendedAttribute ea = screen.getCell(baddr);
ea.fa = 0;
ea.ec = (byte) fillChar;
ea.ucs4 = ucs4;
baddr = (baddr + 1) % size;
} while (baddr != toAddr);
screen.setBufferAddress(baddr);
}
public void processRA() {
processRA(0, 0);
}
/** Process Erase Unprotected to Address (EUA) order. */
public void processEUA(int toAddr) {
int size = screen.getRows() * screen.getCols();
if (size <= 0) return;
toAddr = ((toAddr % size) + size) % size;
int baddr = screen.getBufferAddress();
do {
ExtendedAttribute ea = screen.getCell(baddr);
if (!ea.isFieldAttribute()) {
int faAddr = screen.findFieldAttribute(baddr);
byte faVal = faAddr >= 0 ? screen.getCell(faAddr).fa : 0;
if (!faIsProtected(faVal & 0xFF)) {
ea.ec = 0;
ea.ucs4 = 0;
ea.fg = 0;
ea.bg = 0;
ea.gr = 0;
ea.cs = 0;
}
}
baddr = (baddr + 1) % size;
} while (baddr != toAddr);
screen.setBufferAddress(baddr);
}
public void processEUA() {
processEUA(0);
}
/** Process Graphic Escape (GE) order. */
public void processGE(int geChar) {
int size = screen.getRows() * screen.getCols();
if (size <= 0) return;
int baddr = screen.getBufferAddress();
ExtendedAttribute ea = screen.getCell(baddr);
ea.fa = 0;
ea.ec = (byte) geChar;
ea.cs = CS_GE;
ea.ucs4 = (translator != null) ? translator.mapAPL(geChar) : (char) geChar;
screen.setBufferAddress((baddr + 1) % size);
}
public void processGE() {
processGE(0);
}
/** Process Write Structured Field (WSF) from short buffer. */
public void processWSF(short[] data, int off, int len) {
if (data == null || len <= 0) return;
byte[] bdata = new byte[len];
for (int i = 0; i < len; i++) {
bdata[i] = (byte) (data[off + i] & 0xFF);
}
processWriteStructuredField(bdata, 0, len);
}
public void processWSF(byte[] data, int off, int len) {
processWriteStructuredField(data, off, len);
}
/** Process raw inbound data stream chunk (short[] representation). */
public void processData(short[] data, int off, int len) {
if (data == null || len <= 0) return;
byte[] bdata = new byte[len];
for (int i = 0; i < len; i++) {
bdata[i] = (byte) (data[off + i] & 0xFF);
}
processRecord(bdata, 0, len, true);
}
public void processData(byte[] data, int off, int len) {
processRecord(data, off, len, true);
}
/** Send AID key with explicit cursor address. */
public void sendAid(short aid, int cursorAddress) {
if (inputProcessor != null) {
inputProcessor.sendAid(aid & 0xFFFF, cursorAddress);
}
}
}
@@ -7,6 +7,22 @@ import haus.nightmare.lib3270j.Telnet3270Client;
*/
public class ECLConnection extends haus.nightmare.lib3270j.ecl.ECLConnection {
public ECLConnection() {
super();
}
public ECLConnection(haus.nightmare.lib3270j.ecl.ECLSession session) {
super((haus.nightmare.lib3270j.ecl.ECLSession) session, session != null ? session.getClient() : null);
}
public ECLConnection(String host, int port) {
super(host, port);
}
public ECLConnection(java.util.Properties props) {
super(props);
}
public ECLConnection(haus.nightmare.lib3270j.ecl.ECLSession session, Telnet3270Client client) {
super(session, client);
}
@@ -0,0 +1,33 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLErr.
*/
public class ECLErr extends haus.nightmare.lib3270j.ecl.ECLErr {
private static final long serialVersionUID = 1L;
public ECLErr() {
super();
}
public ECLErr(String text) {
super(text);
}
public ECLErr(String tag, String id, String text) {
super(tag, id, text);
}
public ECLErr(String tag, String id, String text, String extra) {
super(tag, id, text, extra);
}
public ECLErr(Throwable cause) {
super(cause);
}
public ECLErr(String message, Throwable cause) {
super(message, cause);
}
}
@@ -12,4 +12,8 @@ public class ECLOIA extends haus.nightmare.lib3270j.ecl.ECLOIA {
public ECLOIA(ScreenBuffer screen, InputProcessor inputProcessor, TelnetFSM fsm) {
super(screen, inputProcessor, fsm);
}
public ECLOIA(haus.nightmare.lib3270j.eNetwork.ECL.ECLSession session) {
super(session);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLOIANotify.
*/
public interface ECLOIANotify extends haus.nightmare.lib3270j.ecl.ECLOIANotify {
}
@@ -12,4 +12,8 @@ public class ECLPS extends haus.nightmare.lib3270j.ecl.ECLPS {
public ECLPS(ScreenBuffer screen, InputProcessor inputProcessor, EbcdicTranslator translator) {
super(screen, inputProcessor, translator);
}
public ECLPS(haus.nightmare.lib3270j.eNetwork.ECL.ECLSession session) {
super(session);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSBIDIServices.
*/
public interface ECLPSBIDIServices extends haus.nightmare.lib3270j.ecl.ECLPSBIDIServices {
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSGraphicsServices.
*/
public interface ECLPSGraphicsServices extends haus.nightmare.lib3270j.ecl.ECLPSGraphicsServices {
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSHindiServices.
*/
public interface ECLPSHindiServices extends haus.nightmare.lib3270j.ecl.ECLPSHindiServices {
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSTHAIServices.
*/
public interface ECLPSTHAIServices extends haus.nightmare.lib3270j.ecl.ECLPSTHAIServices {
}
@@ -0,0 +1,18 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSUpdate.
*/
public class ECLPSUpdate extends haus.nightmare.lib3270j.ecl.ECLPSUpdate {
private static final long serialVersionUID = 1L;
public ECLPSUpdate(haus.nightmare.lib3270j.ecl.ECLPS ps, int startRow, int startCol,
int endRow, int endCol, int start, int end, boolean fullUpdate, String text) {
super(ps, startRow, startCol, endRow, endCol, start, end, fullUpdate, text);
}
public ECLPSUpdate(int startRow, int startCol, int endRow, int endCol, boolean fullUpdate) {
super(startRow, startCol, endRow, endCol, fullUpdate);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLScreenNotify.
*/
public interface ECLScreenNotify extends haus.nightmare.lib3270j.ecl.ECLScreenNotify {
}
@@ -0,0 +1,19 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLScreenReco.
*/
public class ECLScreenReco extends haus.nightmare.lib3270j.ecl.ECLScreenReco {
public ECLScreenReco() {
super();
}
public ECLScreenReco(haus.nightmare.lib3270j.ecl.ECLSession session) {
super(session);
}
public ECLScreenReco(haus.nightmare.lib3270j.ecl.ECLPS ps) {
super(ps);
}
}
@@ -0,0 +1,13 @@
package haus.nightmare.lib3270j.eNetwork.ECL;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLScreenRecoEvent.
*/
public class ECLScreenRecoEvent extends haus.nightmare.lib3270j.ecl.ECLScreenRecoEvent {
public ECLScreenRecoEvent(haus.nightmare.lib3270j.ecl.ECLScreenReco source,
haus.nightmare.lib3270j.ecl.ECLScreenDesc screenDesc,
haus.nightmare.lib3270j.ecl.ECLPS ps) {
super(source, screenDesc, ps);
}
}
@@ -0,0 +1,15 @@
package haus.nightmare.lib3270j.eNetwork.ECL.bidi;
import haus.nightmare.lib3270j.input.InputProcessor;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
import haus.nightmare.lib3270j.telnet.TelnetFSM;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLOIABIDI.
*/
public class ECLOIABIDI extends haus.nightmare.lib3270j.ecl.ECLOIABIDI {
public ECLOIABIDI(ScreenBuffer screen, InputProcessor inputProcessor, TelnetFSM fsm) {
super(screen, inputProcessor, fsm);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL.event;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLOIANotify in event package.
*/
public interface ECLOIANotify extends haus.nightmare.lib3270j.ecl.ECLOIANotify {
}
@@ -1,5 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL.event;
import haus.nightmare.lib3270j.ecl.ECLPSUpdate;
/**
* IBM Host On-Demand ECLPSEvent compatibility class.
*/
@@ -7,6 +9,15 @@ public class ECLPSEvent extends haus.nightmare.lib3270j.ecl.ECLPSEvent {
private static final long serialVersionUID = 1L;
public ECLPSEvent(Object source, int eventType, int type, int startRow, int startCol,
int endRow, int endCol, int oldCursorAddress, int newCursorAddress,
int rows, int cols, boolean fullUpdate, boolean cursorVisible,
int ringCounter, boolean startPrinterBit, ECLPSUpdate psUpdate) {
super(source, eventType, type, startRow, startCol, endRow, endCol,
oldCursorAddress, newCursorAddress, rows, cols, fullUpdate,
cursorVisible, ringCounter, startPrinterBit, psUpdate);
}
public ECLPSEvent(Object source, int eventType, int startRow, int startCol, int endRow, int endCol,
int oldCursorAddress, int newCursorAddress, int rows, int cols, boolean fullUpdate) {
super(source, eventType, startRow, startCol, endRow, endCol, oldCursorAddress, newCursorAddress, rows, cols, fullUpdate);
@@ -0,0 +1,22 @@
package haus.nightmare.lib3270j.eNetwork.ECL.event;
import java.awt.Image;
import java.awt.Rectangle;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSGraphicsEvent.
*/
public class ECLPSGraphicsEvent extends haus.nightmare.lib3270j.ecl.ECLPSGraphicsEvent {
public ECLPSGraphicsEvent(haus.nightmare.lib3270j.ecl.ECLPS source, int id) {
super(source, id);
}
public ECLPSGraphicsEvent(haus.nightmare.lib3270j.ecl.ECLPS source, int id, Image image) {
super(source, id, image);
}
public ECLPSGraphicsEvent(haus.nightmare.lib3270j.ecl.ECLPS source, int id, Image image, Rectangle rectangle) {
super(source, id, image, rectangle);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL.event;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLPSGraphicsListener.
*/
public interface ECLPSGraphicsListener extends haus.nightmare.lib3270j.ecl.ECLPSGraphicsListener {
}
@@ -0,0 +1,15 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hindi;
import haus.nightmare.lib3270j.input.InputProcessor;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
import haus.nightmare.lib3270j.telnet.TelnetFSM;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLOIAHindi.
*/
public class ECLOIAHindi extends haus.nightmare.lib3270j.ecl.ECLOIAHindi {
public ECLOIAHindi(ScreenBuffer screen, InputProcessor inputProcessor, TelnetFSM fsm) {
super(screen, inputProcessor, fsm);
}
}
@@ -0,0 +1,10 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for Edge.
*/
public class Edge extends haus.nightmare.lib3270j.graphics.Edge {
public Edge(int x1, int y1, int x2, int y2) {
super(x1, y1, x2, y2);
}
}
@@ -0,0 +1,20 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import java.awt.Color;
/**
* Drop-in IBM Host On-Demand compatible facade for FillArea.
*/
public class FillArea extends haus.nightmare.lib3270j.graphics.FillArea {
public FillArea() {
super();
}
public FillArea(int fillRule) {
super(fillRule);
}
public FillArea(int[] px, int[] py, int[] polyCounts, int numPolys, Color color) {
super(px, py, polyCounts, numPolys, color);
}
}
@@ -0,0 +1,10 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for FilletPts.
*/
public class FilletPts extends haus.nightmare.lib3270j.graphics.FilletPts {
public FilletPts() {
super();
}
}
@@ -0,0 +1,12 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import java.awt.Component;
/**
* Drop-in IBM Host On-Demand compatible facade for HODBitImage.
*/
public class HODBitImage extends haus.nightmare.lib3270j.graphics.HODBitImage {
public HODBitImage(Component comp, int width, int height, byte[] data, int baseColor, int depth, boolean useGraphicColors) {
super(comp, width, height, data, baseColor, depth, useGraphicColors);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for HODBounds.
*/
public class HODBounds extends haus.nightmare.lib3270j.graphics.HODBounds {
}
@@ -0,0 +1,10 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for HODColorChangeFilter.
*/
public class HODColorChangeFilter extends haus.nightmare.lib3270j.graphics.HODColorChangeFilter {
public HODColorChangeFilter(int color) {
super(color);
}
}
@@ -0,0 +1,20 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import haus.nightmare.lib3270j.graphics.GraphicsPlane;
/**
* Drop-in IBM Host On-Demand compatible facade for HODGraphicsPlane.
*/
public class HODGraphicsPlane extends haus.nightmare.lib3270j.graphics.HODGraphicsPlane {
public HODGraphicsPlane() {
super();
}
public HODGraphicsPlane(int width, int height) {
super(width, height);
}
public HODGraphicsPlane(GraphicsPlane delegate) {
super(delegate);
}
}
@@ -0,0 +1,30 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
/**
* Drop-in IBM Host On-Demand compatible facade for HODPart.
*/
public class HODPart extends haus.nightmare.lib3270j.graphics.HODPart {
public HODPart() {
super();
}
public HODPart(Component component) {
super(component);
}
public HODPart(Component component, Dimension dimension) {
super(component, dimension);
}
public HODPart(Component component, Rectangle rectangle) {
super(component, rectangle);
}
public HODPart(HODPart hODPart) {
super(hODPart);
}
}
@@ -0,0 +1,16 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import haus.nightmare.lib3270j.graphics.ProgramSymbolManager;
/**
* Drop-in IBM Host On-Demand compatible facade for HODProgramSymbolManager.
*/
public class HODProgramSymbolManager extends haus.nightmare.lib3270j.graphics.HODProgramSymbolManager {
public HODProgramSymbolManager() {
super();
}
public HODProgramSymbolManager(ProgramSymbolManager delegate) {
super(delegate);
}
}
@@ -0,0 +1,10 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for HODTransform.
*/
public class HODTransform extends haus.nightmare.lib3270j.graphics.HODTransform {
public HODTransform(int charW, int charH, int defaultCharW, int defaultCharH) {
super(charW, charH, defaultCharW, defaultCharH);
}
}
@@ -0,0 +1,10 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
/**
* Drop-in IBM Host On-Demand compatible facade for HODTransparentColorFilter.
*/
public class HODTransparentColorFilter extends haus.nightmare.lib3270j.graphics.HODTransparentColorFilter {
public HODTransparentColorFilter(int transparentColor) {
super(transparentColor);
}
}
@@ -0,0 +1,20 @@
package haus.nightmare.lib3270j.eNetwork.ECL.hostgraphics;
import java.awt.Image;
/**
* Drop-in IBM Host On-Demand compatible facade for HODWallpaper.
*/
public class HODWallpaper extends haus.nightmare.lib3270j.graphics.HODWallpaper {
public HODWallpaper() {
super();
}
public HODWallpaper(int displayMode) {
super(displayMode);
}
public HODWallpaper(Image image, int displayMode) {
super(image, displayMode);
}
}
@@ -0,0 +1,15 @@
package haus.nightmare.lib3270j.eNetwork.ECL.thai;
import haus.nightmare.lib3270j.input.InputProcessor;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
import haus.nightmare.lib3270j.telnet.TelnetFSM;
/**
* Drop-in IBM Host On-Demand compatible facade for ECLOIATHAI.
*/
public class ECLOIATHAI extends haus.nightmare.lib3270j.ecl.ECLOIATHAI {
public ECLOIATHAI(ScreenBuffer screen, InputProcessor inputProcessor, TelnetFSM fsm) {
super(screen, inputProcessor, fsm);
}
}
@@ -0,0 +1,29 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.datastream.DataStreamProcessor;
import haus.nightmare.lib3270j.ecl.ECLPS;
import haus.nightmare.lib3270j.ecl.ECLSession;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270.DS3270.
*/
public class DS3270 extends haus.nightmare.lib3270j.tn3270.DS3270 {
public DS3270() {
super();
}
public DS3270(ScreenBuffer screen, EbcdicTranslator translator) {
super(screen, translator);
}
public DS3270(DataStreamProcessor delegate) {
super(delegate);
}
public DS3270(ECLSession session, ECLPS ps) {
super(session, ps);
}
}
@@ -0,0 +1,23 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270;
import haus.nightmare.lib3270j.ecl.ECLPS;
import haus.nightmare.lib3270j.ecl.ECLSession;
import haus.nightmare.lib3270j.nvt.NvtProcessor;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270.NVT3270.
*/
public class NVT3270 extends haus.nightmare.lib3270j.tn3270.NVT3270 {
public NVT3270() {
super();
}
public NVT3270(NvtProcessor nvtProcessor) {
super(nvtProcessor);
}
public NVT3270(String host, ECLSession session, ECLPS ps, haus.nightmare.lib3270j.tn3270.DS3270 ds) {
super(host, session, ps, ds);
}
}
@@ -0,0 +1,24 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.ecl.ECLSession;
import haus.nightmare.lib3270j.input.InputProcessor;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270.PS3270.
*/
public class PS3270 extends haus.nightmare.lib3270j.tn3270.PS3270 {
public PS3270() {
super();
}
public PS3270(ECLSession session) {
super(session);
}
public PS3270(ScreenBuffer screen, InputProcessor inputProcessor, EbcdicTranslator translator) {
super(screen, inputProcessor, translator);
}
}
@@ -0,0 +1,24 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270;
import haus.nightmare.lib3270j.ecl.ECLPS;
import haus.nightmare.lib3270j.ecl.ECLSession;
import haus.nightmare.lib3270j.telnet.TelnetConnection;
import haus.nightmare.lib3270j.telnet.TelnetFSM;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270.Telnet3270E.
*/
public class Telnet3270E extends haus.nightmare.lib3270j.tn3270.Telnet3270E {
public Telnet3270E() {
super();
}
public Telnet3270E(TelnetFSM fsm, TelnetConnection connection) {
super(fsm, connection);
}
public Telnet3270E(String host, ECLSession session, ECLPS ps, haus.nightmare.lib3270j.tn3270.DS3270 ds) {
super(host, session, ps, ds);
}
}
@@ -0,0 +1,19 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270.qr_elem.
*/
public class qr_elem extends haus.nightmare.lib3270j.tn3270.qr_elem {
public qr_elem() {
super();
}
public qr_elem(int type, int sendFlag) {
super(type, sendFlag);
}
public qr_elem(byte type, byte sendFlag) {
super(type, sendFlag);
}
}
@@ -0,0 +1,31 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrintPS3270;
import haus.nightmare.lib3270j.printer.PrintSCS3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
import haus.nightmare.lib3270j.printer.Telnet3270EP;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.DS3270P.
*/
public class DS3270P extends haus.nightmare.lib3270j.printer.DS3270P {
public DS3270P() {
super();
}
public DS3270P(PrinterConfig config) {
super(config);
}
public DS3270P(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
public DS3270P(Telnet3270EP telnet, PrinterConfig config, PD3270 pd,
PrintSCS3270 scs, PrintPS3270 printPs, EbcdicTranslator translator) {
super(telnet, config, pd, scs, printPs, translator);
}
}
@@ -0,0 +1,17 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PD3270.
*/
public class PD3270 extends haus.nightmare.lib3270j.printer.PD3270 {
public PD3270() {
super();
}
public PD3270(PrinterConfig config) {
super(config);
}
}
@@ -0,0 +1,11 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PDT.
*/
public class PDT extends PrinterDefinitionTable {
public PDT(String name, String description) {
super(name, description);
}
}
@@ -0,0 +1,15 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PrintPS3270.
*/
public class PrintPS3270 extends haus.nightmare.lib3270j.printer.PrintPS3270 {
public PrintPS3270(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
}
@@ -0,0 +1,19 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PrintPS3270DB.
*/
public class PrintPS3270DB extends haus.nightmare.lib3270j.printer.PrintPS3270DB {
public PrintPS3270DB(PrinterConfig config) {
super(config);
}
public PrintPS3270DB(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
}
@@ -0,0 +1,15 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PrintSCS3270.
*/
public class PrintSCS3270 extends haus.nightmare.lib3270j.printer.PrintSCS3270 {
public PrintSCS3270(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
}
@@ -0,0 +1,19 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PrintSCS3270DB.
*/
public class PrintSCS3270DB extends haus.nightmare.lib3270j.printer.PrintSCS3270DB {
public PrintSCS3270DB(PrinterConfig config) {
super(config);
}
public PrintSCS3270DB(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
}
@@ -0,0 +1,11 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.PrinterDefinitionTable.
*/
public class PrinterDefinitionTable extends haus.nightmare.lib3270j.printer.PrinterDefinitionTable {
public PrinterDefinitionTable(String name, String description) {
super(name, description);
}
}
@@ -0,0 +1,19 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.printer.PD3270;
import haus.nightmare.lib3270j.printer.PrinterConfig;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.Telnet3270EP.
*/
public class Telnet3270EP extends haus.nightmare.lib3270j.printer.Telnet3270EP {
public Telnet3270EP(PrinterConfig config) {
super(config);
}
public Telnet3270EP(PrinterConfig config, PD3270 pd, EbcdicTranslator translator) {
super(config, pd, translator);
}
}
@@ -0,0 +1,29 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
import haus.nightmare.lib3270j.printer.TimerListener;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.Timer.
*/
public class Timer extends haus.nightmare.lib3270j.printer.Timer {
public Timer() {
super();
}
public Timer(long intervalMs) {
super(intervalMs);
}
public Timer(long intervalMs, TimerListener listener) {
super(intervalMs, listener);
}
public Timer(long intervalMs, TimerListener listener, boolean repeating) {
super(intervalMs, listener, repeating);
}
public Timer(long intervalMs, TimerListener listener, boolean repeating, String timerId) {
super(intervalMs, listener, repeating, timerId);
}
}
@@ -0,0 +1,21 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.TimerEvent.
*/
public class TimerEvent extends haus.nightmare.lib3270j.printer.TimerEvent {
private static final long serialVersionUID = 1L;
public TimerEvent(Object source) {
super(source);
}
public TimerEvent(Object source, String timerId) {
super(source, timerId);
}
public TimerEvent(Object source, String timerId, long timestamp) {
super(source, timerId, timestamp);
}
}
@@ -0,0 +1,7 @@
package haus.nightmare.lib3270j.eNetwork.ECL.tn3270p;
/**
* Drop-in IBM Host On-Demand compatible facade for com.ibm.eNetwork.ECL.tn3270p.TimerListener.
*/
public interface TimerListener extends haus.nightmare.lib3270j.printer.TimerListener {
}
@@ -0,0 +1,34 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
import haus.nightmare.lib3270j.ft.FTConfig;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer.FileTransferFileObject.
*/
public class FileTransferFileObject extends haus.nightmare.lib3270j.xfer.FileTransferFileObject {
public FileTransferFileObject() {
super();
}
public FileTransferFileObject(String name) {
super(name);
}
public FileTransferFileObject(String name, long size) {
super(name, size);
}
public FileTransferFileObject(String name, long size, boolean isDirectory) {
super(name, size, isDirectory);
}
public FileTransferFileObject(String localFile, String hostDatasetName) {
super(localFile, hostDatasetName);
}
public FileTransferFileObject(FTConfig config) {
super(config);
}
}
@@ -0,0 +1,8 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
/**
* Drop-in IBM Host On-Demand compatibility interface for
* com.ibm.eNetwork.ECL.xfer.FileTransferHostDirectoryInterface.
*/
public interface FileTransferHostDirectoryInterface extends haus.nightmare.lib3270j.xfer.FileTransferHostDirectoryInterface {
}
@@ -0,0 +1,8 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
/**
* Drop-in IBM Host On-Demand compatibility interface for
* com.ibm.eNetwork.ECL.xfer.FileTransferInterface.
*/
public interface FileTransferInterface extends haus.nightmare.lib3270j.xfer.FileTransferInterface {
}
@@ -0,0 +1,8 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
/**
* Drop-in IBM Host On-Demand compatibility interface for
* com.ibm.eNetwork.ECL.xfer.FileTransferStatusInterface.
*/
public interface FileTransferStatusInterface extends haus.nightmare.lib3270j.xfer.FileTransferStatusInterface {
}
@@ -0,0 +1,27 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
import java.io.File;
import java.io.FileNotFoundException;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer.XferFileInputStream.
*/
public class XferFileInputStream extends haus.nightmare.lib3270j.xfer.XferFileInputStream {
public XferFileInputStream(String name, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(name, nonIbmText, nonIbmTerminator, asciiTransfer);
}
public XferFileInputStream(File file, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(file, nonIbmText, nonIbmTerminator, asciiTransfer);
}
public XferFileInputStream(String name, byte[] terminators) throws FileNotFoundException {
super(name, terminators);
}
public XferFileInputStream(File file, byte[] terminators) throws FileNotFoundException {
super(file, terminators);
}
}
@@ -0,0 +1,25 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
import haus.nightmare.lib3270j.charset.CodePage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer.XferFileInputUnicode.
*/
public class XferFileInputUnicode extends haus.nightmare.lib3270j.xfer.XferFileInputUnicode {
public XferFileInputUnicode(String filename, byte[] terminators, CodePage cp,
int unicodeType, int sessionType, boolean noso)
throws FileNotFoundException, UnsupportedEncodingException {
super(filename, terminators, cp, unicodeType, sessionType, noso);
}
public XferFileInputUnicode(File file, byte[] terminators, CodePage cp,
int unicodeType, int sessionType, boolean noso)
throws FileNotFoundException, UnsupportedEncodingException {
super(file, terminators, cp, unicodeType, sessionType, noso);
}
}
@@ -0,0 +1,27 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
import java.io.File;
import java.io.FileNotFoundException;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer.XferFileOutputStream.
*/
public class XferFileOutputStream extends haus.nightmare.lib3270j.xfer.XferFileOutputStream {
public XferFileOutputStream(String name, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(name, nonIbmText, nonIbmTerminator, asciiTransfer);
}
public XferFileOutputStream(File file, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(file, nonIbmText, nonIbmTerminator, asciiTransfer);
}
public XferFileOutputStream(String name, boolean append, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(name, append, nonIbmText, nonIbmTerminator, asciiTransfer);
}
public XferFileOutputStream(File file, boolean append, boolean nonIbmText, byte[] nonIbmTerminator, boolean asciiTransfer) throws FileNotFoundException {
super(file, append, nonIbmText, nonIbmTerminator, asciiTransfer);
}
}
@@ -0,0 +1,27 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer;
import haus.nightmare.lib3270j.charset.CodePage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer.XferFileOutputUnicode.
*/
public class XferFileOutputUnicode extends haus.nightmare.lib3270j.xfer.XferFileOutputUnicode {
public XferFileOutputUnicode(String filename, boolean append, byte[] terminators,
boolean asciiTransfer, CodePage cp, int unicodeType,
boolean soFlag, boolean soAlt)
throws FileNotFoundException, UnsupportedEncodingException {
super(filename, append, terminators, asciiTransfer, cp, unicodeType, soFlag, soAlt);
}
public XferFileOutputUnicode(File file, boolean append, byte[] terminators,
boolean asciiTransfer, CodePage cp, int unicodeType,
boolean soFlag, boolean soAlt)
throws FileNotFoundException, UnsupportedEncodingException {
super(file, append, terminators, asciiTransfer, cp, unicodeType, soFlag, soAlt);
}
}
@@ -0,0 +1,27 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer3270;
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
import haus.nightmare.lib3270j.ecl.ECLXfer;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer3270.CMSPrintXfer.
*/
public class CMSPrintXfer extends haus.nightmare.lib3270j.xfer3270.CMSPrintXfer {
public CMSPrintXfer() {
super();
}
public CMSPrintXfer(ECLXfer xfer) {
super(xfer);
}
public CMSPrintXfer(ECLXfer xfer, EbcdicTranslator translator) {
super(xfer, translator);
}
public CMSPrintXfer(Xfer3270 xfer3270) {
super(xfer3270);
}
}
@@ -0,0 +1,37 @@
package haus.nightmare.lib3270j.eNetwork.ECL.xfer3270;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.datastream.DataStreamProcessor;
import haus.nightmare.lib3270j.ecl.ECLSession;
import haus.nightmare.lib3270j.ecl.ECLXfer;
import haus.nightmare.lib3270j.input.InputProcessor;
import haus.nightmare.lib3270j.screen.ScreenBuffer;
import java.net.URL;
/**
* Drop-in IBM Host On-Demand compatibility class for
* com.ibm.eNetwork.ECL.xfer3270.Xfer3270.
*/
public class Xfer3270 extends haus.nightmare.lib3270j.xfer3270.Xfer3270 {
public Xfer3270() {
super();
}
public Xfer3270(ECLSession session) {
super(session);
}
public Xfer3270(ECLSession session, URL url) {
super(session, url);
}
public Xfer3270(ECLXfer xfer) {
super(xfer);
}
public Xfer3270(ScreenBuffer screen, InputProcessor input,
DataStreamProcessor dsProcessor, CodePage codePage) {
super(screen, input, dsProcessor, codePage);
}
}
@@ -0,0 +1,28 @@
package haus.nightmare.lib3270j.eNetwork.HOD.common;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.converters.HODUnsupportedCodepageException;
/**
* IBM Host On-Demand drop-in compatibility facade for HODByteToCharConverter.
*/
public abstract class HODByteToCharConverter extends haus.nightmare.lib3270j.converters.HODByteToCharConverter {
public HODByteToCharConverter() {
super();
}
public HODByteToCharConverter(CodePage codePage) {
super(codePage);
}
public static haus.nightmare.lib3270j.converters.HODByteToCharConverter getHODConverter(String encoding)
throws HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODByteToCharConverter.getHODConverter(encoding);
}
public static haus.nightmare.lib3270j.converters.HODByteToCharConverter getConverter(String encoding)
throws HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODByteToCharConverter.getConverter(encoding);
}
}
@@ -0,0 +1,17 @@
package haus.nightmare.lib3270j.eNetwork.HOD.common;
/**
* IBM Host On-Demand drop-in compatibility facade for HODCharConversionException.
*/
public class HODCharConversionException extends haus.nightmare.lib3270j.converters.HODCharConversionException {
private static final long serialVersionUID = 1L;
public HODCharConversionException() {
super();
}
public HODCharConversionException(String message) {
super(message);
}
}
@@ -0,0 +1,28 @@
package haus.nightmare.lib3270j.eNetwork.HOD.common;
import haus.nightmare.lib3270j.charset.CodePage;
import haus.nightmare.lib3270j.converters.HODUnsupportedCodepageException;
/**
* IBM Host On-Demand drop-in compatibility facade for HODCharToByteConverter.
*/
public abstract class HODCharToByteConverter extends haus.nightmare.lib3270j.converters.HODCharToByteConverter {
public HODCharToByteConverter() {
super();
}
public HODCharToByteConverter(CodePage codePage) {
super(codePage);
}
public static haus.nightmare.lib3270j.converters.HODCharToByteConverter getHODConverter(String encoding)
throws HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODCharToByteConverter.getHODConverter(encoding);
}
public static haus.nightmare.lib3270j.converters.HODCharToByteConverter getConverter(String encoding)
throws HODUnsupportedCodepageException {
return haus.nightmare.lib3270j.converters.HODCharToByteConverter.getConverter(encoding);
}
}
@@ -0,0 +1,17 @@
package haus.nightmare.lib3270j.eNetwork.HOD.common;
/**
* IBM Host On-Demand drop-in compatibility facade for HODUnsupportedCodepageException.
*/
public class HODUnsupportedCodepageException extends haus.nightmare.lib3270j.converters.HODUnsupportedCodepageException {
private static final long serialVersionUID = 1L;
public HODUnsupportedCodepageException() {
super();
}
public HODUnsupportedCodepageException(String encoding) {
super(encoding);
}
}
@@ -0,0 +1,33 @@
package haus.nightmare.lib3270j.eNetwork.security.ssl;
import haus.nightmare.lib3270j.ConnectionConfig;
import haus.nightmare.lib3270j.ecl.ECLConnection;
import haus.nightmare.lib3270j.ecl.ECLSession;
import java.util.Properties;
/**
* IBM Host On-Demand (HoD) canonical package compatibility drop-in facade for
* com.ibm.eNetwork.security.ssl.HODSSLECLSessionImpl.
*/
public class HODSSLECLSessionImpl extends haus.nightmare.lib3270j.security.ssl.HODSSLECLSessionImpl {
public HODSSLECLSessionImpl() {
super();
}
public HODSSLECLSessionImpl(ConnectionConfig config) {
super(config);
}
public HODSSLECLSessionImpl(ECLSession session) {
super(session);
}
public HODSSLECLSessionImpl(ECLConnection connection) {
super(connection);
}
public HODSSLECLSessionImpl(Properties props) {
super(props);
}
}
@@ -0,0 +1,131 @@
package haus.nightmare.lib3270j.ecl;
/**
* Standard implementation of ECLPSBIDIServices conforming to IBM Host On-Demand ECL.
*/
public class DefaultPSBIDIServices implements ECLPSBIDIServices {
private final ECLPS ps;
private String numeralShape = NOMINAL;
private String textType = VISUAL;
private String textOrientation = LEFT_TO_RIGHT;
private String roundTrip = ROUNDTRIP_OFF;
private String lamAlef = LAMALEF_ON;
private String rtlUnicode = RTLUNICODE_ON;
private boolean macroBidiEnabled = false;
private boolean numericSwap = false;
private boolean symmetricSwap = false;
public DefaultPSBIDIServices(ECLPS ps) {
this.ps = ps;
}
@Override
public void SetNumeralShape(String shape) throws ECLErr {
this.numeralShape = shape != null ? shape : NOMINAL;
}
@Override
public String GetNumeralShape() {
return numeralShape;
}
@Override
public void SetTextType(String type) throws ECLErr {
this.textType = type != null ? type : VISUAL;
}
@Override
public String GetTextType() {
return textType;
}
@Override
public void SetTextOrientation(String orientation) throws ECLErr {
this.textOrientation = orientation != null ? orientation : LEFT_TO_RIGHT;
}
@Override
public String GetTextOrientation() {
return textOrientation;
}
@Override
public void setMacroBidiEnabled(boolean enabled) {
this.macroBidiEnabled = enabled;
}
@Override
public boolean isMacroBidiEnabled() {
return macroBidiEnabled;
}
@Override
public void SetRoundTrip(String rt) throws ECLErr {
this.roundTrip = rt != null ? rt : ROUNDTRIP_OFF;
}
@Override
public String GetRoundTrip() {
return roundTrip;
}
@Override
public void SetBIDICursorPos(int pos, boolean visual) throws ECLErr {
if (ps != null) {
ps.setCursorPos(pos - 1);
}
}
@Override
public void SetBIDICursorPos(int pos) throws ECLErr {
SetBIDICursorPos(pos, false);
}
@Override
public void SetBIDICursorPos(int row, int col) throws ECLErr {
if (ps != null) {
ps.setCursorPos(row - 1, col - 1);
}
}
@Override
public void SetLamAlef(String mode) throws ECLErr {
this.lamAlef = mode != null ? mode : LAMALEF_ON;
}
@Override
public String GetLamAlef() {
return lamAlef;
}
@Override
public void SetRTLUnicode(String mode) throws ECLErr {
this.rtlUnicode = mode != null ? mode : RTLUNICODE_ON;
}
@Override
public String GetRTLUnicode() {
return rtlUnicode;
}
@Override
public void setNumericSwap(boolean swap) {
this.numericSwap = swap;
}
@Override
public boolean getNumericSwap() {
return numericSwap;
}
@Override
public void setSymmetricSwap(boolean swap) {
this.symmetricSwap = swap;
}
@Override
public boolean getSymmetricSwap() {
return symmetricSwap;
}
}
@@ -0,0 +1,73 @@
package haus.nightmare.lib3270j.ecl;
import java.awt.Color;
import java.awt.Component;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Standard implementation of ECLPSGraphicsServices conforming to IBM Host On-Demand ECL.
*/
public class DefaultPSGraphicsServices implements ECLPSGraphicsServices {
private final ECLPS ps;
private Component visualComponent;
private Color[] colors;
private final List<ECLPSGraphicsListener> listeners = new CopyOnWriteArrayList<>();
public DefaultPSGraphicsServices(ECLPS ps) {
this.ps = ps;
}
@Override
public void setVisualComponent(Component comp) {
this.visualComponent = comp;
}
public Component getVisualComponent() {
return visualComponent;
}
@Override
public void setGraphicColor(Color[] colors, boolean b) {
this.colors = (colors != null) ? colors.clone() : null;
}
public Color[] getGraphicColors() {
return (colors != null) ? colors.clone() : null;
}
@Override
public void mousePressed(int x, int y, int button) {
if (ps != null && ps.getInputProcessor() != null) {
ps.getInputProcessor().sendGraphicMouseAid(x, y, button == 1, false);
}
ECLPSGraphicsEvent event = new ECLPSGraphicsEvent(ps, ECLPSGraphicsEvent.GRAPHICS_UPDATED);
for (ECLPSGraphicsListener l : listeners) {
try {
l.graphicsUpdated(event);
} catch (Exception ignored) {}
}
}
@Override
public void addGraphicsListener(ECLPSGraphicsListener listener) {
if (listener != null && !listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public void removeGraphicsListener(ECLPSGraphicsListener listener) {
listeners.remove(listener);
}
public void fireGraphicsEvent(int id) {
ECLPSGraphicsEvent event = new ECLPSGraphicsEvent(ps, id);
for (ECLPSGraphicsListener l : listeners) {
try {
l.graphicsEvent(event);
} catch (Exception ignored) {}
}
}
}
@@ -0,0 +1,33 @@
package haus.nightmare.lib3270j.ecl;
/**
* Standard implementation of ECLPSHindiServices conforming to IBM Host On-Demand ECL.
*/
public class DefaultPSHindiServices implements ECLPSHindiServices {
private final ECLPS ps;
public DefaultPSHindiServices(ECLPS ps) {
this.ps = ps;
}
@Override
public int GetHindiCursorCol(int row, int col) {
return col;
}
@Override
public byte GetHindiCursorLevel(int row, int col) {
return 0;
}
@Override
public int GetNormalCursorCol(int row, int col) {
return col;
}
@Override
public void switchToHindiLayer() {
// Layer switch stub
}
}
@@ -0,0 +1,39 @@
package haus.nightmare.lib3270j.ecl;
/**
* Standard implementation of ECLPSTHAIServices conforming to IBM Host On-Demand ECL.
*/
public class DefaultPSTHAIServices implements ECLPSTHAIServices {
private final ECLPS ps;
private int displayMode = 0;
public DefaultPSTHAIServices(ECLPS ps) {
this.ps = ps;
}
@Override
public void SetThaiDisplayMode(int mode) throws ECLErr {
this.displayMode = mode;
}
@Override
public int GetThaiDisplayMode() {
return displayMode;
}
@Override
public int GetThaiCursorCol(int row, int col) {
return col;
}
@Override
public byte GetThaiCursorLevel(int row, int col) {
return 0;
}
@Override
public int GetNormalCursorCol(int row, int col) {
return col;
}
}
@@ -5,6 +5,7 @@ import java.util.EventObject;
/**
* Event object dispatched on communication lifecycle and state transitions.
* Conforms 1:1 to IBM Host On-Demand ECLCommEvent specification.
*/
public class ECLCommEvent extends EventObject {
@@ -35,35 +36,60 @@ public class ECLCommEvent extends EventObject {
public ECLCommEvent(Object source, int eventType, ConnectionState oldState, ConnectionState newState,
String message, String deviceType, String deviceName) {
super(source);
super(source != null ? source : "ECLConnection");
this.eventType = eventType;
this.oldState = oldState;
this.newState = newState;
this.message = message;
this.deviceType = deviceType;
this.deviceName = deviceName;
this.message = message != null ? message : "";
this.deviceType = deviceType != null ? deviceType : "";
this.deviceName = deviceName != null ? deviceName : "";
}
public int getEventType() { return eventType; }
public int GetType() { return eventType; }
public int getType() { return eventType; }
public ConnectionState getOldState() { return oldState; }
public ConnectionState GetOldState() { return oldState; }
public ConnectionState getNewState() { return newState; }
public ConnectionState GetNewState() { return newState; }
public String getMessage() { return message; }
public String GetMessage() { return message; }
public String getErrorMessage() { return message; }
public String GetErrorMessage() { return message; }
public String getDeviceType() { return deviceType; }
public String GetDeviceType() { return deviceType; }
public String getDeviceName() { return deviceName; }
public String GetDeviceName() { return deviceName; }
public String getLUName() { return deviceName; }
public String GetLUName() { return deviceName; }
public boolean isConnected() {
return newState != null && newState.isConnected();
}
public boolean IsConnected() {
return isConnected();
}
public boolean isFullSession() {
return newState != null && newState.isFullSession();
}
public boolean IsFullSession() {
return isFullSession();
}
public ECLConnection getConnection() {
return (getSource() instanceof ECLConnection) ? (ECLConnection) getSource() : null;
}
public ECLConnection GetConnection() {
return getConnection();
}
@Override
public String toString() {
@@ -2,14 +2,39 @@ package haus.nightmare.lib3270j.ecl;
/**
* Listener interface for communication lifecycle events.
* Conforms 1:1 to IBM Host On-Demand ECLCommListener specification.
*/
public interface ECLCommListener {
/**
* Primary HoD notification callback invoked when connection state changes.
* @param event ECLCommEvent containing transition details
*/
default void CommNotifyEvent(ECLCommEvent event) {
commEvent(event);
}
/**
* Called when an error condition occurs on the connection.
* @param conn ECLConnection instance
* @param err ECLErr error descriptor
*/
default void CommNotifyError(ECLConnection conn, ECLErr err) {}
/**
* Called when communication event generation has stopped.
* @param conn ECLConnection instance
* @param reason Stop reason code
*/
default void CommNotifyStop(ECLConnection conn, int reason) {}
// ========== Backward-Compatibility Bridge Methods ==========
/**
* Called when the communication connection state or status changes.
* @param event ECLCommEvent containing transition details
*/
void commEvent(ECLCommEvent event);
default void commEvent(ECLCommEvent event) {}
/**
* Called specifically when the connection is established.
@@ -11,4 +11,26 @@ public interface ECLCommNotify {
* @param connected true if session is connected, false otherwise
*/
void CommNotify(boolean connected);
/**
* Optional event notification callback invoked on communication state change.
* @param event ECLCommEvent
*/
default void CommNotifyEvent(ECLCommEvent event) {
CommNotify(event != null && event.isConnected());
}
/**
* Optional error callback invoked on communication error.
* @param conn ECLConnection instance
* @param err ECLErr error descriptor
*/
default void CommNotifyError(ECLConnection conn, ECLErr err) {}
/**
* Optional stop callback invoked when communication event processing terminates.
* @param conn ECLConnection instance
* @param reason Stop reason code
*/
default void CommNotifyStop(ECLConnection conn, int reason) {}
}
@@ -7,6 +7,7 @@ import haus.nightmare.lib3270j.listener.ConnectionListener;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -19,6 +20,60 @@ public class ECLConnection {
private final List<ECLCommListener> commListeners = new CopyOnWriteArrayList<>();
private final List<ECLCommNotify> commNotifies = new CopyOnWriteArrayList<>();
private String host;
private int port = 23;
private String codePage;
private String deviceName;
private String luName;
private String workstationId = "";
private boolean ssl = false;
private boolean contentionResolution = false;
private boolean luluSession = false;
private boolean isNegCR = false;
private boolean isBIND7FArchitectureViolation = false;
private String keyRemap = "";
private String certificateName = "";
private String certificateSource = "";
private String certificateURL = "";
private String certificatePassword = "";
private boolean certificateProvided = false;
private String securityProtocol = "TLS";
private String tlsProtocolVersion = "TLSv1.2";
private boolean useJSSE = true;
private String jsseTrustStore = "";
private String jsseTrustStoreType = "JKS";
private String jsseTrustStorePassword = "";
private String proxyType = "";
private String proxyServerName = "";
private String proxyServerPort = "";
private String proxyUserId = "";
private String proxyUserPassword = "";
private String proxyAuthenMethod = "";
private String proxySecurityProtocol = "";
private Properties properties = new Properties();
public ECLConnection() {
this(null, null);
}
public ECLConnection(ECLSession session) {
this(session, session != null ? session.getClient() : null);
}
public ECLConnection(String host, int port) {
this(null, null);
this.host = host;
this.port = port;
}
public ECLConnection(Properties props) {
this(null, null);
if (props != null) {
this.properties.putAll(props);
convertData(this.properties);
}
}
public ECLConnection(ECLSession session, Telnet3270Client client) {
this.session = session;
this.client = client;
@@ -70,17 +125,20 @@ public class ECLConnection {
public Telnet3270Client getClient() { return client; }
public String GetHost() {
return (client != null && client.getConfig() != null) ? client.getConfig().getHost() : "";
if (client != null && client.getConfig() != null) return client.getConfig().getHost();
return host != null ? host : "";
}
public String getHost() { return GetHost(); }
public int GetPort() {
return (client != null && client.getConfig() != null) ? client.getConfig().getPort() : 23;
if (client != null && client.getConfig() != null) return client.getConfig().getPort();
return port;
}
public int getPort() { return GetPort(); }
public String GetCodePage() {
return (client != null) ? client.getCodePage() : "037";
if (client != null) return client.getCodePage();
return codePage != null ? codePage : "037";
}
public String getCodePage() { return GetCodePage(); }
@@ -93,7 +151,10 @@ public class ECLConnection {
if (client != null && client.getTelnetFSM() != null && client.getTelnetFSM().getConnectedLu() != null) {
return client.getTelnetFSM().getConnectedLu();
}
return (client != null && client.getConfig() != null) ? client.getConfig().getLuName() : null;
if (client != null && client.getConfig() != null && client.getConfig().getLuName() != null) {
return client.getConfig().getLuName();
}
return luName;
}
public String getLUName() { return GetLUName(); }
@@ -149,7 +210,8 @@ public class ECLConnection {
public boolean isDisconnecting() { return IsDisconnecting(); }
public boolean IsSSL() {
return client != null && client.getConfig() != null && client.getConfig().isUseTls();
if (client != null && client.getConfig() != null) return client.getConfig().isUseTls();
return ssl;
}
public boolean isSSL() { return IsSSL(); }
@@ -176,6 +238,10 @@ public class ECLConnection {
public void StopCommunication() { Disconnect(); }
public void stopCommunication() { Disconnect(); }
public static final int STOP_UNREGISTER = 1;
public static final int STOP_DISCONNECT = 2;
public static final int STOP_ERROR = 3;
// ========== Event Listener Management ==========
public void RegisterCommEvent(ECLCommListener listener) {
@@ -186,7 +252,12 @@ public class ECLConnection {
public void registerCommEvent(ECLCommListener listener) { RegisterCommEvent(listener); }
public void UnregisterCommEvent(ECLCommListener listener) {
commListeners.remove(listener);
if (listener != null) {
commListeners.remove(listener);
try {
listener.CommNotifyStop(this, STOP_UNREGISTER);
} catch (Exception ignored) {}
}
}
public void unregisterCommEvent(ECLCommListener listener) { UnregisterCommEvent(listener); }
@@ -198,30 +269,292 @@ public class ECLConnection {
public void registerCommEvent(ECLCommNotify notify, boolean sync) { RegisterCommEvent(notify, sync); }
public void UnregisterCommEvent(ECLCommNotify notify) {
commNotifies.remove(notify);
if (notify != null) {
commNotifies.remove(notify);
try {
notify.CommNotifyStop(this, STOP_UNREGISTER);
} catch (Exception ignored) {}
}
}
public void unregisterCommEvent(ECLCommNotify notify) { UnregisterCommEvent(notify); }
public void notifyCommError(ECLErr err) {
for (ECLCommListener l : commListeners) {
try {
l.CommNotifyError(this, err);
} catch (Exception ignored) {}
}
for (ECLCommNotify n : commNotifies) {
try {
n.CommNotifyError(this, err);
} catch (Exception ignored) {}
}
}
public void notifyCommStop(int reason) {
for (ECLCommListener l : commListeners) {
try {
l.CommNotifyStop(this, reason);
} catch (Exception ignored) {}
}
for (ECLCommNotify n : commNotifies) {
try {
n.CommNotifyStop(this, reason);
} catch (Exception ignored) {}
}
}
private void notifyCommEvent(ECLCommEvent event) {
for (ECLCommListener l : commListeners) {
try {
l.commEvent(event);
l.CommNotifyEvent(event);
if (event.getEventType() == ECLCommEvent.COMM_CONNECTED) {
l.commConnected(event);
} else if (event.getEventType() == ECLCommEvent.COMM_DISCONNECTED) {
l.commDisconnected(event);
} else if (event.getEventType() == ECLCommEvent.COMM_ERROR) {
l.commError(event);
l.CommNotifyError(this, new ECLErr("ECLConnection", "COMM0001", event.getMessage()));
}
} catch (Exception ignored) {}
}
for (ECLCommNotify n : commNotifies) {
try {
n.CommNotify(event.isConnected());
if (event.getEventType() == ECLCommEvent.COMM_ERROR) {
n.CommNotifyError(this, new ECLErr("ECLConnection", "COMM0001", event.getMessage()));
}
} catch (Exception ignored) {}
}
}
public void convertData(Properties properties) {
if (properties == null) return;
for (String key : properties.stringPropertyNames()) {
String val = properties.getProperty(key);
if (val != null) {
if ("true".equalsIgnoreCase(val)) {
properties.put(key, "1");
} else if ("false".equalsIgnoreCase(val)) {
properties.put(key, "0");
}
}
}
}
public void SetHost(String host) {
this.host = host;
if (client != null && client.getConfig() != null) {
client.getConfig().setHost(host);
}
}
public void setHost(String host) { SetHost(host); }
public void SetPort(int port) {
this.port = port;
if (client != null && client.getConfig() != null) {
client.getConfig().setPort(port);
}
}
public void setPort(int port) { SetPort(port); }
public void SetCodePage(String codePage) {
this.codePage = codePage;
if (client != null) {
client.setCodePage(codePage);
}
}
public void setCodePage(String codePage) { SetCodePage(codePage); }
public void SetDeviceName(String name) {
this.deviceName = name;
this.properties.put("deviceName", name != null ? name : "");
if (client != null && client.getConfig() != null) {
client.getConfig().setTerminalName(name);
}
}
public void setDeviceName(String name) { SetDeviceName(name); }
public String GetDeviceName() { return deviceName != null ? deviceName : GetLUName(); }
public String getDeviceName() { return GetDeviceName(); }
public void SetLUName(String lu) {
this.luName = lu;
if (client != null && client.getConfig() != null) {
client.getConfig().setLuName(lu);
}
}
public void setLUName(String lu) { SetLUName(lu); }
public void SetWorkstationID(String wid) { this.workstationId = wid; }
public void setWorkstationID(String wid) { SetWorkstationID(wid); }
public String GetWorkstationID() { return workstationId; }
public String getWorkstationID() { return workstationId; }
public void SetSSL(boolean ssl) {
this.ssl = ssl;
if (client != null && client.getConfig() != null) {
client.getConfig().setUseTls(ssl);
}
}
public void setSSL(boolean ssl) { SetSSL(ssl); }
public void setContentionResolution(boolean bl) { this.contentionResolution = bl; }
public void SetContentionResolution(boolean bl) { setContentionResolution(bl); }
public boolean getContentionResolution() { return contentionResolution; }
public boolean isContentionResolution() { return contentionResolution; }
public void set_LULU_Session(boolean bl) { this.luluSession = bl; }
public boolean is_LULU_Session() { return luluSession; }
public boolean get_LULU_Session() { return luluSession; }
public boolean isNegotiateCResolution() { return isNegCR; }
public void setNegotiatedCResolution(boolean bl) { this.isNegCR = bl; }
public boolean isBIND7FArchitectureViolation() { return isBIND7FArchitectureViolation; }
public void setBIND7FArchitectureViolation(boolean bl) { this.isBIND7FArchitectureViolation = bl; }
public void setKeyRemap(String remap) { this.keyRemap = remap; }
public void SetKeyRemap(String remap) { setKeyRemap(remap); }
public String getKeyRemap() { return keyRemap; }
public String GetKeyRemap() { return keyRemap; }
public void setCertificateName(String name) {
this.certificateName = name;
if (client != null && client.getConfig() != null) client.getConfig().setKeyStoreAlias(name);
}
public void SetCertificateName(String name) { setCertificateName(name); }
public String getCertificateName() { return certificateName; }
public String GetCertificateName() { return certificateName; }
public void setCertificateSource(String src) { this.certificateSource = src; }
public void SetCertificateSource(String src) { setCertificateSource(src); }
public String getCertificateSource() { return certificateSource; }
public String GetCertificateSource() { return certificateSource; }
public void setCertificateURL(String url) {
this.certificateURL = url;
if (client != null && client.getConfig() != null) client.getConfig().setKeyStorePath(url);
}
public void SetCertificateURL(String url) { setCertificateURL(url); }
public String getCertificateURL() { return certificateURL; }
public String GetCertificateURL() { return certificateURL; }
public void setCertificatePassword(String pwd) {
this.certificatePassword = pwd;
if (client != null && client.getConfig() != null) client.getConfig().setKeyStorePassword(pwd);
}
public void SetCertificatePassword(String pwd) { setCertificatePassword(pwd); }
public String getCertificatePassword() { return certificatePassword; }
public String GetCertificatePassword() { return certificatePassword; }
public void setCertificateProvided(boolean prov) { this.certificateProvided = prov; }
public void SetCertificateProvided(boolean prov) { setCertificateProvided(prov); }
public boolean isCertificateProvided() { return certificateProvided; }
public void setSecurityProtocol(String prot) {
this.securityProtocol = prot;
if (client != null && client.getConfig() != null) client.getConfig().setSslProtocol(prot);
}
public void SetSecurityProtocol(String prot) { setSecurityProtocol(prot); }
public String getSecurityProtocol() { return securityProtocol; }
public String GetSecurityProtocol() { return securityProtocol; }
public void setTLSProtocolVersion(String ver) {
this.tlsProtocolVersion = ver;
if (client != null && client.getConfig() != null && ver != null) {
client.getConfig().setSslProtocol(ver);
client.getConfig().setEnabledProtocols(ver);
}
}
public void SetTLSProtocolVersion(String ver) { setTLSProtocolVersion(ver); }
public String getTLSProtocolVersion() { return tlsProtocolVersion; }
public String GetTLSProtocolVersion() { return tlsProtocolVersion; }
public void setUseJSSE(boolean jsse) { this.useJSSE = jsse; }
public void SetUseJSSE(boolean jsse) { setUseJSSE(jsse); }
public boolean isUseJSSE() { return useJSSE; }
public void setJSSETrustStore(String ts) {
this.jsseTrustStore = ts;
if (client != null && client.getConfig() != null) client.getConfig().setTrustStorePath(ts);
}
public void SetJSSETrustStore(String ts) { setJSSETrustStore(ts); }
public String getJSSETrustStore() { return jsseTrustStore; }
public String GetJSSETrustStore() { return jsseTrustStore; }
public void setJSSETrustStoreType(String type) {
this.jsseTrustStoreType = type;
if (client != null && client.getConfig() != null) client.getConfig().setTrustStoreType(type);
}
public void SetJSSETrustStoreType(String type) { setJSSETrustStoreType(type); }
public String getJSSETrustStoreType() { return jsseTrustStoreType; }
public String GetJSSETrustStoreType() { return jsseTrustStoreType; }
public void setJSSETrustStorePassword(String pwd) {
this.jsseTrustStorePassword = pwd;
if (client != null && client.getConfig() != null) client.getConfig().setTrustStorePassword(pwd);
}
public void SetJSSETrustStorePassword(String pwd) { setJSSETrustStorePassword(pwd); }
public String getJSSETrustStorePassword() { return jsseTrustStorePassword; }
public String GetJSSETrustStorePassword() { return jsseTrustStorePassword; }
public haus.nightmare.lib3270j.security.ssl.HODSSLECLSessionImpl getSSLSessionImpl() {
return (session != null) ? session.getSSLSessionImpl() : new haus.nightmare.lib3270j.security.ssl.HODSSLECLSessionImpl(this);
}
public haus.nightmare.lib3270j.security.ssl.HODSSLECLSessionImpl GetSSLSessionImpl() {
return getSSLSessionImpl();
}
public void setProxy(String proxy) { this.proxyServerName = proxy; }
public void SetProxy(String proxy) { setProxy(proxy); }
public String getProxy() { return proxyServerName; }
public String GetProxy() { return proxyServerName; }
public void setProxyType(String type) { this.proxyType = type; }
public void SetProxyType(String type) { setProxyType(type); }
public String getProxyType() { return proxyType; }
public String GetProxyType() { return proxyType; }
public void setProxyServerName(String name) { this.proxyServerName = name; }
public void SetProxyServerName(String name) { setProxyServerName(name); }
public String getProxyServerName() { return proxyServerName; }
public String GetProxyServerName() { return proxyServerName; }
public void setProxyServerPort(String port) { this.proxyServerPort = port; }
public void SetProxyServerPort(String port) { setProxyServerPort(port); }
public String getProxyServerPort() { return proxyServerPort; }
public String GetProxyServerPort() { return proxyServerPort; }
public void setProxyUserID(String uid) { this.proxyUserId = uid; }
public void SetProxyUserID(String uid) { setProxyUserID(uid); }
public String getProxyUserID() { return proxyUserId; }
public String GetProxyUserID() { return proxyUserId; }
public void setProxyUserPassword(String pwd) { this.proxyUserPassword = pwd; }
public void SetProxyUserPassword(String pwd) { setProxyUserPassword(pwd); }
public String getProxyUserPassword() { return proxyUserPassword; }
public String GetProxyUserPassword() { return proxyUserPassword; }
public void setProxyAuthenMethod(String method) { this.proxyAuthenMethod = method; }
public void SetProxyAuthenMethod(String method) { setProxyAuthenMethod(method); }
public String getProxyAuthenMethod() { return proxyAuthenMethod; }
public String GetProxyAuthenMethod() { return proxyAuthenMethod; }
public void setProxySecurityProtocol(String prot) { this.proxySecurityProtocol = prot; }
public void SetProxySecurityProtocol(String prot) { setProxySecurityProtocol(prot); }
public String getProxySecurityProtocol() { return proxySecurityProtocol; }
public String GetProxySecurityProtocol() { return proxySecurityProtocol; }
public void setProperties(Properties props) {
if (props != null) {
this.properties.putAll(props);
convertData(this.properties);
}
}
public void SetProperties(Properties props) { setProperties(props); }
public Properties getProperties() { return properties; }
public Properties GetProperties() { return properties; }
@Override
public String toString() {
return String.format("ECLConnection[host=%s, port=%d, state=%s, lu=%s, ssl=%b]",
@@ -0,0 +1,70 @@
package haus.nightmare.lib3270j.ecl;
/**
* Conforms to IBM Host On-Demand ECLErr checked exception.
*/
public class ECLErr extends Exception {
private static final long serialVersionUID = 1L;
private String tag = "";
private String id = "";
private String text = "";
public ECLErr() {
super();
}
public ECLErr(String text) {
super(text);
this.text = text;
}
public ECLErr(String tag, String id, String text) {
super(formatMsg(tag, id, text));
this.tag = tag;
this.id = id;
this.text = text;
}
public ECLErr(String tag, String id, String text, String extra) {
super(formatMsg(tag, id, text + " " + extra));
this.tag = tag;
this.id = id;
this.text = text + " " + extra;
}
public ECLErr(Throwable cause) {
super(cause);
}
public ECLErr(String message, Throwable cause) {
super(message, cause);
this.text = message;
}
private static String formatMsg(String tag, String id, String text) {
StringBuilder sb = new StringBuilder();
if (tag != null && !tag.isEmpty()) sb.append(tag).append(" ");
if (id != null && !id.isEmpty()) sb.append(id).append(": ");
if (text != null) sb.append(text);
return sb.toString();
}
public String getTag() { return tag; }
public String GetTag() { return tag; }
public String getID() { return id; }
public String GetID() { return id; }
public String getText() { return text; }
public String GetText() { return text; }
public String getErrorText() { return getMessage(); }
public String GetErrorText() { return getMessage(); }
@Override
public String toString() {
return "ECLErr[tag=" + tag + ", id=" + id + ", text=" + text + "]";
}
}
@@ -106,6 +106,36 @@ public class ECLField {
}
public boolean IsDisplay() { return isDisplay(); }
public boolean isPenDetectable() {
return !isProtected() && (getLiveAttribute() & 0x0C) != 0;
}
public boolean IsPenDetectable() { return isPenDetectable(); }
public void setFieldAttribute(char attr) {
if (ps != null && ps.getScreenBuffer() != null) {
ExtendedAttribute cell = ps.getScreenBuffer().getCell(startPos);
if (cell != null) {
cell.fa = (byte) (attr & 0xFF);
ps.getScreenBuffer().markAllChanged();
ps.getScreenBuffer().updateDisplaySnapshot();
}
}
}
public void SetFieldAttribute(char attr) { setFieldAttribute(attr); }
public int getStartFieldPos() {
return startPos;
}
public int GetStartFieldPos() { return getStartFieldPos(); }
public char[] copyPlanes(int plane) {
if (length <= 0 || ps == null) return new char[0];
char[] buf = new char[length];
ps.getPlane(plane, buf, dataStart, length);
return buf;
}
public char[] CopyPlanes(int plane) { return copyPlanes(plane); }
public boolean isPenSelectable() {
return faIsSelectable(getLiveAttribute() & 0xFF);
}

Some files were not shown because too many files have changed in this diff Show More