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 .cli import create_opts, parse_args
|
|||||||
from .config import MINIMUM_FONT_SIZE, cached_values, initial_window_size
|
from .config import MINIMUM_FONT_SIZE, cached_values, initial_window_size
|
||||||
from .constants import set_boss, wakeup
|
from .constants import set_boss, wakeup
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, create_os_window,
|
ChildMonitor, create_os_window, current_os_window, destroy_global_data,
|
||||||
current_os_window, destroy_global_data, destroy_sprite_map,
|
destroy_sprite_map, get_clipboard_string, glfw_post_empty_event,
|
||||||
get_clipboard_string, glfw_post_empty_event, layout_sprite_map,
|
layout_sprite_map, mark_os_window_for_close, show_window,
|
||||||
mark_os_window_for_close, show_window, toggle_fullscreen,
|
toggle_fullscreen, viewport_for_window
|
||||||
viewport_for_window
|
|
||||||
)
|
)
|
||||||
from .fonts.render import prerender, resize_fonts, set_font_family
|
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 .session import create_session
|
||||||
from .tabs import SpecialWindow, TabManager
|
from .tabs import SpecialWindow, TabManager
|
||||||
from .utils import (
|
from .utils import (
|
||||||
@ -288,12 +287,6 @@ class Boss:
|
|||||||
old_focus.focus_changed(False)
|
old_focus.focus_changed(False)
|
||||||
tab.active_window.focus_changed(True)
|
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):
|
def open_url(self, url):
|
||||||
if url:
|
if url:
|
||||||
open_url(url, self.opts.open_url_with)
|
open_url(url, self.opts.open_url_with)
|
||||||
|
|||||||
@ -151,10 +151,10 @@ decoration_as_sgr(uint8_t decoration) {
|
|||||||
|
|
||||||
const char*
|
const char*
|
||||||
cursor_as_sgr(Cursor *self, Cursor *prev) {
|
cursor_as_sgr(Cursor *self, Cursor *prev) {
|
||||||
static char buf[128], *p;
|
static char buf[128];
|
||||||
#define SZ sizeof(buf) - (p - buf) - 2
|
#define SZ sizeof(buf) - (p - buf) - 2
|
||||||
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
|
#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->bold != prev->bold) P("%d", self->bold ? 1 : 22);
|
||||||
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
|
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
|
||||||
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
|
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#undef _DARWIN_C_SOURCE
|
#undef _DARWIN_C_SOURCE
|
||||||
#endif
|
#endif
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
|
#include "control-codes.h"
|
||||||
#include "modes.h"
|
#include "modes.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@ -229,8 +230,6 @@ PyInit_fast_data_types(void) {
|
|||||||
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "DECORATION", DECORATION_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_AddStringMacro(m, ERROR_PREFIX);
|
||||||
PyModule_AddIntMacro(m, CURSOR_BLOCK);
|
PyModule_AddIntMacro(m, CURSOR_BLOCK);
|
||||||
PyModule_AddIntMacro(m, CURSOR_BEAM);
|
PyModule_AddIntMacro(m, CURSOR_BEAM);
|
||||||
@ -239,6 +238,10 @@ PyInit_fast_data_types(void) {
|
|||||||
PyModule_AddIntMacro(m, DECCOLM);
|
PyModule_AddIntMacro(m, DECCOLM);
|
||||||
PyModule_AddIntMacro(m, DECOM);
|
PyModule_AddIntMacro(m, DECOM);
|
||||||
PyModule_AddIntMacro(m, IRM);
|
PyModule_AddIntMacro(m, IRM);
|
||||||
|
PyModule_AddIntMacro(m, CSI);
|
||||||
|
PyModule_AddIntMacro(m, DCS);
|
||||||
|
PyModule_AddIntMacro(m, APC);
|
||||||
|
PyModule_AddIntMacro(m, OSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|||||||
@ -270,6 +270,7 @@ void change_wcwidth(bool use9);
|
|||||||
void set_mouse_cursor(MouseShape);
|
void set_mouse_cursor(MouseShape);
|
||||||
void mouse_event(int, int);
|
void mouse_event(int, int);
|
||||||
void scroll_event(double, double);
|
void scroll_event(double, double);
|
||||||
|
void fake_scroll(bool);
|
||||||
void set_special_key_combo(int glfw_key, int mods);
|
void set_special_key_combo(int glfw_key, int mods);
|
||||||
void on_text_input(unsigned int codepoint, int mods);
|
void on_text_input(unsigned int codepoint, int mods);
|
||||||
void on_key_input(int key, int scancode, int action, 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;
|
if (!data_loaded) return NULL;
|
||||||
snprintf(add_response, 10, "OK");
|
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 rbuf;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
23
kitty/keys.c
23
kitty/keys.c
@ -9,6 +9,7 @@
|
|||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
|
#include "control-codes.h"
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) {
|
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
|
void
|
||||||
on_key_input(int key, int scancode, int action, int mods) {
|
on_key_input(int key, int scancode, int action, int mods) {
|
||||||
Window *w = active_window();
|
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) ||
|
(action == GLFW_REPEAT && screen->modes.mDECARM) ||
|
||||||
screen->modes.mEXTENDED_KEYBOARD
|
screen->modes.mEXTENDED_KEYBOARD
|
||||||
) {
|
) {
|
||||||
const char *data = key_to_bytes(lkey, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
send_key_to_child(w, lkey, mods, action);
|
||||||
if (data) schedule_write_to_child(w->id, (data + 1), *data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
|
||||||
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
||||||
#define M(name, arg_type) {#name, (PyCFunction)py##name, arg_type, 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
|
m |= 0x4
|
||||||
if mods & defines.GLFW_MOD_SUPER:
|
if mods & defines.GLFW_MOD_SUPER:
|
||||||
m |= 0x8
|
m |= 0x8
|
||||||
return '\033_K{}{}{}\033\\'.format(
|
return 'K{}{}{}'.format(
|
||||||
action_map[action], base64_encode(m), name
|
action_map[action], base64_encode(m), name
|
||||||
).encode('ascii')
|
).encode('ascii')
|
||||||
|
|
||||||
|
|||||||
@ -73,8 +73,8 @@
|
|||||||
// Bracketed paste mode
|
// Bracketed paste mode
|
||||||
// http://cirw.in/blog/bracketed-paste
|
// http://cirw.in/blog/bracketed-paste
|
||||||
#define BRACKETED_PASTE (2004 << 5)
|
#define BRACKETED_PASTE (2004 << 5)
|
||||||
#define BRACKETED_PASTE_START "\033[200~"
|
#define BRACKETED_PASTE_START "200~"
|
||||||
#define BRACKETED_PASTE_END "\033[201~"
|
#define BRACKETED_PASTE_END "201~"
|
||||||
|
|
||||||
// Styled underlines
|
// Styled underlines
|
||||||
#define STYLED_UNDERLINES (2016 << 5)
|
#define STYLED_UNDERLINES (2016 << 5)
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
|
#include "control-codes.h"
|
||||||
|
|
||||||
static MouseShape mouse_cursor_shape = BEAM;
|
static MouseShape mouse_cursor_shape = BEAM;
|
||||||
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
||||||
@ -41,7 +42,7 @@ button_map(int button) {
|
|||||||
|
|
||||||
static char mouse_event_buf[64];
|
static char mouse_event_buf[64];
|
||||||
|
|
||||||
size_t
|
int
|
||||||
encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
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 x = w->mouse_cell_x + 1, y = w->mouse_cell_y + 1; // 1 based indexing
|
||||||
unsigned int cb = 0;
|
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;
|
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
|
||||||
switch(screen->modes.mouse_tracking_protocol) {
|
switch(screen->modes.mouse_tracking_protocol) {
|
||||||
case SGR_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;
|
break;
|
||||||
case URXVT_PROTOCOL:
|
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;
|
break;
|
||||||
case UTF8_PROTOCOL:
|
case UTF8_PROTOCOL:
|
||||||
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32;
|
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32;
|
||||||
unsigned int sz = 4;
|
unsigned int sz = 2;
|
||||||
sz += encode_utf8(x + 32, mouse_event_buf + sz);
|
sz += encode_utf8(x + 32, mouse_event_buf + sz);
|
||||||
sz += encode_utf8(y + 32, mouse_event_buf + sz);
|
sz += encode_utf8(y + 32, mouse_event_buf + sz);
|
||||||
return sz;
|
return sz;
|
||||||
@ -75,8 +76,8 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
|||||||
default:
|
default:
|
||||||
if (x > 223 || y > 223) return 0;
|
if (x > 223 || y > 223) return 0;
|
||||||
else {
|
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;
|
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32; mouse_event_buf[2] = x + 32; mouse_event_buf[3] = y + 32;
|
||||||
return 6;
|
return 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -190,8 +191,8 @@ HANDLER(handle_move_event) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!mouse_cell_changed) return;
|
if (!mouse_cell_changed) return;
|
||||||
size_t sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0);
|
int 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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers);
|
int sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers);
|
||||||
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
|
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);
|
screen_history_scroll(screen, abs(s), upwards);
|
||||||
} else {
|
} else {
|
||||||
if (screen->modes.mouse_tracking_mode) {
|
if (screen->modes.mouse_tracking_mode) {
|
||||||
size_t sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
|
int 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);
|
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||||
} else {
|
} 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;
|
REPORT_ERROR("Unknown charset: 0x%x", ch); break;
|
||||||
}
|
}
|
||||||
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:
|
default:
|
||||||
REPORT_ERROR("Unhandled charset related escape code: 0x%x 0x%x", screen->parser_buf[0], ch); break;
|
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 "unicode-data.h"
|
||||||
#include "modes.h"
|
#include "modes.h"
|
||||||
#include "wcwidth9.h"
|
#include "wcwidth9.h"
|
||||||
|
#include "control-codes.h"
|
||||||
|
|
||||||
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
|
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
|
||||||
static Selection EMPTY_SELECTION = {0};
|
static Selection EMPTY_SELECTION = {0};
|
||||||
@ -104,9 +105,9 @@ screen_reset(Screen *self) {
|
|||||||
linebuf_clear(self->linebuf, BLANK_CHAR);
|
linebuf_clear(self->linebuf, BLANK_CHAR);
|
||||||
grman_clear(self->grman);
|
grman_clear(self->grman);
|
||||||
self->modes = empty_modes;
|
self->modes = empty_modes;
|
||||||
#define RC(name) self->color_profile->overridden.name = 0
|
#define R(name) self->color_profile->overridden.name = 0
|
||||||
RC(default_fg); RC(default_bg); RC(cursor_color); RC(highlight_fg); RC(highlight_bg);
|
R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg);
|
||||||
#undef RC
|
#undef R
|
||||||
RESET_CHARSETS;
|
RESET_CHARSETS;
|
||||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||||
screen_normal_keypad_mode(self);
|
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); }
|
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
|
void
|
||||||
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
|
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
|
||||||
unsigned int x = self->cursor->x, y = self->cursor->y;
|
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);
|
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 (x != self->cursor->x || y != self->cursor->y) {
|
||||||
if (self->cursor->x >= self->columns) { self->cursor->x = 0; 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);
|
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
|
#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);
|
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);
|
set_mode_from_const(self, mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
screen_set_8bit_controls(Screen *self, bool yes) {
|
||||||
|
self->modes.eight_bit_controls = yes;
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// Cursor {{{
|
// Cursor {{{
|
||||||
@ -944,10 +975,10 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
|||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
switch(start_modifier) {
|
switch(start_modifier) {
|
||||||
case 0:
|
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;
|
break;
|
||||||
case '>':
|
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;
|
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
|
// We dont implement the private device status codes, since I haven't come
|
||||||
// across any programs that use them
|
// across any programs that use them
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
static char buf[50];
|
static char buf[64];
|
||||||
switch(which) {
|
switch(which) {
|
||||||
case 5: // device status
|
case 5: // device status
|
||||||
write_str_to_child("\x1b[0n");
|
write_escape_code_to_child(self, CSI, "0n");
|
||||||
break;
|
break;
|
||||||
case 6: // cursor position
|
case 6: // cursor position
|
||||||
x = self->cursor->x; y = self->cursor->y;
|
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);
|
if (self->modes.mDECOM) y -= MAX(y, self->margin_top);
|
||||||
// 1-based indexing
|
// 1-based indexing
|
||||||
int sz = snprintf(buf, sizeof(buf) - 1, "\x1b[%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
|
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
|
||||||
if (sz > 0) write_to_child(self, buf, sz);
|
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1002,8 +1033,8 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
|
|||||||
case STYLED_UNDERLINES:
|
case STYLED_UNDERLINES:
|
||||||
ans = 3; break;
|
ans = 3; break;
|
||||||
}
|
}
|
||||||
int sz = snprintf(buf, sizeof(buf) - 1, "\x1b[%s%u;%u$y", (private ? "?" : ""), which, ans);
|
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%u$y", (private ? "?" : ""), which, ans);
|
||||||
if (sz > 0) write_to_child(self, buf, sz);
|
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1093,16 +1124,16 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
|||||||
case CURSOR_BEAM:
|
case CURSOR_BEAM:
|
||||||
shape = self->cursor->blink ? 5 : 6; break;
|
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) {
|
} else if (strcmp("m", query) == 0) {
|
||||||
// SGR
|
// 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) {
|
} 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 {
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1523,6 +1554,23 @@ toggle_alt_screen(Screen *self) {
|
|||||||
Py_RETURN_NONE;
|
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)
|
WRAP2(cursor_position, 1, 1)
|
||||||
|
|
||||||
#define COUNT_WRAP(name) WRAP1(name, 1)
|
#define COUNT_WRAP(name) WRAP1(name, 1)
|
||||||
@ -1580,8 +1628,10 @@ static PyMethodDef methods[] = {
|
|||||||
MND(rescale_images, METH_VARARGS)
|
MND(rescale_images, METH_VARARGS)
|
||||||
MND(text_for_selection, METH_NOARGS)
|
MND(text_for_selection, METH_NOARGS)
|
||||||
MND(scroll, METH_VARARGS)
|
MND(scroll, METH_VARARGS)
|
||||||
|
MND(send_escape_code_to_child, METH_VARARGS)
|
||||||
MND(toggle_alt_screen, METH_NOARGS)
|
MND(toggle_alt_screen, METH_NOARGS)
|
||||||
MND(reset_callbacks, METH_NOARGS)
|
MND(reset_callbacks, METH_NOARGS)
|
||||||
|
MND(paste, METH_O)
|
||||||
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
|||||||
@ -15,6 +15,7 @@ typedef struct {
|
|||||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
||||||
MouseTrackingMode mouse_tracking_mode;
|
MouseTrackingMode mouse_tracking_mode;
|
||||||
MouseTrackingProtocol mouse_tracking_protocol;
|
MouseTrackingProtocol mouse_tracking_protocol;
|
||||||
|
bool eight_bit_controls; // S8C1T
|
||||||
} ScreenModes;
|
} ScreenModes;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -66,6 +67,7 @@ void parse_worker_dump(Screen *screen, PyObject *dump_callback);
|
|||||||
void screen_align(Screen*);
|
void screen_align(Screen*);
|
||||||
void screen_restore_cursor(Screen *);
|
void screen_restore_cursor(Screen *);
|
||||||
void screen_save_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_position(Screen*, unsigned int, unsigned int);
|
||||||
void screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/);
|
void screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/);
|
||||||
void screen_erase_in_line(Screen *, unsigned int, bool);
|
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*);
|
void set_color_table_color(Screen *self, unsigned int code, PyObject*);
|
||||||
uint32_t* translation_table(uint32_t which);
|
uint32_t* translation_table(uint32_t which);
|
||||||
void screen_request_capabilities(Screen *, char, PyObject *);
|
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 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 select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count);
|
||||||
void report_device_status(Screen *self, unsigned int which, bool UNUSED);
|
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:
|
if qname in string_capabilities and '%' not in val:
|
||||||
val = key_as_bytes(qname).decode('ascii')
|
val = key_as_bytes(qname).decode('ascii')
|
||||||
ans.append(q + '=' + hexlify(str(val).encode('utf-8')).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:
|
except Exception:
|
||||||
return b'\033P0+r' + query_string.encode('utf-8') + b'\033\\'
|
return '0+r' + query_string
|
||||||
|
|||||||
@ -12,13 +12,12 @@ from .constants import (
|
|||||||
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BLIT_PROGRAM, BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BG_PROGRAM,
|
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
||||||
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM,
|
CELL_SPECIAL_PROGRAM, CSI, CURSOR_PROGRAM, DCS, GRAPHICS_PREMULT_PROGRAM,
|
||||||
GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE,
|
GRAPHICS_PROGRAM, OSC, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
||||||
SCROLL_PAGE, Screen, add_window, compile_program, glfw_post_empty_event,
|
add_window, compile_program, glfw_post_empty_event, init_cell_program,
|
||||||
init_cell_program, init_cursor_program, set_clipboard_string,
|
init_cursor_program, set_clipboard_string, set_window_render_data,
|
||||||
set_window_render_data, update_window_title, update_window_visibility,
|
update_window_title, update_window_visibility, viewport_for_window
|
||||||
viewport_for_window
|
|
||||||
)
|
)
|
||||||
from .keys import keyboard_mode_name
|
from .keys import keyboard_mode_name
|
||||||
from .rgb import to_color
|
from .rgb import to_color
|
||||||
@ -171,10 +170,10 @@ class Window:
|
|||||||
def focus_changed(self, focused):
|
def focus_changed(self, focused):
|
||||||
if focused:
|
if focused:
|
||||||
if self.screen.focus_tracking_enabled:
|
if self.screen.focus_tracking_enabled:
|
||||||
self.write_to_child(b'\x1b[I')
|
self.screen.send_escape_code_to_child(CSI, 'I')
|
||||||
else:
|
else:
|
||||||
if self.screen.focus_tracking_enabled:
|
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):
|
def title_changed(self, new_title):
|
||||||
if self.override_title is None:
|
if self.override_title is None:
|
||||||
@ -206,11 +205,11 @@ class Window:
|
|||||||
if dirtied:
|
if dirtied:
|
||||||
self.screen.mark_as_dirty()
|
self.screen.mark_as_dirty()
|
||||||
|
|
||||||
def report_color(self, osc, r, g, b):
|
def report_color(self, code, r, g, b):
|
||||||
r |= r << 8
|
r |= r << 8
|
||||||
g |= g << 8
|
g |= g << 8
|
||||||
b |= b << 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):
|
def set_dynamic_color(self, code, value):
|
||||||
if isinstance(value, bytes):
|
if isinstance(value, bytes):
|
||||||
@ -257,7 +256,7 @@ class Window:
|
|||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
def request_capabilities(self, q):
|
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 @@ class Window:
|
|||||||
if isinstance(text, str):
|
if isinstance(text, str):
|
||||||
text = text.encode('utf-8')
|
text = text.encode('utf-8')
|
||||||
if self.screen.in_bracketed_paste_mode:
|
if self.screen.in_bracketed_paste_mode:
|
||||||
bpe = BRACKETED_PASTE_END.encode('ascii')
|
text = text.replace(b'\033[201~', b'')
|
||||||
text = BRACKETED_PASTE_START.encode('ascii') + text.replace(bpe, b'') + bpe
|
self.screen.paste(text)
|
||||||
self.write_to_child(text)
|
|
||||||
|
|
||||||
def copy_to_clipboard(self):
|
def copy_to_clipboard(self):
|
||||||
text = self.text_for_selection()
|
text = self.text_for_selection()
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class Callbacks:
|
|||||||
|
|
||||||
def request_capabilities(self, q):
|
def request_capabilities(self, q):
|
||||||
from kitty.terminfo import get_capabilities
|
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):
|
def use_utf8(self, on):
|
||||||
self.iutf8 = on
|
self.iutf8 = on
|
||||||
|
|||||||
@ -198,7 +198,7 @@ class TestParser(BaseTest):
|
|||||||
q = hexlify(b'kind').decode('ascii')
|
q = hexlify(b'kind').decode('ascii')
|
||||||
pb('a\033P+q{}\x9cbcde'.format(q), 'a', ('screen_request_capabilities', 43, q), 'bcde')
|
pb('a\033P+q{}\x9cbcde'.format(q), 'a', ('screen_request_capabilities', 43, q), 'bcde')
|
||||||
self.ae(str(s.line(0)), 'abcde')
|
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()
|
c.clear()
|
||||||
pb('\033P$q q\033\\', ('screen_request_capabilities', ord('$'), ' q'))
|
pb('\033P$q q\033\\', ('screen_request_capabilities', ord('$'), ' q'))
|
||||||
self.ae(c.wtcbuf, b'\033P1$r1 q\033\\')
|
self.ae(c.wtcbuf, b'\033P1$r1 q\033\\')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user