Lightpen on
This commit is contained in:
@@ -829,39 +829,51 @@ public class GocaDecoder {
|
||||
|
||||
private void processArc(byte[] data, int off, int len, boolean fromCurPos, boolean isFull) {
|
||||
int pos = off;
|
||||
int startX = curX;
|
||||
int startY = curY;
|
||||
int centerX = curX;
|
||||
int centerY = curY;
|
||||
|
||||
if (!fromCurPos && pos + 4 <= off + len) {
|
||||
startX = readCoord(data, pos);
|
||||
startY = readCoord(data, pos + 2);
|
||||
centerX = readCoord(data, pos);
|
||||
centerY = readCoord(data, pos + 2);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
double multiplier = 1.0;
|
||||
if (pos + 2 <= off + len) {
|
||||
multiplier = (data[pos] & 0xFF) + ((data[pos + 1] & 0xFF) / 255.0);
|
||||
if (multiplier == 0.0) multiplier = 1.0;
|
||||
double sweepFraction = 1.0;
|
||||
if (!isFull && pos + 2 <= off + len) {
|
||||
byte intPart = data[pos];
|
||||
double fracPart = (data[pos + 1] & 0xFF) / 256.0;
|
||||
sweepFraction = intPart + (intPart >= 0 ? fracPart : -fracPart);
|
||||
}
|
||||
|
||||
int dxP = Math.abs(arcParamP - arcParamR);
|
||||
int dyQ = Math.abs(arcParamQ - arcParamS);
|
||||
if (dxP == 0) dxP = 10;
|
||||
if (dyQ == 0) dyQ = 10;
|
||||
int pxCenter = plane.mapX(centerX);
|
||||
int pyCenter = plane.mapY(centerY);
|
||||
int pxCur = plane.mapX(curX);
|
||||
int pyCur = plane.mapY(curY);
|
||||
|
||||
int rxVirtual = (int) (dxP * multiplier);
|
||||
int ryVirtual = (int) (dyQ * multiplier);
|
||||
double radius = Math.sqrt(Math.pow(pxCur - pxCenter, 2) + Math.pow(pyCur - pyCenter, 2));
|
||||
int rx = (int) Math.round(radius);
|
||||
int ry = rx;
|
||||
if (rx <= 0) {
|
||||
rx = 10;
|
||||
ry = 10;
|
||||
}
|
||||
|
||||
int rx = Math.abs(plane.mapX(rxVirtual) - plane.mapX(0));
|
||||
int ry = Math.abs(plane.mapY(ryVirtual) - plane.mapY(0));
|
||||
if (rx <= 0) rx = 10;
|
||||
if (ry <= 0) ry = 10;
|
||||
double startAngleRad = Math.atan2(pyCenter - pyCur, pxCur - pxCenter);
|
||||
double startAngleDeg = Math.toDegrees(startAngleRad);
|
||||
if (startAngleDeg < 0) startAngleDeg += 360.0;
|
||||
|
||||
double sweepAngleDeg = isFull ? 360.0 : (sweepFraction * 360.0);
|
||||
|
||||
plane.drawArc(plane.mapX(startX), plane.mapY(startY), rx, ry, 0.0, 360.0,
|
||||
plane.drawArc(pxCenter, pyCenter, rx, ry, startAngleDeg, sweepAngleDeg,
|
||||
curColor, lineType, lineWidth, isFull);
|
||||
|
||||
curX = startX;
|
||||
curY = startY;
|
||||
// Arc ends at the end of the sweep
|
||||
double endAngleRad = Math.toRadians(startAngleDeg + sweepAngleDeg);
|
||||
int pxEnd = (int) Math.round(pxCenter + rx * Math.cos(endAngleRad));
|
||||
int pyEnd = (int) Math.round(pyCenter - ry * Math.sin(endAngleRad));
|
||||
|
||||
curX = plane.unmapX(pxEnd);
|
||||
curY = plane.unmapY(pyEnd);
|
||||
}
|
||||
|
||||
private void processFillet(byte[] data, int off, int len, boolean fromCurPos) {
|
||||
@@ -932,8 +944,9 @@ public class GocaDecoder {
|
||||
int textLen = end - pos;
|
||||
if (textLen <= 0) return;
|
||||
|
||||
int cw = charWidth > 0 ? (int) Math.round((double) charWidth * plane.getCanvasWidth() / (plane.getScreenCols() * 9.0)) : 12;
|
||||
int ch = charHeight > 0 ? (int) Math.round((double) charHeight * plane.getCanvasHeight() / (plane.getScreenRows() * 16.0)) : 20;
|
||||
// IBM 3279 vector graphics base cell is 9x12
|
||||
int cw = charWidth > 0 ? (int) Math.round((double) charWidth * plane.getCanvasWidth() / (plane.getScreenCols() * 9.0)) : 10;
|
||||
int ch = charHeight > 0 ? (int) Math.round((double) charHeight * plane.getCanvasHeight() / (plane.getScreenRows() * 12.0)) : 14;
|
||||
|
||||
if (charSet != 0 && programSymbolManager != null) {
|
||||
for (int i = 0; i < textLen; i++) {
|
||||
|
||||
@@ -40,6 +40,7 @@ public class GraphicsPlane {
|
||||
private int canvasHeight = 600;
|
||||
private int[] rgbBuffer;
|
||||
private boolean hasContent = false;
|
||||
private long updateCount = 0;
|
||||
|
||||
private int screenCols = 80;
|
||||
private int screenRows = 24;
|
||||
@@ -79,6 +80,11 @@ public class GraphicsPlane {
|
||||
Arrays.fill(rgbBuffer, 0);
|
||||
}
|
||||
hasContent = false;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
public synchronized long getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public synchronized boolean hasContent() {
|
||||
@@ -162,6 +168,7 @@ public class GraphicsPlane {
|
||||
if (x >= 0 && x < canvasWidth && y >= 0 && y < canvasHeight) {
|
||||
rgbBuffer[y * canvasWidth + x] = colorArgb;
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +210,7 @@ public class GraphicsPlane {
|
||||
}
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
private boolean shouldPlotLinePixel(int step, int lineType) {
|
||||
@@ -266,6 +274,7 @@ public class GraphicsPlane {
|
||||
prevY = nextY;
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,6 +313,7 @@ public class GraphicsPlane {
|
||||
}
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,6 +390,7 @@ public class GraphicsPlane {
|
||||
}
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,6 +456,7 @@ public class GraphicsPlane {
|
||||
break;
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
private static final int[] VSS_OFFSETS = new int[256];
|
||||
@@ -493,6 +505,7 @@ public class GraphicsPlane {
|
||||
}
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
private void drawVssChar(int x, int y, char c, int color, int cw, int ch) {
|
||||
@@ -558,5 +571,6 @@ public class GraphicsPlane {
|
||||
}
|
||||
}
|
||||
hasContent = true;
|
||||
updateCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +352,59 @@ public class InputProcessor {
|
||||
|
||||
// ========== Cursor movement ==========
|
||||
|
||||
/**
|
||||
* Simulate a Text Light Pen selection.
|
||||
*/
|
||||
public boolean lightPenSelect(int address) {
|
||||
if (screen == null || !screen.isFormatted()) {
|
||||
return false;
|
||||
}
|
||||
int size = screen.getRows() * screen.getCols();
|
||||
int faPos = screen.findFieldAttribute(address);
|
||||
if (faPos < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExtendedAttribute faCell = screen.getCell(faPos);
|
||||
int fa = faCell.fa & 0xFF;
|
||||
if (!org.lib3270j.protocol.DS3270Constants.faIsSelectable(fa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int designatorPos = (faPos + 1) % size;
|
||||
ExtendedAttribute desCell = screen.getCell(designatorPos);
|
||||
int ebcdic = desCell.ec & 0xFF;
|
||||
char ascii = (char) desCell.ucs4;
|
||||
|
||||
screen.setCursorAddress(designatorPos);
|
||||
|
||||
if (ebcdic == 0x00 || ebcdic == 0x40 || ascii == ' ' || ascii == 0 || (ebcdic != 0x50 && ascii != '&' && ebcdic != 0x6F && ascii != '?' && ebcdic != 0x6E && ascii != '>')) {
|
||||
faCell.fa |= org.lib3270j.protocol.DS3270Constants.FA_MODIFY;
|
||||
sendAid(org.lib3270j.protocol.DS3270Constants.AID_SELECT);
|
||||
return true;
|
||||
} else if (ebcdic == 0x50 || ascii == '&') {
|
||||
faCell.fa |= org.lib3270j.protocol.DS3270Constants.FA_MODIFY;
|
||||
sendAid(org.lib3270j.protocol.DS3270Constants.AID_ENTER);
|
||||
return true;
|
||||
} else if (ebcdic == 0x6F || ascii == '?') {
|
||||
desCell.ec = (byte) 0x6E;
|
||||
desCell.ucs4 = '>';
|
||||
faCell.fa |= org.lib3270j.protocol.DS3270Constants.FA_MODIFY;
|
||||
screen.updateDisplaySnapshot();
|
||||
return true;
|
||||
} else if (ebcdic == 0x6E || ascii == '>') {
|
||||
desCell.ec = (byte) 0x6F;
|
||||
desCell.ucs4 = '?';
|
||||
faCell.fa &= ~org.lib3270j.protocol.DS3270Constants.FA_MODIFY;
|
||||
screen.updateDisplaySnapshot();
|
||||
return true;
|
||||
} else {
|
||||
faCell.fa |= org.lib3270j.protocol.DS3270Constants.FA_MODIFY;
|
||||
sendAid(org.lib3270j.protocol.DS3270Constants.AID_SELECT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void cursorUp() {
|
||||
int addr = screen.getCursorAddress();
|
||||
addr -= screen.getCols();
|
||||
|
||||
Reference in New Issue
Block a user