ibm5250 0.1.0.dev2__tar.gz → 0.1.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/PKG-INFO +1 -1
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/pyproject.toml +1 -1
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/connection.py +6 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/constants.py +1 -1
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/data-stream-logic.md +1 -1
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/datastream.py +20 -3
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/uv.lock +1 -1
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/.github/copilot-instructions.md +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/.github/workflows/README.md +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/.github/workflows/publish.yml +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/.gitignore +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/LICENSE +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/README.md +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/scripts/compute_version.py +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/__init__.py +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/exceptions.py +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/screen.py +0 -0
- {ibm5250-0.1.0.dev2 → ibm5250-0.1.0.dev4}/src/ibm5250/terminal.py +0 -0
|
@@ -197,6 +197,10 @@ class TN5250Connection:
|
|
|
197
197
|
self._ttype_will_sent = False
|
|
198
198
|
self._negotiated_ttype = "IBM-3477-FG" # screen model reported to IBM i
|
|
199
199
|
|
|
200
|
+
# Byte 9 (opcode/var-header length) of the last received TN5250E record.
|
|
201
|
+
# Used to detect header-only Cancel-Invite records (opcode 0x0A).
|
|
202
|
+
self._last_recv_opcode: int = 0x03
|
|
203
|
+
|
|
200
204
|
# TLS
|
|
201
205
|
if use_tls and tls_context is None:
|
|
202
206
|
tls_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
@@ -342,6 +346,7 @@ class TN5250Connection:
|
|
|
342
346
|
log.debug("Short TN5250E frame (%d bytes), skipping", len(frame))
|
|
343
347
|
continue
|
|
344
348
|
hdr = TN5250EHeader.from_bytes(frame)
|
|
349
|
+
self._last_recv_opcode = frame[9] # byte 9: opcode / var_len
|
|
345
350
|
payload = bytes(frame[_TN5250E_HEADER_LEN:])
|
|
346
351
|
log.debug(
|
|
347
352
|
"← TN5250E type=%02X data_type=%02X payload=%d bytes",
|
|
@@ -361,6 +366,7 @@ class TN5250Connection:
|
|
|
361
366
|
frame_bytes[:2], "big"
|
|
362
367
|
) == len(frame_bytes):
|
|
363
368
|
hdr = TN5250EHeader.from_bytes(frame_bytes)
|
|
369
|
+
self._last_recv_opcode = frame_bytes[9] # byte 9: opcode
|
|
364
370
|
var_hdr_len = frame_bytes[
|
|
365
371
|
9
|
|
366
372
|
] # RFC 2877 variable-header length field
|
|
@@ -139,7 +139,7 @@ class Order:
|
|
|
139
139
|
ERASE_TO_ADDRESS = (
|
|
140
140
|
0x12 # Erase to Address — 2 address bytes (fill with nulls)
|
|
141
141
|
)
|
|
142
|
-
INSERT_CURSOR = 0x13 # Insert Cursor —
|
|
142
|
+
INSERT_CURSOR = 0x13 # Insert Cursor — 2 address bytes; marks cursor pos
|
|
143
143
|
MOVE_CURSOR = 0x14 # Move Cursor — 2 address bytes
|
|
144
144
|
GROUP_ERASE_TO_ADDRESS = 0x16 # Group Erase to Address — 2 address bytes (fill with nulls, within field group)
|
|
145
145
|
START_FIELD = 0x1D # Start Field — 2-byte FFW [+ 2-byte FCW pairs]
|
|
@@ -78,7 +78,7 @@ After the command + CC bytes, the rest of the record is a stream of **orders** i
|
|
|
78
78
|
| **SBA** — Set Buffer Address (`0x11`) + row + col | Move the write position to a specific screen cell |
|
|
79
79
|
| **SF** — Start Field (`0x1D`) + FFW [+ FCWs] | Define a new input/output field at the current position. The FFW (Field Format Word, 2 bytes) defines field type — bypass/input, numeric, non-display, etc. Optional FCW (Field Control Word) pairs add behaviours like mandatory entry, right-adjust, or monocase. |
|
|
80
80
|
| **MF** — Modify Field (`0x2C`) + FFW [+ FCWs] | Modify an existing field's attributes |
|
|
81
|
-
| **IC** — Insert Cursor (`0x13`) | Place the cursor at the current position
|
|
81
|
+
| **IC** — Insert Cursor (`0x13`) | Place the cursor at the 2-byte address that follows (falls back to the current position only when no address bytes remain) |
|
|
82
82
|
| **MC** — Move Cursor (`0x14`) + row + col | Move the cursor to a specific position |
|
|
83
83
|
| **RA** — Repeat to Address (`0x3C`) + row + col + char | Repeat a character from current position up to the target |
|
|
84
84
|
| **EA** — Erase to Address (`0x12`) + row + col | Erase (fill with nulls) from current position to target |
|
|
@@ -369,9 +369,26 @@ class DataStreamParser:
|
|
|
369
369
|
|
|
370
370
|
case Order.INSERT_CURSOR:
|
|
371
371
|
byte_offset += 1
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
372
|
+
# 5250 IC carries a 2-byte cursor address. Only 3270-style
|
|
373
|
+
# operandless IC (synthetic/edge streams) omits it, which we
|
|
374
|
+
# detect by there being fewer than 2 bytes left.
|
|
375
|
+
if byte_offset + 2 > total_bytes:
|
|
376
|
+
yield DSEvent(
|
|
377
|
+
type=DSEventType.SET_CURSOR,
|
|
378
|
+
position=current_buffer_position,
|
|
379
|
+
)
|
|
380
|
+
else:
|
|
381
|
+
address_high, address_low = (
|
|
382
|
+
data_view[byte_offset],
|
|
383
|
+
data_view[byte_offset + 1],
|
|
384
|
+
)
|
|
385
|
+
byte_offset += 2
|
|
386
|
+
row, col = max(1, address_high) - 1, max(1, address_low) - 1
|
|
387
|
+
yield from self._maybe_resize(row, col)
|
|
388
|
+
yield DSEvent(
|
|
389
|
+
type=DSEventType.SET_CURSOR,
|
|
390
|
+
position=row * self.cols + col,
|
|
391
|
+
)
|
|
375
392
|
|
|
376
393
|
case Order.MOVE_CURSOR:
|
|
377
394
|
byte_offset += 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|