mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-11 14:45:31 +03:00
Support S8C1T mode
That is, eight bit control codes. When in S8C1T mode, kitty will send only eight bit control codes to the client.
This commit is contained in:
parent
ed9b332da5
commit
c17c6cae4c
@ -9,14 +9,13 @@
|
||||
from .config import MINIMUM_FONT_SIZE, cached_values, initial_window_size
|
||||
from .constants import set_boss, wakeup
|
||||
from .fast_data_types import (
|
||||
GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, create_os_window,
|
||||
current_os_window, destroy_global_data, destroy_sprite_map,
|
||||
get_clipboard_string, glfw_post_empty_event, layout_sprite_map,
|
||||
mark_os_window_for_close, show_window, toggle_fullscreen,
|
||||
viewport_for_window
|
||||
ChildMonitor, create_os_window, current_os_window, destroy_global_data,
|
||||
destroy_sprite_map, get_clipboard_string, glfw_post_empty_event,
|
||||
layout_sprite_map, mark_os_window_for_close, show_window,
|
||||
toggle_fullscreen, viewport_for_window
|
||||
)
|
||||
from .fonts.render import prerender, resize_fonts, set_font_family
|
||||
from .keys import get_key_map, get_shortcut
|
||||
from .keys import get_shortcut
|
||||
from .session import create_session
|
||||
from .tabs import SpecialWindow, TabManager
|
||||
from .utils import (
|
||||
@ -288,12 +287,6 @@ def switch_focus_to(self, window_idx):
|
||||
old_focus.focus_changed(False)
|
||||
tab.active_window.focus_changed(True)
|
||||
|
||||
def send_fake_scroll(self, window_idx, amt, upwards):
|
||||
tab = self.active_tab
|
||||
w = tab.windows[window_idx]
|
||||
k = get_key_map(w.screen)[GLFW_KEY_UP if upwards else GLFW_KEY_DOWN]
|
||||
w.write_to_child(k * amt)
|
||||
|
||||
def open_url(self, url):
|
||||
if url:
|
||||
open_url(url, self.opts.open_url_with)
|
||||
|
@ -151,10 +151,10 @@ decoration_as_sgr(uint8_t decoration) {
|
||||
|
||||
const char*
|
||||
cursor_as_sgr(Cursor *self, Cursor *prev) {
|
||||
static char buf[128], *p;
|
||||
static char buf[128];
|
||||
#define SZ sizeof(buf) - (p - buf) - 2
|
||||
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
|
||||
p = buf;
|
||||
char *p = buf;
|
||||
if (self->bold != prev->bold) P("%d", self->bold ? 1 : 22);
|
||||
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
|
||||
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
#include "data-types.h"
|
||||
#include "control-codes.h"
|
||||
#include "modes.h"
|
||||
#include <stddef.h>
|
||||
#include <termios.h>
|
||||
@ -229,8 +230,6 @@ PyInit_fast_data_types(void) {
|
||||
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
||||
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
||||
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
|
||||
PyModule_AddStringMacro(m, BRACKETED_PASTE_START);
|
||||
PyModule_AddStringMacro(m, BRACKETED_PASTE_END);
|
||||
PyModule_AddStringMacro(m, ERROR_PREFIX);
|
||||
PyModule_AddIntMacro(m, CURSOR_BLOCK);
|
||||
PyModule_AddIntMacro(m, CURSOR_BEAM);
|
||||
@ -239,6 +238,10 @@ 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);
|
||||
}
|
||||
|
||||
return m;
|
||||
|
@ -270,6 +270,7 @@ void change_wcwidth(bool use9);
|
||||
void set_mouse_cursor(MouseShape);
|
||||
void mouse_event(int, int);
|
||||
void scroll_event(double, double);
|
||||
void fake_scroll(bool);
|
||||
void set_special_key_combo(int glfw_key, int mods);
|
||||
void on_text_input(unsigned int codepoint, int mods);
|
||||
void on_key_input(int key, int scancode, int action, int mods);
|
||||
|
@ -515,7 +515,7 @@ create_add_response(GraphicsManager UNUSED *self, bool data_loaded, uint32_t iid
|
||||
if (!data_loaded) return NULL;
|
||||
snprintf(add_response, 10, "OK");
|
||||
}
|
||||
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "\033_Gi=%u;%s\033\\", iid, add_response);
|
||||
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "Gi=%u;%s", iid, add_response);
|
||||
return rbuf;
|
||||
}
|
||||
return NULL;
|
||||
|
23
kitty/keys.c
23
kitty/keys.c
@ -9,6 +9,7 @@
|
||||
#include "state.h"
|
||||
#include "screen.h"
|
||||
#include "glfw-wrapper.h"
|
||||
#include "control-codes.h"
|
||||
|
||||
const char*
|
||||
key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) {
|
||||
@ -133,6 +134,16 @@ get_localized_key(int key, int scancode) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
send_key_to_child(Window *w, int key, int mods, int action) {
|
||||
Screen *screen = w->render_data.screen;
|
||||
const char *data = key_to_bytes(key, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
||||
if (data) {
|
||||
if (screen->modes.mEXTENDED_KEYBOARD) write_escape_code_to_child(screen, APC, data + 1);
|
||||
else schedule_write_to_child(w->id, (data + 1), *data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_key_input(int key, int scancode, int action, int mods) {
|
||||
Window *w = active_window();
|
||||
@ -168,11 +179,19 @@ on_key_input(int key, int scancode, int action, int mods) {
|
||||
(action == GLFW_REPEAT && screen->modes.mDECARM) ||
|
||||
screen->modes.mEXTENDED_KEYBOARD
|
||||
) {
|
||||
const char *data = key_to_bytes(lkey, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
||||
if (data) schedule_write_to_child(w->id, (data + 1), *data);
|
||||
send_key_to_child(w, lkey, mods, action);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fake_scroll(bool upwards) {
|
||||
Window *w = active_window();
|
||||
if (!w) return;
|
||||
Screen *screen = w->render_data.screen;
|
||||
send_key_to_child(w, upwards ? GLFW_KEY_UP : GLFW_KEY_DOWN, 0, GLFW_PRESS);
|
||||
if (screen->modes.mEXTENDED_KEYBOARD) send_key_to_child(w, upwards ? GLFW_KEY_UP : GLFW_KEY_DOWN, 0, GLFW_RELEASE);
|
||||
}
|
||||
|
||||
#define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
|
||||
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
||||
#define M(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
||||
|
11124
kitty/keys.h
generated
11124
kitty/keys.h
generated
File diff suppressed because it is too large
Load Diff
@ -144,7 +144,7 @@ def extended_key_event(key, mods, action):
|
||||
m |= 0x4
|
||||
if mods & defines.GLFW_MOD_SUPER:
|
||||
m |= 0x8
|
||||
return '\033_K{}{}{}\033\\'.format(
|
||||
return 'K{}{}{}'.format(
|
||||
action_map[action], base64_encode(m), name
|
||||
).encode('ascii')
|
||||
|
||||
|
@ -73,8 +73,8 @@
|
||||
// Bracketed paste mode
|
||||
// http://cirw.in/blog/bracketed-paste
|
||||
#define BRACKETED_PASTE (2004 << 5)
|
||||
#define BRACKETED_PASTE_START "\033[200~"
|
||||
#define BRACKETED_PASTE_END "\033[201~"
|
||||
#define BRACKETED_PASTE_START "200~"
|
||||
#define BRACKETED_PASTE_END "201~"
|
||||
|
||||
// Styled underlines
|
||||
#define STYLED_UNDERLINES (2016 << 5)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include "glfw-wrapper.h"
|
||||
#include "control-codes.h"
|
||||
|
||||
static MouseShape mouse_cursor_shape = BEAM;
|
||||
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
||||
@ -41,7 +42,7 @@ button_map(int button) {
|
||||
|
||||
static char mouse_event_buf[64];
|
||||
|
||||
size_t
|
||||
int
|
||||
encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
||||
unsigned int x = w->mouse_cell_x + 1, y = w->mouse_cell_y + 1; // 1 based indexing
|
||||
unsigned int cb = 0;
|
||||
@ -60,14 +61,14 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
||||
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
|
||||
switch(screen->modes.mouse_tracking_protocol) {
|
||||
case SGR_PROTOCOL:
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
|
||||
break;
|
||||
case URXVT_PROTOCOL:
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[%d;%d;%dM", cb + 32, x, y);
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "%d;%d;%dM", cb + 32, x, y);
|
||||
break;
|
||||
case UTF8_PROTOCOL:
|
||||
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32;
|
||||
unsigned int sz = 4;
|
||||
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32;
|
||||
unsigned int sz = 2;
|
||||
sz += encode_utf8(x + 32, mouse_event_buf + sz);
|
||||
sz += encode_utf8(y + 32, mouse_event_buf + sz);
|
||||
return sz;
|
||||
@ -75,8 +76,8 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
||||
default:
|
||||
if (x > 223 || y > 223) return 0;
|
||||
else {
|
||||
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32; mouse_event_buf[4] = x + 32; mouse_event_buf[5] = y + 32;
|
||||
return 6;
|
||||
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32; mouse_event_buf[2] = x + 32; mouse_event_buf[3] = y + 32;
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -190,8 +191,8 @@ HANDLER(handle_move_event) {
|
||||
}
|
||||
} else {
|
||||
if (!mouse_cell_changed) return;
|
||||
size_t sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0);
|
||||
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
|
||||
int sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,8 +280,8 @@ HANDLER(handle_button_event) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
size_t sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers);
|
||||
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
|
||||
int sz = encode_mouse_event(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); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,10 +355,10 @@ scroll_event(double UNUSED xoffset, double yoffset) {
|
||||
screen_history_scroll(screen, abs(s), upwards);
|
||||
} else {
|
||||
if (screen->modes.mouse_tracking_mode) {
|
||||
size_t sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
|
||||
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
|
||||
int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
} else {
|
||||
call_boss(send_fake_scroll, "IiO", window_idx, abs(s), upwards ? Py_True : Py_False);
|
||||
fake_scroll(upwards);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,6 +276,16 @@ handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_cal
|
||||
REPORT_ERROR("Unknown charset: 0x%x", ch); break;
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
switch(ch) {
|
||||
case 'F':
|
||||
case 'G':
|
||||
REPORT_COMMAND(screen_set_8bit_controls, ch == 'G');
|
||||
screen_set_8bit_controls(screen, ch == 'G');
|
||||
break;
|
||||
}
|
||||
REPORT_ERROR("Unhandled ESC SP escape code: 0x%x", ch); break;
|
||||
break;
|
||||
default:
|
||||
REPORT_ERROR("Unhandled charset related escape code: 0x%x 0x%x", screen->parser_buf[0], ch); break;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "unicode-data.h"
|
||||
#include "modes.h"
|
||||
#include "wcwidth9.h"
|
||||
#include "control-codes.h"
|
||||
|
||||
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
|
||||
static Selection EMPTY_SELECTION = {0};
|
||||
@ -104,9 +105,9 @@ screen_reset(Screen *self) {
|
||||
linebuf_clear(self->linebuf, BLANK_CHAR);
|
||||
grman_clear(self->grman);
|
||||
self->modes = empty_modes;
|
||||
#define RC(name) self->color_profile->overridden.name = 0
|
||||
RC(default_fg); RC(default_bg); RC(cursor_color); RC(highlight_fg); RC(highlight_bg);
|
||||
#undef RC
|
||||
#define R(name) self->color_profile->overridden.name = 0
|
||||
R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg);
|
||||
#undef R
|
||||
RESET_CHARSETS;
|
||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||
screen_normal_keypad_mode(self);
|
||||
@ -355,13 +356,37 @@ write_to_child(Screen *self, const char *data, size_t sz) {
|
||||
if (self->test_child != Py_None) { PyObject *r = PyObject_CallMethod(self->test_child, "write", "y#", data, sz); if (r == NULL) PyErr_Print(); Py_CLEAR(r); }
|
||||
}
|
||||
|
||||
#define write_str_to_child(s) write_to_child(self, (s), sizeof((s)) - 1)
|
||||
void
|
||||
write_escape_code_to_child(Screen *self, unsigned char which, const char *data) {
|
||||
static char buf[512];
|
||||
size_t sz;
|
||||
switch(which) {
|
||||
case DCS:
|
||||
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x90" : "\033P", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
|
||||
break;
|
||||
case CSI:
|
||||
sz = snprintf(buf, sizeof(buf) - 1, "%s%s", self->modes.eight_bit_controls ? "\x9b" : "\033[", data);
|
||||
break;
|
||||
case OSC:
|
||||
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9d" : "\033]", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
|
||||
break;
|
||||
case PM:
|
||||
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9e" : "\033^", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
|
||||
break;
|
||||
case APC:
|
||||
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9f" : "\033_", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
|
||||
break;
|
||||
default:
|
||||
fatal("Unknown escape code to write: %u", which);
|
||||
}
|
||||
write_to_child(self, buf, sz);
|
||||
}
|
||||
|
||||
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);
|
||||
if (response != NULL) write_to_child(self, response, strlen(response));
|
||||
if (response != NULL) write_escape_code_to_child(self, APC, response);
|
||||
if (x != self->cursor->x || y != self->cursor->y) {
|
||||
if (self->cursor->x >= self->columns) { self->cursor->x = 0; self->cursor->y++; }
|
||||
if (self->cursor->y > self->margin_bottom) screen_scroll(self, self->cursor->y - self->margin_bottom);
|
||||
@ -470,14 +495,20 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
||||
#undef MOUSE_MODE
|
||||
}
|
||||
|
||||
void screen_set_mode(Screen *self, unsigned int mode) {
|
||||
void
|
||||
screen_set_mode(Screen *self, unsigned int mode) {
|
||||
set_mode_from_const(self, mode, true);
|
||||
}
|
||||
|
||||
void screen_reset_mode(Screen *self, unsigned int mode) {
|
||||
void
|
||||
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;
|
||||
}
|
||||
// }}}
|
||||
|
||||
// Cursor {{{
|
||||
@ -944,10 +975,10 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
||||
if (mode == 0) {
|
||||
switch(start_modifier) {
|
||||
case 0:
|
||||
write_str_to_child("\x1b[?62;c"); // VT-220 with no extra info
|
||||
write_escape_code_to_child(self, CSI, "?62;c");
|
||||
break;
|
||||
case '>':
|
||||
write_str_to_child("\x1b[>1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
|
||||
write_escape_code_to_child(self, CSI, ">1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -958,10 +989,10 @@ report_device_status(Screen *self, unsigned int which, bool private) {
|
||||
// We dont implement the private device status codes, since I haven't come
|
||||
// across any programs that use them
|
||||
unsigned int x, y;
|
||||
static char buf[50];
|
||||
static char buf[64];
|
||||
switch(which) {
|
||||
case 5: // device status
|
||||
write_str_to_child("\x1b[0n");
|
||||
write_escape_code_to_child(self, CSI, "0n");
|
||||
break;
|
||||
case 6: // cursor position
|
||||
x = self->cursor->x; y = self->cursor->y;
|
||||
@ -971,8 +1002,8 @@ 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, "\x1b[%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
|
||||
if (sz > 0) write_to_child(self, buf, sz);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1002,8 +1033,8 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
|
||||
case STYLED_UNDERLINES:
|
||||
ans = 3; break;
|
||||
}
|
||||
int sz = snprintf(buf, sizeof(buf) - 1, "\x1b[%s%u;%u$y", (private ? "?" : ""), which, ans);
|
||||
if (sz > 0) write_to_child(self, buf, sz);
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1093,16 +1124,16 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
||||
case CURSOR_BEAM:
|
||||
shape = self->cursor->blink ? 5 : 6; break;
|
||||
}
|
||||
shape = snprintf(buf, sizeof(buf), "\033P1$r%d q\033\\", shape);
|
||||
shape = snprintf(buf, sizeof(buf), "1$r%d q", shape);
|
||||
} else if (strcmp("m", query) == 0) {
|
||||
// SGR
|
||||
shape = snprintf(buf, sizeof(buf), "\033P1$r%sm\033\\", cursor_as_sgr(self->cursor, &blank_cursor));
|
||||
shape = snprintf(buf, sizeof(buf), "1$r%sm", cursor_as_sgr(self->cursor, &blank_cursor));
|
||||
} else if (strcmp("r", query) == 0) {
|
||||
shape = snprintf(buf, sizeof(buf), "\033P1$r%u;%ur\033\\", self->margin_top + 1, self->margin_bottom + 1);
|
||||
shape = snprintf(buf, sizeof(buf), "1$r%u;%ur", self->margin_top + 1, self->margin_bottom + 1);
|
||||
} else {
|
||||
shape = snprintf(buf, sizeof(buf), "\033P0$r%s\033\\", query);
|
||||
shape = snprintf(buf, sizeof(buf), "0$r%s", query);
|
||||
}
|
||||
if (shape) write_to_child(self, buf, shape);
|
||||
if (shape > 0) write_escape_code_to_child(self, DCS, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1523,6 +1554,23 @@ toggle_alt_screen(Screen *self) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
send_escape_code_to_child(Screen *self, PyObject *args) {
|
||||
int code;
|
||||
char *text;
|
||||
if (!PyArg_ParseTuple(args, "is", &code, &text)) return NULL;
|
||||
write_escape_code_to_child(self, code, text);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
paste(Screen *self, PyObject *bytes) {
|
||||
if (self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_START);
|
||||
write_to_child(self, PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
|
||||
if (self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_END);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
WRAP2(cursor_position, 1, 1)
|
||||
|
||||
#define COUNT_WRAP(name) WRAP1(name, 1)
|
||||
@ -1580,8 +1628,10 @@ static PyMethodDef methods[] = {
|
||||
MND(rescale_images, METH_VARARGS)
|
||||
MND(text_for_selection, METH_NOARGS)
|
||||
MND(scroll, METH_VARARGS)
|
||||
MND(send_escape_code_to_child, METH_VARARGS)
|
||||
MND(toggle_alt_screen, METH_NOARGS)
|
||||
MND(reset_callbacks, METH_NOARGS)
|
||||
MND(paste, METH_O)
|
||||
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
|
@ -15,6 +15,7 @@ typedef struct {
|
||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
||||
MouseTrackingMode mouse_tracking_mode;
|
||||
MouseTrackingProtocol mouse_tracking_protocol;
|
||||
bool eight_bit_controls; // S8C1T
|
||||
} ScreenModes;
|
||||
|
||||
typedef struct {
|
||||
@ -66,6 +67,7 @@ void parse_worker_dump(Screen *screen, PyObject *dump_callback);
|
||||
void screen_align(Screen*);
|
||||
void screen_restore_cursor(Screen *);
|
||||
void screen_save_cursor(Screen *);
|
||||
void write_escape_code_to_child(Screen *self, unsigned char which, const char *data);
|
||||
void screen_cursor_position(Screen*, unsigned int, unsigned int);
|
||||
void screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/);
|
||||
void screen_erase_in_line(Screen *, unsigned int, bool);
|
||||
@ -111,6 +113,7 @@ void set_dynamic_color(Screen *self, unsigned int code, PyObject*);
|
||||
void set_color_table_color(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 report_device_attributes(Screen *self, unsigned int UNUSED mode, char start_modifier);
|
||||
void select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count);
|
||||
void report_device_status(Screen *self, unsigned int which, bool UNUSED);
|
||||
|
@ -452,6 +452,6 @@ def get_capabilities(query_string):
|
||||
if qname in string_capabilities and '%' not in val:
|
||||
val = key_as_bytes(qname).decode('ascii')
|
||||
ans.append(q + '=' + hexlify(str(val).encode('utf-8')).decode('ascii'))
|
||||
return b'\033P1+r' + ';'.join(ans).encode('utf-8') + b'\033\\'
|
||||
return '1+r' + ';'.join(ans)
|
||||
except Exception:
|
||||
return b'\033P0+r' + query_string.encode('utf-8') + b'\033\\'
|
||||
return '0+r' + query_string
|
||||
|
@ -12,13 +12,12 @@
|
||||
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
||||
)
|
||||
from .fast_data_types import (
|
||||
BLIT_PROGRAM, BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BG_PROGRAM,
|
||||
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM,
|
||||
GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE,
|
||||
SCROLL_PAGE, Screen, add_window, compile_program, glfw_post_empty_event,
|
||||
init_cell_program, init_cursor_program, set_clipboard_string,
|
||||
set_window_render_data, update_window_title, update_window_visibility,
|
||||
viewport_for_window
|
||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
||||
CELL_SPECIAL_PROGRAM, CSI, CURSOR_PROGRAM, DCS, GRAPHICS_PREMULT_PROGRAM,
|
||||
GRAPHICS_PROGRAM, OSC, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
||||
add_window, compile_program, glfw_post_empty_event, init_cell_program,
|
||||
init_cursor_program, set_clipboard_string, set_window_render_data,
|
||||
update_window_title, update_window_visibility, viewport_for_window
|
||||
)
|
||||
from .keys import keyboard_mode_name
|
||||
from .rgb import to_color
|
||||
@ -171,10 +170,10 @@ def use_utf8(self, on):
|
||||
def focus_changed(self, focused):
|
||||
if focused:
|
||||
if self.screen.focus_tracking_enabled:
|
||||
self.write_to_child(b'\x1b[I')
|
||||
self.screen.send_escape_code_to_child(CSI, 'I')
|
||||
else:
|
||||
if self.screen.focus_tracking_enabled:
|
||||
self.write_to_child(b'\x1b[O')
|
||||
self.screen.send_escape_code_to_child(CSI, 'O')
|
||||
|
||||
def title_changed(self, new_title):
|
||||
if self.override_title is None:
|
||||
@ -206,11 +205,11 @@ def item(raw):
|
||||
if dirtied:
|
||||
self.screen.mark_as_dirty()
|
||||
|
||||
def report_color(self, osc, r, g, b):
|
||||
def report_color(self, code, r, g, b):
|
||||
r |= r << 8
|
||||
g |= g << 8
|
||||
b |= b << 8
|
||||
self.write_to_child('\033]{};rgb:{:04x}/{:04x}/{:04x}\033\\'.format(osc, r, g, b))
|
||||
self.screen.send_escape_code_to_child(OSC, '{};rgb:{:04x}/{:04x}/{:04x}'.format(code, r, g, b))
|
||||
|
||||
def set_dynamic_color(self, code, value):
|
||||
if isinstance(value, bytes):
|
||||
@ -257,7 +256,7 @@ def set_color_table_color(self, code, value):
|
||||
self.refresh()
|
||||
|
||||
def request_capabilities(self, q):
|
||||
self.write_to_child(get_capabilities(q))
|
||||
self.screen.send_escape_code_to_child(DCS, get_capabilities(q))
|
||||
|
||||
# }}}
|
||||
|
||||
@ -290,9 +289,8 @@ def paste(self, text):
|
||||
if isinstance(text, str):
|
||||
text = text.encode('utf-8')
|
||||
if self.screen.in_bracketed_paste_mode:
|
||||
bpe = BRACKETED_PASTE_END.encode('ascii')
|
||||
text = BRACKETED_PASTE_START.encode('ascii') + text.replace(bpe, b'') + bpe
|
||||
self.write_to_child(text)
|
||||
text = text.replace(b'\033[201~', b'')
|
||||
self.screen.paste(text)
|
||||
|
||||
def copy_to_clipboard(self):
|
||||
text = self.text_for_selection()
|
||||
|
@ -29,7 +29,8 @@ def set_color_table_color(self, code, data):
|
||||
|
||||
def request_capabilities(self, q):
|
||||
from kitty.terminfo import get_capabilities
|
||||
self.write(get_capabilities(q))
|
||||
c = get_capabilities(q)
|
||||
self.write(c.encode('ascii'))
|
||||
|
||||
def use_utf8(self, on):
|
||||
self.iutf8 = on
|
||||
|
@ -198,7 +198,7 @@ def test_dcs_codes(self):
|
||||
q = hexlify(b'kind').decode('ascii')
|
||||
pb('a\033P+q{}\x9cbcde'.format(q), 'a', ('screen_request_capabilities', 43, q), 'bcde')
|
||||
self.ae(str(s.line(0)), 'abcde')
|
||||
self.ae(c.wtcbuf, '\033P1+r{}={}\033\\'.format(q, '1b5b313b3242').encode('ascii'))
|
||||
self.ae(c.wtcbuf, '1+r{}={}'.format(q, '1b5b313b3242').encode('ascii'))
|
||||
c.clear()
|
||||
pb('\033P$q q\033\\', ('screen_request_capabilities', ord('$'), ' q'))
|
||||
self.ae(c.wtcbuf, b'\033P1$r1 q\033\\')
|
||||
|
Loading…
Reference in New Issue
Block a user