green-screen-proxy 0.3.0

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.
Files changed (67) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +32 -0
  3. package/dist/hp6530/connection.d.ts +51 -0
  4. package/dist/hp6530/connection.js +258 -0
  5. package/dist/hp6530/constants.d.ts +64 -0
  6. package/dist/hp6530/constants.js +135 -0
  7. package/dist/hp6530/encoder.d.ts +37 -0
  8. package/dist/hp6530/encoder.js +89 -0
  9. package/dist/hp6530/parser.d.ts +45 -0
  10. package/dist/hp6530/parser.js +255 -0
  11. package/dist/hp6530/screen.d.ts +104 -0
  12. package/dist/hp6530/screen.js +252 -0
  13. package/dist/mock/mock-routes.d.ts +2 -0
  14. package/dist/mock/mock-routes.js +231 -0
  15. package/dist/protocols/hp6530-handler.d.ts +29 -0
  16. package/dist/protocols/hp6530-handler.js +64 -0
  17. package/dist/protocols/index.d.ts +11 -0
  18. package/dist/protocols/index.js +27 -0
  19. package/dist/protocols/tn3270-handler.d.ts +26 -0
  20. package/dist/protocols/tn3270-handler.js +61 -0
  21. package/dist/protocols/tn5250-handler.d.ts +26 -0
  22. package/dist/protocols/tn5250-handler.js +62 -0
  23. package/dist/protocols/types.d.ts +59 -0
  24. package/dist/protocols/types.js +7 -0
  25. package/dist/protocols/vt-handler.d.ts +30 -0
  26. package/dist/protocols/vt-handler.js +67 -0
  27. package/dist/routes.d.ts +2 -0
  28. package/dist/routes.js +141 -0
  29. package/dist/server.d.ts +1 -0
  30. package/dist/server.js +34 -0
  31. package/dist/session.d.ts +32 -0
  32. package/dist/session.js +88 -0
  33. package/dist/tn3270/connection.d.ts +31 -0
  34. package/dist/tn3270/connection.js +266 -0
  35. package/dist/tn3270/constants.d.ts +262 -0
  36. package/dist/tn3270/constants.js +261 -0
  37. package/dist/tn3270/encoder.d.ts +24 -0
  38. package/dist/tn3270/encoder.js +97 -0
  39. package/dist/tn3270/parser.d.ts +22 -0
  40. package/dist/tn3270/parser.js +284 -0
  41. package/dist/tn3270/screen.d.ts +89 -0
  42. package/dist/tn3270/screen.js +207 -0
  43. package/dist/tn5250/connection.d.ts +41 -0
  44. package/dist/tn5250/connection.js +254 -0
  45. package/dist/tn5250/constants.d.ts +128 -0
  46. package/dist/tn5250/constants.js +156 -0
  47. package/dist/tn5250/ebcdic.d.ts +10 -0
  48. package/dist/tn5250/ebcdic.js +89 -0
  49. package/dist/tn5250/encoder.d.ts +30 -0
  50. package/dist/tn5250/encoder.js +121 -0
  51. package/dist/tn5250/parser.d.ts +33 -0
  52. package/dist/tn5250/parser.js +412 -0
  53. package/dist/tn5250/screen.d.ts +80 -0
  54. package/dist/tn5250/screen.js +155 -0
  55. package/dist/vt/connection.d.ts +45 -0
  56. package/dist/vt/connection.js +229 -0
  57. package/dist/vt/constants.d.ts +97 -0
  58. package/dist/vt/constants.js +163 -0
  59. package/dist/vt/encoder.d.ts +30 -0
  60. package/dist/vt/encoder.js +55 -0
  61. package/dist/vt/parser.d.ts +36 -0
  62. package/dist/vt/parser.js +534 -0
  63. package/dist/vt/screen.d.ts +101 -0
  64. package/dist/vt/screen.js +424 -0
  65. package/dist/websocket.d.ts +6 -0
  66. package/dist/websocket.js +50 -0
  67. package/package.json +57 -0
@@ -0,0 +1,262 @@
1
+ export { TELNET } from '../tn5250/constants.js';
2
+ export declare const CMD3270: {
3
+ readonly WRITE: 241;
4
+ readonly ERASE_WRITE: 245;
5
+ readonly ERASE_WRITE_ALTERNATE: 126;
6
+ readonly READ_BUFFER: 242;
7
+ readonly READ_MODIFIED: 246;
8
+ readonly READ_MODIFIED_ALL: 110;
9
+ readonly ERASE_ALL_UNPROTECTED: 111;
10
+ readonly WRITE_STRUCTURED_FIELD: 243;
11
+ readonly SNA_WRITE: 1;
12
+ readonly SNA_ERASE_WRITE: 5;
13
+ readonly SNA_ERASE_WRITE_ALTERNATE: 13;
14
+ readonly SNA_READ_BUFFER: 2;
15
+ readonly SNA_READ_MODIFIED: 6;
16
+ readonly SNA_READ_MODIFIED_ALL: 14;
17
+ readonly SNA_ERASE_ALL_UNPROTECTED: 15;
18
+ };
19
+ export declare const ORDER3270: {
20
+ readonly SBA: 17;
21
+ readonly SF: 29;
22
+ readonly SFE: 41;
23
+ readonly SA: 40;
24
+ readonly MF: 44;
25
+ readonly IC: 19;
26
+ readonly PT: 5;
27
+ readonly RA: 60;
28
+ readonly EUA: 18;
29
+ readonly GE: 8;
30
+ };
31
+ export declare const WCC: {
32
+ readonly RESET_MDT: 2;
33
+ readonly RESET_KEYBOARD: 64;
34
+ readonly SOUND_ALARM: 4;
35
+ readonly RESET_PARTITION: 1;
36
+ readonly START_PRINTER: 8;
37
+ };
38
+ export declare const AID3270: {
39
+ readonly ENTER: 125;
40
+ readonly PF1: 241;
41
+ readonly PF2: 242;
42
+ readonly PF3: 243;
43
+ readonly PF4: 244;
44
+ readonly PF5: 245;
45
+ readonly PF6: 246;
46
+ readonly PF7: 247;
47
+ readonly PF8: 248;
48
+ readonly PF9: 249;
49
+ readonly PF10: 122;
50
+ readonly PF11: 123;
51
+ readonly PF12: 124;
52
+ readonly PF13: 193;
53
+ readonly PF14: 194;
54
+ readonly PF15: 195;
55
+ readonly PF16: 196;
56
+ readonly PF17: 197;
57
+ readonly PF18: 198;
58
+ readonly PF19: 199;
59
+ readonly PF20: 200;
60
+ readonly PF21: 201;
61
+ readonly PF22: 74;
62
+ readonly PF23: 75;
63
+ readonly PF24: 76;
64
+ readonly PA1: 108;
65
+ readonly PA2: 110;
66
+ readonly PA3: 107;
67
+ readonly CLEAR: 109;
68
+ readonly STRUCTURED_FIELD: 136;
69
+ readonly NO_AID: 96;
70
+ };
71
+ export declare const KEY_TO_AID3270: Record<string, number>;
72
+ export declare const FIELD_ATTR: {
73
+ readonly PROTECTED: 32;
74
+ readonly NUMERIC: 16;
75
+ readonly DISPLAY_MASK: 12;
76
+ readonly DISPLAY_NORMAL: 0;
77
+ readonly DISPLAY_NORMAL_PEN: 4;
78
+ readonly DISPLAY_HIGH: 8;
79
+ readonly DISPLAY_NON: 12;
80
+ readonly MDT: 1;
81
+ };
82
+ export declare const EXTENDED_ATTR: {
83
+ readonly HIGHLIGHT: 65;
84
+ readonly COLOR: 66;
85
+ readonly CHARSET: 67;
86
+ readonly FIELD_OUTLINING: 197;
87
+ readonly TRANSPARENCY: 70;
88
+ readonly ALL: 0;
89
+ };
90
+ export declare const HIGHLIGHT: {
91
+ readonly DEFAULT: 0;
92
+ readonly NORMAL: 240;
93
+ readonly BLINK: 241;
94
+ readonly REVERSE: 242;
95
+ readonly UNDERSCORE: 244;
96
+ };
97
+ export declare const COLOR: {
98
+ readonly DEFAULT: 0;
99
+ readonly BLUE: 241;
100
+ readonly RED: 242;
101
+ readonly PINK: 243;
102
+ readonly GREEN: 244;
103
+ readonly TURQUOISE: 245;
104
+ readonly YELLOW: 246;
105
+ readonly WHITE: 247;
106
+ };
107
+ export declare const ADDRESS_TABLE: number[];
108
+ export declare const ADDRESS_REVERSE: Map<number, number>;
109
+ /**
110
+ * Decode a 3270 buffer address from 2 bytes.
111
+ * Supports 12-bit (bits 7-6 of first byte are 00) and 14-bit addressing.
112
+ */
113
+ export declare function decodeBufferAddress(byte1: number, byte2: number): number;
114
+ /**
115
+ * Encode a buffer address into 2 bytes using 12-bit encoding.
116
+ */
117
+ export declare function encodeBufferAddress12(address: number): [number, number];
118
+ /**
119
+ * Encode a buffer address into 2 bytes using 14-bit binary encoding.
120
+ */
121
+ export declare function encodeBufferAddress14(address: number): [number, number];
122
+ export declare const SCREEN3270: {
123
+ readonly MODEL2_ROWS: 24;
124
+ readonly MODEL2_COLS: 80;
125
+ readonly MODEL3_ROWS: 32;
126
+ readonly MODEL3_COLS: 80;
127
+ readonly MODEL4_ROWS: 43;
128
+ readonly MODEL4_COLS: 80;
129
+ readonly MODEL5_ROWS: 27;
130
+ readonly MODEL5_COLS: 132;
131
+ };
132
+ export declare const TERMINAL_TYPE_3270 = "IBM-3278-2";
133
+ export declare const TERMINAL_TYPE_3270_M3 = "IBM-3278-3";
134
+ export declare const TERMINAL_TYPE_3270_M4 = "IBM-3278-4";
135
+ export declare const TERMINAL_TYPE_3270_M5 = "IBM-3278-5";
136
+ export declare const TERMINAL_TYPE_3270E = "IBM-3278-2-E";
137
+ export declare const OPT_TN3270E = 40;
138
+ export declare const CMD: {
139
+ readonly WRITE: 241;
140
+ readonly ERASE_WRITE: 245;
141
+ readonly ERASE_WRITE_ALTERNATE: 126;
142
+ readonly READ_BUFFER: 242;
143
+ readonly READ_MODIFIED: 246;
144
+ readonly READ_MODIFIED_ALL: 110;
145
+ readonly ERASE_ALL_UNPROTECTED: 111;
146
+ readonly WRITE_STRUCTURED_FIELD: 243;
147
+ readonly SNA_WRITE: 1;
148
+ readonly SNA_ERASE_WRITE: 5;
149
+ readonly SNA_ERASE_WRITE_ALTERNATE: 13;
150
+ readonly SNA_READ_BUFFER: 2;
151
+ readonly SNA_READ_MODIFIED: 6;
152
+ readonly SNA_READ_MODIFIED_ALL: 14;
153
+ readonly SNA_ERASE_ALL_UNPROTECTED: 15;
154
+ };
155
+ export declare const SNA_CMD: {
156
+ readonly WRITE: 1;
157
+ readonly ERASE_WRITE: 5;
158
+ readonly ERASE_WRITE_ALTERNATE: 13;
159
+ readonly READ_BUFFER: 2;
160
+ readonly READ_MODIFIED: 6;
161
+ readonly READ_MODIFIED_ALL: 14;
162
+ readonly ERASE_ALL_UNPROTECTED: 15;
163
+ readonly WRITE_STRUCTURED_FIELD: 243;
164
+ };
165
+ export declare const ORDER: {
166
+ readonly SBA: 17;
167
+ readonly SF: 29;
168
+ readonly SFE: 41;
169
+ readonly SA: 40;
170
+ readonly MF: 44;
171
+ readonly IC: 19;
172
+ readonly PT: 5;
173
+ readonly RA: 60;
174
+ readonly EUA: 18;
175
+ readonly GE: 8;
176
+ };
177
+ export declare const AID: {
178
+ readonly ENTER: 125;
179
+ readonly PF1: 241;
180
+ readonly PF2: 242;
181
+ readonly PF3: 243;
182
+ readonly PF4: 244;
183
+ readonly PF5: 245;
184
+ readonly PF6: 246;
185
+ readonly PF7: 247;
186
+ readonly PF8: 248;
187
+ readonly PF9: 249;
188
+ readonly PF10: 122;
189
+ readonly PF11: 123;
190
+ readonly PF12: 124;
191
+ readonly PF13: 193;
192
+ readonly PF14: 194;
193
+ readonly PF15: 195;
194
+ readonly PF16: 196;
195
+ readonly PF17: 197;
196
+ readonly PF18: 198;
197
+ readonly PF19: 199;
198
+ readonly PF20: 200;
199
+ readonly PF21: 201;
200
+ readonly PF22: 74;
201
+ readonly PF23: 75;
202
+ readonly PF24: 76;
203
+ readonly PA1: 108;
204
+ readonly PA2: 110;
205
+ readonly PA3: 107;
206
+ readonly CLEAR: 109;
207
+ readonly STRUCTURED_FIELD: 136;
208
+ readonly NO_AID: 96;
209
+ };
210
+ export declare const KEY_TO_AID: Record<string, number>;
211
+ export declare const FA: {
212
+ readonly PROTECTED: 32;
213
+ readonly NUMERIC: 16;
214
+ readonly DISPLAY_MASK: 12;
215
+ readonly DISPLAY_HIDDEN: 12;
216
+ readonly DISPLAY_INTENSIFIED: 8;
217
+ readonly MDT: 1;
218
+ };
219
+ export declare const EXT_ATTR: {
220
+ readonly HIGHLIGHT: 65;
221
+ readonly COLOR: 66;
222
+ readonly CHARSET: 67;
223
+ readonly FIELD_OUTLINING: 197;
224
+ readonly TRANSPARENCY: 70;
225
+ readonly ALL: 0;
226
+ };
227
+ export declare const decodeAddress: typeof decodeBufferAddress;
228
+ export declare function encodeAddress(addr: number, _screenSize: number): Buffer;
229
+ export declare const SCREEN: {
230
+ readonly MODEL_2_ROWS: 24;
231
+ readonly MODEL_2_COLS: 80;
232
+ };
233
+ export declare const TERMINAL_TYPE = "IBM-3278-2";
234
+ export declare const TN3270E: {
235
+ readonly CONNECT: 1;
236
+ readonly DEVICE_TYPE: 2;
237
+ readonly FUNCTIONS: 3;
238
+ readonly IS: 4;
239
+ readonly REASON: 5;
240
+ readonly REJECT: 6;
241
+ readonly REQUEST: 7;
242
+ readonly SEND: 8;
243
+ readonly FUNC_BIND_IMAGE: 0;
244
+ readonly FUNC_DATA_STREAM_CTL: 1;
245
+ readonly FUNC_RESPONSES: 2;
246
+ readonly FUNC_SCS_CTL_CODES: 3;
247
+ readonly FUNC_SYSREQ: 4;
248
+ readonly DT_3270_DATA: 0;
249
+ readonly DT_SCS_DATA: 1;
250
+ readonly DT_RESPONSE: 2;
251
+ readonly DT_BIND_IMAGE: 3;
252
+ readonly DT_UNBIND: 4;
253
+ readonly DT_NVT_DATA: 5;
254
+ readonly DT_REQUEST: 6;
255
+ readonly DT_SSCP_LU_DATA: 7;
256
+ readonly DT_PRINT_EOJ: 8;
257
+ readonly NO_RESPONSE: 0;
258
+ readonly ERROR_RESPONSE: 1;
259
+ readonly ALWAYS_RESPONSE: 2;
260
+ readonly POSITIVE_RESPONSE: 0;
261
+ readonly NEGATIVE_RESPONSE: 1;
262
+ };
@@ -0,0 +1,261 @@
1
+ // === Telnet Constants (shared with TN5250) ===
2
+ export { TELNET } from '../tn5250/constants.js';
3
+ // === 3270 Command Codes ===
4
+ export const CMD3270 = {
5
+ WRITE: 0xF1, // Write
6
+ ERASE_WRITE: 0xF5, // Erase/Write
7
+ ERASE_WRITE_ALTERNATE: 0x7E, // Erase/Write Alternate
8
+ READ_BUFFER: 0xF2, // Read Buffer
9
+ READ_MODIFIED: 0xF6, // Read Modified
10
+ READ_MODIFIED_ALL: 0x6E, // Read Modified All
11
+ ERASE_ALL_UNPROTECTED: 0x6F, // Erase All Unprotected
12
+ WRITE_STRUCTURED_FIELD: 0xF3, // Write Structured Field
13
+ // SNA variants (without 0x40 bit set)
14
+ SNA_WRITE: 0x01,
15
+ SNA_ERASE_WRITE: 0x05,
16
+ SNA_ERASE_WRITE_ALTERNATE: 0x0D,
17
+ SNA_READ_BUFFER: 0x02,
18
+ SNA_READ_MODIFIED: 0x06,
19
+ SNA_READ_MODIFIED_ALL: 0x0E,
20
+ SNA_ERASE_ALL_UNPROTECTED: 0x0F,
21
+ };
22
+ // === 3270 Order Codes ===
23
+ export const ORDER3270 = {
24
+ SBA: 0x11, // Set Buffer Address
25
+ SF: 0x1D, // Start Field
26
+ SFE: 0x29, // Start Field Extended
27
+ SA: 0x28, // Set Attribute
28
+ MF: 0x2C, // Modify Field
29
+ IC: 0x13, // Insert Cursor
30
+ PT: 0x05, // Program Tab
31
+ RA: 0x3C, // Repeat to Address
32
+ EUA: 0x12, // Erase Unprotected to Address
33
+ GE: 0x08, // Graphic Escape
34
+ };
35
+ // === WCC (Write Control Character) bits ===
36
+ export const WCC = {
37
+ RESET_MDT: 0x02, // Reset Modified Data Tags
38
+ RESET_KEYBOARD: 0x40, // Reset keyboard lock
39
+ SOUND_ALARM: 0x04, // Sound audible alarm
40
+ RESET_PARTITION: 0x01, // Reset partition characteristics
41
+ START_PRINTER: 0x08, // Start printer
42
+ };
43
+ // === 3270 AID (Attention Identifier) bytes ===
44
+ export const AID3270 = {
45
+ ENTER: 0x7D,
46
+ PF1: 0xF1, PF2: 0xF2, PF3: 0xF3, PF4: 0xF4,
47
+ PF5: 0xF5, PF6: 0xF6, PF7: 0xF7, PF8: 0xF8,
48
+ PF9: 0xF9, PF10: 0x7A, PF11: 0x7B, PF12: 0x7C,
49
+ PF13: 0xC1, PF14: 0xC2, PF15: 0xC3, PF16: 0xC4,
50
+ PF17: 0xC5, PF18: 0xC6, PF19: 0xC7, PF20: 0xC8,
51
+ PF21: 0xC9, PF22: 0x4A, PF23: 0x4B, PF24: 0x4C,
52
+ PA1: 0x6C,
53
+ PA2: 0x6E,
54
+ PA3: 0x6B,
55
+ CLEAR: 0x6D,
56
+ STRUCTURED_FIELD: 0x88,
57
+ NO_AID: 0x60,
58
+ };
59
+ // Map key names (from frontend) to AID bytes
60
+ export const KEY_TO_AID3270 = {
61
+ 'Enter': AID3270.ENTER,
62
+ 'F1': AID3270.PF1, 'F2': AID3270.PF2, 'F3': AID3270.PF3, 'F4': AID3270.PF4,
63
+ 'F5': AID3270.PF5, 'F6': AID3270.PF6, 'F7': AID3270.PF7, 'F8': AID3270.PF8,
64
+ 'F9': AID3270.PF9, 'F10': AID3270.PF10, 'F11': AID3270.PF11, 'F12': AID3270.PF12,
65
+ 'F13': AID3270.PF13, 'F14': AID3270.PF14, 'F15': AID3270.PF15, 'F16': AID3270.PF16,
66
+ 'F17': AID3270.PF17, 'F18': AID3270.PF18, 'F19': AID3270.PF19, 'F20': AID3270.PF20,
67
+ 'F21': AID3270.PF21, 'F22': AID3270.PF22, 'F23': AID3270.PF23, 'F24': AID3270.PF24,
68
+ 'PA1': AID3270.PA1,
69
+ 'PA2': AID3270.PA2,
70
+ 'PA3': AID3270.PA3,
71
+ 'Clear': AID3270.CLEAR,
72
+ 'PageUp': AID3270.PF7, // Common mapping
73
+ 'PageDown': AID3270.PF8, // Common mapping
74
+ };
75
+ // === 3270 Field Attribute Byte ===
76
+ // Bit layout (bit 7 = MSB):
77
+ // Bit 7: always 1 (attribute indicator, but occupies buffer position as 0x00 display)
78
+ // Bit 6: protected (1) / unprotected (0)
79
+ // Bit 5: numeric (1) / alphanumeric (0)
80
+ // Bits 4-3: display - 00=normal/pen-detectable, 01=normal/pen-detectable,
81
+ // 10=high-intensity/selector-pen, 11=non-display
82
+ // Bit 2: reserved
83
+ // Bit 1: MDT (Modified Data Tag)
84
+ // Bit 0: reserved
85
+ export const FIELD_ATTR = {
86
+ PROTECTED: 0x20, // Bit 5 in attribute byte (bit 6 of logical layout)
87
+ NUMERIC: 0x10, // Bit 4
88
+ DISPLAY_MASK: 0x0C, // Bits 3-2
89
+ DISPLAY_NORMAL: 0x00,
90
+ DISPLAY_NORMAL_PEN: 0x04,
91
+ DISPLAY_HIGH: 0x08,
92
+ DISPLAY_NON: 0x0C,
93
+ MDT: 0x01, // Bit 0 as stored (bit 1 of logical layout)
94
+ };
95
+ // === Extended Attribute Types (for SFE/SA/MF) ===
96
+ export const EXTENDED_ATTR = {
97
+ HIGHLIGHT: 0x41,
98
+ COLOR: 0x42,
99
+ CHARSET: 0x43,
100
+ FIELD_OUTLINING: 0xC5,
101
+ TRANSPARENCY: 0x46,
102
+ ALL: 0x00, // Reset all
103
+ };
104
+ // Highlight values
105
+ export const HIGHLIGHT = {
106
+ DEFAULT: 0x00,
107
+ NORMAL: 0xF0,
108
+ BLINK: 0xF1,
109
+ REVERSE: 0xF2,
110
+ UNDERSCORE: 0xF4,
111
+ };
112
+ // Color values
113
+ export const COLOR = {
114
+ DEFAULT: 0x00,
115
+ BLUE: 0xF1,
116
+ RED: 0xF2,
117
+ PINK: 0xF3,
118
+ GREEN: 0xF4,
119
+ TURQUOISE: 0xF5,
120
+ YELLOW: 0xF6,
121
+ WHITE: 0xF7,
122
+ };
123
+ // === 3270 Buffer Address Encoding ===
124
+ // 12-bit/14-bit/16-bit address encoding lookup table
125
+ // Each 6-bit value (0-63) maps to a specific byte value
126
+ export const ADDRESS_TABLE = [
127
+ 0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
128
+ 0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
129
+ 0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
130
+ 0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
131
+ 0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
132
+ 0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
133
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
134
+ 0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
135
+ ];
136
+ // Build reverse lookup: encoded byte -> 6-bit value
137
+ export const ADDRESS_REVERSE = new Map();
138
+ for (let i = 0; i < ADDRESS_TABLE.length; i++) {
139
+ ADDRESS_REVERSE.set(ADDRESS_TABLE[i], i);
140
+ }
141
+ /**
142
+ * Decode a 3270 buffer address from 2 bytes.
143
+ * Supports 12-bit (bits 7-6 of first byte are 00) and 14-bit addressing.
144
+ */
145
+ export function decodeBufferAddress(byte1, byte2) {
146
+ // Check addressing mode from high bits of first byte
147
+ if ((byte1 & 0xC0) === 0x00) {
148
+ // 14-bit binary address
149
+ return ((byte1 & 0x3F) << 8) | byte2;
150
+ }
151
+ else {
152
+ // 12-bit encoded address (standard for 24x80)
153
+ const high = ADDRESS_REVERSE.get(byte1) ?? 0;
154
+ const low = ADDRESS_REVERSE.get(byte2) ?? 0;
155
+ return (high << 6) | low;
156
+ }
157
+ }
158
+ /**
159
+ * Encode a buffer address into 2 bytes using 12-bit encoding.
160
+ */
161
+ export function encodeBufferAddress12(address) {
162
+ const high = (address >> 6) & 0x3F;
163
+ const low = address & 0x3F;
164
+ return [ADDRESS_TABLE[high], ADDRESS_TABLE[low]];
165
+ }
166
+ /**
167
+ * Encode a buffer address into 2 bytes using 14-bit binary encoding.
168
+ */
169
+ export function encodeBufferAddress14(address) {
170
+ return [(address >> 8) & 0x3F, address & 0xFF];
171
+ }
172
+ // === Screen Dimensions ===
173
+ export const SCREEN3270 = {
174
+ // Model 2: 24x80 (standard)
175
+ MODEL2_ROWS: 24,
176
+ MODEL2_COLS: 80,
177
+ // Model 3: 32x80
178
+ MODEL3_ROWS: 32,
179
+ MODEL3_COLS: 80,
180
+ // Model 4: 43x80
181
+ MODEL4_ROWS: 43,
182
+ MODEL4_COLS: 80,
183
+ // Model 5: 27x132
184
+ MODEL5_ROWS: 27,
185
+ MODEL5_COLS: 132,
186
+ };
187
+ // Terminal type strings
188
+ export const TERMINAL_TYPE_3270 = 'IBM-3278-2'; // Model 2 (24x80)
189
+ export const TERMINAL_TYPE_3270_M3 = 'IBM-3278-3'; // Model 3 (32x80)
190
+ export const TERMINAL_TYPE_3270_M4 = 'IBM-3278-4'; // Model 4 (43x80)
191
+ export const TERMINAL_TYPE_3270_M5 = 'IBM-3278-5'; // Model 5 (27x132)
192
+ export const TERMINAL_TYPE_3270E = 'IBM-3278-2-E'; // TN3270E variant
193
+ // TN3270E option code (RFC 2355)
194
+ export const OPT_TN3270E = 0x28;
195
+ // === Aliases used by connection.ts, encoder.ts, parser.ts, screen.ts ===
196
+ export const CMD = CMD3270;
197
+ export const SNA_CMD = {
198
+ WRITE: CMD3270.SNA_WRITE,
199
+ ERASE_WRITE: CMD3270.SNA_ERASE_WRITE,
200
+ ERASE_WRITE_ALTERNATE: CMD3270.SNA_ERASE_WRITE_ALTERNATE,
201
+ READ_BUFFER: CMD3270.SNA_READ_BUFFER,
202
+ READ_MODIFIED: CMD3270.SNA_READ_MODIFIED,
203
+ READ_MODIFIED_ALL: CMD3270.SNA_READ_MODIFIED_ALL,
204
+ ERASE_ALL_UNPROTECTED: CMD3270.SNA_ERASE_ALL_UNPROTECTED,
205
+ WRITE_STRUCTURED_FIELD: CMD3270.WRITE_STRUCTURED_FIELD,
206
+ };
207
+ export const ORDER = ORDER3270;
208
+ export const AID = AID3270;
209
+ export const KEY_TO_AID = KEY_TO_AID3270;
210
+ export const FA = {
211
+ PROTECTED: FIELD_ATTR.PROTECTED,
212
+ NUMERIC: FIELD_ATTR.NUMERIC,
213
+ DISPLAY_MASK: FIELD_ATTR.DISPLAY_MASK,
214
+ DISPLAY_HIDDEN: FIELD_ATTR.DISPLAY_NON,
215
+ DISPLAY_INTENSIFIED: FIELD_ATTR.DISPLAY_HIGH,
216
+ MDT: FIELD_ATTR.MDT,
217
+ };
218
+ export const EXT_ATTR = EXTENDED_ATTR;
219
+ export const decodeAddress = decodeBufferAddress;
220
+ export function encodeAddress(addr, _screenSize) {
221
+ const [b1, b2] = encodeBufferAddress12(addr);
222
+ return Buffer.from([b1, b2]);
223
+ }
224
+ export const SCREEN = {
225
+ MODEL_2_ROWS: SCREEN3270.MODEL2_ROWS,
226
+ MODEL_2_COLS: SCREEN3270.MODEL2_COLS,
227
+ };
228
+ export const TERMINAL_TYPE = TERMINAL_TYPE_3270;
229
+ // TN3270E subnegotiation types
230
+ export const TN3270E = {
231
+ CONNECT: 0x01,
232
+ DEVICE_TYPE: 0x02,
233
+ FUNCTIONS: 0x03,
234
+ IS: 0x04,
235
+ REASON: 0x05,
236
+ REJECT: 0x06,
237
+ REQUEST: 0x07,
238
+ SEND: 0x08,
239
+ // Function request flags
240
+ FUNC_BIND_IMAGE: 0x00,
241
+ FUNC_DATA_STREAM_CTL: 0x01,
242
+ FUNC_RESPONSES: 0x02,
243
+ FUNC_SCS_CTL_CODES: 0x03,
244
+ FUNC_SYSREQ: 0x04,
245
+ // Data header types (when TN3270E mode is active)
246
+ DT_3270_DATA: 0x00,
247
+ DT_SCS_DATA: 0x01,
248
+ DT_RESPONSE: 0x02,
249
+ DT_BIND_IMAGE: 0x03,
250
+ DT_UNBIND: 0x04,
251
+ DT_NVT_DATA: 0x05,
252
+ DT_REQUEST: 0x06,
253
+ DT_SSCP_LU_DATA: 0x07,
254
+ DT_PRINT_EOJ: 0x08,
255
+ // Response flags
256
+ NO_RESPONSE: 0x00,
257
+ ERROR_RESPONSE: 0x01,
258
+ ALWAYS_RESPONSE: 0x02,
259
+ POSITIVE_RESPONSE: 0x00,
260
+ NEGATIVE_RESPONSE: 0x01,
261
+ };
@@ -0,0 +1,24 @@
1
+ import { ScreenBuffer3270 } from './screen.js';
2
+ /**
3
+ * Encodes 3270 client responses (AID key + modified field data)
4
+ * for sending back to the z/OS host.
5
+ */
6
+ export declare class TN3270Encoder {
7
+ private screen;
8
+ constructor(screen: ScreenBuffer3270);
9
+ /**
10
+ * Build a 3270 Read Modified response for an AID key press.
11
+ * Format: AID + cursor_addr(2) + [SBA(1) + addr(2) + field_data]... + IAC EOR
12
+ */
13
+ buildAidResponse(keyName: string): Buffer | null;
14
+ /**
15
+ * Wrap data with Telnet IAC EOR framing.
16
+ * Escapes any 0xFF bytes in the data.
17
+ */
18
+ private wrapWithEOR;
19
+ /**
20
+ * Insert text at the current cursor position in the current field.
21
+ * Returns true if text was successfully inserted.
22
+ */
23
+ insertText(text: string): boolean;
24
+ }
@@ -0,0 +1,97 @@
1
+ import { TELNET } from '../tn5250/constants.js';
2
+ import { KEY_TO_AID, AID, ORDER, encodeAddress } from './constants.js';
3
+ import { charToEbcdic, EBCDIC_SPACE } from '../tn5250/ebcdic.js';
4
+ /**
5
+ * Encodes 3270 client responses (AID key + modified field data)
6
+ * for sending back to the z/OS host.
7
+ */
8
+ export class TN3270Encoder {
9
+ screen;
10
+ constructor(screen) {
11
+ this.screen = screen;
12
+ }
13
+ /**
14
+ * Build a 3270 Read Modified response for an AID key press.
15
+ * Format: AID + cursor_addr(2) + [SBA(1) + addr(2) + field_data]... + IAC EOR
16
+ */
17
+ buildAidResponse(keyName) {
18
+ const aidByte = KEY_TO_AID[keyName];
19
+ if (aidByte === undefined)
20
+ return null;
21
+ const parts = [];
22
+ // AID byte
23
+ parts.push(Buffer.from([aidByte]));
24
+ // Cursor address (2 bytes)
25
+ parts.push(encodeAddress(this.screen.cursorAddr, this.screen.size));
26
+ // For short-read AIDs (PA keys, Clear), no field data
27
+ if (aidByte === AID.PA1 || aidByte === AID.PA2 || aidByte === AID.PA3 || aidByte === AID.CLEAR) {
28
+ return this.wrapWithEOR(Buffer.concat(parts));
29
+ }
30
+ // Collect modified fields
31
+ for (const field of this.screen.fields) {
32
+ if (!field.modified)
33
+ continue;
34
+ if (this.screen.isProtected(field))
35
+ continue;
36
+ // SBA order + field start address
37
+ const sba = Buffer.alloc(3);
38
+ sba[0] = ORDER.SBA;
39
+ const addrBuf = encodeAddress(field.startAddr, this.screen.size);
40
+ sba[1] = addrBuf[0];
41
+ sba[2] = addrBuf[1];
42
+ parts.push(sba);
43
+ // Field data in EBCDIC, trimmed
44
+ const value = this.screen.getFieldValue(field);
45
+ const ebcdicData = Buffer.alloc(value.length);
46
+ for (let i = 0; i < value.length; i++) {
47
+ ebcdicData[i] = charToEbcdic(value[i]);
48
+ }
49
+ // Trim trailing EBCDIC spaces
50
+ let trimLen = ebcdicData.length;
51
+ while (trimLen > 0 && ebcdicData[trimLen - 1] === EBCDIC_SPACE) {
52
+ trimLen--;
53
+ }
54
+ if (trimLen > 0) {
55
+ parts.push(ebcdicData.subarray(0, trimLen));
56
+ }
57
+ }
58
+ return this.wrapWithEOR(Buffer.concat(parts));
59
+ }
60
+ /**
61
+ * Wrap data with Telnet IAC EOR framing.
62
+ * Escapes any 0xFF bytes in the data.
63
+ */
64
+ wrapWithEOR(data) {
65
+ const escaped = [];
66
+ for (let i = 0; i < data.length; i++) {
67
+ escaped.push(data[i]);
68
+ if (data[i] === TELNET.IAC) {
69
+ escaped.push(TELNET.IAC);
70
+ }
71
+ }
72
+ escaped.push(TELNET.IAC, TELNET.EOR);
73
+ return Buffer.from(escaped);
74
+ }
75
+ /**
76
+ * Insert text at the current cursor position in the current field.
77
+ * Returns true if text was successfully inserted.
78
+ */
79
+ insertText(text) {
80
+ const field = this.screen.getFieldAtCursor();
81
+ if (!field || this.screen.isProtected(field))
82
+ return false;
83
+ let cursorAddr = this.screen.cursorAddr;
84
+ const fieldEnd = (field.startAddr + field.length) % this.screen.size;
85
+ for (const ch of text) {
86
+ if (cursorAddr === fieldEnd)
87
+ break;
88
+ this.screen.buffer[cursorAddr] = ch;
89
+ cursorAddr = (cursorAddr + 1) % this.screen.size;
90
+ }
91
+ this.screen.cursorAddr = cursorAddr;
92
+ field.modified = true;
93
+ // Set MDT in the attribute
94
+ this.screen.attrBuffer[field.attrAddr] |= 0x01;
95
+ return true;
96
+ }
97
+ }
@@ -0,0 +1,22 @@
1
+ import { ScreenBuffer3270 } from './screen.js';
2
+ /**
3
+ * Parses 3270 data stream records and updates the screen buffer.
4
+ */
5
+ export declare class TN3270Parser {
6
+ private screen;
7
+ constructor(screen: ScreenBuffer3270);
8
+ /**
9
+ * Parse a 3270 data stream record.
10
+ * Returns true if the screen was modified.
11
+ */
12
+ parseRecord(record: Buffer): boolean;
13
+ /**
14
+ * Parse a Write or Erase/Write command body.
15
+ * Starts at `offset` which points to the WCC byte.
16
+ */
17
+ private parseWrite;
18
+ /** Parse structured fields */
19
+ private parseStructuredFields;
20
+ /** Advance cursor to the start of the next unprotected field */
21
+ private advanceToNextUnprotected;
22
+ }