mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-22 20:17:45 +03:00
Write escape codes to children atomically
Ensure a partial escape code is never written
This commit is contained in:
parent
d1a76bbcd9
commit
0e248b3faa
@ -246,9 +246,18 @@ add_child(ChildMonitor *self, PyObject *args) {
|
||||
}
|
||||
|
||||
bool
|
||||
schedule_write_to_child(unsigned long id, const char *data, size_t sz) {
|
||||
schedule_write_to_child(unsigned long id, unsigned int num, ...) {
|
||||
ChildMonitor *self = the_monitor;
|
||||
bool found = false;
|
||||
const char *data;
|
||||
size_t sz = 0;
|
||||
va_list ap;
|
||||
va_start(ap, num);
|
||||
for (unsigned int i = 0; i < num; i++) {
|
||||
data = va_arg(ap, const char*);
|
||||
sz += va_arg(ap, size_t);
|
||||
}
|
||||
va_end(ap);
|
||||
children_mutex(lock);
|
||||
for (size_t i = 0; i < self->count; i++) {
|
||||
if (children[i].id == id) {
|
||||
@ -266,8 +275,14 @@ schedule_write_to_child(unsigned long id, const char *data, size_t sz) {
|
||||
screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz);
|
||||
if (screen->write_buf == NULL) { fatal("Out of memory."); }
|
||||
}
|
||||
memcpy(screen->write_buf + screen->write_buf_used, data, sz);
|
||||
screen->write_buf_used += sz;
|
||||
va_start(ap, num);
|
||||
for (unsigned int i = 0; i < num; i++) {
|
||||
data = va_arg(ap, const char*);
|
||||
size_t dsz = va_arg(ap, size_t);
|
||||
memcpy(screen->write_buf + screen->write_buf_used, data, dsz);
|
||||
screen->write_buf_used += dsz;
|
||||
}
|
||||
va_end(ap);
|
||||
if (screen->write_buf_sz > BUFSIZ && screen->write_buf_used < BUFSIZ) {
|
||||
screen->write_buf_sz = BUFSIZ;
|
||||
screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz);
|
||||
@ -288,7 +303,7 @@ needs_write(ChildMonitor UNUSED *self, PyObject *args) {
|
||||
unsigned long id, sz;
|
||||
const char *data;
|
||||
if (!PyArg_ParseTuple(args, "ks#", &id, &data, &sz)) return NULL;
|
||||
if (schedule_write_to_child(id, data, sz)) { Py_RETURN_TRUE; }
|
||||
if (schedule_write_to_child(id, 1, data, (size_t)sz)) { Py_RETURN_TRUE; }
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ const char* cursor_as_sgr(Cursor*, Cursor*);
|
||||
|
||||
double monotonic();
|
||||
PyObject* cm_thread_write(PyObject *self, PyObject *args);
|
||||
bool schedule_write_to_child(unsigned long id, const char *data, size_t sz);
|
||||
bool schedule_write_to_child(unsigned long id, unsigned int num, ...);
|
||||
bool set_iutf8(int, bool);
|
||||
|
||||
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);
|
||||
|
@ -80,12 +80,12 @@ send_key_to_child(Window *w, int key, int mods, int action) {
|
||||
const char *data = key_to_bytes(key, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
||||
if (data) {
|
||||
if (screen->modes.mEXTENDED_KEYBOARD) {
|
||||
if (*data == 1) schedule_write_to_child(w->id, (data + 1), 1);
|
||||
if (*data == 1) schedule_write_to_child(w->id, 1, (data + 1), 1);
|
||||
else write_escape_code_to_child(screen, APC, data + 1);
|
||||
} else {
|
||||
if (*data > 2 && data[1] == 0x1b && data[2] == '[') { // CSI code
|
||||
write_escape_code_to_child(screen, CSI, data + 3);
|
||||
} else schedule_write_to_child(w->id, (data + 1), *data);
|
||||
} else schedule_write_to_child(w->id, 1, (data + 1), *data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,7 +141,7 @@ on_key_input(int key, int scancode, int action, int mods, const char* text, int
|
||||
return;
|
||||
case 2: // commit text
|
||||
if (text && *text) {
|
||||
schedule_write_to_child(w->id, text, strlen(text));
|
||||
schedule_write_to_child(w->id, 1, text, strlen(text));
|
||||
debug("committed pre-edit text: %s\n", text);
|
||||
} else debug("committed pre-edit text: (null)\n");
|
||||
return;
|
||||
@ -184,7 +184,7 @@ on_key_input(int key, int scancode, int action, int mods, const char* text, int
|
||||
bool ok_to_send = action == GLFW_PRESS || action == GLFW_REPEAT || screen->modes.mEXTENDED_KEYBOARD;
|
||||
if (ok_to_send) {
|
||||
if (has_text) {
|
||||
schedule_write_to_child(w->id, text, strlen(text));
|
||||
schedule_write_to_child(w->id, 1, text, strlen(text));
|
||||
debug("sent text to child\n");
|
||||
} else {
|
||||
send_key_to_child(w, key, mods, action);
|
||||
|
@ -499,10 +499,15 @@ select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count,
|
||||
} else cursor_from_sgr(self->cursor, params, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_to_test_child(Screen *self, const char *data, size_t sz) {
|
||||
PyObject *r = PyObject_CallMethod(self->test_child, "write", "y#", data, sz); if (r == NULL) PyErr_Print(); Py_CLEAR(r);
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_to_child(Screen *self, const char *data, size_t sz) {
|
||||
if (self->window_id) schedule_write_to_child(self->window_id, data, 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->window_id) schedule_write_to_child(self->window_id, 1, data, sz);
|
||||
if (self->test_child != Py_None) { write_to_test_child(self, data, sz); }
|
||||
}
|
||||
|
||||
void
|
||||
@ -527,9 +532,18 @@ write_escape_code_to_child(Screen *self, unsigned char which, const char *data)
|
||||
default:
|
||||
fatal("Unknown escape code to write: %u", which);
|
||||
}
|
||||
write_to_child(self, prefix, strlen(prefix));
|
||||
write_to_child(self, data, strlen(data));
|
||||
if (suffix[0]) write_to_child(self, suffix, strlen(suffix));
|
||||
if (self->window_id) {
|
||||
if (suffix[0]) {
|
||||
schedule_write_to_child(self->window_id, 3, prefix, strlen(prefix), data, strlen(data), suffix, strlen(suffix));
|
||||
} else {
|
||||
schedule_write_to_child(self->window_id, 2, prefix, strlen(prefix), data, strlen(data));
|
||||
}
|
||||
}
|
||||
if (self->test_child != Py_None) {
|
||||
write_to_test_child(self, prefix, strlen(prefix));
|
||||
write_to_test_child(self, data, strlen(data));
|
||||
if (suffix[0]) write_to_test_child(self, suffix, strlen(suffix));
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
Loading…
Reference in New Issue
Block a user