Get kitty building with the new VT parser
This commit is contained in:
parent
b083ad9038
commit
5f809bf249
20 changed files with 1482 additions and 2136 deletions
|
|
@ -52,7 +52,7 @@ def parse_flag(keymap: KeymapType, type_map: Dict[str, Any], command_class: str)
|
|||
q = ' && '.join(f"g.{attr} != '{x}'" for x in sorted(allowed_values))
|
||||
lines.append(f'''
|
||||
case {attr}: {{
|
||||
g.{attr} = screen->parser_buf[pos++] & 0xff;
|
||||
g.{attr} = parser_buf[pos++];
|
||||
if ({q}) {{
|
||||
REPORT_ERROR("Malformed {command_class} control block, unknown flag value for {attr}: 0x%x", g.{attr});
|
||||
return;
|
||||
|
|
@ -116,22 +116,23 @@ def generate(
|
|||
parr = 'static uint8_t payload[4096];'
|
||||
payload_case = f'''
|
||||
case PAYLOAD: {{
|
||||
sz = screen->parser_buf_pos - pos;
|
||||
sz = parser_buf_pos - pos;
|
||||
g.payload_sz = sizeof(payload);
|
||||
if (!base64_decode32(screen->parser_buf + pos, sz, payload, &g.payload_sz)) {{
|
||||
if (!base64_decode8(parser_buf + pos, sz, payload, &g.payload_sz)) {{
|
||||
REPORT_ERROR("Failed to parse {command_class} command payload with error: payload size (%zu) too large", sz); return; }}
|
||||
pos = screen->parser_buf_pos;
|
||||
pos = parser_buf_pos;
|
||||
}}
|
||||
break;
|
||||
'''
|
||||
callback = f'{callback_name}(screen, &g, payload)'
|
||||
callback = f'{callback_name}(self->screen, &g, payload)'
|
||||
else:
|
||||
payload_after_value = payload = parr = payload_case = ''
|
||||
callback = f'{callback_name}(screen, &g)'
|
||||
callback = f'{callback_name}(self->screen, &g)'
|
||||
|
||||
return f'''
|
||||
#include "base64.h"
|
||||
static inline void
|
||||
{function_name}(Screen *screen, PyObject UNUSED *dump_callback) {{
|
||||
{function_name}(PS *self, const uint8_t *parser_buf, const size_t parser_buf_pos) {{
|
||||
unsigned int pos = 1;
|
||||
enum PARSER_STATES {{ KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE {payload} }};
|
||||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||
|
|
@ -144,12 +145,12 @@ def generate(
|
|||
{parr}
|
||||
{keys_enum}
|
||||
enum KEYS key = '{initial_key}';
|
||||
if (screen->parser_buf[pos] == ';') state = AFTER_VALUE;
|
||||
if (parser_buf[pos] == ';') state = AFTER_VALUE;
|
||||
|
||||
while (pos < screen->parser_buf_pos) {{
|
||||
while (pos < parser_buf_pos) {{
|
||||
switch(state) {{
|
||||
case KEY:
|
||||
key = screen->parser_buf[pos++];
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch(key) {{
|
||||
{handle_key}
|
||||
|
|
@ -160,8 +161,8 @@ def generate(
|
|||
break;
|
||||
|
||||
case EQUAL:
|
||||
if (screen->parser_buf[pos++] != '=') {{
|
||||
REPORT_ERROR("Malformed {command_class} control block, no = after key, found: 0x%x instead", screen->parser_buf[pos-1]);
|
||||
if (parser_buf[pos++] != '=') {{
|
||||
REPORT_ERROR("Malformed {command_class} control block, no = after key, found: 0x%x instead", parser_buf[pos-1]);
|
||||
return;
|
||||
}}
|
||||
state = value_state;
|
||||
|
|
@ -178,16 +179,16 @@ def generate(
|
|||
|
||||
case INT:
|
||||
#define READ_UINT \\
|
||||
for (i = pos; i < MIN(screen->parser_buf_pos, pos + 10); i++) {{ \\
|
||||
if (screen->parser_buf[i] < '0' || screen->parser_buf[i] > '9') break; \\
|
||||
for (i = pos; i < MIN(parser_buf_pos, pos + 10); i++) {{ \\
|
||||
if (parser_buf[i] < '0' || parser_buf[i] > '9') break; \\
|
||||
}} \\
|
||||
if (i == pos) {{ REPORT_ERROR("Malformed {command_class} control block, expecting an integer value for key: %c", key & 0xFF); return; }} \\
|
||||
lcode = utoi(screen->parser_buf + pos, i - pos); pos = i; \\
|
||||
lcode = utoi(parser_buf + pos, i - pos); pos = i; \\
|
||||
if (lcode > UINT32_MAX) {{ REPORT_ERROR("Malformed {command_class} control block, number is too large"); return; }} \\
|
||||
code = lcode;
|
||||
|
||||
is_negative = false;
|
||||
if(screen->parser_buf[pos] == '-') {{ is_negative = true; pos++; }}
|
||||
if(parser_buf[pos] == '-') {{ is_negative = true; pos++; }}
|
||||
#define I(x) case x: g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; break
|
||||
READ_UINT;
|
||||
switch(key) {{
|
||||
|
|
@ -210,10 +211,10 @@ def generate(
|
|||
#undef READ_UINT
|
||||
|
||||
case AFTER_VALUE:
|
||||
switch (screen->parser_buf[pos++]) {{
|
||||
switch (parser_buf[pos++]) {{
|
||||
default:
|
||||
REPORT_ERROR("Malformed {command_class} control block, expecting a comma or semi-colon after a value, found: 0x%x",
|
||||
screen->parser_buf[pos - 1]);
|
||||
parser_buf[pos - 1]);
|
||||
return;
|
||||
case ',':
|
||||
state = KEY;
|
||||
|
|
|
|||
|
|
@ -112,11 +112,11 @@ def read_data_from_shared_memory(shm_name: str) -> Any:
|
|||
return json.loads(shm.read_data_with_size())
|
||||
|
||||
|
||||
def get_ssh_data(msg: str, request_id: str) -> Iterator[bytes]:
|
||||
def get_ssh_data(msgb: memoryview, request_id: str) -> Iterator[bytes]:
|
||||
from base64 import standard_b64decode
|
||||
yield b'\nKITTY_DATA_START\n' # to discard leading data
|
||||
try:
|
||||
msg = standard_b64decode(msg).decode('utf-8')
|
||||
msg = standard_b64decode(msgb).decode('utf-8')
|
||||
md = dict(x.split('=', 1) for x in msg.split(':'))
|
||||
pw = md['pw']
|
||||
pwfilename = md['pwfile']
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ def add_child(self, window: Window) -> None:
|
|||
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
|
||||
self.window_id_map[window.id] = window
|
||||
|
||||
def _handle_remote_command(self, cmd: str, window: Optional[Window] = None, peer_id: int = 0) -> RCResponse:
|
||||
def _handle_remote_command(self, cmd: memoryview, window: Optional[Window] = None, peer_id: int = 0) -> RCResponse:
|
||||
from .remote_control import is_cmd_allowed, parse_cmd, remote_control_allowed
|
||||
response = None
|
||||
window = window or None
|
||||
|
|
@ -778,7 +778,7 @@ def peer_message_received(self, msg_bytes: bytes, peer_id: int, is_remote_contro
|
|||
cmd_prefix = b'\x1bP@kitty-cmd'
|
||||
terminator = b'\x1b\\'
|
||||
if msg_bytes.startswith(cmd_prefix) and msg_bytes.endswith(terminator):
|
||||
cmd = msg_bytes[len(cmd_prefix):-len(terminator)].decode('utf-8')
|
||||
cmd = memoryview(msg_bytes[len(cmd_prefix):-len(terminator)])
|
||||
response = self._handle_remote_command(cmd, peer_id=peer_id)
|
||||
if response is None:
|
||||
return None
|
||||
|
|
@ -834,7 +834,7 @@ def peer_message_received(self, msg_bytes: bytes, peer_id: int, is_remote_contro
|
|||
log_error('Unknown message received over single instance socket, ignoring')
|
||||
return None
|
||||
|
||||
def handle_remote_cmd(self, cmd: str, window: Optional[Window] = None) -> None:
|
||||
def handle_remote_cmd(self, cmd: memoryview, window: Optional[Window] = None) -> None:
|
||||
response = self._handle_remote_command(cmd, window)
|
||||
if response is not None and not isinstance(response, AsyncResponse) and window is not None:
|
||||
window.send_cmd_response(response)
|
||||
|
|
|
|||
199
kitty/charsets.c
generated
199
kitty/charsets.c
generated
|
|
@ -10,205 +10,6 @@
|
|||
#include "data-types.h"
|
||||
|
||||
|
||||
static uint32_t charset_translations[5][256] = {
|
||||
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* VT100 graphics mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
|
||||
0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
|
||||
0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
|
||||
0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
|
||||
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
|
||||
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* IBM Codepage 437 mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
},
|
||||
// VAX 42 map
|
||||
{
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x043b, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x0435,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0441, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0435, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x043a,
|
||||
0x0070, 0x0071, 0x0442, 0x0073, 0x043b, 0x0435, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
},
|
||||
/* UK mapping, same as 8-bit Latin1 except the pound sign replaces # */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x00a3, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
uint32_t*
|
||||
translation_table(uint32_t which) {
|
||||
switch(which){
|
||||
case 'B':
|
||||
return charset_translations[0];
|
||||
case '0':
|
||||
return charset_translations[1];
|
||||
case 'U':
|
||||
return charset_translations[2];
|
||||
case 'V':
|
||||
return charset_translations[3];
|
||||
case 'A':
|
||||
return charset_translations[4];
|
||||
default:
|
||||
return charset_translations[0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *latin1_charset = charset_translations[0];
|
||||
|
||||
// UTF-8 decode taken from: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
|
||||
static const uint8_t utf8_data[] = {
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@
|
|||
from .conf.utils import uniq
|
||||
from .constants import supports_primary_selection
|
||||
from .fast_data_types import (
|
||||
ESC_OSC,
|
||||
GLFW_CLIPBOARD,
|
||||
GLFW_PRIMARY_SELECTION,
|
||||
OSC,
|
||||
find_in_memoryview,
|
||||
get_boss,
|
||||
get_clipboard_mime,
|
||||
get_options,
|
||||
|
|
@ -335,11 +336,17 @@ def __init__(self, window_id: int) -> None:
|
|||
self.currently_asking_permission_for: Optional[ReadRequest] = None
|
||||
self.in_flight_write_request: Optional[WriteRequest] = None
|
||||
|
||||
def parse_osc_5522(self, data: str) -> None:
|
||||
def parse_osc_5522(self, data: memoryview) -> None:
|
||||
import base64
|
||||
|
||||
from .notify import sanitize_id
|
||||
metadata, _, epayload = data.partition(';')
|
||||
idx = find_in_memoryview(data, ord(b';'))
|
||||
if idx > -1:
|
||||
metadata = str(data[:idx], "utf-8", "replace")
|
||||
epayload = data[idx+1:]
|
||||
else:
|
||||
metadata = str(data, "utf-8", "replace")
|
||||
epayload = data[len(data):]
|
||||
m: Dict[str, str] = {}
|
||||
for record in metadata.split(':'):
|
||||
try:
|
||||
|
|
@ -381,12 +388,12 @@ def parse_osc_5522(self, data: str) -> None:
|
|||
wr.add_base64_data(epayload, mime)
|
||||
except OSError:
|
||||
if w is not None:
|
||||
w.screen.send_escape_code_to_child(OSC, wr.encode_response(status='EIO'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, wr.encode_response(status='EIO'))
|
||||
self.in_flight_write_request = None
|
||||
raise
|
||||
except Exception:
|
||||
if w is not None:
|
||||
w.screen.send_escape_code_to_child(OSC, wr.encode_response(status='EINVAL'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, wr.encode_response(status='EINVAL'))
|
||||
self.in_flight_write_request = None
|
||||
raise
|
||||
else:
|
||||
|
|
@ -394,18 +401,24 @@ def parse_osc_5522(self, data: str) -> None:
|
|||
wr.commit()
|
||||
self.in_flight_write_request = None
|
||||
if w is not None:
|
||||
w.screen.send_escape_code_to_child(OSC, wr.encode_response(status='DONE'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, wr.encode_response(status='DONE'))
|
||||
|
||||
def parse_osc_52(self, data: str, is_partial: bool = False) -> None:
|
||||
where, text = data.partition(';')[::2]
|
||||
if text == '?':
|
||||
def parse_osc_52(self, data: memoryview, is_partial: bool = False) -> None:
|
||||
idx = find_in_memoryview(data, ord(b';'))
|
||||
if idx > -1:
|
||||
where = str(data[idx:], "utf-8", 'replace')
|
||||
data = data[idx+1:]
|
||||
else:
|
||||
where = str(data, "utf-8", 'replace')
|
||||
data = data[len(data):]
|
||||
if len(data) == 1 and data.tobytes() == b'?':
|
||||
rr = ReadRequest(is_primary_selection=ClipboardType.from_osc52_where_field(where) is ClipboardType.primary_selection)
|
||||
self.handle_read_request(rr)
|
||||
else:
|
||||
wr = self.in_flight_write_request
|
||||
if wr is None:
|
||||
wr = self.in_flight_write_request = WriteRequest(ClipboardType.from_osc52_where_field(where) is ClipboardType.primary_selection)
|
||||
wr.add_base64_data(text)
|
||||
wr.add_base64_data(data)
|
||||
if is_partial:
|
||||
return
|
||||
self.in_flight_write_request = None
|
||||
|
|
@ -426,7 +439,7 @@ def fulfill_write_request(self, wr: WriteRequest, allowed: bool = True) -> None:
|
|||
if not allowed or not cp.enabled:
|
||||
self.in_flight_write_request = None
|
||||
if w is not None:
|
||||
w.screen.send_escape_code_to_child(OSC, wr.encode_response(status='EPERM' if not allowed else 'ENOSYS'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, wr.encode_response(status='EPERM' if not allowed else 'ENOSYS'))
|
||||
|
||||
def fulfill_legacy_write_request(self, wr: WriteRequest, allowed: bool = True) -> None:
|
||||
cp = get_boss().primary_selection if wr.is_primary_selection else get_boss().clipboard
|
||||
|
|
@ -455,12 +468,12 @@ def fulfill_read_request(self, rr: ReadRequest, allowed: bool = True) -> None:
|
|||
return
|
||||
cp = get_boss().primary_selection if rr.is_primary_selection else get_boss().clipboard
|
||||
if not cp.enabled:
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(status='ENOSYS'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(status='ENOSYS'))
|
||||
return
|
||||
if not allowed:
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(status='EPERM'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(status='EPERM'))
|
||||
return
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(status='OK'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(status='OK'))
|
||||
|
||||
current_mime = ''
|
||||
|
||||
|
|
@ -468,7 +481,7 @@ def write_chunks(data: bytes) -> None:
|
|||
assert w is not None
|
||||
mv = memoryview(data)
|
||||
while mv:
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(payload=mv[:4096], mime=current_mime))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(payload=mv[:4096], mime=current_mime))
|
||||
mv = mv[4096:]
|
||||
|
||||
for mime in rr.mime_types:
|
||||
|
|
@ -477,20 +490,20 @@ def write_chunks(data: bytes) -> None:
|
|||
payload = ' '.join(cp.get_available_mime_types_for_paste()).encode('utf-8')
|
||||
if payload:
|
||||
payload += b'\n'
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(payload=payload, mime=current_mime))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(payload=payload, mime=current_mime))
|
||||
continue
|
||||
try:
|
||||
cp.get_mime(mime, write_chunks)
|
||||
except Exception as e:
|
||||
log_error(f'Failed to read requested mime type {mime} with error: {e}')
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(status='DONE'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(status='DONE'))
|
||||
|
||||
def reject_read_request(self, rr: ReadRequest) -> None:
|
||||
if rr.protocol_type is ProtocolType.osc_52:
|
||||
return self.fulfill_legacy_read_request(rr, False)
|
||||
w = get_boss().window_id_map.get(self.window_id)
|
||||
if w is not None:
|
||||
w.screen.send_escape_code_to_child(OSC, rr.encode_response(status='EPERM'))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, rr.encode_response(status='EPERM'))
|
||||
|
||||
def fulfill_legacy_read_request(self, rr: ReadRequest, allowed: bool = True) -> None:
|
||||
cp = get_boss().primary_selection if rr.is_primary_selection else get_boss().clipboard
|
||||
|
|
@ -500,7 +513,7 @@ def fulfill_legacy_read_request(self, rr: ReadRequest, allowed: bool = True) ->
|
|||
if cp.enabled and allowed:
|
||||
text = cp.get_text()
|
||||
loc = 'p' if rr.is_primary_selection else 'c'
|
||||
w.screen.send_escape_code_to_child(OSC, encode_osc52(loc, text))
|
||||
w.screen.send_escape_code_to_child(ESC_OSC, encode_osc52(loc, text))
|
||||
|
||||
def ask_to_read_clipboard(self, rr: ReadRequest) -> None:
|
||||
if rr.mime_types == (TARGETS_MIME,):
|
||||
|
|
|
|||
|
|
@ -55,19 +55,6 @@
|
|||
// *Delete*: Is ignored.
|
||||
#define DEL 0x7f
|
||||
|
||||
#ifndef NO_C1_CONTROLS
|
||||
#define IND 0x84
|
||||
#define NEL 0x85
|
||||
#define HTS 0x88
|
||||
#define RI 0x8d
|
||||
#define DCS 0x90
|
||||
#define CSI 0x9b
|
||||
#define ST 0x9c
|
||||
#define OSC 0x9d
|
||||
#define PM 0x9e
|
||||
#define APC 0x9f
|
||||
#endif
|
||||
|
||||
// Sharp control codes
|
||||
// -------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -320,6 +320,17 @@ expand_ansi_c_escapes(PyObject *self UNUSED, PyObject *src) {
|
|||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
find_in_memoryview(PyObject *self UNUSED, PyObject *args) {
|
||||
const char *buf; Py_ssize_t sz;
|
||||
unsigned char q;
|
||||
if (!PyArg_ParseTuple(args, "y#b", &buf, &sz, &q)) return NULL;
|
||||
const char *p = memchr(buf, q, sz);
|
||||
Py_ssize_t ans = -1;
|
||||
if (p) ans = p - buf;
|
||||
return PyLong_FromSsize_t(ans);
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
|
||||
{"expand_ansi_c_escapes", (PyCFunction)expand_ansi_c_escapes, METH_O, ""},
|
||||
|
|
@ -335,13 +346,12 @@ static PyMethodDef module_methods[] = {
|
|||
{"base64_encode", (PyCFunction)pybase64_encode, METH_VARARGS, ""},
|
||||
{"base64_decode", (PyCFunction)pybase64_decode, METH_VARARGS, ""},
|
||||
{"thread_write", (PyCFunction)cm_thread_write, METH_VARARGS, ""},
|
||||
{"parse_bytes", (PyCFunction)parse_bytes, METH_VARARGS, ""},
|
||||
{"parse_bytes_dump", (PyCFunction)parse_bytes_dump, METH_VARARGS, ""},
|
||||
{"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""},
|
||||
{"locale_is_valid", (PyCFunction)locale_is_valid, METH_VARARGS, ""},
|
||||
{"shm_open", (PyCFunction)py_shm_open, METH_VARARGS, ""},
|
||||
{"shm_unlink", (PyCFunction)py_shm_unlink, METH_VARARGS, ""},
|
||||
{"wrapped_kitten_names", (PyCFunction)wrapped_kittens, METH_NOARGS, ""},
|
||||
{"find_in_memoryview", (PyCFunction)find_in_memoryview, METH_VARARGS, ""},
|
||||
#ifdef __APPLE__
|
||||
METHODB(user_cache_dir, METH_NOARGS),
|
||||
METHODB(process_group_map, METH_NOARGS),
|
||||
|
|
@ -481,11 +491,12 @@ PyInit_fast_data_types(void) {
|
|||
PyModule_AddIntMacro(m, DECCOLM);
|
||||
PyModule_AddIntMacro(m, DECOM);
|
||||
PyModule_AddIntMacro(m, IRM);
|
||||
PyModule_AddIntMacro(m, CSI);
|
||||
PyModule_AddIntMacro(m, DCS);
|
||||
PyModule_AddIntMacro(m, APC);
|
||||
PyModule_AddIntMacro(m, OSC);
|
||||
PyModule_AddIntMacro(m, FILE_TRANSFER_CODE);
|
||||
PyModule_AddIntMacro(m, ESC_CSI);
|
||||
PyModule_AddIntMacro(m, ESC_OSC);
|
||||
PyModule_AddIntMacro(m, ESC_APC);
|
||||
PyModule_AddIntMacro(m, ESC_DCS);
|
||||
PyModule_AddIntMacro(m, ESC_PM);
|
||||
#ifdef __APPLE__
|
||||
// Apple says its SHM_NAME_MAX but SHM_NAME_MAX is not actually declared in typical CrApple style.
|
||||
// This value is based on experimentation and from qsharedmemory.cpp in Qt
|
||||
|
|
|
|||
|
|
@ -263,8 +263,6 @@ CELL_BG_PROGRAM: int
|
|||
CELL_FG_PROGRAM: int
|
||||
CELL_PROGRAM: int
|
||||
CELL_SPECIAL_PROGRAM: int
|
||||
CSI: int
|
||||
DCS: int
|
||||
DECORATION: int
|
||||
DIM: int
|
||||
GRAPHICS_ALPHA_MASK_PROGRAM: int
|
||||
|
|
@ -274,8 +272,12 @@ MARK: int
|
|||
MARK_MASK: int
|
||||
DECORATION_MASK: int
|
||||
NUM_UNDERLINE_STYLES: int
|
||||
OSC: int
|
||||
FILE_TRANSFER_CODE: int
|
||||
ESC_CSI: int
|
||||
ESC_OSC: int
|
||||
ESC_DCS: int
|
||||
ESC_APC: int
|
||||
ESC_PM: int
|
||||
REVERSE: int
|
||||
SCROLL_FULL: int
|
||||
SCROLL_LINE: int
|
||||
|
|
@ -1564,3 +1566,4 @@ def cocoa_recreate_global_menu() -> None: ...
|
|||
def cocoa_clear_global_shortcuts() -> None: ...
|
||||
def update_pointer_shape(os_window_id: int) -> None: ...
|
||||
def os_window_focus_counters() -> Dict[int, int]: ...
|
||||
def find_in_memoryview(buf: Union[bytes, memoryview, bytearray], chr: int) -> int: ...
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
from typing import IO, Any, Callable, DefaultDict, Deque, Dict, Iterable, Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from kittens.transfer.utils import IdentityCompressor, ZlibCompressor, abspath, expand_home, home_path
|
||||
from kitty.fast_data_types import FILE_TRANSFER_CODE, OSC, AES256GCMDecrypt, add_timer, base64_decode, base64_encode, get_boss, get_options
|
||||
from kitty.fast_data_types import ESC_OSC, FILE_TRANSFER_CODE, AES256GCMDecrypt, add_timer, base64_decode, base64_encode, get_boss, get_options
|
||||
from kitty.types import run_once
|
||||
|
||||
from .utils import log_error
|
||||
|
|
@ -855,7 +855,7 @@ def prune_expired(self) -> None:
|
|||
if self.active_sends[a].is_expired:
|
||||
self.drop_send(a)
|
||||
|
||||
def handle_serialized_command(self, data: str) -> None:
|
||||
def handle_serialized_command(self, data: memoryview) -> None:
|
||||
try:
|
||||
cmd = FileTransmissionCommand.deserialize(data)
|
||||
except Exception as e:
|
||||
|
|
@ -1147,7 +1147,7 @@ def write_ftc_to_child(self, payload: FileTransmissionCommand, appendleft: bool
|
|||
window = boss.window_id_map.get(self.window_id)
|
||||
if window is not None:
|
||||
data = tuple(payload.get_serialized_fields(prefix_with_osc_code=True))
|
||||
queued = window.screen.send_escape_code_to_child(OSC, data)
|
||||
queued = window.screen.send_escape_code_to_child(ESC_OSC, data)
|
||||
if not queued:
|
||||
if use_pending:
|
||||
if appendleft:
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ HANDLER(handle_move_event) {
|
|||
} else {
|
||||
if (!mouse_cell_changed && screen->modes.mouse_tracking_protocol != SGR_PIXEL_PROTOCOL) return;
|
||||
int sz = encode_mouse_button(w, button, button >=0 ? DRAG : MOVE, modifiers);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -566,7 +566,7 @@ HANDLER(handle_button_event) {
|
|||
if (!dispatch_mouse_event(w, button, is_release ? -1 : 1, modifiers, screen->modes.mouse_tracking_mode != 0)) {
|
||||
if (screen->modes.mouse_tracking_mode != 0) {
|
||||
int sz = encode_mouse_button(w, button, is_release ? RELEASE : PRESS, modifiers);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf); }
|
||||
}
|
||||
}
|
||||
// the windows array might have been re-alloced in dispatch_mouse_event
|
||||
|
|
@ -957,7 +957,7 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
|
|||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
for (s = abs(s); s > 0; s--) {
|
||||
write_escape_code_to_child(screen, CSI, mouse_event_buf);
|
||||
write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -974,7 +974,7 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
|
|||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
for (s = abs(s); s > 0; s--) {
|
||||
write_escape_code_to_child(screen, CSI, mouse_event_buf);
|
||||
write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -999,7 +999,7 @@ send_mouse_event(PyObject *self UNUSED, PyObject *args, PyObject *kw) {
|
|||
int sz = encode_mouse_event_impl(&mpos, screen->modes.mouse_tracking_protocol, button, action, mods);
|
||||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
write_escape_code_to_child(screen, CSI, mouse_event_buf);
|
||||
write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf);
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
44
kitty/parse-graphics-command.h
generated
44
kitty/parse-graphics-command.h
generated
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
static inline void parse_graphics_code(Screen *screen,
|
||||
PyObject UNUSED *dump_callback) {
|
||||
#include "base64.h"
|
||||
static inline void parse_graphics_code(PS *self, const uint8_t *parser_buf,
|
||||
const size_t parser_buf_pos) {
|
||||
unsigned int pos = 1;
|
||||
enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD };
|
||||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||
|
|
@ -48,13 +49,13 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
};
|
||||
|
||||
enum KEYS key = 'a';
|
||||
if (screen->parser_buf[pos] == ';')
|
||||
if (parser_buf[pos] == ';')
|
||||
state = AFTER_VALUE;
|
||||
|
||||
while (pos < screen->parser_buf_pos) {
|
||||
while (pos < parser_buf_pos) {
|
||||
switch (state) {
|
||||
case KEY:
|
||||
key = screen->parser_buf[pos++];
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch (key) {
|
||||
case action:
|
||||
|
|
@ -153,10 +154,10 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
break;
|
||||
|
||||
case EQUAL:
|
||||
if (screen->parser_buf[pos++] != '=') {
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key, "
|
||||
"found: 0x%x instead",
|
||||
screen->parser_buf[pos - 1]);
|
||||
parser_buf[pos - 1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
|
|
@ -166,7 +167,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
switch (key) {
|
||||
|
||||
case action: {
|
||||
g.action = screen->parser_buf[pos++] & 0xff;
|
||||
g.action = parser_buf[pos++];
|
||||
if (g.action != 'T' && g.action != 'a' && g.action != 'c' &&
|
||||
g.action != 'd' && g.action != 'f' && g.action != 'p' &&
|
||||
g.action != 'q' && g.action != 't') {
|
||||
|
|
@ -178,7 +179,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
} break;
|
||||
|
||||
case delete_action: {
|
||||
g.delete_action = screen->parser_buf[pos++] & 0xff;
|
||||
g.delete_action = parser_buf[pos++];
|
||||
if (g.delete_action != 'A' && g.delete_action != 'C' &&
|
||||
g.delete_action != 'F' && g.delete_action != 'I' &&
|
||||
g.delete_action != 'N' && g.delete_action != 'P' &&
|
||||
|
|
@ -197,7 +198,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
} break;
|
||||
|
||||
case transmission_type: {
|
||||
g.transmission_type = screen->parser_buf[pos++] & 0xff;
|
||||
g.transmission_type = parser_buf[pos++];
|
||||
if (g.transmission_type != 'd' && g.transmission_type != 'f' &&
|
||||
g.transmission_type != 's' && g.transmission_type != 't') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
|
|
@ -208,7 +209,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
} break;
|
||||
|
||||
case compressed: {
|
||||
g.compressed = screen->parser_buf[pos++] & 0xff;
|
||||
g.compressed = parser_buf[pos++];
|
||||
if (g.compressed != 'z') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
"value for compressed: 0x%x",
|
||||
|
|
@ -225,8 +226,8 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
|
||||
case INT:
|
||||
#define READ_UINT \
|
||||
for (i = pos; i < MIN(screen->parser_buf_pos, pos + 10); i++) { \
|
||||
if (screen->parser_buf[i] < '0' || screen->parser_buf[i] > '9') \
|
||||
for (i = pos; i < MIN(parser_buf_pos, pos + 10); i++) { \
|
||||
if (parser_buf[i] < '0' || parser_buf[i] > '9') \
|
||||
break; \
|
||||
} \
|
||||
if (i == pos) { \
|
||||
|
|
@ -235,7 +236,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
key & 0xFF); \
|
||||
return; \
|
||||
} \
|
||||
lcode = utoi(screen->parser_buf + pos, i - pos); \
|
||||
lcode = utoi(parser_buf + pos, i - pos); \
|
||||
pos = i; \
|
||||
if (lcode > UINT32_MAX) { \
|
||||
REPORT_ERROR( \
|
||||
|
|
@ -245,7 +246,7 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
code = lcode;
|
||||
|
||||
is_negative = false;
|
||||
if (screen->parser_buf[pos] == '-') {
|
||||
if (parser_buf[pos] == '-') {
|
||||
is_negative = true;
|
||||
pos++;
|
||||
}
|
||||
|
|
@ -302,11 +303,11 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
#undef READ_UINT
|
||||
|
||||
case AFTER_VALUE:
|
||||
switch (screen->parser_buf[pos++]) {
|
||||
switch (parser_buf[pos++]) {
|
||||
default:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting a "
|
||||
"comma or semi-colon after a value, found: 0x%x",
|
||||
screen->parser_buf[pos - 1]);
|
||||
parser_buf[pos - 1]);
|
||||
return;
|
||||
case ',':
|
||||
state = KEY;
|
||||
|
|
@ -318,16 +319,15 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
break;
|
||||
|
||||
case PAYLOAD: {
|
||||
sz = screen->parser_buf_pos - pos;
|
||||
sz = parser_buf_pos - pos;
|
||||
g.payload_sz = sizeof(payload);
|
||||
if (!base64_decode32(screen->parser_buf + pos, sz, payload,
|
||||
&g.payload_sz)) {
|
||||
if (!base64_decode8(parser_buf + pos, sz, payload, &g.payload_sz)) {
|
||||
REPORT_ERROR("Failed to parse GraphicsCommand command payload with "
|
||||
"error: payload size (%zu) too large",
|
||||
sz);
|
||||
return;
|
||||
}
|
||||
pos = screen->parser_buf_pos;
|
||||
pos = parser_buf_pos;
|
||||
} break;
|
||||
|
||||
} // end switch
|
||||
|
|
@ -373,5 +373,5 @@ static inline void parse_graphics_code(Screen *screen,
|
|||
"offset_from_parent_y", (int)g.offset_from_parent_y, "payload_sz",
|
||||
g.payload_sz, payload, g.payload_sz);
|
||||
|
||||
screen_handle_graphics_command(screen, &g, payload);
|
||||
screen_handle_graphics_command(self->screen, &g, payload);
|
||||
}
|
||||
|
|
|
|||
1608
kitty/parser.c
1608
kitty/parser.c
File diff suppressed because it is too large
Load diff
|
|
@ -52,7 +52,7 @@ def encode_response_for_peer(response: Any) -> bytes:
|
|||
return b'\x1bP@kitty-cmd' + json.dumps(response).encode('utf-8') + b'\x1b\\'
|
||||
|
||||
|
||||
def parse_cmd(serialized_cmd: str, encryption_key: EllipticCurveKey) -> Dict[str, Any]:
|
||||
def parse_cmd(serialized_cmd: memoryview, encryption_key: EllipticCurveKey) -> Dict[str, Any]:
|
||||
try:
|
||||
pcmd = json.loads(serialized_cmd)
|
||||
except Exception:
|
||||
|
|
|
|||
192
kitty/screen.c
192
kitty/screen.c
|
|
@ -10,6 +10,7 @@
|
|||
if (PyModule_AddFunctions(module, module_methods) != 0) return false; \
|
||||
}
|
||||
|
||||
#include "control-codes.h"
|
||||
#include "state.h"
|
||||
#include "iqsort.h"
|
||||
#include "fonts.h"
|
||||
|
|
@ -24,8 +25,8 @@
|
|||
#include "modes.h"
|
||||
#include "wcwidth-std.h"
|
||||
#include "wcswidth.h"
|
||||
#include "control-codes.h"
|
||||
#include "keys.h"
|
||||
#include "vt-parser.h"
|
||||
|
||||
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
|
||||
|
||||
|
|
@ -81,14 +82,6 @@ static void update_overlay_position(Screen *self);
|
|||
static void render_overlay_line(Screen *self, Line *line, FONTS_DATA_HANDLE fonts_data);
|
||||
static void update_overlay_line_data(Screen *self, uint8_t *data);
|
||||
|
||||
#define RESET_CHARSETS \
|
||||
self->g0_charset = translation_table(0); \
|
||||
self->g1_charset = self->g0_charset; \
|
||||
self->g_charset = self->g0_charset; \
|
||||
self->current_charset = 0; \
|
||||
self->utf8_state = 0; \
|
||||
self->utf8_codepoint = 0; \
|
||||
self->use_latin1 = false;
|
||||
#define CALLBACK(...) \
|
||||
if (self->callbacks != Py_None) { \
|
||||
PyObject *callback_ret = PyObject_CallMethod(self->callbacks, __VA_ARGS__); \
|
||||
|
|
@ -114,6 +107,8 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||
Py_CLEAR(self); PyErr_Format(PyExc_RuntimeError, "Failed to create Screen write_buf_lock mutex: %s", strerror(ret));
|
||||
return NULL;
|
||||
}
|
||||
self->vt_parser = alloc_vt_parser(window_id);
|
||||
if (self->vt_parser == NULL) { Py_CLEAR(self); return PyErr_NoMemory(); }
|
||||
self->reload_all_gpu_data = true;
|
||||
self->cell_size.width = cell_width; self->cell_size.height = cell_height;
|
||||
self->columns = columns; self->lines = lines;
|
||||
|
|
@ -127,7 +122,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||
self->scroll_changed = false;
|
||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||
self->history_line_added_count = 0;
|
||||
RESET_CHARSETS;
|
||||
reset_vt_parser(self->vt_parser);
|
||||
self->callbacks = callbacks; Py_INCREF(callbacks);
|
||||
self->test_child = test_child; Py_INCREF(test_child);
|
||||
self->cursor = alloc_cursor();
|
||||
|
|
@ -194,7 +189,7 @@ screen_reset(Screen *self) {
|
|||
#define R(name) self->color_profile->overridden.name.val = 0
|
||||
R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg);
|
||||
#undef R
|
||||
RESET_CHARSETS;
|
||||
reset_vt_parser(self->vt_parser);
|
||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||
screen_normal_keypad_mode(self);
|
||||
init_tabstops(self->main_tabstops, self->columns);
|
||||
|
|
@ -207,10 +202,6 @@ screen_reset(Screen *self) {
|
|||
set_dynamic_color(self, 110, NULL);
|
||||
set_dynamic_color(self, 111, NULL);
|
||||
set_color_table_color(self, 104, NULL);
|
||||
self->parser_state = 0;
|
||||
self->parser_text_start = 0;
|
||||
self->parser_buf_pos = 0;
|
||||
self->parser_has_pending_text = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -466,6 +457,7 @@ static void
|
|||
dealloc(Screen* self) {
|
||||
pthread_mutex_destroy(&self->read_buf_lock);
|
||||
pthread_mutex_destroy(&self->write_buf_lock);
|
||||
free_vt_parser(self->vt_parser); self->vt_parser = NULL;
|
||||
Py_CLEAR(self->main_grman);
|
||||
Py_CLEAR(self->alt_grman);
|
||||
Py_CLEAR(self->last_reported_cwd);
|
||||
|
|
@ -495,34 +487,6 @@ dealloc(Screen* self) {
|
|||
|
||||
// Draw text {{{
|
||||
|
||||
void
|
||||
screen_change_charset(Screen *self, uint32_t which) {
|
||||
switch(which) {
|
||||
case 0:
|
||||
self->current_charset = 0;
|
||||
self->g_charset = self->g0_charset;
|
||||
break;
|
||||
case 1:
|
||||
self->current_charset = 1;
|
||||
self->g_charset = self->g1_charset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
screen_designate_charset(Screen *self, uint32_t which, uint32_t as) {
|
||||
switch(which) {
|
||||
case 0:
|
||||
self->g0_charset = translation_table(as);
|
||||
if (self->current_charset == 0) self->g_charset = self->g0_charset;
|
||||
break;
|
||||
case 1:
|
||||
self->g1_charset = translation_table(as);
|
||||
if (self->current_charset == 1) self->g_charset = self->g1_charset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
move_widened_char(Screen *self, CPUCell* cpu_cell, GPUCell *gpu_cell, index_type xpos, index_type ypos) {
|
||||
self->cursor->x = xpos; self->cursor->y = ypos;
|
||||
|
|
@ -681,8 +645,8 @@ draw_combining_char(Screen *self, char_type ch) {
|
|||
}
|
||||
|
||||
static void
|
||||
draw_codepoint(Screen *self, char_type och, bool from_input_stream) {
|
||||
if (is_ignored_char(och)) return;
|
||||
draw_codepoint(Screen *self, char_type ch, bool from_input_stream) {
|
||||
if (is_ignored_char(ch)) return;
|
||||
if (!self->has_activity_since_last_focus && !self->has_focus && self->callbacks != Py_None) {
|
||||
PyObject *ret = PyObject_CallMethod(self->callbacks, "on_activity_since_last_focus", NULL);
|
||||
if (ret == NULL) PyErr_Print();
|
||||
|
|
@ -691,7 +655,6 @@ draw_codepoint(Screen *self, char_type och, bool from_input_stream) {
|
|||
Py_DECREF(ret);
|
||||
}
|
||||
}
|
||||
uint32_t ch = och < 256 ? self->g_charset[och] : och;
|
||||
if (UNLIKELY(is_combining_char(ch))) {
|
||||
if (UNLIKELY(is_flag_codepoint(ch))) {
|
||||
if (draw_second_flag_codepoint(self, ch)) return;
|
||||
|
|
@ -816,23 +779,23 @@ write_to_child(Screen *self, const char *data, size_t sz) {
|
|||
}
|
||||
|
||||
static void
|
||||
get_prefix_and_suffix_for_escape_code(const Screen *self, unsigned char which, const char ** prefix, const char ** suffix) {
|
||||
*suffix = self->modes.eight_bit_controls ? "\x9c" : "\033\\";
|
||||
get_prefix_and_suffix_for_escape_code(unsigned char which, const char ** prefix, const char ** suffix) {
|
||||
*suffix = "\033\\";
|
||||
switch(which) {
|
||||
case DCS:
|
||||
*prefix = self->modes.eight_bit_controls ? "\x90" : "\033P";
|
||||
case ESC_DCS:
|
||||
*prefix = "\033P";
|
||||
break;
|
||||
case CSI:
|
||||
*prefix = self->modes.eight_bit_controls ? "\x9b" : "\033["; *suffix = "";
|
||||
case ESC_CSI:
|
||||
*prefix = "\033["; *suffix = "";
|
||||
break;
|
||||
case OSC:
|
||||
*prefix = self->modes.eight_bit_controls ? "\x9d" : "\033]";
|
||||
case ESC_OSC:
|
||||
*prefix = "\033]";
|
||||
break;
|
||||
case PM:
|
||||
*prefix = self->modes.eight_bit_controls ? "\x9e" : "\033^";
|
||||
case ESC_PM:
|
||||
*prefix = "\033^";
|
||||
break;
|
||||
case APC:
|
||||
*prefix = self->modes.eight_bit_controls ? "\x9f" : "\033_";
|
||||
case ESC_APC:
|
||||
*prefix = "\033_";
|
||||
break;
|
||||
default:
|
||||
fatal("Unknown escape code to write: %u", which);
|
||||
|
|
@ -843,7 +806,7 @@ bool
|
|||
write_escape_code_to_child(Screen *self, unsigned char which, const char *data) {
|
||||
bool written = false;
|
||||
const char *prefix, *suffix;
|
||||
get_prefix_and_suffix_for_escape_code(self, which, &prefix, &suffix);
|
||||
get_prefix_and_suffix_for_escape_code(which, &prefix, &suffix);
|
||||
if (self->window_id) {
|
||||
if (suffix[0]) {
|
||||
written = schedule_write_to_child(self->window_id, 3, prefix, strlen(prefix), data, strlen(data), suffix, strlen(suffix));
|
||||
|
|
@ -863,7 +826,7 @@ static bool
|
|||
write_escape_code_to_child_python(Screen *self, unsigned char which, PyObject *data) {
|
||||
bool written = false;
|
||||
const char *prefix, *suffix;
|
||||
get_prefix_and_suffix_for_escape_code(self, which, &prefix, &suffix);
|
||||
get_prefix_and_suffix_for_escape_code(which, &prefix, &suffix);
|
||||
if (self->window_id) written = schedule_write_to_child_python(self->window_id, prefix, data, suffix);
|
||||
if (self->test_child != Py_None) {
|
||||
write_to_test_child(self, prefix, strlen(prefix));
|
||||
|
|
@ -911,7 +874,7 @@ void
|
|||
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
|
||||
unsigned int x = self->cursor->x, y = self->cursor->y;
|
||||
const char *response = grman_handle_command(self->grman, cmd, payload, self->cursor, &self->is_dirty, self->cell_size);
|
||||
if (response != NULL) write_escape_code_to_child(self, APC, response);
|
||||
if (response != NULL) write_escape_code_to_child(self, ESC_APC, response);
|
||||
if (x != self->cursor->x || y != self->cursor->y) {
|
||||
bool in_margins = cursor_within_margins(self);
|
||||
if (self->cursor->x >= self->columns) { self->cursor->x = 0; self->cursor->y++; }
|
||||
|
|
@ -1070,11 +1033,6 @@ screen_reset_mode(Screen *self, unsigned int mode) {
|
|||
set_mode_from_const(self, mode, false);
|
||||
}
|
||||
|
||||
void
|
||||
screen_set_8bit_controls(Screen *self, bool yes) {
|
||||
self->modes.eight_bit_controls = yes;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
screen_current_key_encoding_flags(Screen *self) {
|
||||
for (unsigned i = arraysz(self->main_key_encoding_flags); i-- > 0; ) {
|
||||
|
|
@ -1090,7 +1048,7 @@ screen_report_key_encoding_flags(Screen *self) {
|
|||
debug("\x1b[35mReporting key encoding flags: %u\x1b[39m\n", screen_current_key_encoding_flags(self));
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "?%uu", screen_current_key_encoding_flags(self));
|
||||
write_escape_code_to_child(self, CSI, buf);
|
||||
write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1534,14 +1492,6 @@ screen_linefeed(Screen *self) {
|
|||
} \
|
||||
}
|
||||
|
||||
#define COPY_CHARSETS(self, sp) \
|
||||
sp->utf8_state = self->utf8_state; \
|
||||
sp->utf8_codepoint = self->utf8_codepoint; \
|
||||
sp->g0_charset = self->g0_charset; \
|
||||
sp->g1_charset = self->g1_charset; \
|
||||
sp->current_charset = self->current_charset; \
|
||||
sp->use_latin1 = self->use_latin1;
|
||||
|
||||
void
|
||||
screen_save_cursor(Screen *self) {
|
||||
Savepoint *sp = self->linebuf == self->main_linebuf ? &self->main_savepoint : &self->alt_savepoint;
|
||||
|
|
@ -1549,7 +1499,6 @@ screen_save_cursor(Screen *self) {
|
|||
sp->mDECOM = self->modes.mDECOM;
|
||||
sp->mDECAWM = self->modes.mDECAWM;
|
||||
sp->mDECSCNM = self->modes.mDECSCNM;
|
||||
COPY_CHARSETS(self, sp);
|
||||
sp->is_valid = true;
|
||||
}
|
||||
|
||||
|
|
@ -1626,11 +1575,8 @@ screen_restore_cursor(Screen *self) {
|
|||
if (!sp->is_valid) {
|
||||
screen_cursor_position(self, 1, 1);
|
||||
screen_reset_mode(self, DECOM);
|
||||
RESET_CHARSETS;
|
||||
screen_reset_mode(self, DECSCNM);
|
||||
} else {
|
||||
COPY_CHARSETS(sp, self);
|
||||
self->g_charset = self->current_charset ? self->g1_charset : self->g0_charset;
|
||||
set_mode_from_const(self, DECOM, sp->mDECOM);
|
||||
set_mode_from_const(self, DECAWM, sp->mDECAWM);
|
||||
set_mode_from_const(self, DECSCNM, sp->mDECSCNM);
|
||||
|
|
@ -1965,12 +1911,6 @@ screen_erase_characters(Screen *self, unsigned int count) {
|
|||
|
||||
// Device control {{{
|
||||
|
||||
void
|
||||
screen_use_latin1(Screen *self, bool on) {
|
||||
self->use_latin1 = on; self->utf8_state = 0; self->utf8_codepoint = 0;
|
||||
CALLBACK("use_utf8", "O", on ? Py_False : Py_True);
|
||||
}
|
||||
|
||||
bool
|
||||
screen_invert_colors(Screen *self) {
|
||||
bool inverted = false;
|
||||
|
|
@ -1998,10 +1938,10 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
|||
if (mode == 0) {
|
||||
switch(start_modifier) {
|
||||
case 0:
|
||||
write_escape_code_to_child(self, CSI, "?62;c");
|
||||
write_escape_code_to_child(self, ESC_CSI, "?62;c");
|
||||
break;
|
||||
case '>':
|
||||
write_escape_code_to_child(self, CSI, ">1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
|
||||
write_escape_code_to_child(self, ESC_CSI, ">1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2010,7 +1950,7 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
|||
void
|
||||
screen_xtversion(Screen *self, unsigned int mode) {
|
||||
if (mode == 0) {
|
||||
write_escape_code_to_child(self, DCS, ">|kitty(" XT_VERSION ")");
|
||||
write_escape_code_to_child(self, ESC_DCS, ">|kitty(" XT_VERSION ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2038,7 +1978,7 @@ screen_report_size(Screen *self, unsigned int which) {
|
|||
}
|
||||
if (code) {
|
||||
snprintf(buf, sizeof(buf), "%u;%u;%ut", code, height, width);
|
||||
write_escape_code_to_child(self, CSI, buf);
|
||||
write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2059,7 +1999,7 @@ report_device_status(Screen *self, unsigned int which, bool private) {
|
|||
static char buf[64];
|
||||
switch(which) {
|
||||
case 5: // device status
|
||||
write_escape_code_to_child(self, CSI, "0n");
|
||||
write_escape_code_to_child(self, ESC_CSI, "0n");
|
||||
break;
|
||||
case 6: // cursor position
|
||||
x = self->cursor->x; y = self->cursor->y;
|
||||
|
|
@ -2070,7 +2010,7 @@ report_device_status(Screen *self, unsigned int which, bool private) {
|
|||
if (self->modes.mDECOM) y -= MAX(y, self->margin_top);
|
||||
// 1-based indexing
|
||||
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
|
||||
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
||||
if (sz > 0) write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2114,7 +2054,7 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
|
|||
ans = self->pending_mode.activated_at ? 1 : 2; break;
|
||||
}
|
||||
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%u$y", (private ? "?" : ""), which, ans);
|
||||
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
||||
if (sz > 0) write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2173,7 +2113,7 @@ set_icon(Screen *self, PyObject *icon) {
|
|||
|
||||
void
|
||||
set_dynamic_color(Screen *self, unsigned int code, PyObject *color) {
|
||||
if (color == NULL) { CALLBACK("set_dynamic_color", "Is", code, ""); }
|
||||
if (color == NULL) { CALLBACK("set_dynamic_color", "I", code); }
|
||||
else { CALLBACK("set_dynamic_color", "IO", code, color); }
|
||||
}
|
||||
|
||||
|
|
@ -2185,36 +2125,29 @@ clipboard_control(Screen *self, int code, PyObject *data) {
|
|||
|
||||
void
|
||||
file_transmission(Screen *self, PyObject *data) {
|
||||
if (PyUnicode_READY(data) != 0) { PyErr_Clear(); return; }
|
||||
CALLBACK("file_transmission", "O", data);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_prompt_mark(Screen *self, PyObject *parts, PromptKind *pk) {
|
||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(parts); i++) {
|
||||
PyObject *token = PyList_GET_ITEM(parts, i);
|
||||
if (PyUnicode_CompareWithASCIIString(token, "k=s") == 0) *pk = SECONDARY_PROMPT;
|
||||
else if (PyUnicode_CompareWithASCIIString(token, "redraw=0") == 0) self->prompt_settings.redraws_prompts_at_all = 0;
|
||||
parse_prompt_mark(Screen *self, char *buf, PromptKind *pk) {
|
||||
char *saveptr, *str = buf;
|
||||
while (true) {
|
||||
const char *token = strtok_r(str, ";", &saveptr); str = NULL;
|
||||
if (token == NULL) return;
|
||||
if (strcmp(token, "k=s") == 0) *pk = SECONDARY_PROMPT;
|
||||
else if (strcmp(token, "redraw=0") == 0) self->prompt_settings.redraws_prompts_at_all = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shell_prompt_marking(Screen *self, PyObject *data) {
|
||||
if (PyUnicode_READY(data) != 0) { PyErr_Clear(); return; }
|
||||
if (PyUnicode_GET_LENGTH(data) > 0 && self->cursor->y < self->lines) {
|
||||
Py_UCS4 ch = PyUnicode_READ_CHAR(data, 0);
|
||||
shell_prompt_marking(Screen *self, char *buf) {
|
||||
if (self->cursor->y < self->lines) {
|
||||
char ch = buf[0];
|
||||
switch (ch) {
|
||||
case 'A': {
|
||||
PromptKind pk = PROMPT_START;
|
||||
self->prompt_settings.redraws_prompts_at_all = 1;
|
||||
if (PyUnicode_FindChar(data, ';', 0, PyUnicode_GET_LENGTH(data), 1)) {
|
||||
RAII_PyObject(sep, PyUnicode_FromString(";"));
|
||||
if (sep) {
|
||||
RAII_PyObject(parts, PyUnicode_Split(data, sep, -1));
|
||||
if (parts) parse_prompt_mark(self, parts, &pk);
|
||||
}
|
||||
}
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
parse_prompt_mark(self, buf+1, &pk);
|
||||
self->linebuf->line_attrs[self->cursor->y].prompt_kind = pk;
|
||||
if (pk == PROMPT_START)
|
||||
CALLBACK("cmd_output_marking", "O", Py_False);
|
||||
|
|
@ -2225,11 +2158,7 @@ shell_prompt_marking(Screen *self, PyObject *data) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (global_state.debug_rendering) {
|
||||
fprintf(stderr, "prompt_marking: x=%d y=%d op=", self->cursor->x, self->cursor->y);
|
||||
PyObject_Print(data, stderr, 0);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
if (global_state.debug_rendering) fprintf(stderr, "prompt_marking: x=%d y=%d op=%s\n", self->cursor->x, self->cursor->y, buf);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -2262,7 +2191,7 @@ screen_history_scroll_to_prompt(Screen *self, int num_of_prompts_to_jump) {
|
|||
|
||||
void
|
||||
set_color_table_color(Screen *self, unsigned int code, PyObject *color) {
|
||||
if (color == NULL) { CALLBACK("set_color_table_color", "Is", code, ""); }
|
||||
if (color == NULL) { CALLBACK("set_color_table_color", "I", code); }
|
||||
else { CALLBACK("set_color_table_color", "IO", code, color); }
|
||||
}
|
||||
|
||||
|
|
@ -2315,7 +2244,7 @@ screen_report_color_stack(Screen *self) {
|
|||
colorprofile_report_stack(self->color_profile, &idx, &count);
|
||||
char buf[128] = {0};
|
||||
snprintf(buf, arraysz(buf), "%u;%u#Q", idx, count);
|
||||
write_escape_code_to_child(self, CSI, buf);
|
||||
write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
}
|
||||
|
||||
void screen_handle_kitty_dcs(Screen *self, const char *callback_name, PyObject *cmd) {
|
||||
|
|
@ -2323,17 +2252,15 @@ void screen_handle_kitty_dcs(Screen *self, const char *callback_name, PyObject *
|
|||
}
|
||||
|
||||
void
|
||||
screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
||||
screen_request_capabilities(Screen *self, char c, const char *query) {
|
||||
static char buf[128];
|
||||
int shape = 0;
|
||||
const char *query;
|
||||
switch(c) {
|
||||
case '+':
|
||||
CALLBACK("request_capabilities", "O", q);
|
||||
break;
|
||||
case '+': {
|
||||
CALLBACK("request_capabilities", "s", query);
|
||||
} break;
|
||||
case '$':
|
||||
// report status DECRQSS
|
||||
query = PyUnicode_AsUTF8(q);
|
||||
if (strcmp(" q", query) == 0) {
|
||||
// cursor shape DECSCUSR
|
||||
switch(self->cursor->shape) {
|
||||
|
|
@ -2358,7 +2285,7 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
|||
} else {
|
||||
shape = snprintf(buf, sizeof(buf), "0$r");
|
||||
}
|
||||
if (shape > 0) write_escape_code_to_child(self, DCS, buf);
|
||||
if (shape > 0) write_escape_code_to_child(self, ESC_DCS, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -3573,17 +3500,12 @@ draw(Screen *self, PyObject *src) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
extern void
|
||||
parse_sgr(Screen *screen, uint32_t *buf, unsigned int num, int *params, PyObject *dump_callback, const char *report_name, Region *region);
|
||||
|
||||
static PyObject*
|
||||
apply_sgr(Screen *self, PyObject *src) {
|
||||
if (!PyUnicode_Check(src)) { PyErr_SetString(PyExc_TypeError, "A unicode string is required"); return NULL; }
|
||||
if (PyUnicode_READY(src) != 0) { return PyErr_NoMemory(); }
|
||||
Py_UCS4 *buf = PyUnicode_AsUCS4Copy(src);
|
||||
if (!buf) return NULL;
|
||||
int params[MAX_PARAMS] = {0};
|
||||
parse_sgr(self, buf, PyUnicode_GET_LENGTH(src), params, NULL, "parse_sgr", NULL);
|
||||
parse_sgr(self, (const uint8_t*)PyUnicode_AsUTF8(src), PyUnicode_GET_LENGTH(src), params, "parse_sgr", NULL);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -4356,9 +4278,9 @@ paste_(Screen *self, PyObject *bytes, bool allow_bracketed_paste) {
|
|||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "Must paste() bytes"); return NULL;
|
||||
}
|
||||
if (allow_bracketed_paste && self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_START);
|
||||
if (allow_bracketed_paste && self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, ESC_CSI, BRACKETED_PASTE_START);
|
||||
write_to_child(self, data, sz);
|
||||
if (allow_bracketed_paste && self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_END);
|
||||
if (allow_bracketed_paste && self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, ESC_CSI, BRACKETED_PASTE_END);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -4381,7 +4303,7 @@ focus_changed(Screen *self, PyObject *has_focus_) {
|
|||
self->has_focus = has_focus;
|
||||
if (has_focus) self->has_activity_since_last_focus = false;
|
||||
else if (screen_is_overlay_active(self)) deactivate_overlay_line(self);
|
||||
if (self->modes.mFOCUS_TRACKING) write_escape_code_to_child(self, CSI, has_focus ? "I" : "O");
|
||||
if (self->modes.mFOCUS_TRACKING) write_escape_code_to_child(self, ESC_CSI, has_focus ? "I" : "O");
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
Py_RETURN_FALSE;
|
||||
|
|
@ -4521,7 +4443,6 @@ line_edge_colors(Screen *self, PyObject *a UNUSED) {
|
|||
WRAP0(update_only_line_graphics_data)
|
||||
WRAP0(bell)
|
||||
|
||||
|
||||
#define MND(name, args) {#name, (PyCFunction)name, args, #name},
|
||||
#define MODEFUNC(name) MND(name, METH_NOARGS) MND(set_##name, METH_O)
|
||||
|
||||
|
|
@ -4637,6 +4558,7 @@ static PyGetSetDef getsetters[] = {
|
|||
static PyMemberDef members[] = {
|
||||
{"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"},
|
||||
{"cursor", T_OBJECT_EX, offsetof(Screen, cursor), READONLY, "cursor"},
|
||||
{"vt_parser", T_OBJECT_EX, offsetof(Screen, vt_parser), READONLY, "vt_parser"},
|
||||
{"last_reported_cwd", T_OBJECT, offsetof(Screen, last_reported_cwd), READONLY, "last_reported_cwd"},
|
||||
{"grman", T_OBJECT_EX, offsetof(Screen, grman), READONLY, "grman"},
|
||||
{"color_profile", T_OBJECT_EX, offsetof(Screen, color_profile), READONLY, "color_profile"},
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vt-parser.h"
|
||||
#include "graphics.h"
|
||||
#include "monotonic.h"
|
||||
#define MAX_PARAMS 256
|
||||
|
|
@ -17,7 +18,6 @@ typedef struct {
|
|||
mBRACKETED_PASTE, mFOCUS_TRACKING, mDECSACE, mHANDLE_TERMIOS_SIGNALS;
|
||||
MouseTrackingMode mouse_tracking_mode;
|
||||
MouseTrackingProtocol mouse_tracking_protocol;
|
||||
bool eight_bit_controls; // S8C1T
|
||||
} ScreenModes;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -58,9 +58,6 @@ typedef struct {
|
|||
#define SAVEPOINTS_SZ 256
|
||||
|
||||
typedef struct {
|
||||
uint32_t utf8_state, utf8_codepoint, *g0_charset, *g1_charset;
|
||||
unsigned int current_charset;
|
||||
bool use_latin1;
|
||||
Cursor cursor;
|
||||
bool mDECOM, mDECAWM, mDECSCNM;
|
||||
bool is_valid;
|
||||
|
|
@ -92,15 +89,12 @@ typedef struct {
|
|||
CellPixelSize cell_size;
|
||||
OverlayLine overlay_line;
|
||||
id_type window_id;
|
||||
uint32_t utf8_codepoint, *g0_charset, *g1_charset, *g_charset;
|
||||
UTF8State utf8_state;
|
||||
unsigned int current_charset;
|
||||
Selections selections, url_ranges;
|
||||
struct {
|
||||
unsigned int cursor_x, cursor_y, scrolled_by;
|
||||
index_type lines, columns;
|
||||
} last_rendered;
|
||||
bool use_latin1, is_dirty, scroll_changed, reload_all_gpu_data;
|
||||
bool is_dirty, scroll_changed, reload_all_gpu_data;
|
||||
Cursor *cursor;
|
||||
Savepoint main_savepoint, alt_savepoint;
|
||||
PyObject *callbacks, *test_child;
|
||||
|
|
@ -113,9 +107,6 @@ typedef struct {
|
|||
ColorProfile *color_profile;
|
||||
monotonic_t start_visual_bell_at;
|
||||
|
||||
uint32_t parser_buf[8*1024];
|
||||
unsigned int parser_state, parser_text_start, parser_buf_pos;
|
||||
bool parser_has_pending_text;
|
||||
uint8_t read_buf[READ_BUF_SZ], *write_buf;
|
||||
monotonic_t new_input_at;
|
||||
size_t read_buf_sz, write_buf_sz, write_buf_used;
|
||||
|
|
@ -167,6 +158,7 @@ typedef struct {
|
|||
struct {
|
||||
uint8_t stack[16], count;
|
||||
} main_pointer_shape_stack, alternate_pointer_shape_stack;
|
||||
Parser *vt_parser;
|
||||
} Screen;
|
||||
|
||||
|
||||
|
|
@ -221,26 +213,21 @@ void screen_repeat_character(Screen *self, unsigned int count);
|
|||
void screen_delete_characters(Screen *self, unsigned int count);
|
||||
void screen_erase_characters(Screen *self, unsigned int count);
|
||||
void screen_set_margins(Screen *self, unsigned int top, unsigned int bottom);
|
||||
void screen_change_charset(Screen *, uint32_t to);
|
||||
void screen_handle_cmd(Screen *, PyObject *cmd);
|
||||
void screen_push_colors(Screen *, unsigned int);
|
||||
void screen_pop_colors(Screen *, unsigned int);
|
||||
void screen_report_color_stack(Screen *);
|
||||
void screen_handle_kitty_dcs(Screen *, const char *callback_name, PyObject *cmd);
|
||||
void screen_designate_charset(Screen *, uint32_t which, uint32_t as);
|
||||
void screen_use_latin1(Screen *, bool);
|
||||
void set_title(Screen *self, PyObject*);
|
||||
void desktop_notify(Screen *self, unsigned int, PyObject*);
|
||||
void set_icon(Screen *self, PyObject*);
|
||||
void set_dynamic_color(Screen *self, unsigned int code, PyObject*);
|
||||
void clipboard_control(Screen *self, int code, PyObject*);
|
||||
void shell_prompt_marking(Screen *self, PyObject*);
|
||||
void shell_prompt_marking(Screen *self, char *buf);
|
||||
void file_transmission(Screen *self, PyObject*);
|
||||
void set_color_table_color(Screen *self, unsigned int code, PyObject*);
|
||||
void process_cwd_notification(Screen *self, unsigned int code, PyObject*);
|
||||
uint32_t* translation_table(uint32_t which);
|
||||
void screen_request_capabilities(Screen *, char, PyObject *);
|
||||
void screen_set_8bit_controls(Screen *, bool);
|
||||
void screen_request_capabilities(Screen *, char, const char *);
|
||||
void report_device_attributes(Screen *self, unsigned int UNUSED mode, char start_modifier);
|
||||
void select_graphic_rendition(Screen *self, int *params, unsigned int count, Region*);
|
||||
void report_device_status(Screen *self, unsigned int which, bool UNUSED);
|
||||
|
|
@ -285,6 +272,7 @@ int screen_cursor_at_a_shell_prompt(const Screen *);
|
|||
bool screen_fake_move_cursor_to_position(Screen *, index_type x, index_type y);
|
||||
bool screen_send_signal_for_key(Screen *, char key);
|
||||
bool get_line_edge_colors(Screen *self, color_type *left, color_type *right);
|
||||
void parse_sgr(Screen *screen, const uint8_t *buf, unsigned int num, int *params, const char *report_name, Region *region);
|
||||
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
|
||||
DECLARE_CH_SCREEN_HANDLER(bell)
|
||||
DECLARE_CH_SCREEN_HANDLER(backspace)
|
||||
|
|
|
|||
1302
kitty/vt-parser.c
1302
kitty/vt-parser.c
File diff suppressed because it is too large
Load diff
|
|
@ -17,6 +17,6 @@ typedef struct Parser {
|
|||
} Parser;
|
||||
|
||||
|
||||
Parser* alloc_parser(id_type window_id);
|
||||
void parse_vte(Parser*);
|
||||
void parse_vte_dump(Parser*);
|
||||
Parser* alloc_vt_parser(id_type window_id);
|
||||
void free_vt_parser(Parser*);
|
||||
void reset_vt_parser(Parser*);
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@
|
|||
CURSOR_BEAM,
|
||||
CURSOR_BLOCK,
|
||||
CURSOR_UNDERLINE,
|
||||
DCS,
|
||||
ESC_DCS,
|
||||
ESC_OSC,
|
||||
GLFW_MOD_CONTROL,
|
||||
GLFW_PRESS,
|
||||
GLFW_RELEASE,
|
||||
GLFW_REPEAT,
|
||||
NO_CURSOR_SHAPE,
|
||||
OSC,
|
||||
SCROLL_FULL,
|
||||
SCROLL_LINE,
|
||||
SCROLL_PAGE,
|
||||
|
|
@ -190,14 +190,16 @@ def modify_argv_for_launch_with_cwd(self, argv: List[str], env: Optional[Dict[st
|
|||
return window.get_cwd_of_child(oldest=self.request_type is CwdRequestType.oldest) or ''
|
||||
|
||||
|
||||
def process_title_from_child(title: str, is_base64: bool) -> str:
|
||||
def process_title_from_child(title: memoryview, is_base64: bool, default_title: str) -> str:
|
||||
if is_base64:
|
||||
from base64 import standard_b64decode
|
||||
try:
|
||||
title = standard_b64decode(title).decode('utf-8', 'replace')
|
||||
stitle = standard_b64decode(title).decode('utf-8', 'replace')
|
||||
except Exception:
|
||||
title = 'undecodeable title'
|
||||
return sanitize_title(title)
|
||||
stitle = 'undecodeable title'
|
||||
else:
|
||||
stitle = str(title, 'utf-8', 'replace')
|
||||
return sanitize_title(stitle or default_title)
|
||||
|
||||
|
||||
@lru_cache(maxsize=64)
|
||||
|
|
@ -446,7 +448,7 @@ def cmd_output(screen: Screen, which: CommandOutput = CommandOutput.last_run, as
|
|||
return ''.join(lines)
|
||||
|
||||
|
||||
def process_remote_print(msg: str) -> str:
|
||||
def process_remote_print(msg: memoryview) -> str:
|
||||
from base64 import standard_b64decode
|
||||
|
||||
from .cli import green
|
||||
|
|
@ -1004,7 +1006,8 @@ def osc_1337(self, raw_data: str) -> None:
|
|||
ukey, has_equal, uval = val.partition('=')
|
||||
self.set_user_var(ukey, (base64_decode(uval) if uval else b'') if has_equal == '=' else None)
|
||||
|
||||
def desktop_notify(self, osc_code: int, raw_data: str) -> None:
|
||||
def desktop_notify(self, osc_code: int, raw_datab: memoryview) -> None:
|
||||
raw_data = str(raw_datab, 'utf-8', 'replace')
|
||||
if osc_code == 1337:
|
||||
self.osc_1337(raw_data)
|
||||
if osc_code == 777:
|
||||
|
|
@ -1016,9 +1019,6 @@ def desktop_notify(self, osc_code: int, raw_data: str) -> None:
|
|||
if cmd is not None and osc_code == 99:
|
||||
self.prev_osc99_cmd = cmd
|
||||
|
||||
def use_utf8(self, on: bool) -> None:
|
||||
get_boss().child_monitor.set_iutf8_winid(self.id, on)
|
||||
|
||||
def on_mouse_event(self, event: Dict[str, Any]) -> bool:
|
||||
event['mods'] = event.get('mods', 0) & mod_mask
|
||||
ev = MouseEvent(**event)
|
||||
|
|
@ -1119,13 +1119,13 @@ def focus_changed(self, focused: bool) -> None:
|
|||
# Cancel IME composition after loses focus
|
||||
update_ime_position_for_window(self.id, False, -1)
|
||||
|
||||
def title_changed(self, new_title: Optional[str], is_base64: bool = False) -> None:
|
||||
self.child_title = process_title_from_child(new_title or self.default_title, is_base64)
|
||||
def title_changed(self, new_title: Optional[memoryview], is_base64: bool = False) -> None:
|
||||
self.child_title = process_title_from_child(new_title or memoryview(b''), is_base64, self.default_title)
|
||||
self.call_watchers(self.watchers.on_title_change, {'title': self.child_title, 'from_child': True})
|
||||
if self.override_title is None:
|
||||
self.title_updated()
|
||||
|
||||
def icon_changed(self, new_icon: object) -> None:
|
||||
def icon_changed(self, new_icon: memoryview) -> None:
|
||||
pass # TODO: Implement this
|
||||
|
||||
@property
|
||||
|
|
@ -1190,20 +1190,20 @@ def report_color(self, code: str, r: int, g: int, b: int) -> None:
|
|||
r |= r << 8
|
||||
g |= g << 8
|
||||
b |= b << 8
|
||||
self.screen.send_escape_code_to_child(OSC, f'{code};rgb:{r:04x}/{g:04x}/{b:04x}')
|
||||
self.screen.send_escape_code_to_child(ESC_OSC, f'{code};rgb:{r:04x}/{g:04x}/{b:04x}')
|
||||
|
||||
def report_notification_activated(self, identifier: str) -> None:
|
||||
identifier = sanitize_identifier_pat().sub('', identifier)
|
||||
self.screen.send_escape_code_to_child(OSC, f'99;i={identifier};')
|
||||
self.screen.send_escape_code_to_child(ESC_OSC, f'99;i={identifier};')
|
||||
|
||||
|
||||
def set_dynamic_color(self, code: int, value: Union[str, bytes]) -> None:
|
||||
if isinstance(value, bytes):
|
||||
value = value.decode('utf-8')
|
||||
def set_dynamic_color(self, code: int, value: Union[str, bytes, memoryview] = '') -> None:
|
||||
if isinstance(value, (bytes, memoryview)):
|
||||
value = str(value, 'utf-8', 'replace')
|
||||
if code == 22:
|
||||
ret = set_pointer_shape(self.screen, value, self.os_window_id)
|
||||
if ret:
|
||||
self.screen.send_escape_code_to_child(OSC, '22:' + ret)
|
||||
self.screen.send_escape_code_to_child(ESC_OSC, '22:' + ret)
|
||||
color_changes: Dict[DynamicColor, Optional[str]] = {}
|
||||
for val in value.split(';'):
|
||||
w = DYNAMIC_COLOR_CODES.get(code)
|
||||
|
|
@ -1218,7 +1218,8 @@ def set_dynamic_color(self, code: int, value: Union[str, bytes]) -> None:
|
|||
if color_changes:
|
||||
self.change_colors(color_changes)
|
||||
|
||||
def set_color_table_color(self, code: int, value: str) -> None:
|
||||
def set_color_table_color(self, code: int, bvalue: Optional[memoryview] = None) -> None:
|
||||
value = str(bvalue or b'', 'utf-8', 'replace')
|
||||
cp = self.screen.color_profile
|
||||
if code == 4:
|
||||
changed = False
|
||||
|
|
@ -1247,12 +1248,12 @@ def set_color_table_color(self, code: int, value: str) -> None:
|
|||
|
||||
def request_capabilities(self, q: str) -> None:
|
||||
for result in get_capabilities(q, get_options()):
|
||||
self.screen.send_escape_code_to_child(DCS, result)
|
||||
self.screen.send_escape_code_to_child(ESC_DCS, result)
|
||||
|
||||
def handle_remote_cmd(self, cmd: str) -> None:
|
||||
def handle_remote_cmd(self, cmd: memoryview) -> None:
|
||||
get_boss().handle_remote_cmd(cmd, self)
|
||||
|
||||
def handle_remote_echo(self, msg: str) -> None:
|
||||
def handle_remote_echo(self, msg: memoryview) -> None:
|
||||
from base64 import standard_b64decode
|
||||
data = standard_b64decode(msg)
|
||||
# ensure we are not writing any control char back as this can lead to command injection on shell prompts
|
||||
|
|
@ -1260,12 +1261,12 @@ def handle_remote_echo(self, msg: str) -> None:
|
|||
data = re.sub(rb'[^ -~]', b'', data)
|
||||
self.write_to_child(data)
|
||||
|
||||
def handle_remote_ssh(self, msg: str) -> None:
|
||||
def handle_remote_ssh(self, msg: memoryview) -> None:
|
||||
from kittens.ssh.utils import get_ssh_data
|
||||
for line in get_ssh_data(msg, f'{os.getpid()}-{self.id}'):
|
||||
self.write_to_child(line)
|
||||
|
||||
def handle_kitten_result(self, msg: str) -> None:
|
||||
def handle_kitten_result(self, msg: memoryview) -> None:
|
||||
import base64
|
||||
self.kitten_result = json.loads(base64.b85decode(msg))
|
||||
for processor in self.kitten_result_processors:
|
||||
|
|
@ -1278,17 +1279,18 @@ def handle_kitten_result(self, msg: str) -> None:
|
|||
def add_kitten_result_processor(self, callback: Callable[['Window', Any], None]) -> None:
|
||||
self.kitten_result_processors.append(callback)
|
||||
|
||||
def handle_overlay_ready(self, msg: str) -> None:
|
||||
def handle_overlay_ready(self, msg: memoryview) -> None:
|
||||
boss = get_boss()
|
||||
tab = boss.tab_for_window(self)
|
||||
if tab is not None:
|
||||
tab.move_window_to_top_of_group(self)
|
||||
|
||||
def append_remote_data(self, msg: str) -> str:
|
||||
if not msg:
|
||||
def append_remote_data(self, msgb: memoryview) -> str:
|
||||
if not msgb:
|
||||
cdata = ''.join(self.current_remote_data)
|
||||
self.current_remote_data = []
|
||||
return cdata
|
||||
msg = str(msgb, 'utf-8', 'replace')
|
||||
num, rest = msg.split(':', 1)
|
||||
max_size = get_options().clipboard_max_size * 1024 * 1024
|
||||
if num == '0' or sum(map(len, self.current_remote_data)) > max_size:
|
||||
|
|
@ -1296,13 +1298,13 @@ def append_remote_data(self, msg: str) -> str:
|
|||
self.current_remote_data.append(rest)
|
||||
return ''
|
||||
|
||||
def handle_remote_edit(self, msg: str) -> None:
|
||||
def handle_remote_edit(self, msg: memoryview) -> None:
|
||||
cdata = self.append_remote_data(msg)
|
||||
if cdata:
|
||||
from .launch import remote_edit
|
||||
remote_edit(cdata, self)
|
||||
|
||||
def handle_remote_clone(self, msg: str) -> None:
|
||||
def handle_remote_clone(self, msg: memoryview) -> None:
|
||||
cdata = self.append_remote_data(msg)
|
||||
if cdata:
|
||||
ac = get_options().allow_cloning
|
||||
|
|
@ -1321,8 +1323,9 @@ def handle_remote_clone_confirmation(self, cdata: str, confirmed: bool) -> None:
|
|||
from .launch import clone_and_launch
|
||||
clone_and_launch(cdata, self)
|
||||
|
||||
def handle_remote_askpass(self, msg: str) -> None:
|
||||
def handle_remote_askpass(self, msgb: memoryview) -> None:
|
||||
from .shm import SharedMemory
|
||||
msg = str(msgb, 'utf-8')
|
||||
with SharedMemory(name=msg, readonly=True) as shm:
|
||||
shm.seek(1)
|
||||
data = json.loads(shm.read_data_with_size())
|
||||
|
|
@ -1350,17 +1353,17 @@ def callback(ans: Any) -> None:
|
|||
else:
|
||||
log_error(f'Ignoring ask request with unknown type: {data["type"]}')
|
||||
|
||||
def handle_remote_print(self, msg: str) -> None:
|
||||
def handle_remote_print(self, msg: memoryview) -> None:
|
||||
text = process_remote_print(msg)
|
||||
print(text, end='', flush=True)
|
||||
|
||||
def send_cmd_response(self, response: Any) -> None:
|
||||
self.screen.send_escape_code_to_child(DCS, '@kitty-cmd' + json.dumps(response))
|
||||
self.screen.send_escape_code_to_child(ESC_DCS, '@kitty-cmd' + json.dumps(response))
|
||||
|
||||
def file_transmission(self, data: str) -> None:
|
||||
def file_transmission(self, data: memoryview) -> None:
|
||||
self.file_transmission_control.handle_serialized_command(data)
|
||||
|
||||
def clipboard_control(self, data: str, is_partial: Optional[bool] = False) -> None:
|
||||
def clipboard_control(self, data: memoryview, is_partial: Optional[bool] = False) -> None:
|
||||
if is_partial is None:
|
||||
self.clipboard_request_manager.parse_osc_5522(data)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from kitty.config import finalize_keys, finalize_mouse_mappings
|
||||
from kitty.fast_data_types import Cursor, HistoryBuf, LineBuf, Screen, get_options, parse_bytes, set_options
|
||||
from kitty.fast_data_types import Cursor, HistoryBuf, LineBuf, Screen, get_options, set_options
|
||||
from kitty.options.parse import merge_result_dicts
|
||||
from kitty.options.types import Options, defaults
|
||||
from kitty.types import MouseEvent
|
||||
|
|
@ -323,7 +323,7 @@ def process_input_from_child(self, timeout=10):
|
|||
break
|
||||
bytes_read += len(data)
|
||||
self.received_bytes += data
|
||||
parse_bytes(self.screen, data)
|
||||
self.screen.vt_parser.parse_bytes(self.screen, data)
|
||||
return bytes_read
|
||||
|
||||
def wait_till(self, q, timeout=10):
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -614,8 +614,6 @@ def get_vcs_rev() -> str:
|
|||
|
||||
|
||||
def get_source_specific_defines(env: Env, src: str) -> Tuple[str, Optional[List[str]]]:
|
||||
if src == 'kitty/parser_dump.c':
|
||||
return 'kitty/parser.c', ['DUMP_COMMANDS']
|
||||
if src == 'kitty/vt-parser-dump.c':
|
||||
return 'kitty/vt-parser.c', ['DUMP_COMMANDS']
|
||||
if src == 'kitty/data-types.c':
|
||||
|
|
@ -770,7 +768,6 @@ def find_c_files() -> Tuple[List[str], List[str]]:
|
|||
ans.append(os.path.join('kitty', x))
|
||||
elif ext == '.h':
|
||||
headers.append(os.path.join('kitty', x))
|
||||
ans.append('kitty/parser_dump.c')
|
||||
ans.append('kitty/vt-parser-dump.c')
|
||||
return ans, headers
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue