GDDM Tweaking
Build and Test j3270 / Build JAR & Run Tests (push) Successful in 41s

This commit is contained in:
2026-08-27 18:14:39 +00:00
parent 540a8dfd1d
commit 2e9b6d325a
9 changed files with 185 additions and 47 deletions
@@ -163,10 +163,20 @@ public class TerminalPanel extends JPanel {
// IMPORTANT ARCHITECTURE NOTE:
// 1. In GDDM Graphic Cursor Mode (3179G / GOCA), mouse events represent graphic light-pen touches.
// Text drag-selection is explicitly suppressed so blue selection boxes do not artifact over graphics.
// 2. In Text Light Pen mode (Alt+L on 3270 formatted screens), clicks toggle selectable fields.
// 2. In Text Light Pen / Selectable Field mode (per IBM Host On-Demand MouseMgr.java / PS3270.java),
// clicks on detectable fields (faIsSelectable) trigger field selection or cursor select.
// 3. In standard alphanumeric mode, click-drag selects text for copy-paste.
boolean isGraphic = client.getGocaDecoder() != null && client.getGocaDecoder().isGraphicsCursorActive();
if (isGraphic || lightPenMode) {
boolean isSelectableField = false;
if (sb.isFormatted()) {
int faPos = sb.findFieldAttribute(row * displayCols + col);
if (faPos >= 0) {
int fa = sb.getCell(faPos).fa & 0xFF;
isSelectableField = haus.nightmare.lib3270j.protocol.DS3270Constants.faIsSelectable(fa) &&
!haus.nightmare.lib3270j.protocol.DS3270Constants.faIsZero(fa);
}
}
if (isGraphic || lightPenMode || isSelectableField) {
clearSelection();
} else {
selectionStartRow = row;
@@ -277,6 +287,25 @@ public class TerminalPanel extends JPanel {
return;
}
// Automatic Light-Pen / Selectable Field detection on mouse click:
// Per IBM Host On-Demand (MouseMgr.java / PS3270.java) and 3270 specifications:
// If the clicked screen location belongs to a detectable field (faIsSelectable and not faIsZero),
// automatically process light-pen / cursor selection (e.g. immediate selection, Enter, or toggling ? -> >).
if (sb.isFormatted()) {
int faPos = sb.findFieldAttribute(clickAddr);
if (faPos >= 0) {
int fa = sb.getCell(faPos).fa & 0xFF;
if (haus.nightmare.lib3270j.protocol.DS3270Constants.faIsSelectable(fa) &&
!haus.nightmare.lib3270j.protocol.DS3270Constants.faIsZero(fa)) {
clearSelection();
if (client.lightPenSelect(clickAddr)) {
refreshScreen();
return;
}
}
}
}
if (lightPenMode) {
clearSelection();
sb.setCursorAddress(clickAddr);
@@ -947,8 +976,8 @@ public class TerminalPanel extends JPanel {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
int fontSize = (int) Math.round(ch * 0.95);
if (fontSize < 10) fontSize = 10;
int fontSize = Math.min((int) Math.round(ch * 0.82), (int) Math.round(cw * 1.45));
if (fontSize < 9) fontSize = 9;
Font f = (boldTerminalFont != null ? boldTerminalFont : terminalFont).deriveFont((float) fontSize);
g2.setFont(f);
FontMetrics fm = g2.getFontMetrics();
@@ -1154,10 +1183,11 @@ public class TerminalPanel extends JPanel {
Font f = bold ? boldTerminalFont : terminalFont;
g2.setFont(f);
g2.setColor(fgColor);
int textY = y + fontAscent + Math.max(0, (cellHeight - (fontAscent + fontDescent)) / 2);
if (ch < 128) {
g2.drawString(CHAR_STRINGS[ch], x, y + fontAscent);
g2.drawString(CHAR_STRINGS[ch], x, textY);
} else {
g2.drawString(String.valueOf(ch), x, y + fontAscent);
g2.drawString(String.valueOf(ch), x, textY);
}
}
}
@@ -1165,8 +1195,8 @@ public class TerminalPanel extends JPanel {
// Draw underline
if (underline) {
g2.setColor(fgColor);
g2.drawLine(x, y + cellHeight - fontDescent,
x + cellWidth - 1, y + cellHeight - fontDescent);
int ulY = Math.min(y + cellHeight - 1, y + fontAscent + Math.max(0, (cellHeight - (fontAscent + fontDescent)) / 2) + 2);
g2.drawLine(x, ulY, x + cellWidth - 1, ulY);
}
// Draw selection highlight