Cleanup datastream and Graphics
This commit is contained in:
@@ -363,8 +363,11 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
boolean isEnterField = (desEbcdic == 0x50 || desAscii == '&' || desAscii == '\uFF06');
|
||||
boolean isProtected = haus.nightmare.lib3270j.protocol.DS3270Constants.faIsProtected(fa);
|
||||
|
||||
// Only auto-select toggle fields (?/>), enter fields (&), or unprotected space fields
|
||||
if (lightPenMode || isToggleField || isEnterField || !isProtected) {
|
||||
boolean isDoubleClick = (e.getClickCount() >= 2);
|
||||
// For detectable fields (FA bits 4-5 = 01 or 11):
|
||||
// Double-clicking or invoking mnemonic [cursel] toggles the designator character (? -> >).
|
||||
// If field has immediate select attribute, immediately transmit Cursor Select AID (0x7E).
|
||||
if (lightPenMode || isDoubleClick || isToggleField || isEnterField || !isProtected) {
|
||||
if (client.lightPenSelect(clickAddr)) {
|
||||
refreshScreen();
|
||||
return;
|
||||
@@ -1343,7 +1346,41 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
blinkTimer = new Timer(500, e -> {
|
||||
cursorVisible = !cursorVisible;
|
||||
textBlinkVisible = !textBlinkVisible;
|
||||
repaint();
|
||||
|
||||
// Check if there are any blinking cells or fields on the screen
|
||||
boolean hasBlinkingCells = false;
|
||||
ScreenBuffer sb = (client != null) ? client.getScreenBuffer() : null;
|
||||
if (sb != null) {
|
||||
int total = sb.getDisplayRows() * sb.getDisplayCols();
|
||||
byte curFaGr = 0;
|
||||
for (int i = 0; i < total; i++) {
|
||||
ExtendedAttribute c = sb.getDisplayCell(i);
|
||||
if (c.isFieldAttribute()) {
|
||||
curFaGr = c.gr;
|
||||
}
|
||||
if ((c.gr & ExtendedAttribute.GR_BLINK) != 0 || (curFaGr & ExtendedAttribute.GR_BLINK) != 0) {
|
||||
hasBlinkingCells = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBlinkingCells) {
|
||||
repaint();
|
||||
} else if (sb != null && client != null && client.getConnectionState() != null && client.getConnectionState().isFullSession()) {
|
||||
// Only repaint the cursor cell bounding rect
|
||||
int cols = sb.getDisplayCols();
|
||||
int ox = getRenderOffsetX();
|
||||
int oy = getRenderOffsetY();
|
||||
int curAddr = sb.getDisplayCursorAddress();
|
||||
int curRow = curAddr / cols;
|
||||
int curCol = curAddr % cols;
|
||||
int cx = ox + curCol * cellWidth;
|
||||
int cy = oy + curRow * cellHeight;
|
||||
repaint(cx, cy, cellWidth, cellHeight);
|
||||
} else {
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
blinkTimer.start();
|
||||
}
|
||||
@@ -1609,6 +1646,9 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
}
|
||||
}
|
||||
|
||||
// Field Outlining (0xC2 / TY_FOUTLINE)
|
||||
drawOutlining(g2, ea, currentFieldEa, baddr, row, col, x, y, cellWidth, cellHeight, rows, cols, sb, fgColor);
|
||||
|
||||
if (isCellSelected(row, col)) {
|
||||
g2.setColor(SELECTION_COLOR);
|
||||
g2.fillRect(x, y, cellWidth, cellHeight);
|
||||
@@ -1628,7 +1668,7 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
}
|
||||
|
||||
// Check text blink (500ms cycle)
|
||||
boolean blink = (gr & GR_BLINK) != 0;
|
||||
boolean blink = (gr & GR_BLINK) != 0 || (currentFieldEa != null && (currentFieldEa.gr & GR_BLINK) != 0);
|
||||
boolean suppressGlyph = blink && !textBlinkVisible;
|
||||
|
||||
// Draw character or Programmed Symbol
|
||||
@@ -1662,12 +1702,15 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
}
|
||||
}
|
||||
|
||||
if (underline) {
|
||||
if (underline && !suppressGlyph) {
|
||||
g2.setColor(fgColor);
|
||||
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);
|
||||
}
|
||||
|
||||
// Field Outlining (0xC2 / TY_FOUTLINE)
|
||||
drawOutlining(g2, ea, currentFieldEa, baddr, row, col, x, y, cellWidth, cellHeight, rows, cols, sb, fgColor);
|
||||
|
||||
// Draw search highlight
|
||||
if (isCellSearchHighlighted(row, col)) {
|
||||
g2.setColor(SEARCH_HIGHLIGHT_COLOR);
|
||||
@@ -1835,6 +1878,57 @@ public class TerminalPanel extends JPanel implements java.awt.print.Printable {
|
||||
return faIsHigh(fa & 0xFF) ? monoIntensify : monoNormal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render field outline lines around cells based on ea.ol or field attribute outline.
|
||||
* Conforms to IBM 3270 Extended Data Stream / Host On-Demand DS3270 TY_FOUTLINE (0xC2).
|
||||
*
|
||||
* Bit 0 (0x01): Underline -> draw line at y + cellHeight - 1
|
||||
* Bit 1 (0x02): Right vertical line -> draw line at x + cellWidth - 1
|
||||
* Bit 2 (0x04): Overline -> draw line at y
|
||||
* Bit 3 (0x08): Left vertical line -> draw line at x
|
||||
*/
|
||||
private void drawOutlining(Graphics2D g2, ExtendedAttribute ea, ExtendedAttribute currentFieldEa,
|
||||
int baddr, int row, int col, int x, int y,
|
||||
int cellWidth, int cellHeight, int rows, int cols,
|
||||
ScreenBuffer sb, Color fgColor) {
|
||||
int outline = ea.ol & 0xFF;
|
||||
if (outline == 0 && currentFieldEa != null && currentFieldEa.ol != 0) {
|
||||
int fol = currentFieldEa.ol & 0xFF;
|
||||
if ((fol & ExtendedAttribute.OL_UNDERLINE) != 0) outline |= ExtendedAttribute.OL_UNDERLINE;
|
||||
if ((fol & ExtendedAttribute.OL_OVERLINE) != 0) outline |= ExtendedAttribute.OL_OVERLINE;
|
||||
|
||||
int size = rows * cols;
|
||||
int prevAddr = (baddr - 1 + size) % size;
|
||||
if (sb.getDisplayCell(prevAddr).isFieldAttribute() || col == 0) {
|
||||
if ((fol & ExtendedAttribute.OL_LEFT) != 0) outline |= ExtendedAttribute.OL_LEFT;
|
||||
}
|
||||
int nextAddr = (baddr + 1) % size;
|
||||
if (sb.getDisplayCell(nextAddr).isFieldAttribute() || col == cols - 1) {
|
||||
if ((fol & ExtendedAttribute.OL_RIGHT) != 0) outline |= ExtendedAttribute.OL_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
if (outline != 0) {
|
||||
g2.setColor(fgColor);
|
||||
// Bit 0 (0x01): Underline -> draw line at y + cellHeight - 1
|
||||
if ((outline & ExtendedAttribute.OL_UNDERLINE) != 0) {
|
||||
g2.drawLine(x, y + cellHeight - 1, x + cellWidth - 1, y + cellHeight - 1);
|
||||
}
|
||||
// Bit 1 (0x02): Right vertical line -> draw line at x + cellWidth - 1
|
||||
if ((outline & ExtendedAttribute.OL_RIGHT) != 0) {
|
||||
g2.drawLine(x + cellWidth - 1, y, x + cellWidth - 1, y + cellHeight - 1);
|
||||
}
|
||||
// Bit 2 (0x04): Overline -> draw line at y
|
||||
if ((outline & ExtendedAttribute.OL_OVERLINE) != 0) {
|
||||
g2.drawLine(x, y, x + cellWidth - 1, y);
|
||||
}
|
||||
// Bit 3 (0x08): Left vertical line -> draw line at x
|
||||
if ((outline & ExtendedAttribute.OL_LEFT) != 0) {
|
||||
g2.drawLine(x, y, x, y + cellHeight - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (blinkTimer != null)
|
||||
blinkTimer.stop();
|
||||
|
||||
Reference in New Issue
Block a user