Remove trailing whitespace from native code files
This commit is contained in:
parent
15f5ea92b8
commit
0fcce6ec58
18
kitty/charsets.c
generated
18
kitty/charsets.c
generated
@ -43,7 +43,7 @@ static uint32_t charset_translations[5][256] = {
|
|||||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||||
},
|
},
|
||||||
/* VT100 graphics mapped to Unicode */
|
/* VT100 graphics mapped to Unicode */
|
||||||
{
|
{
|
||||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||||
@ -81,7 +81,7 @@ static uint32_t charset_translations[5][256] = {
|
|||||||
},
|
},
|
||||||
/* IBM Codepage 437 mapped to Unicode */
|
/* IBM Codepage 437 mapped to Unicode */
|
||||||
{
|
{
|
||||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||||
@ -113,7 +113,7 @@ static uint32_t charset_translations[5][256] = {
|
|||||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||||
},
|
},
|
||||||
// VAX 42 map
|
// VAX 42 map
|
||||||
{
|
{
|
||||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||||
@ -183,13 +183,13 @@ static uint32_t charset_translations[5][256] = {
|
|||||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t*
|
uint32_t*
|
||||||
translation_table(uint32_t which) {
|
translation_table(uint32_t which) {
|
||||||
switch(which){
|
switch(which){
|
||||||
case 'B':
|
case 'B':
|
||||||
return charset_translations[0];
|
return charset_translations[0];
|
||||||
case '0':
|
case '0':
|
||||||
@ -208,7 +208,7 @@ translation_table(uint32_t which) {
|
|||||||
uint32_t *latin1_charset = charset_translations[0];
|
uint32_t *latin1_charset = charset_translations[0];
|
||||||
|
|
||||||
// UTF-8 decode taken from: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
// UTF-8 decode taken from: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||||
|
|
||||||
static const uint8_t utf8_data[] = {
|
static const uint8_t utf8_data[] = {
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
||||||
@ -226,7 +226,7 @@ static const uint8_t utf8_data[] = {
|
|||||||
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
decode_utf8(uint32_t* state, uint32_t* codep, uint8_t byte) {
|
decode_utf8(uint32_t* state, uint32_t* codep, uint8_t byte) {
|
||||||
uint32_t type = utf8_data[byte];
|
uint32_t type = utf8_data[byte];
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ base64_decode(const uint32_t *src, size_t src_sz, uint8_t *dest, size_t dest_cap
|
|||||||
if (!src_sz) { *dest_sz = 0; return NULL; }
|
if (!src_sz) { *dest_sz = 0; return NULL; }
|
||||||
if (src_sz % 4 != 0) return "base64 encoded data must have a length that is a multiple of four";
|
if (src_sz % 4 != 0) return "base64 encoded data must have a length that is a multiple of four";
|
||||||
*dest_sz = (src_sz / 4) * 3;
|
*dest_sz = (src_sz / 4) * 3;
|
||||||
if (src[src_sz - 1] == '=') (*dest_sz)--;
|
if (src[src_sz - 1] == '=') (*dest_sz)--;
|
||||||
if (src[src_sz - 2] == '=') (*dest_sz)--;
|
if (src[src_sz - 2] == '=') (*dest_sz)--;
|
||||||
if (*dest_sz > dest_capacity) return "output buffer too small";
|
if (*dest_sz > dest_capacity) return "output buffer too small";
|
||||||
for (size_t i = 0, j = 0; i < src_sz;) {
|
for (size_t i = 0, j = 0; i < src_sz;) {
|
||||||
|
|||||||
@ -95,7 +95,7 @@ set_thread_name(const char *name) {
|
|||||||
#define FREE_CHILD(x) \
|
#define FREE_CHILD(x) \
|
||||||
Py_CLEAR((x).screen); x = EMPTY_CHILD;
|
Py_CLEAR((x).screen); x = EMPTY_CHILD;
|
||||||
|
|
||||||
#define XREF_CHILD(x, OP) OP(x.screen);
|
#define XREF_CHILD(x, OP) OP(x.screen);
|
||||||
#define INCREF_CHILD(x) XREF_CHILD(x, Py_INCREF)
|
#define INCREF_CHILD(x) XREF_CHILD(x, Py_INCREF)
|
||||||
#define DECREF_CHILD(x) XREF_CHILD(x, Py_DECREF)
|
#define DECREF_CHILD(x) XREF_CHILD(x, Py_DECREF)
|
||||||
|
|
||||||
@ -138,12 +138,12 @@ self_pipe(int fds[2]) {
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||||
ChildMonitor *self;
|
ChildMonitor *self;
|
||||||
PyObject *dump_callback, *death_notify;
|
PyObject *dump_callback, *death_notify;
|
||||||
int talk_fd = -1;
|
int talk_fd = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
|
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
|
||||||
if (!PyArg_ParseTuple(args, "OO|i", &death_notify, &dump_callback, &talk_fd)) return NULL;
|
if (!PyArg_ParseTuple(args, "OO|i", &death_notify, &dump_callback, &talk_fd)) return NULL;
|
||||||
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
|
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
|
||||||
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
|
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -163,7 +163,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->dump_callback = dump_callback; Py_INCREF(dump_callback);
|
self->dump_callback = dump_callback; Py_INCREF(dump_callback);
|
||||||
parse_func = parse_worker_dump;
|
parse_func = parse_worker_dump;
|
||||||
} else parse_func = parse_worker;
|
} else parse_func = parse_worker;
|
||||||
self->count = 0;
|
self->count = 0;
|
||||||
fds[0].fd = wakeup_fds[0]; fds[1].fd = signal_fds[0];
|
fds[0].fd = wakeup_fds[0]; fds[1].fd = signal_fds[0];
|
||||||
fds[0].events = POLLIN; fds[1].events = POLLIN;
|
fds[0].events = POLLIN; fds[1].events = POLLIN;
|
||||||
the_monitor = self;
|
the_monitor = self;
|
||||||
@ -187,7 +187,7 @@ dealloc(ChildMonitor* self) {
|
|||||||
}
|
}
|
||||||
close(wakeup_fds[0]);
|
close(wakeup_fds[0]);
|
||||||
close(wakeup_fds[1]);
|
close(wakeup_fds[1]);
|
||||||
close(signal_fds[0]);
|
close(signal_fds[0]);
|
||||||
close(signal_fds[1]);
|
close(signal_fds[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +243,7 @@ add_child(ChildMonitor *self, PyObject *args) {
|
|||||||
#define A(attr) &add_queue[add_queue_count].attr
|
#define A(attr) &add_queue[add_queue_count].attr
|
||||||
if (!PyArg_ParseTuple(args, "kiiO", A(id), A(pid), A(fd), A(screen))) {
|
if (!PyArg_ParseTuple(args, "kiiO", A(id), A(pid), A(fd), A(screen))) {
|
||||||
children_mutex(unlock);
|
children_mutex(unlock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#undef A
|
#undef A
|
||||||
INCREF_CHILD(add_queue[add_queue_count]);
|
INCREF_CHILD(add_queue[add_queue_count]);
|
||||||
@ -259,12 +259,12 @@ schedule_write_to_child(unsigned long id, const char *data, size_t sz) {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
for (size_t i = 0; i < self->count; i++) {
|
for (size_t i = 0; i < self->count; i++) {
|
||||||
if (children[i].id == id) {
|
if (children[i].id == id) {
|
||||||
found = true;
|
found = true;
|
||||||
Screen *screen = children[i].screen;
|
Screen *screen = children[i].screen;
|
||||||
screen_mutex(lock, write);
|
screen_mutex(lock, write);
|
||||||
size_t space_left = screen->write_buf_sz - screen->write_buf_used;
|
size_t space_left = screen->write_buf_sz - screen->write_buf_used;
|
||||||
if (space_left < sz) {
|
if (space_left < sz) {
|
||||||
if (screen->write_buf_used + sz > 100 * 1024 * 1024) {
|
if (screen->write_buf_used + sz > 100 * 1024 * 1024) {
|
||||||
fprintf(stderr, "Too much data being sent to child with id: %lu, ignoring it\n", id);
|
fprintf(stderr, "Too much data being sent to child with id: %lu, ignoring it\n", id);
|
||||||
screen_mutex(unlock, write);
|
screen_mutex(unlock, write);
|
||||||
@ -295,7 +295,7 @@ needs_write(ChildMonitor UNUSED *self, PyObject *args) {
|
|||||||
#define needs_write_doc "needs_write(id, data) -> Queue data to be written to child."
|
#define needs_write_doc "needs_write(id, data) -> Queue data to be written to child."
|
||||||
unsigned long id, sz;
|
unsigned long id, sz;
|
||||||
const char *data;
|
const char *data;
|
||||||
if (!PyArg_ParseTuple(args, "ks#", &id, &data, &sz)) return NULL;
|
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, data, sz)) { Py_RETURN_TRUE; }
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
}
|
}
|
||||||
@ -332,7 +332,7 @@ parse_input(ChildMonitor *self) {
|
|||||||
PyObject *msg = NULL;
|
PyObject *msg = NULL;
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
while (remove_queue_count) {
|
while (remove_queue_count) {
|
||||||
remove_queue_count--;
|
remove_queue_count--;
|
||||||
remove_notify[remove_count] = remove_queue[remove_queue_count].id;
|
remove_notify[remove_count] = remove_queue[remove_queue_count].id;
|
||||||
remove_count++;
|
remove_count++;
|
||||||
FREE_CHILD(remove_queue[remove_queue_count]);
|
FREE_CHILD(remove_queue[remove_queue_count]);
|
||||||
@ -544,7 +544,7 @@ update_window_title(Window *w, OSWindow *os_window) {
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
simple_render_screen(PyObject UNUSED *self, PyObject *args) {
|
simple_render_screen(PyObject UNUSED *self, PyObject *args) {
|
||||||
#define simple_render_screen_doc "Render a Screen object, with no cursor"
|
#define simple_render_screen_doc "Render a Screen object, with no cursor"
|
||||||
Screen *screen;
|
Screen *screen;
|
||||||
float xstart, ystart, dx, dy;
|
float xstart, ystart, dx, dy;
|
||||||
static ssize_t vao_idx = -1, gvao_idx = -1;
|
static ssize_t vao_idx = -1, gvao_idx = -1;
|
||||||
if (vao_idx == -1) vao_idx = create_cell_vao();
|
if (vao_idx == -1) vao_idx = create_cell_vao();
|
||||||
@ -563,7 +563,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int *active_window_id
|
|||||||
#define WD w->render_data
|
#define WD w->render_data
|
||||||
if (w->visible && WD.screen) {
|
if (w->visible && WD.screen) {
|
||||||
if (w->last_drag_scroll_at > 0) {
|
if (w->last_drag_scroll_at > 0) {
|
||||||
if (now - w->last_drag_scroll_at >= 0.02) {
|
if (now - w->last_drag_scroll_at >= 0.02) {
|
||||||
if (drag_scroll(w, os_window)) {
|
if (drag_scroll(w, os_window)) {
|
||||||
w->last_drag_scroll_at = now;
|
w->last_drag_scroll_at = now;
|
||||||
set_maximum_wait(0.02);
|
set_maximum_wait(0.02);
|
||||||
@ -592,7 +592,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int *active_window_id
|
|||||||
static inline void
|
static inline void
|
||||||
render(double now) {
|
render(double now) {
|
||||||
double time_since_last_render = now - last_render_at;
|
double time_since_last_render = now - last_render_at;
|
||||||
if (time_since_last_render < OPT(repaint_delay)) {
|
if (time_since_last_render < OPT(repaint_delay)) {
|
||||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -663,7 +663,7 @@ cm_thread_write(PyObject UNUSED *self, PyObject *args) {
|
|||||||
if (!PyArg_ParseTuple(args, "is#", &fd, &buf, &sz)) return NULL;
|
if (!PyArg_ParseTuple(args, "is#", &fd, &buf, &sz)) return NULL;
|
||||||
ThreadWriteData *data = alloc_twd(sz);
|
ThreadWriteData *data = alloc_twd(sz);
|
||||||
if (data == NULL) return PyErr_NoMemory();
|
if (data == NULL) return PyErr_NoMemory();
|
||||||
data->fd = fd;
|
data->fd = fd;
|
||||||
memcpy(data->buf, buf, data->sz);
|
memcpy(data->buf, buf, data->sz);
|
||||||
int ret = pthread_create(&thread, NULL, thread_write, data);
|
int ret = pthread_create(&thread, NULL, thread_write, data);
|
||||||
if (ret != 0) { free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); }
|
if (ret != 0) { free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); }
|
||||||
@ -716,7 +716,7 @@ main_loop(ChildMonitor *self) {
|
|||||||
Tab *tab = os_window->tabs + t;
|
Tab *tab = os_window->tabs + t;
|
||||||
for (size_t w = 0; w < tab->num_windows; w++) mark_child_for_close(self, tab->windows[w].id);
|
for (size_t w = 0; w < tab->num_windows; w++) mark_child_for_close(self, tab->windows[w].id);
|
||||||
}
|
}
|
||||||
remove_os_window(os_window->id);
|
remove_os_window(os_window->id);
|
||||||
} else has_open_windows = true;
|
} else has_open_windows = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -748,7 +748,7 @@ hangup(pid_t pid) {
|
|||||||
if (errno == ESRCH) return;
|
if (errno == ESRCH) return;
|
||||||
if (errno != 0) { perror("Failed to get process group id for child"); return; }
|
if (errno != 0) { perror("Failed to get process group id for child"); return; }
|
||||||
if (killpg(pgid, SIGHUP) != 0) {
|
if (killpg(pgid, SIGHUP) != 0) {
|
||||||
if (errno != ESRCH) perror("Failed to kill child");
|
if (errno != ESRCH) perror("Failed to kill child");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +763,7 @@ cleanup_child(ssize_t i) {
|
|||||||
static inline void
|
static inline void
|
||||||
remove_children(ChildMonitor *self) {
|
remove_children(ChildMonitor *self) {
|
||||||
if (self->count > 0) {
|
if (self->count > 0) {
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (ssize_t i = self->count - 1; i >= 0; i--) {
|
for (ssize_t i = self->count - 1; i >= 0; i--) {
|
||||||
if (children[i].needs_removal) {
|
if (children[i].needs_removal) {
|
||||||
count++;
|
count++;
|
||||||
@ -839,7 +839,7 @@ write_to_child(int fd, Screen *screen) {
|
|||||||
while (written < screen->write_buf_used) {
|
while (written < screen->write_buf_used) {
|
||||||
ret = write(fd, screen->write_buf + written, screen->write_buf_used - written);
|
ret = write(fd, screen->write_buf + written, screen->write_buf_used - written);
|
||||||
if (ret > 0) { written += ret; }
|
if (ret > 0) { written += ret; }
|
||||||
else if (ret == 0) {
|
else if (ret == 0) {
|
||||||
// could mean anything, ignore
|
// could mean anything, ignore
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -858,7 +858,7 @@ io_loop(void *data) {
|
|||||||
// The I/O thread loop
|
// The I/O thread loop
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret;
|
int ret;
|
||||||
bool has_more, data_received;
|
bool has_more, data_received;
|
||||||
Screen *screen;
|
Screen *screen;
|
||||||
ChildMonitor *self = (ChildMonitor*)data;
|
ChildMonitor *self = (ChildMonitor*)data;
|
||||||
set_thread_name("KittyChildMon");
|
set_thread_name("KittyChildMon");
|
||||||
@ -880,7 +880,7 @@ io_loop(void *data) {
|
|||||||
ret = poll(fds, self->count + EXTRA_FDS, -1);
|
ret = poll(fds, self->count + EXTRA_FDS, -1);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
if (fds[0].revents && POLLIN) drain_fd(fds[0].fd); // wakeup
|
if (fds[0].revents && POLLIN) drain_fd(fds[0].fd); // wakeup
|
||||||
if (fds[1].revents && POLLIN) {
|
if (fds[1].revents && POLLIN) {
|
||||||
data_received = true;
|
data_received = true;
|
||||||
drain_fd(fds[1].fd);
|
drain_fd(fds[1].fd);
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
@ -891,7 +891,7 @@ io_loop(void *data) {
|
|||||||
if (fds[EXTRA_FDS + i].revents & (POLLIN | POLLHUP)) {
|
if (fds[EXTRA_FDS + i].revents & (POLLIN | POLLHUP)) {
|
||||||
data_received = true;
|
data_received = true;
|
||||||
has_more = read_bytes(fds[EXTRA_FDS + i].fd, children[i].screen);
|
has_more = read_bytes(fds[EXTRA_FDS + i].fd, children[i].screen);
|
||||||
if (!has_more) {
|
if (!has_more) {
|
||||||
// child is dead
|
// child is dead
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
children[i].needs_removal = true;
|
children[i].needs_removal = true;
|
||||||
@ -968,7 +968,7 @@ handle_peer(ChildMonitor *self, int s) {
|
|||||||
static void*
|
static void*
|
||||||
talk_loop(void *data) {
|
talk_loop(void *data) {
|
||||||
// The I/O thread loop
|
// The I/O thread loop
|
||||||
|
|
||||||
ChildMonitor *self = (ChildMonitor*)data;
|
ChildMonitor *self = (ChildMonitor*)data;
|
||||||
set_thread_name("KittyTalkMon");
|
set_thread_name("KittyTalkMon");
|
||||||
|
|
||||||
@ -986,7 +986,7 @@ talk_loop(void *data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
static PyMethodDef methods[] = {
|
static PyMethodDef methods[] = {
|
||||||
METHOD(add_child, METH_VARARGS)
|
METHOD(add_child, METH_VARARGS)
|
||||||
@ -1007,11 +1007,11 @@ PyTypeObject ChildMonitor_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.ChildMonitor",
|
.tp_name = "fast_data_types.ChildMonitor",
|
||||||
.tp_basicsize = sizeof(ChildMonitor),
|
.tp_basicsize = sizeof(ChildMonitor),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "ChildMonitor",
|
.tp_doc = "ChildMonitor",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
@ -1023,7 +1023,7 @@ bool
|
|||||||
init_child_monitor(PyObject *module) {
|
init_child_monitor(PyObject *module) {
|
||||||
if (PyType_Ready(&ChildMonitor_Type) < 0) return false;
|
if (PyType_Ready(&ChildMonitor_Type) < 0) return false;
|
||||||
if (PyModule_AddObject(module, "ChildMonitor", (PyObject *)&ChildMonitor_Type) != 0) return false;
|
if (PyModule_AddObject(module, "ChildMonitor", (PyObject *)&ChildMonitor_Type) != 0) return false;
|
||||||
Py_INCREF(&ChildMonitor_Type);
|
Py_INCREF(&ChildMonitor_Type);
|
||||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
static NSMenuItem* title_menu = NULL;
|
static NSMenuItem* title_menu = NULL;
|
||||||
|
|
||||||
static NSString*
|
static NSString*
|
||||||
find_app_name(void) {
|
find_app_name(void) {
|
||||||
size_t i;
|
size_t i;
|
||||||
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
||||||
@ -141,7 +141,7 @@ cocoa_update_title(PyObject *pytitle) {
|
|||||||
bool
|
bool
|
||||||
cocoa_make_window_resizable(void *w) {
|
cocoa_make_window_resizable(void *w) {
|
||||||
NSWindow *window = (NSWindow*)w;
|
NSWindow *window = (NSWindow*)w;
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
[window setStyleMask:
|
[window setStyleMask:
|
||||||
[window styleMask] | NSWindowStyleMaskResizable];
|
[window styleMask] | NSWindowStyleMaskResizable];
|
||||||
@ -167,7 +167,7 @@ cocoa_get_lang(PyObject UNUSED *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
|
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ PyObject* create_256_color_table() {
|
|||||||
uint8_t v = 8 + i * 10;
|
uint8_t v = 8 + i * 10;
|
||||||
FG_BG_256[j] = (v << 16) | (v << 8) | v;
|
FG_BG_256[j] = (v << 16) | (v << 8) | v;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *ans = PyTuple_New(255);
|
PyObject *ans = PyTuple_New(255);
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
for (i=0; i < 255; i++) {
|
for (i=0; i < 255; i++) {
|
||||||
@ -62,7 +62,7 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) {
|
|||||||
if (FG_BG_256[255] == 0) create_256_color_table();
|
if (FG_BG_256[255] == 0) create_256_color_table();
|
||||||
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
|
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
|
||||||
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
|
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
|
||||||
self->dirty = true;
|
self->dirty = true;
|
||||||
}
|
}
|
||||||
return (PyObject*) self;
|
return (PyObject*) self;
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ update_ansi_color_table(ColorProfile *self, PyObject *val) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
color_type
|
color_type
|
||||||
colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval) {
|
colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval) {
|
||||||
color_type t = entry & 0xFF, r;
|
color_type t = entry & 0xFF, r;
|
||||||
switch(t) {
|
switch(t) {
|
||||||
@ -128,7 +128,7 @@ as_color(ColorProfile *self, PyObject *val) {
|
|||||||
default:
|
default:
|
||||||
ans = Py_None; Py_INCREF(Py_None);
|
ans = Py_None; Py_INCREF(Py_None);
|
||||||
}
|
}
|
||||||
if (ans == NULL) ans = Py_BuildValue("BBB", (unsigned char)(col >> 16), (unsigned char)((col >> 8) & 0xFF), (unsigned char)(col & 0xFF));
|
if (ans == NULL) ans = Py_BuildValue("BBB", (unsigned char)(col >> 16), (unsigned char)((col >> 8) & 0xFF), (unsigned char)(col & 0xFF));
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,13 +177,13 @@ copy_color_table_to_buffer(ColorProfile *self, color_type *buf, int offset, size
|
|||||||
}
|
}
|
||||||
self->dirty = false;
|
self->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
color_table_address(ColorProfile *self) {
|
color_table_address(ColorProfile *self) {
|
||||||
#define color_table_address_doc "Pointer address to start of color table"
|
#define color_table_address_doc "Pointer address to start of color table"
|
||||||
return PyLong_FromVoidPtr((void*)self->color_table);
|
return PyLong_FromVoidPtr((void*)self->color_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
|
|
||||||
@ -227,13 +227,13 @@ PyTypeObject ColorProfile_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.ColorProfile",
|
.tp_name = "fast_data_types.ColorProfile",
|
||||||
.tp_basicsize = sizeof(ColorProfile),
|
.tp_basicsize = sizeof(ColorProfile),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "ColorProfile",
|
.tp_doc = "ColorProfile",
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_getset = getsetters,
|
.tp_getset = getsetters,
|
||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
};
|
};
|
||||||
|
|
||||||
INIT_TYPE(ColorProfile)
|
INIT_TYPE(ColorProfile)
|
||||||
|
|||||||
@ -69,7 +69,7 @@
|
|||||||
// Sharp control codes
|
// Sharp control codes
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
// Align display
|
// Align display
|
||||||
#define DECALN '8'
|
#define DECALN '8'
|
||||||
|
|
||||||
// Esc control codes
|
// Esc control codes
|
||||||
@ -180,7 +180,7 @@
|
|||||||
|
|
||||||
// Scroll down by the specified number of lines
|
// Scroll down by the specified number of lines
|
||||||
#define SD 'T'
|
#define SD 'T'
|
||||||
|
|
||||||
// *Erase character*: Erase the indicated # of characters on the
|
// *Erase character*: Erase the indicated # of characters on the
|
||||||
// current line.
|
// current line.
|
||||||
#define ECH 'X'
|
#define ECH 'X'
|
||||||
@ -212,7 +212,7 @@
|
|||||||
|
|
||||||
// *Select graphics rendition*: The terminal can display the following
|
// *Select graphics rendition*: The terminal can display the following
|
||||||
// character attributes that change the character display without
|
// character attributes that change the character display without
|
||||||
// changing the character
|
// changing the character
|
||||||
#define SGR 'm'
|
#define SGR 'm'
|
||||||
|
|
||||||
// *Device status report*.
|
// *Device status report*.
|
||||||
|
|||||||
@ -86,7 +86,7 @@ dealloc(CTFace* self) {
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
font_descriptor_to_python(CTFontDescriptorRef descriptor) {
|
font_descriptor_to_python(CTFontDescriptorRef descriptor) {
|
||||||
NSURL *url = (NSURL *) CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
NSURL *url = (NSURL *) CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
||||||
NSString *psName = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute);
|
NSString *psName = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute);
|
||||||
NSString *family = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute);
|
NSString *family = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute);
|
||||||
NSString *style = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute);
|
NSString *style = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute);
|
||||||
NSDictionary *traits = (NSDictionary *) CTFontDescriptorCopyAttribute(descriptor, kCTFontTraitsAttribute);
|
NSDictionary *traits = (NSDictionary *) CTFontDescriptorCopyAttribute(descriptor, kCTFontTraitsAttribute);
|
||||||
@ -94,8 +94,8 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
|
|||||||
NSNumber *weightVal = traits[(id)kCTFontWeightTrait];
|
NSNumber *weightVal = traits[(id)kCTFontWeightTrait];
|
||||||
NSNumber *widthVal = traits[(id)kCTFontWidthTrait];
|
NSNumber *widthVal = traits[(id)kCTFontWidthTrait];
|
||||||
|
|
||||||
PyObject *ans = Py_BuildValue("{ssssssss sOsOsO sfsfsI}",
|
PyObject *ans = Py_BuildValue("{ssssssss sOsOsO sfsfsI}",
|
||||||
"path", [[url path] UTF8String],
|
"path", [[url path] UTF8String],
|
||||||
"postscript_name", [psName UTF8String],
|
"postscript_name", [psName UTF8String],
|
||||||
"family", [family UTF8String],
|
"family", [family UTF8String],
|
||||||
"style", [style UTF8String],
|
"style", [style UTF8String],
|
||||||
@ -148,7 +148,7 @@ static PyObject*
|
|||||||
coretext_all_fonts(PyObject UNUSED *_self) {
|
coretext_all_fonts(PyObject UNUSED *_self) {
|
||||||
static CTFontCollectionRef collection = NULL;
|
static CTFontCollectionRef collection = NULL;
|
||||||
if (collection == NULL) collection = CTFontCollectionCreateFromAvailableFonts(NULL);
|
if (collection == NULL) collection = CTFontCollectionCreateFromAvailableFonts(NULL);
|
||||||
NSArray *matches = (NSArray *) CTFontCollectionCreateMatchingFontDescriptors(collection);
|
NSArray *matches = (NSArray *) CTFontCollectionCreateMatchingFontDescriptors(collection);
|
||||||
PyObject *ans = PyTuple_New([matches count]), *temp;
|
PyObject *ans = PyTuple_New([matches count]), *temp;
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
for (unsigned int i = 0; i < [matches count]; i++) {
|
for (unsigned int i = 0; i < [matches count]; i++) {
|
||||||
@ -173,7 +173,7 @@ find_substitute_face(CFStringRef str, CTFontRef old_font) {
|
|||||||
if (new_font == old_font) { CFRelease(new_font); continue; }
|
if (new_font == old_font) { CFRelease(new_font); continue; }
|
||||||
return new_font;
|
return new_font;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_ValueError, "CoreText returned the same font as a fallback font");
|
PyErr_SetString(PyExc_ValueError, "CoreText returned the same font as a fallback font");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ create_fallback_face(PyObject *base_face, Cell* cell, bool UNUSED bold, bool UNU
|
|||||||
return (PyObject*)ct_face(new_font);
|
return (PyObject*)ct_face(new_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
glyph_id_for_codepoint(PyObject *s, char_type ch) {
|
glyph_id_for_codepoint(PyObject *s, char_type ch) {
|
||||||
CTFace *self = (CTFace*)s;
|
CTFace *self = (CTFace*)s;
|
||||||
unichar chars[2] = {0};
|
unichar chars[2] = {0};
|
||||||
@ -216,7 +216,7 @@ set_size_for_face(PyObject *s, unsigned int UNUSED desired_height, bool force) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_font_t*
|
hb_font_t*
|
||||||
harfbuzz_font_for_face(PyObject* s) {
|
harfbuzz_font_for_face(PyObject* s) {
|
||||||
CTFace *self = (CTFace*)s;
|
CTFace *self = (CTFace*)s;
|
||||||
if (!self->hb_font) {
|
if (!self->hb_font) {
|
||||||
@ -227,7 +227,7 @@ harfbuzz_font_for_face(PyObject* s) {
|
|||||||
return self->hb_font;
|
return self->hb_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
||||||
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
|
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
|
||||||
CTFace *self = (CTFace*)s;
|
CTFace *self = (CTFace*)s;
|
||||||
@ -241,10 +241,10 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
|
|||||||
if (glyphs[i]) {
|
if (glyphs[i]) {
|
||||||
w = (unsigned int)(ceilf(
|
w = (unsigned int)(ceilf(
|
||||||
CTFontGetAdvancesForGlyphs(self->ct_font, kCTFontOrientationHorizontal, glyphs+i, NULL, 1)));
|
CTFontGetAdvancesForGlyphs(self->ct_font, kCTFontOrientationHorizontal, glyphs+i, NULL, 1)));
|
||||||
if (w > width) width = w;
|
if (w > width) width = w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*cell_width = MAX(1, width);
|
*cell_width = MAX(1, width);
|
||||||
*underline_position = floor(self->ascent - self->underline_position + 0.5);
|
*underline_position = floor(self->ascent - self->underline_position + 0.5);
|
||||||
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
|
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
|
||||||
*baseline = (unsigned int)self->ascent;
|
*baseline = (unsigned int)self->ascent;
|
||||||
@ -252,7 +252,7 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
|
|||||||
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
|
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
|
||||||
CFStringRef ts = CFSTR("test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test");
|
CFStringRef ts = CFSTR("test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test");
|
||||||
CFMutableAttributedStringRef test_string = CFAttributedStringCreateMutable(kCFAllocatorDefault, CFStringGetLength(ts));
|
CFMutableAttributedStringRef test_string = CFAttributedStringCreateMutable(kCFAllocatorDefault, CFStringGetLength(ts));
|
||||||
CFAttributedStringReplaceString(test_string, CFRangeMake(0, 0), ts);
|
CFAttributedStringReplaceString(test_string, CFRangeMake(0, 0), ts);
|
||||||
CFAttributedStringSetAttribute(test_string, CFRangeMake(0, CFStringGetLength(ts)), kCTFontAttributeName, self->ct_font);
|
CFAttributedStringSetAttribute(test_string, CFRangeMake(0, CFStringGetLength(ts)), kCTFontAttributeName, self->ct_font);
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
CGPathAddRect(path, NULL, CGRectMake(10, 10, 200, 200));
|
CGPathAddRect(path, NULL, CGRectMake(10, 10, 200, 200));
|
||||||
@ -263,7 +263,7 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
|
|||||||
CTFrameGetLineOrigins(test_frame, CFRangeMake(0, 1), &origin1);
|
CTFrameGetLineOrigins(test_frame, CFRangeMake(0, 1), &origin1);
|
||||||
CTFrameGetLineOrigins(test_frame, CFRangeMake(1, 1), &origin2);
|
CTFrameGetLineOrigins(test_frame, CFRangeMake(1, 1), &origin2);
|
||||||
CGFloat line_height = origin1.y - origin2.y;
|
CGFloat line_height = origin1.y - origin2.y;
|
||||||
CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);
|
CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);
|
||||||
*cell_height = MAX(4, (unsigned int)ceilf(line_height));
|
*cell_height = MAX(4, (unsigned int)ceilf(line_height));
|
||||||
#undef count
|
#undef count
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ face_from_descriptor(PyObject *descriptor) {
|
|||||||
return (PyObject*) ct_face(font);
|
return (PyObject*) ct_face(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
face_from_path(const char *path, int UNUSED index) {
|
face_from_path(const char *path, int UNUSED index) {
|
||||||
CFStringRef s = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
|
CFStringRef s = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
|
||||||
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, s, kCFURLPOSIXPathStyle, false);
|
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, s, kCFURLPOSIXPathStyle, false);
|
||||||
@ -315,7 +315,7 @@ render_color_glyph(CTFontRef font, uint8_t *buf, int glyph_id, unsigned int widt
|
|||||||
if (ctx == NULL) fatal("Out of memory");
|
if (ctx == NULL) fatal("Out of memory");
|
||||||
CGContextSetShouldAntialias(ctx, true);
|
CGContextSetShouldAntialias(ctx, true);
|
||||||
CGContextSetShouldSmoothFonts(ctx, true); // sub-pixel antialias
|
CGContextSetShouldSmoothFonts(ctx, true); // sub-pixel antialias
|
||||||
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
|
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
|
||||||
CGAffineTransform transform = CGAffineTransformIdentity;
|
CGAffineTransform transform = CGAffineTransformIdentity;
|
||||||
CGContextSetTextDrawingMode(ctx, kCGTextFill);
|
CGContextSetTextDrawingMode(ctx, kCGTextFill);
|
||||||
CGGlyph glyph = glyph_id;
|
CGGlyph glyph = glyph_id;
|
||||||
@ -353,7 +353,7 @@ render_glyphs(CTFontRef font, unsigned int width, unsigned int height, unsigned
|
|||||||
CGContextSetGrayFillColor(render_ctx, 1, 1); // white glyphs
|
CGContextSetGrayFillColor(render_ctx, 1, 1); // white glyphs
|
||||||
CGContextSetTextDrawingMode(render_ctx, kCGTextFill);
|
CGContextSetTextDrawingMode(render_ctx, kCGTextFill);
|
||||||
CGContextSetTextMatrix(render_ctx, CGAffineTransformIdentity);
|
CGContextSetTextMatrix(render_ctx, CGAffineTransformIdentity);
|
||||||
CGContextSetTextPosition(render_ctx, 0, height - baseline);
|
CGContextSetTextPosition(render_ctx, 0, height - baseline);
|
||||||
CTFontDrawGlyphs(font, glyphs, positions, num_glyphs, render_ctx);
|
CTFontDrawGlyphs(font, glyphs, positions, num_glyphs, render_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ static PyMethodDef methods[] = {
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
repr(CTFace *self) {
|
repr(CTFace *self) {
|
||||||
char buf[1024] = {0};
|
char buf[1024] = {0};
|
||||||
snprintf(buf, sizeof(buf)/sizeof(buf[0]), "ascent=%.1f, descent=%.1f, leading=%.1f, point_sz=%.1f, scaled_point_sz=%.1f, underline_position=%.1f underline_thickness=%.1f",
|
snprintf(buf, sizeof(buf)/sizeof(buf[0]), "ascent=%.1f, descent=%.1f, leading=%.1f, point_sz=%.1f, scaled_point_sz=%.1f, underline_position=%.1f underline_thickness=%.1f",
|
||||||
(self->ascent), (self->descent), (self->leading), (self->point_sz), (self->scaled_point_sz), (self->underline_position), (self->underline_thickness));
|
(self->ascent), (self->descent), (self->leading), (self->point_sz), (self->scaled_point_sz), (self->underline_position), (self->underline_thickness));
|
||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"Face(family=%U, full_name=%U, postscript_name=%U, path=%U, units_per_em=%u, %s)",
|
"Face(family=%U, full_name=%U, postscript_name=%U, path=%U, units_per_em=%u, %s)",
|
||||||
@ -455,8 +455,8 @@ PyTypeObject CTFace_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.CTFace",
|
.tp_name = "fast_data_types.CTFace",
|
||||||
.tp_basicsize = sizeof(CTFace),
|
.tp_basicsize = sizeof(CTFace),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "CoreText Font face",
|
.tp_doc = "CoreText Font face",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
@ -465,10 +465,10 @@ PyTypeObject CTFace_Type = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
init_CoreText(PyObject *module) {
|
init_CoreText(PyObject *module) {
|
||||||
if (PyType_Ready(&CTFace_Type) < 0) return 0;
|
if (PyType_Ready(&CTFace_Type) < 0) return 0;
|
||||||
if (PyModule_AddObject(module, "CTFace", (PyObject *)&CTFace_Type) != 0) return 0;
|
if (PyModule_AddObject(module, "CTFace", (PyObject *)&CTFace_Type) != 0) return 0;
|
||||||
if (PyModule_AddFunctions(module, module_methods) != 0) return 0;
|
if (PyModule_AddFunctions(module, module_methods) != 0) return 0;
|
||||||
if (Py_AtExit(finalize) != 0) {
|
if (Py_AtExit(finalize) != 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to register the CoreText at exit handler");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to register the CoreText at exit handler");
|
||||||
|
|||||||
@ -39,7 +39,7 @@ repr(Cursor *self) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor_reset_display_attrs(Cursor *self) {
|
cursor_reset_display_attrs(Cursor *self) {
|
||||||
self->bg = 0; self->fg = 0; self->decoration_fg = 0;
|
self->bg = 0; self->fg = 0; self->decoration_fg = 0;
|
||||||
self->decoration = 0; self->bold = false; self->italic = false; self->reverse = false; self->strikethrough = false;
|
self->decoration = 0; self->bold = false; self->italic = false; self->reverse = false; self->strikethrough = false;
|
||||||
@ -50,25 +50,25 @@ static inline void
|
|||||||
parse_color(unsigned int *params, unsigned int *i, unsigned int count, uint32_t *result) {
|
parse_color(unsigned int *params, unsigned int *i, unsigned int count, uint32_t *result) {
|
||||||
unsigned int attr;
|
unsigned int attr;
|
||||||
uint8_t r, g, b;
|
uint8_t r, g, b;
|
||||||
if (*i < count) {
|
if (*i < count) {
|
||||||
attr = params[(*i)++];
|
attr = params[(*i)++];
|
||||||
switch(attr) {
|
switch(attr) {
|
||||||
case 5:
|
case 5:
|
||||||
if (*i < count) *result = (params[(*i)++] & 0xFF) << 8 | 1;
|
if (*i < count) *result = (params[(*i)++] & 0xFF) << 8 | 1;
|
||||||
break;
|
break;
|
||||||
case 2: \
|
case 2: \
|
||||||
if (*i < count - 2) {
|
if (*i < count - 2) {
|
||||||
/* Ignore the first parameter in a four parameter RGB */
|
/* Ignore the first parameter in a four parameter RGB */
|
||||||
/* sequence (unused color space id), see https://github.com/kovidgoyal/kitty/issues/227 */
|
/* sequence (unused color space id), see https://github.com/kovidgoyal/kitty/issues/227 */
|
||||||
if (*i < count - 3) (*i)++;
|
if (*i < count - 3) (*i)++;
|
||||||
r = params[(*i)++] & 0xFF;
|
r = params[(*i)++] & 0xFF;
|
||||||
g = params[(*i)++] & 0xFF;
|
g = params[(*i)++] & 0xFF;
|
||||||
b = params[(*i)++] & 0xFF;
|
b = params[(*i)++] & 0xFF;
|
||||||
*result = r << 24 | g << 16 | b << 8 | 2;
|
*result = r << 24 | g << 16 | b << 8 | 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,13 +109,13 @@ START_ALLOW_CASE_RANGE
|
|||||||
self->strikethrough = false; break;
|
self->strikethrough = false; break;
|
||||||
case 30 ... 37:
|
case 30 ... 37:
|
||||||
self->fg = ((attr - 30) << 8) | 1; break;
|
self->fg = ((attr - 30) << 8) | 1; break;
|
||||||
case 38:
|
case 38:
|
||||||
SET_COLOR(fg);
|
SET_COLOR(fg);
|
||||||
case 39:
|
case 39:
|
||||||
self->fg = 0; break;
|
self->fg = 0; break;
|
||||||
case 40 ... 47:
|
case 40 ... 47:
|
||||||
self->bg = ((attr - 40) << 8) | 1; break;
|
self->bg = ((attr - 40) << 8) | 1; break;
|
||||||
case 48:
|
case 48:
|
||||||
SET_COLOR(bg);
|
SET_COLOR(bg);
|
||||||
case 49:
|
case 49:
|
||||||
self->bg = 0; break;
|
self->bg = 0; break;
|
||||||
@ -124,7 +124,7 @@ START_ALLOW_CASE_RANGE
|
|||||||
case 100 ... 107:
|
case 100 ... 107:
|
||||||
self->bg = ((attr - 100 + 8) << 8) | 1; break;
|
self->bg = ((attr - 100 + 8) << 8) | 1; break;
|
||||||
case DECORATION_FG_CODE:
|
case DECORATION_FG_CODE:
|
||||||
SET_COLOR(decoration_fg);
|
SET_COLOR(decoration_fg);
|
||||||
case DECORATION_FG_CODE + 1:
|
case DECORATION_FG_CODE + 1:
|
||||||
self->decoration_fg = 0; break;
|
self->decoration_fg = 0; break;
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *para
|
|||||||
attr = params[i++];
|
attr = params[i++];
|
||||||
switch(attr) {
|
switch(attr) {
|
||||||
case 0:
|
case 0:
|
||||||
RANGE { cell->attrs &= WIDTH_MASK; cell->fg = 0; cell->bg = 0; cell->decoration_fg = 0; }
|
RANGE { cell->attrs &= WIDTH_MASK; cell->fg = 0; cell->bg = 0; cell->decoration_fg = 0; }
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
SET(BOLD_SHIFT);
|
SET(BOLD_SHIFT);
|
||||||
@ -177,13 +177,13 @@ apply_sgr_to_cells(Cell *first_cell, unsigned int cell_count, unsigned int *para
|
|||||||
START_ALLOW_CASE_RANGE
|
START_ALLOW_CASE_RANGE
|
||||||
case 30 ... 37:
|
case 30 ... 37:
|
||||||
SIMPLE(fg, ((attr - 30) << 8) | 1);
|
SIMPLE(fg, ((attr - 30) << 8) | 1);
|
||||||
case 38:
|
case 38:
|
||||||
SET_COLOR(fg);
|
SET_COLOR(fg);
|
||||||
case 39:
|
case 39:
|
||||||
SIMPLE(fg, 0);
|
SIMPLE(fg, 0);
|
||||||
case 40 ... 47:
|
case 40 ... 47:
|
||||||
SIMPLE(bg, ((attr - 40) << 8) | 1);
|
SIMPLE(bg, ((attr - 40) << 8) | 1);
|
||||||
case 48:
|
case 48:
|
||||||
SET_COLOR(bg);
|
SET_COLOR(bg);
|
||||||
case 49:
|
case 49:
|
||||||
SIMPLE(bg, 0);
|
SIMPLE(bg, 0);
|
||||||
@ -224,14 +224,14 @@ color_as_sgr(char *buf, size_t sz, unsigned long val, unsigned simple_code, unsi
|
|||||||
static inline const char*
|
static inline const char*
|
||||||
decoration_as_sgr(uint8_t decoration) {
|
decoration_as_sgr(uint8_t decoration) {
|
||||||
switch(decoration) {
|
switch(decoration) {
|
||||||
case 1: return "4";
|
case 1: return "4";
|
||||||
case 2: return "4:2";
|
case 2: return "4:2";
|
||||||
case 3: return "4:3";
|
case 3: return "4:3";
|
||||||
default: return "24";
|
default: return "24";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
cursor_as_sgr(Cursor *self, Cursor *prev) {
|
cursor_as_sgr(Cursor *self, Cursor *prev) {
|
||||||
static char buf[128];
|
static char buf[128];
|
||||||
#define SZ sizeof(buf) - (p - buf) - 2
|
#define SZ sizeof(buf) - (p - buf) - 2
|
||||||
@ -267,8 +267,8 @@ void cursor_reset(Cursor *self) {
|
|||||||
|
|
||||||
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
||||||
#define CCY(x) dest->x = src->x;
|
#define CCY(x) dest->x = src->x;
|
||||||
CCY(x); CCY(y); CCY(shape); CCY(blink);
|
CCY(x); CCY(y); CCY(shape); CCY(blink);
|
||||||
CCY(bold); CCY(italic); CCY(strikethrough); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
CCY(bold); CCY(italic); CCY(strikethrough); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
@ -317,21 +317,21 @@ PyTypeObject Cursor_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.Cursor",
|
.tp_name = "fast_data_types.Cursor",
|
||||||
.tp_basicsize = sizeof(Cursor),
|
.tp_basicsize = sizeof(Cursor),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_repr = (reprfunc)repr,
|
.tp_repr = (reprfunc)repr,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "Cursors",
|
.tp_doc = "Cursors",
|
||||||
.tp_richcompare = richcmp,
|
.tp_richcompare = richcmp,
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
.tp_getset = getseters,
|
.tp_getset = getseters,
|
||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
};
|
};
|
||||||
|
|
||||||
RICHCMP(Cursor)
|
RICHCMP(Cursor)
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
Cursor*
|
Cursor*
|
||||||
cursor_copy(Cursor *self) {
|
cursor_copy(Cursor *self) {
|
||||||
Cursor* ans;
|
Cursor* ans;
|
||||||
|
|||||||
@ -163,8 +163,8 @@ static PyMethodDef module_methods[] = {
|
|||||||
static struct PyModuleDef module = {
|
static struct PyModuleDef module = {
|
||||||
.m_base = PyModuleDef_HEAD_INIT,
|
.m_base = PyModuleDef_HEAD_INIT,
|
||||||
.m_name = "fast_data_types", /* name of module */
|
.m_name = "fast_data_types", /* name of module */
|
||||||
.m_doc = NULL,
|
.m_doc = NULL,
|
||||||
.m_size = -1,
|
.m_size = -1,
|
||||||
.m_methods = module_methods
|
.m_methods = module_methods
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
|||||||
|
|
||||||
#define CURSOR_TO_ATTRS(c, w) \
|
#define CURSOR_TO_ATTRS(c, w) \
|
||||||
((w) | (((c->decoration & 3) << DECORATION_SHIFT) | ((c->bold & 1) << BOLD_SHIFT) | \
|
((w) | (((c->decoration & 3) << DECORATION_SHIFT) | ((c->bold & 1) << BOLD_SHIFT) | \
|
||||||
((c->italic & 1) << ITALIC_SHIFT) | ((c->reverse & 1) << REVERSE_SHIFT) | ((c->strikethrough & 1) << STRIKE_SHIFT)))
|
((c->italic & 1) << ITALIC_SHIFT) | ((c->reverse & 1) << REVERSE_SHIFT) | ((c->strikethrough & 1) << STRIKE_SHIFT)))
|
||||||
|
|
||||||
#define ATTRS_TO_CURSOR(a, c) \
|
#define ATTRS_TO_CURSOR(a, c) \
|
||||||
(c)->decoration = (a >> DECORATION_SHIFT) & 3; (c)->bold = (a >> BOLD_SHIFT) & 1; (c)->italic = (a >> ITALIC_SHIFT) & 1; \
|
(c)->decoration = (a >> DECORATION_SHIFT) & 3; (c)->bold = (a >> BOLD_SHIFT) & 1; (c)->italic = (a >> ITALIC_SHIFT) & 1; \
|
||||||
@ -221,7 +221,7 @@ typedef struct {
|
|||||||
#define PARSER_BUF_SZ (8 * 1024)
|
#define PARSER_BUF_SZ (8 * 1024)
|
||||||
#define READ_BUF_SZ (1024*1024)
|
#define READ_BUF_SZ (1024*1024)
|
||||||
|
|
||||||
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
||||||
|
|
||||||
#define left_shift_line(line, at, num) \
|
#define left_shift_line(line, at, num) \
|
||||||
for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \
|
for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \
|
||||||
@ -243,7 +243,7 @@ typedef struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Global functions
|
// Global functions
|
||||||
const char* base64_decode(const uint32_t *src, size_t src_sz, uint8_t *dest, size_t dest_capacity, size_t *dest_sz);
|
const char* base64_decode(const uint32_t *src, size_t src_sz, uint8_t *dest, size_t dest_capacity, size_t *dest_sz);
|
||||||
Line* alloc_line();
|
Line* alloc_line();
|
||||||
Cursor* alloc_cursor();
|
Cursor* alloc_cursor();
|
||||||
|
|||||||
4
kitty/emoji.h
generated
4
kitty/emoji.h
generated
@ -274,7 +274,7 @@ static inline bool is_emoji(uint32_t code) {
|
|||||||
return true;
|
return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static inline bool is_emoji_modifier(uint32_t code) {
|
static inline bool is_emoji_modifier(uint32_t code) {
|
||||||
switch(code) {
|
switch(code) {
|
||||||
@ -282,6 +282,6 @@ static inline bool is_emoji_modifier(uint32_t code) {
|
|||||||
return true;
|
return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
END_ALLOW_CASE_RANGE
|
END_ALLOW_CASE_RANGE
|
||||||
|
|||||||
@ -131,9 +131,9 @@ add_charset(FcPattern *pat, size_t num) {
|
|||||||
charset = FcCharSetCreate();
|
charset = FcCharSetCreate();
|
||||||
if (charset == NULL) { PyErr_NoMemory(); goto end; }
|
if (charset == NULL) { PyErr_NoMemory(); goto end; }
|
||||||
for (size_t i = 0; i < num; i++) {
|
for (size_t i = 0; i < num; i++) {
|
||||||
if (!FcCharSetAddChar(charset, char_buf[i])) {
|
if (!FcCharSetAddChar(charset, char_buf[i])) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to add character to fontconfig charset");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to add character to fontconfig charset");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AP(FcPatternAddCharSet, FC_CHARSET, charset, "charset");
|
AP(FcPatternAddCharSet, FC_CHARSET, charset, "charset");
|
||||||
@ -214,7 +214,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_fontconfig_library(PyObject *module) {
|
init_fontconfig_library(PyObject *module) {
|
||||||
if (!FcInit()) {
|
if (!FcInit()) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to initialize the fontconfig library");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to initialize the fontconfig library");
|
||||||
|
|||||||
@ -57,7 +57,7 @@ static char_type shape_buffer[2048] = {0};
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *face;
|
PyObject *face;
|
||||||
// Map glyphs to sprite map co-ords
|
// Map glyphs to sprite map co-ords
|
||||||
SpritePosition sprite_map[1024];
|
SpritePosition sprite_map[1024];
|
||||||
SpecialGlyphCache special_glyph_cache[1024];
|
SpecialGlyphCache special_glyph_cache[1024];
|
||||||
bool bold, italic;
|
bool bold, italic;
|
||||||
} Font;
|
} Font;
|
||||||
@ -79,7 +79,7 @@ static Fonts fonts = {0};
|
|||||||
|
|
||||||
// Sprites {{{
|
// Sprites {{{
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sprite_map_set_error(int error) {
|
sprite_map_set_error(int error) {
|
||||||
switch(error) {
|
switch(error) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -163,7 +163,7 @@ special_glyph_cache_for(Font *font, glyph_index glyph) {
|
|||||||
}
|
}
|
||||||
if (!s->next) {
|
if (!s->next) {
|
||||||
s->next = calloc(1, sizeof(SpecialGlyphCache));
|
s->next = calloc(1, sizeof(SpecialGlyphCache));
|
||||||
if (s->next == NULL) return NULL;
|
if (s->next == NULL) return NULL;
|
||||||
}
|
}
|
||||||
s = s->next;
|
s = s->next;
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ clear_sprite_map(Font *font) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
clear_special_glyph_cache(Font *font) {
|
clear_special_glyph_cache(Font *font) {
|
||||||
#define CLEAR(s) s->filled = false; s->glyph = 0;
|
#define CLEAR(s) s->filled = false; s->glyph = 0;
|
||||||
SpecialGlyphCache *s;
|
SpecialGlyphCache *s;
|
||||||
for (size_t i = 0; i < sizeof(font->special_glyph_cache)/sizeof(font->special_glyph_cache[0]); i++) {
|
for (size_t i = 0; i < sizeof(font->special_glyph_cache)/sizeof(font->special_glyph_cache[0]); i++) {
|
||||||
s = font->special_glyph_cache + i;
|
s = font->special_glyph_cache + i;
|
||||||
@ -247,14 +247,14 @@ init_font(Font *f, PyObject *descriptor, bool bold, bool italic, bool is_face) {
|
|||||||
PyObject *face;
|
PyObject *face;
|
||||||
if (is_face) { face = descriptor; Py_INCREF(face); }
|
if (is_face) { face = descriptor; Py_INCREF(face); }
|
||||||
else { face = desc_to_face(descriptor); if (face == NULL) return false; }
|
else { face = desc_to_face(descriptor); if (face == NULL) return false; }
|
||||||
f->face = face;
|
f->face = face;
|
||||||
f->bold = bold; f->italic = italic;
|
f->bold = bold; f->italic = italic;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
del_font(Font *f) {
|
del_font(Font *f) {
|
||||||
Py_CLEAR(f->face);
|
Py_CLEAR(f->face);
|
||||||
free_maps(f);
|
free_maps(f);
|
||||||
f->bold = false; f->italic = false;
|
f->bold = false; f->italic = false;
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ del_font(Font *f) {
|
|||||||
static unsigned int cell_width = 0, cell_height = 0, baseline = 0, underline_position = 0, underline_thickness = 0;
|
static unsigned int cell_width = 0, cell_height = 0, baseline = 0, underline_position = 0, underline_thickness = 0;
|
||||||
static pixel *canvas = NULL;
|
static pixel *canvas = NULL;
|
||||||
#define CELLS_IN_CANVAS ((MAX_NUM_EXTRA_GLYPHS + 1) * 3)
|
#define CELLS_IN_CANVAS ((MAX_NUM_EXTRA_GLYPHS + 1) * 3)
|
||||||
static inline void
|
static inline void
|
||||||
clear_canvas(void) { memset(canvas, 0, CELLS_IN_CANVAS * cell_width * cell_height * sizeof(pixel)); }
|
clear_canvas(void) { memset(canvas, 0, CELLS_IN_CANVAS * cell_width * cell_height * sizeof(pixel)); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -320,7 +320,7 @@ face_has_codepoint(PyObject* face, char_type cp) {
|
|||||||
return glyph_id_for_codepoint(face, cp) > 0;
|
return glyph_id_for_codepoint(face, cp) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
has_cell_text(Font *self, Cell *cell) {
|
has_cell_text(Font *self, Cell *cell) {
|
||||||
if (!face_has_codepoint(self->face, cell->ch)) return false;
|
if (!face_has_codepoint(self->face, cell->ch)) return false;
|
||||||
if (cell->cc) {
|
if (cell->cc) {
|
||||||
@ -443,7 +443,7 @@ render_alpha_mask(uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
render_box_cell(Cell *cell) {
|
render_box_cell(Cell *cell) {
|
||||||
int error = 0;
|
int error = 0;
|
||||||
glyph_index glyph = box_glyph_id(cell->ch);
|
glyph_index glyph = box_glyph_id(cell->ch);
|
||||||
@ -469,7 +469,7 @@ render_box_cell(Cell *cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
load_hb_buffer(Cell *first_cell, index_type num_cells) {
|
load_hb_buffer(Cell *first_cell, index_type num_cells) {
|
||||||
index_type num;
|
index_type num;
|
||||||
hb_buffer_clear_contents(harfbuzz_buffer);
|
hb_buffer_clear_contents(harfbuzz_buffer);
|
||||||
while (num_cells) {
|
while (num_cells) {
|
||||||
@ -523,10 +523,10 @@ render_group(unsigned int num_cells, unsigned int num_glyphs, Cell *cells, hb_gl
|
|||||||
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, canvas, cell_width, cell_height, num_cells, baseline, &was_colored);
|
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, canvas, cell_width, cell_height, num_cells, baseline, &was_colored);
|
||||||
if (PyErr_Occurred()) PyErr_Print();
|
if (PyErr_Occurred()) PyErr_Print();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < num_cells; i++) {
|
for (unsigned int i = 0; i < num_cells; i++) {
|
||||||
sprite_position[i]->rendered = true;
|
sprite_position[i]->rendered = true;
|
||||||
sprite_position[i]->colored = was_colored;
|
sprite_position[i]->colored = was_colored;
|
||||||
set_cell_sprite(cells + i, sprite_position[i]);
|
set_cell_sprite(cells + i, sprite_position[i]);
|
||||||
pixel *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i, num_cells);
|
pixel *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i, num_cells);
|
||||||
current_send_sprite_to_gpu(sprite_position[i]->x, sprite_position[i]->y, sprite_position[i]->z, buf);
|
current_send_sprite_to_gpu(sprite_position[i]->x, sprite_position[i]->y, sprite_position[i]->z, buf);
|
||||||
}
|
}
|
||||||
@ -549,11 +549,11 @@ is_special_glyph(glyph_index glyph_id, Font *font, CellData* cell_data) {
|
|||||||
if (s == NULL) return false;
|
if (s == NULL) return false;
|
||||||
if (!s->filled) {
|
if (!s->filled) {
|
||||||
s->is_special = cell_data->current_codepoint ? (
|
s->is_special = cell_data->current_codepoint ? (
|
||||||
glyph_id != glyph_id_for_codepoint(font->face, cell_data->current_codepoint) ? true : false)
|
glyph_id != glyph_id_for_codepoint(font->face, cell_data->current_codepoint) ? true : false)
|
||||||
:
|
:
|
||||||
false;
|
false;
|
||||||
s->filled = true;
|
s->filled = true;
|
||||||
}
|
}
|
||||||
return s->is_special;
|
return s->is_special;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,7 +601,7 @@ next_group(Font *font, unsigned int *num_group_cells, unsigned int *num_group_gl
|
|||||||
// how to break text into cells. In addition, we have to deal with
|
// how to break text into cells. In addition, we have to deal with
|
||||||
// monospace ligature fonts that use dummy glyphs of zero size to implement
|
// monospace ligature fonts that use dummy glyphs of zero size to implement
|
||||||
// their ligatures.
|
// their ligatures.
|
||||||
|
|
||||||
CellData cell_data;
|
CellData cell_data;
|
||||||
cell_data.cell = cells; cell_data.num_codepoints = num_codepoints_in_cell(cells); cell_data.codepoints_consumed = 0; cell_data.current_codepoint = cells->ch;
|
cell_data.cell = cells; cell_data.num_codepoints = num_codepoints_in_cell(cells); cell_data.codepoints_consumed = 0; cell_data.current_codepoint = cells->ch;
|
||||||
#define LIMIT (MAX_NUM_EXTRA_GLYPHS + 1)
|
#define LIMIT (MAX_NUM_EXTRA_GLYPHS + 1)
|
||||||
@ -616,7 +616,7 @@ next_group(Font *font, unsigned int *num_group_cells, unsigned int *num_group_gl
|
|||||||
glyph_index glyph_id = info[nglyphs].codepoint;
|
glyph_index glyph_id = info[nglyphs].codepoint;
|
||||||
cluster = info[nglyphs].cluster;
|
cluster = info[nglyphs].cluster;
|
||||||
is_special = is_special_glyph(glyph_id, font, &cell_data);
|
is_special = is_special_glyph(glyph_id, font, &cell_data);
|
||||||
if (prev_was_special && !is_special) break;
|
if (prev_was_special && !is_special) break;
|
||||||
glyphs_in_group[nglyphs++] = glyph_id;
|
glyphs_in_group[nglyphs++] = glyph_id;
|
||||||
// Soak up a number of codepoints indicated by the difference in cluster numbers.
|
// Soak up a number of codepoints indicated by the difference in cluster numbers.
|
||||||
if (cluster > previous_cluster || nglyphs == 1) {
|
if (cluster > previous_cluster || nglyphs == 1) {
|
||||||
@ -693,14 +693,14 @@ test_shape(PyObject UNUSED *self, PyObject *args) {
|
|||||||
if (face == NULL) return NULL;
|
if (face == NULL) return NULL;
|
||||||
font = calloc(1, sizeof(Font));
|
font = calloc(1, sizeof(Font));
|
||||||
font->face = face;
|
font->face = face;
|
||||||
}
|
}
|
||||||
hb_glyph_info_t *info;
|
hb_glyph_info_t *info;
|
||||||
hb_glyph_position_t *positions;
|
hb_glyph_position_t *positions;
|
||||||
unsigned int num_glyphs = shape(line->cells, num, harfbuzz_font_for_face(font->face), &info, &positions);
|
unsigned int num_glyphs = shape(line->cells, num, harfbuzz_font_for_face(font->face), &info, &positions);
|
||||||
|
|
||||||
PyObject *ans = PyList_New(0);
|
PyObject *ans = PyList_New(0);
|
||||||
unsigned int run_pos = 0, cell_pos = 0, num_group_glyphs, num_group_cells;
|
unsigned int run_pos = 0, cell_pos = 0, num_group_glyphs, num_group_cells;
|
||||||
ExtraGlyphs extra_glyphs;
|
ExtraGlyphs extra_glyphs;
|
||||||
glyph_index first_glyph;
|
glyph_index first_glyph;
|
||||||
while(run_pos < num_glyphs && cell_pos < num) {
|
while(run_pos < num_glyphs && cell_pos < num) {
|
||||||
first_glyph = next_group(font, &num_group_cells, &num_group_glyphs, line->cells + cell_pos, info + run_pos, num_glyphs - run_pos, num - cell_pos, &extra_glyphs);
|
first_glyph = next_group(font, &num_group_cells, &num_group_glyphs, line->cells + cell_pos, info + run_pos, num_glyphs - run_pos, num - cell_pos, &extra_glyphs);
|
||||||
@ -713,7 +713,7 @@ test_shape(PyObject UNUSED *self, PyObject *args) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
render_run(Cell *first_cell, index_type num_cells, ssize_t font_idx) {
|
render_run(Cell *first_cell, index_type num_cells, ssize_t font_idx) {
|
||||||
switch(font_idx) {
|
switch(font_idx) {
|
||||||
default:
|
default:
|
||||||
@ -763,7 +763,7 @@ set_font(PyObject UNUSED *m, PyObject *args) {
|
|||||||
for (size_t i = 0; i < fonts.fonts_count; i++) del_font(fonts.fonts + i);
|
for (size_t i = 0; i < fonts.fonts_count; i++) del_font(fonts.fonts + i);
|
||||||
ensure_space_for(&fonts, fonts, Font, num_fonts, fonts_capacity, 5, true);
|
ensure_space_for(&fonts, fonts, Font, num_fonts, fonts_capacity, 5, true);
|
||||||
fonts.fonts_count = 1;
|
fonts.fonts_count = 1;
|
||||||
#define A(attr, bold, italic) { if(attr) { if (!init_font(&fonts.fonts[fonts.fonts_count], attr, bold, italic, false)) return NULL; fonts.attr##_font_idx = fonts.fonts_count++; } else fonts.attr##_font_idx = -1; }
|
#define A(attr, bold, italic) { if(attr) { if (!init_font(&fonts.fonts[fonts.fonts_count], attr, bold, italic, false)) return NULL; fonts.attr##_font_idx = fonts.fonts_count++; } else fonts.attr##_font_idx = -1; }
|
||||||
A(medium, false, false);
|
A(medium, false, false);
|
||||||
A(bold, true, false); A(italic, false, true); A(bi, true, true);
|
A(bold, true, false); A(italic, false, true); A(bi, true, true);
|
||||||
#undef A
|
#undef A
|
||||||
@ -925,7 +925,7 @@ error:
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
get_fallback_font(PyObject UNUSED *self, PyObject *args) {
|
get_fallback_font(PyObject UNUSED *self, PyObject *args) {
|
||||||
PyObject *text;
|
PyObject *text;
|
||||||
int bold, italic;
|
int bold, italic;
|
||||||
if (!PyArg_ParseTuple(args, "Upp", &text, &bold, &italic)) return NULL;
|
if (!PyArg_ParseTuple(args, "Upp", &text, &bold, &italic)) return NULL;
|
||||||
static Py_UCS4 char_buf[16];
|
static Py_UCS4 char_buf[16];
|
||||||
@ -958,7 +958,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_fonts(PyObject *module) {
|
init_fonts(PyObject *module) {
|
||||||
if (Py_AtExit(finalize) != 0) {
|
if (Py_AtExit(finalize) != 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to register the fonts module at exit handler");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to register the fonts module at exit handler");
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
unsigned int glyph_id_for_codepoint(PyObject *, char_type);
|
unsigned int glyph_id_for_codepoint(PyObject *, char_type);
|
||||||
hb_font_t* harfbuzz_font_for_face(PyObject*);
|
hb_font_t* harfbuzz_font_for_face(PyObject*);
|
||||||
bool set_size_for_face(PyObject*, unsigned int, bool);
|
bool set_size_for_face(PyObject*, unsigned int, bool);
|
||||||
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
|
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
|
||||||
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored);
|
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored);
|
||||||
PyObject* create_fallback_face(PyObject *base_face, Cell* cell, bool bold, bool italic);
|
PyObject* create_fallback_face(PyObject *base_face, Cell* cell, bool bold, bool italic);
|
||||||
PyObject* specialize_font_descriptor(PyObject *base_descriptor);
|
PyObject* specialize_font_descriptor(PyObject *base_descriptor);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ PyTypeObject Face_Type;
|
|||||||
|
|
||||||
static PyObject* FreeType_Exception = NULL;
|
static PyObject* FreeType_Exception = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
set_freetype_error(const char* prefix, int err_code) {
|
set_freetype_error(const char* prefix, int err_code) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
#undef FTERRORS_H_
|
#undef FTERRORS_H_
|
||||||
@ -54,7 +54,7 @@ set_freetype_error(const char* prefix, int err_code) {
|
|||||||
|
|
||||||
#ifdef FT_ERRORS_H
|
#ifdef FT_ERRORS_H
|
||||||
#include FT_ERRORS_H
|
#include FT_ERRORS_H
|
||||||
#else
|
#else
|
||||||
FT_ERROR_START_LIST FT_ERROR_END_LIST
|
FT_ERROR_START_LIST FT_ERROR_END_LIST
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -121,8 +121,8 @@ set_font_size(Face *self, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_freetype_error("Failed to set char size, with error:", error);
|
set_freetype_error("Failed to set char size, with error:", error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !error;
|
return !error;
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle) {
|
|||||||
PyObject*
|
PyObject*
|
||||||
ft_face_from_data(const uint8_t* data, size_t sz, void *extra_data, free_extra_data_func fed, PyObject *path, int hinting, int hintstyle, float apple_leading) {
|
ft_face_from_data(const uint8_t* data, size_t sz, void *extra_data, free_extra_data_func fed, PyObject *path, int hinting, int hintstyle, float apple_leading) {
|
||||||
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
||||||
if (ans == NULL) return NULL;
|
if (ans == NULL) return NULL;
|
||||||
int error = FT_New_Memory_Face(library, data, sz, 0, &ans->face);
|
int error = FT_New_Memory_Face(library, data, sz, 0, &ans->face);
|
||||||
if(error) { set_freetype_error("Failed to load memory face, with error:", error); Py_CLEAR(ans); return NULL; }
|
if(error) { set_freetype_error("Failed to load memory face, with error:", error); Py_CLEAR(ans); return NULL; }
|
||||||
if (!init_ft_face(ans, path, hinting, hintstyle)) { Py_CLEAR(ans); return NULL; }
|
if (!init_ft_face(ans, path, hinting, hintstyle)) { Py_CLEAR(ans); return NULL; }
|
||||||
@ -232,7 +232,7 @@ face_from_descriptor(PyObject *descriptor) {
|
|||||||
}
|
}
|
||||||
return (PyObject*)self;
|
return (PyObject*)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
face_from_path(const char *path, int index) {
|
face_from_path(const char *path, int index) {
|
||||||
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
||||||
@ -265,7 +265,7 @@ repr(Face *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
load_glyph(Face *self, int glyph_index, int load_type) {
|
load_glyph(Face *self, int glyph_index, int load_type) {
|
||||||
int flags = get_load_flags(self->hinting, self->hintstyle, load_type);
|
int flags = get_load_flags(self->hinting, self->hintstyle, load_type);
|
||||||
int error = FT_Load_Glyph(self->face, glyph_index, flags);
|
int error = FT_Load_Glyph(self->face, glyph_index, flags);
|
||||||
@ -285,7 +285,7 @@ calc_cell_width(Face *self) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
||||||
Face *self = (Face*)s;
|
Face *self = (Face*)s;
|
||||||
*cell_width = calc_cell_width(self);
|
*cell_width = calc_cell_width(self);
|
||||||
@ -295,7 +295,7 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
|
|||||||
*underline_thickness = MAX(1, font_units_to_pixels(self, self->underline_thickness));
|
*underline_thickness = MAX(1, font_units_to_pixels(self, self->underline_thickness));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
glyph_id_for_codepoint(PyObject *s, char_type cp) {
|
glyph_id_for_codepoint(PyObject *s, char_type cp) {
|
||||||
return FT_Get_Char_Index(((Face*)s)->face, cp);
|
return FT_Get_Char_Index(((Face*)s)->face, cp);
|
||||||
}
|
}
|
||||||
@ -376,12 +376,12 @@ downsample_bitmap(ProcessedBitmap *bm, unsigned int width, unsigned int cell_hei
|
|||||||
for (unsigned int y=sr; y < MIN(sr + factor, bm->rows); y++) {
|
for (unsigned int y=sr; y < MIN(sr + factor, bm->rows); y++) {
|
||||||
uint8_t *p = bm->buf + (y * bm->stride) + sc * 4;
|
uint8_t *p = bm->buf + (y * bm->stride) + sc * 4;
|
||||||
for (unsigned int x=sc; x < MIN(sc + factor, bm->width); x++, count++) {
|
for (unsigned int x=sc; x < MIN(sc + factor, bm->width); x++, count++) {
|
||||||
b += *(p++); g += *(p++); r += *(p++); a += *(p++);
|
b += *(p++); g += *(p++); r += *(p++); a += *(p++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
d[0] = b / count; d[1] = g / count; d[2] = r / count; d[3] = a / count;
|
d[0] = b / count; d[1] = g / count; d[2] = r / count; d[3] = a / count;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,7 +506,7 @@ render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *inf
|
|||||||
y = (float)positions[i].y_offset / 64.0f;
|
y = (float)positions[i].y_offset / 64.0f;
|
||||||
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, &self->face->glyph->metrics, baseline);
|
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, &self->face->glyph->metrics, baseline);
|
||||||
x += (float)positions[i].x_advance / 64.0f;
|
x += (float)positions[i].x_advance / 64.0f;
|
||||||
if (bm.needs_free) free(bm.buf);
|
if (bm.needs_free) free(bm.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// center the glyphs in the canvas
|
// center the glyphs in the canvas
|
||||||
@ -560,8 +560,8 @@ PyTypeObject Face_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.Face",
|
.tp_name = "fast_data_types.Face",
|
||||||
.tp_basicsize = sizeof(Face),
|
.tp_basicsize = sizeof(Face),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "FreeType Font face",
|
.tp_doc = "FreeType Font face",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
@ -573,11 +573,11 @@ free_freetype() {
|
|||||||
FT_Done_FreeType(library);
|
FT_Done_FreeType(library);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_freetype_library(PyObject *m) {
|
init_freetype_library(PyObject *m) {
|
||||||
if (PyType_Ready(&Face_Type) < 0) return 0;
|
if (PyType_Ready(&Face_Type) < 0) return 0;
|
||||||
if (PyModule_AddObject(m, "Face", (PyObject *)&Face_Type) != 0) return 0;
|
if (PyModule_AddObject(m, "Face", (PyObject *)&Face_Type) != 0) return 0;
|
||||||
Py_INCREF(&Face_Type);
|
Py_INCREF(&Face_Type);
|
||||||
FreeType_Exception = PyErr_NewException("fast_data_types.FreeTypeError", NULL, NULL);
|
FreeType_Exception = PyErr_NewException("fast_data_types.FreeTypeError", NULL, NULL);
|
||||||
if (FreeType_Exception == NULL) return false;
|
if (FreeType_Exception == NULL) return false;
|
||||||
if (PyModule_AddObject(m, "FreeTypeError", FreeType_Exception) != 0) return false;
|
if (PyModule_AddObject(m, "FreeTypeError", FreeType_Exception) != 0) return false;
|
||||||
|
|||||||
1622
kitty/gl-wrapper.c
generated
1622
kitty/gl-wrapper.c
generated
File diff suppressed because it is too large
Load Diff
40
kitty/gl.h
40
kitty/gl.h
@ -22,24 +22,24 @@ static void
|
|||||||
check_for_gl_error(const char *name, void UNUSED *funcptr, int UNUSED len_args, ...) {
|
check_for_gl_error(const char *name, void UNUSED *funcptr, int UNUSED len_args, ...) {
|
||||||
#define f(msg) fatal("OpenGL error: %s (calling function: %s)", msg, name); break;
|
#define f(msg) fatal("OpenGL error: %s (calling function: %s)", msg, name); break;
|
||||||
GLenum code = glad_glGetError();
|
GLenum code = glad_glGetError();
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case GL_NO_ERROR: break;
|
case GL_NO_ERROR: break;
|
||||||
case GL_INVALID_ENUM:
|
case GL_INVALID_ENUM:
|
||||||
f("An enum value is invalid (GL_INVALID_ENUM)");
|
f("An enum value is invalid (GL_INVALID_ENUM)");
|
||||||
case GL_INVALID_VALUE:
|
case GL_INVALID_VALUE:
|
||||||
f("An numeric value is invalid (GL_INVALID_VALUE)");
|
f("An numeric value is invalid (GL_INVALID_VALUE)");
|
||||||
case GL_INVALID_OPERATION:
|
case GL_INVALID_OPERATION:
|
||||||
f("This operation is invalid (GL_INVALID_OPERATION)");
|
f("This operation is invalid (GL_INVALID_OPERATION)");
|
||||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||||
f("The framebuffer object is not complete (GL_INVALID_FRAMEBUFFER_OPERATION)");
|
f("The framebuffer object is not complete (GL_INVALID_FRAMEBUFFER_OPERATION)");
|
||||||
case GL_OUT_OF_MEMORY:
|
case GL_OUT_OF_MEMORY:
|
||||||
f("There is not enough memory left to execute the command. (GL_OUT_OF_MEMORY)");
|
f("There is not enough memory left to execute the command. (GL_OUT_OF_MEMORY)");
|
||||||
case GL_STACK_UNDERFLOW:
|
case GL_STACK_UNDERFLOW:
|
||||||
f("An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_UNDERFLOW)");
|
f("An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_UNDERFLOW)");
|
||||||
case GL_STACK_OVERFLOW:
|
case GL_STACK_OVERFLOW:
|
||||||
f("An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_OVERFLOW)");
|
f("An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_OVERFLOW)");
|
||||||
default:
|
default:
|
||||||
fatal("An unknown OpenGL error occurred with code: %d (calling function: %s)", code, name);
|
fatal("An unknown OpenGL error occurred with code: %d (calling function: %s)", code, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ update_surface_size(int w, int h, GLuint offscreen_texture_id) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
free_texture(GLuint *tex_id) {
|
free_texture(GLuint *tex_id) {
|
||||||
glDeleteTextures(1, tex_id);
|
glDeleteTextures(1, tex_id);
|
||||||
*tex_id = 0;
|
*tex_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +288,7 @@ add_buffer_to_vao(ssize_t vao_idx, GLenum usage) {
|
|||||||
static void
|
static void
|
||||||
add_located_attribute_to_vao(ssize_t vao_idx, GLint aloc, GLint size, GLenum data_type, GLsizei stride, void *offset, GLuint divisor) {
|
add_located_attribute_to_vao(ssize_t vao_idx, GLint aloc, GLint size, GLenum data_type, GLsizei stride, void *offset, GLuint divisor) {
|
||||||
VAO *vao = vaos + vao_idx;
|
VAO *vao = vaos + vao_idx;
|
||||||
if (!vao->num_buffers) fatal("You must create a buffer for this attribute first");
|
if (!vao->num_buffers) fatal("You must create a buffer for this attribute first");
|
||||||
ssize_t buf = vao->buffers[vao->num_buffers - 1];
|
ssize_t buf = vao->buffers[vao->num_buffers - 1];
|
||||||
bind_buffer(buf);
|
bind_buffer(buf);
|
||||||
glEnableVertexAttribArray(aloc);
|
glEnableVertexAttribArray(aloc);
|
||||||
@ -315,7 +315,7 @@ add_located_attribute_to_vao(ssize_t vao_idx, GLint aloc, GLint size, GLenum dat
|
|||||||
static inline void
|
static inline void
|
||||||
add_attribute_to_vao(int p, ssize_t vao_idx, const char *name, GLint size, GLenum data_type, GLsizei stride, void *offset, GLuint divisor) {
|
add_attribute_to_vao(int p, ssize_t vao_idx, const char *name, GLint size, GLenum data_type, GLsizei stride, void *offset, GLuint divisor) {
|
||||||
GLint aloc = attrib_location(p, name);
|
GLint aloc = attrib_location(p, name);
|
||||||
if (aloc == -1) fatal("No attribute named: %s found in this program", name);
|
if (aloc == -1) fatal("No attribute named: %s found in this program", name);
|
||||||
add_located_attribute_to_vao(vao_idx, aloc, size, data_type, stride, offset, divisor);
|
add_located_attribute_to_vao(vao_idx, aloc, size, data_type, stride, offset, divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
kitty/glfw-wrapper.h
generated
2
kitty/glfw-wrapper.h
generated
@ -804,7 +804,7 @@
|
|||||||
* @sa @ref glfwGetProcAddress
|
* @sa @ref glfwGetProcAddress
|
||||||
*
|
*
|
||||||
* @since Added in version 3.0.
|
* @since Added in version 3.0.
|
||||||
|
|
||||||
* @ingroup context
|
* @ingroup context
|
||||||
*/
|
*/
|
||||||
typedef void (*GLFWglproc)(void);
|
typedef void (*GLFWglproc)(void);
|
||||||
|
|||||||
56
kitty/glfw.c
56
kitty/glfw.c
@ -34,7 +34,7 @@ update_os_window_viewport(OSWindow *window, bool notify_boss) {
|
|||||||
|
|
||||||
// callbacks {{{
|
// callbacks {{{
|
||||||
|
|
||||||
void
|
void
|
||||||
update_os_window_references() {
|
update_os_window_references() {
|
||||||
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
||||||
OSWindow *w = global_state.os_windows + i;
|
OSWindow *w = global_state.os_windows + i;
|
||||||
@ -68,10 +68,10 @@ is_window_ready_for_callbacks() {
|
|||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
show_mouse_cursor(GLFWwindow *w) {
|
show_mouse_cursor(GLFWwindow *w) {
|
||||||
if (glfwGetInputMode(w, GLFW_CURSOR) != GLFW_CURSOR_NORMAL) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
|
if (glfwGetInputMode(w, GLFW_CURSOR) != GLFW_CURSOR_NORMAL) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
framebuffer_size_callback(GLFWwindow *w, int width, int height) {
|
framebuffer_size_callback(GLFWwindow *w, int width, int height) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
if (width > 100 && height > 100) {
|
if (width > 100 && height > 100) {
|
||||||
@ -86,7 +86,7 @@ framebuffer_size_callback(GLFWwindow *w, int width, int height) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
char_mods_callback(GLFWwindow *w, unsigned int codepoint, int mods) {
|
char_mods_callback(GLFWwindow *w, unsigned int codepoint, int mods) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
||||||
@ -94,7 +94,7 @@ char_mods_callback(GLFWwindow *w, unsigned int codepoint, int mods) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
|
key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
||||||
@ -105,7 +105,7 @@ key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
|
mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
show_mouse_cursor(w);
|
show_mouse_cursor(w);
|
||||||
@ -118,7 +118,7 @@ mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
show_mouse_cursor(w);
|
show_mouse_cursor(w);
|
||||||
@ -131,7 +131,7 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scroll_callback(GLFWwindow *w, double xoffset, double yoffset) {
|
scroll_callback(GLFWwindow *w, double xoffset, double yoffset) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
show_mouse_cursor(w);
|
show_mouse_cursor(w);
|
||||||
@ -141,12 +141,12 @@ scroll_callback(GLFWwindow *w, double xoffset, double yoffset) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_focus_callback(GLFWwindow *w, int focused) {
|
window_focus_callback(GLFWwindow *w, int focused) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
global_state.callback_os_window->is_focused = focused ? true : false;
|
global_state.callback_os_window->is_focused = focused ? true : false;
|
||||||
if (focused) {
|
if (focused) {
|
||||||
show_mouse_cursor(w);
|
show_mouse_cursor(w);
|
||||||
focus_in_event();
|
focus_in_event();
|
||||||
}
|
}
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
@ -158,7 +158,7 @@ window_focus_callback(GLFWwindow *w, int focused) {
|
|||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drop_callback(GLFWwindow *w, int count, const char **paths) {
|
drop_callback(GLFWwindow *w, int count, const char **paths) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
PyObject *p = PyTuple_New(count);
|
PyObject *p = PyTuple_New(count);
|
||||||
@ -201,7 +201,7 @@ set_default_window_icon(PyObject UNUSED *self, PyObject *args) {
|
|||||||
|
|
||||||
static GLFWwindow *current_os_window_ctx = NULL;
|
static GLFWwindow *current_os_window_ctx = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
make_os_window_context_current(OSWindow *w) {
|
make_os_window_context_current(OSWindow *w) {
|
||||||
if (w->handle != current_os_window_ctx) {
|
if (w->handle != current_os_window_ctx) {
|
||||||
current_os_window_ctx = w->handle;
|
current_os_window_ctx = w->handle;
|
||||||
@ -288,7 +288,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
click_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
click_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
||||||
arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||||
if (standard_cursor == NULL || click_cursor == NULL || arrow_cursor == NULL) {
|
if (standard_cursor == NULL || click_cursor == NULL || arrow_cursor == NULL) {
|
||||||
PyErr_SetString(PyExc_ValueError, "Failed to create standard mouse cursors"); return NULL;
|
PyErr_SetString(PyExc_ValueError, "Failed to create standard mouse cursors"); return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
||||||
current_os_window_ctx = glfw_window;
|
current_os_window_ctx = glfw_window;
|
||||||
glfwSwapInterval(swap_interval); // a value of 1 makes mouse selection laggy
|
glfwSwapInterval(swap_interval); // a value of 1 makes mouse selection laggy
|
||||||
if (is_first_window) {
|
if (is_first_window) {
|
||||||
set_dpi_from_window(NULL);
|
set_dpi_from_window(NULL);
|
||||||
gl_init();
|
gl_init();
|
||||||
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER));
|
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER));
|
||||||
@ -378,14 +378,14 @@ show_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
void
|
void
|
||||||
destroy_os_window(OSWindow *w) {
|
destroy_os_window(OSWindow *w) {
|
||||||
if (w->handle) {
|
if (w->handle) {
|
||||||
glfwDestroyWindow(w->handle);
|
glfwDestroyWindow(w->handle);
|
||||||
if (current_os_window_ctx == w->handle) current_os_window_ctx = NULL;
|
if (current_os_window_ctx == w->handle) current_os_window_ctx = NULL;
|
||||||
}
|
}
|
||||||
w->handle = NULL;
|
w->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global functions {{{
|
// Global functions {{{
|
||||||
static void
|
static void
|
||||||
error_callback(int error, const char* description) {
|
error_callback(int error, const char* description) {
|
||||||
fprintf(stderr, "[glfw error %d]: %s\n", error, description);
|
fprintf(stderr, "[glfw error %d]: %s\n", error, description);
|
||||||
}
|
}
|
||||||
@ -522,11 +522,11 @@ toggle_fullscreen(PyObject UNUSED *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ring_audio_bell(OSWindow *w) {
|
ring_audio_bell(OSWindow *w) {
|
||||||
static double last_bell_at = -1;
|
static double last_bell_at = -1;
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
if (now - last_bell_at <= 0.1) return;
|
if (now - last_bell_at <= 0.1) return;
|
||||||
last_bell_at = now;
|
last_bell_at = now;
|
||||||
if (w->handle) {
|
if (w->handle) {
|
||||||
glfwWindowBell(w->handle, OPT(x11_bell_volume));
|
glfwWindowBell(w->handle, OPT(x11_bell_volume));
|
||||||
@ -555,7 +555,7 @@ hide_mouse(OSWindow *w) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
swap_window_buffers(OSWindow *w) {
|
swap_window_buffers(OSWindow *w) {
|
||||||
glfwSwapBuffers(w->handle);
|
glfwSwapBuffers(w->handle);
|
||||||
}
|
}
|
||||||
@ -571,7 +571,7 @@ wakeup_main_loop() {
|
|||||||
glfwPostEmptyEvent();
|
glfwPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mark_os_window_for_close(OSWindow* w, bool yes) {
|
mark_os_window_for_close(OSWindow* w, bool yes) {
|
||||||
glfwSetWindowShouldClose(w->handle, yes);
|
glfwSetWindowShouldClose(w->handle, yes);
|
||||||
}
|
}
|
||||||
@ -694,14 +694,14 @@ static PyMethodDef module_methods[] = {
|
|||||||
METHODB(x11_window_id, METH_O),
|
METHODB(x11_window_id, METH_O),
|
||||||
METHODB(set_primary_selection, METH_VARARGS),
|
METHODB(set_primary_selection, METH_VARARGS),
|
||||||
METHODB(glfw_poll_events, METH_NOARGS),
|
METHODB(glfw_poll_events, METH_NOARGS),
|
||||||
{"glfw_init", (PyCFunction)glfw_init, METH_VARARGS, ""},
|
{"glfw_init", (PyCFunction)glfw_init, METH_VARARGS, ""},
|
||||||
{"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""},
|
{"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""},
|
||||||
{"glfw_wait_events", (PyCFunction)glfw_wait_events, METH_VARARGS, ""},
|
{"glfw_wait_events", (PyCFunction)glfw_wait_events, METH_VARARGS, ""},
|
||||||
{"glfw_post_empty_event", (PyCFunction)glfw_post_empty_event, METH_NOARGS, ""},
|
{"glfw_post_empty_event", (PyCFunction)glfw_post_empty_event, METH_NOARGS, ""},
|
||||||
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""},
|
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""},
|
||||||
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""},
|
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""},
|
||||||
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
|
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
|
||||||
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
|
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -81,7 +81,7 @@ static inline void
|
|||||||
remove_from_array(void *array, size_t item_size, size_t idx, size_t array_count) {
|
remove_from_array(void *array, size_t item_size, size_t idx, size_t array_count) {
|
||||||
size_t num_to_right = array_count - 1 - idx;
|
size_t num_to_right = array_count - 1 - idx;
|
||||||
uint8_t *p = (uint8_t*)array;
|
uint8_t *p = (uint8_t*)array;
|
||||||
if (num_to_right > 0) memmove(p + (idx * item_size), p + ((idx + 1) * item_size), num_to_right * item_size);
|
if (num_to_right > 0) memmove(p + (idx * item_size), p + ((idx + 1) * item_size), num_to_right * item_size);
|
||||||
memset(p + (item_size * (array_count - 1)), 0, item_size);
|
memset(p + (item_size * (array_count - 1)), 0, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ trim_predicate(Image *img) {
|
|||||||
static int
|
static int
|
||||||
oldest_last(const void* a, const void *b) {
|
oldest_last(const void* a, const void *b) {
|
||||||
double ans = ((Image*)(b))->atime - ((Image*)(a))->atime;
|
double ans = ((Image*)(b))->atime - ((Image*)(a))->atime;
|
||||||
return ans < 0 ? -1 : (ans == 0 ? 0 : 1);
|
return ans < 0 ? -1 : (ans == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -171,7 +171,7 @@ mmap_img_file(GraphicsManager UNUSED *self, Image *img, int fd, size_t sz, off_t
|
|||||||
sz = s.st_size;
|
sz = s.st_size;
|
||||||
}
|
}
|
||||||
void *addr = mmap(0, sz, PROT_READ, MAP_SHARED, fd, offset);
|
void *addr = mmap(0, sz, PROT_READ, MAP_SHARED, fd, offset);
|
||||||
if (addr == MAP_FAILED) ABRT(EBADF, "Failed to map image file fd: %d at offset: %zd with size: %zu with error: [%d] %s", fd, offset, sz, errno, strerror(errno));
|
if (addr == MAP_FAILED) ABRT(EBADF, "Failed to map image file fd: %d at offset: %zd with size: %zu with error: [%d] %s", fd, offset, sz, errno, strerror(errno));
|
||||||
img->load_data.mapped_file = addr;
|
img->load_data.mapped_file = addr;
|
||||||
img->load_data.mapped_file_sz = sz;
|
img->load_data.mapped_file_sz = sz;
|
||||||
return true;
|
return true;
|
||||||
@ -267,7 +267,7 @@ inflate_png_inner(struct png_jmp_data *d, uint8_t *buf, size_t bufsz) {
|
|||||||
if (!info) ABRT(ENOMEM, "Failed to create PNG info structure");
|
if (!info) ABRT(ENOMEM, "Failed to create PNG info structure");
|
||||||
|
|
||||||
if (setjmp(jb)) goto err;
|
if (setjmp(jb)) goto err;
|
||||||
|
|
||||||
png_set_read_fn(png, &f, read_png_from_buffer);
|
png_set_read_fn(png, &f, read_png_from_buffer);
|
||||||
png_read_info(png, info);
|
png_read_info(png, info);
|
||||||
png_byte color_type, bit_depth;
|
png_byte color_type, bit_depth;
|
||||||
@ -312,7 +312,7 @@ inflate_png(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufsz
|
|||||||
if (d.ok) {
|
if (d.ok) {
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
img->load_data.buf = d.decompressed;
|
img->load_data.buf = d.decompressed;
|
||||||
img->load_data.buf_capacity = d.sz;
|
img->load_data.buf_capacity = d.sz;
|
||||||
img->load_data.buf_used = d.sz;
|
img->load_data.buf_used = d.sz;
|
||||||
img->load_data.data_sz = d.sz;
|
img->load_data.data_sz = d.sz;
|
||||||
img->width = d.width; img->height = d.height;
|
img->width = d.width; img->height = d.height;
|
||||||
@ -376,7 +376,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
img->atime = monotonic(); img->used_storage = 0;
|
img->atime = monotonic(); img->used_storage = 0;
|
||||||
img->width = g->data_width; img->height = g->data_height;
|
img->width = g->data_width; img->height = g->data_height;
|
||||||
switch(fmt) {
|
switch(fmt) {
|
||||||
case PNG:
|
case PNG:
|
||||||
if (g->data_sz > MAX_DATA_SZ) ABRT(EINVAL, "PNG data size too large");
|
if (g->data_sz > MAX_DATA_SZ) ABRT(EINVAL, "PNG data size too large");
|
||||||
img->load_data.is_4byte_aligned = true;
|
img->load_data.is_4byte_aligned = true;
|
||||||
img->load_data.is_opaque = false;
|
img->load_data.is_opaque = false;
|
||||||
@ -513,7 +513,7 @@ create_add_response(GraphicsManager UNUSED *self, bool data_loaded, uint32_t iid
|
|||||||
if (iid) {
|
if (iid) {
|
||||||
if (!has_add_respose) {
|
if (!has_add_respose) {
|
||||||
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, "Gi=%u;%s", iid, add_response);
|
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "Gi=%u;%s", iid, add_response);
|
||||||
return rbuf;
|
return rbuf;
|
||||||
@ -541,18 +541,18 @@ update_dest_rect(ImageRef *ref, uint32_t num_cols, uint32_t num_rows) {
|
|||||||
t = ref->src_width + ref->cell_x_offset;
|
t = ref->src_width + ref->cell_x_offset;
|
||||||
num_cols = t / global_state.cell_width;
|
num_cols = t / global_state.cell_width;
|
||||||
if (t > num_cols * global_state.cell_width) num_cols += 1;
|
if (t > num_cols * global_state.cell_width) num_cols += 1;
|
||||||
}
|
}
|
||||||
if (num_rows == 0) {
|
if (num_rows == 0) {
|
||||||
t = ref->src_height + ref->cell_y_offset;
|
t = ref->src_height + ref->cell_y_offset;
|
||||||
num_rows = t / global_state.cell_height;
|
num_rows = t / global_state.cell_height;
|
||||||
if (t > num_rows * global_state.cell_height) num_rows += 1;
|
if (t > num_rows * global_state.cell_height) num_rows += 1;
|
||||||
}
|
}
|
||||||
ref->effective_num_rows = num_rows;
|
ref->effective_num_rows = num_rows;
|
||||||
ref->effective_num_cols = num_cols;
|
ref->effective_num_cols = num_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_put_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, Image *img) {
|
handle_put_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, Image *img) {
|
||||||
has_add_respose = false;
|
has_add_respose = false;
|
||||||
if (img == NULL) img = img_by_client_id(self, g->id);
|
if (img == NULL) img = img_by_client_id(self, g->id);
|
||||||
@ -584,12 +584,12 @@ handle_put_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, b
|
|||||||
c->x += ref->effective_num_cols; c->y += ref->effective_num_rows - 1;
|
c->x += ref->effective_num_cols; c->y += ref->effective_num_rows - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_by_zindex_and_image(const void *a_, const void *b_) {
|
cmp_by_zindex_and_image(const void *a_, const void *b_) {
|
||||||
const ImageRenderData *a = (const ImageRenderData*)a_, *b = (const ImageRenderData*)b_;
|
const ImageRenderData *a = (const ImageRenderData*)a_, *b = (const ImageRenderData*)b_;
|
||||||
int ans = a->z_index - b->z_index;
|
int ans = a->z_index - b->z_index;
|
||||||
if (ans == 0) ans = a->image_id - b->image_id;
|
if (ans == 0) ans = a->image_id - b->image_id;
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -656,9 +656,9 @@ filter_refs(GraphicsManager *self, const void* data, bool free_images, bool (*fi
|
|||||||
size_t i, j;
|
size_t i, j;
|
||||||
|
|
||||||
if (self->image_count) {
|
if (self->image_count) {
|
||||||
for (i = self->image_count; i-- > 0;) {
|
for (i = self->image_count; i-- > 0;) {
|
||||||
img = self->images + i;
|
img = self->images + i;
|
||||||
for (j = img->refcnt; j-- > 0;) {
|
for (j = img->refcnt; j-- > 0;) {
|
||||||
ref = img->refs + j;
|
ref = img->refs + j;
|
||||||
if (filter_func(ref, img, data)) {
|
if (filter_func(ref, img, data)) {
|
||||||
remove_from_array(img->refs, sizeof(ImageRef), j, img->refcnt--);
|
remove_from_array(img->refs, sizeof(ImageRef), j, img->refcnt--);
|
||||||
@ -718,7 +718,7 @@ scroll_filter_margins_func(ImageRef* ref, Image* img, const void* data) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grman_scroll_images(GraphicsManager *self, const ScrollData *data) {
|
grman_scroll_images(GraphicsManager *self, const ScrollData *data) {
|
||||||
filter_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
|
filter_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
|
||||||
}
|
}
|
||||||
@ -799,18 +799,18 @@ handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
void
|
void
|
||||||
grman_resize(GraphicsManager *self, index_type UNUSED old_lines, index_type UNUSED lines, index_type UNUSED old_columns, index_type UNUSED columns) {
|
grman_resize(GraphicsManager *self, index_type UNUSED old_lines, index_type UNUSED lines, index_type UNUSED old_columns, index_type UNUSED columns) {
|
||||||
self->layers_dirty = true;
|
self->layers_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grman_rescale(GraphicsManager *self, unsigned int UNUSED old_cell_width, unsigned int UNUSED old_cell_height) {
|
grman_rescale(GraphicsManager *self, unsigned int UNUSED old_cell_width, unsigned int UNUSED old_cell_height) {
|
||||||
ImageRef *ref; Image *img;
|
ImageRef *ref; Image *img;
|
||||||
self->layers_dirty = true;
|
self->layers_dirty = true;
|
||||||
for (size_t i = self->image_count; i-- > 0;) {
|
for (size_t i = self->image_count; i-- > 0;) {
|
||||||
img = self->images + i;
|
img = self->images + i;
|
||||||
for (size_t j = img->refcnt; j-- > 0;) {
|
for (size_t j = img->refcnt; j-- > 0;) {
|
||||||
ref = img->refs + j;
|
ref = img->refs + j;
|
||||||
ref->cell_x_offset = MIN(ref->cell_x_offset, global_state.cell_width - 1);
|
ref->cell_x_offset = MIN(ref->cell_x_offset, global_state.cell_width - 1);
|
||||||
ref->cell_y_offset = MIN(ref->cell_y_offset, global_state.cell_height - 1);
|
ref->cell_y_offset = MIN(ref->cell_y_offset, global_state.cell_height - 1);
|
||||||
@ -925,7 +925,7 @@ W(update_layers) {
|
|||||||
for (size_t i = 0; i < self->count; i++) {
|
for (size_t i = 0; i < self->count; i++) {
|
||||||
ImageRenderData *r = self->render_data + i;
|
ImageRenderData *r = self->render_data + i;
|
||||||
#define R(offset) Py_BuildValue("{sf sf sf sf}", "left", r->vertices[offset + 8], "top", r->vertices[offset + 1], "right", r->vertices[offset], "bottom", r->vertices[offset + 5])
|
#define R(offset) Py_BuildValue("{sf sf sf sf}", "left", r->vertices[offset + 8], "top", r->vertices[offset + 1], "right", r->vertices[offset], "bottom", r->vertices[offset + 5])
|
||||||
PyTuple_SET_ITEM(ans, i,
|
PyTuple_SET_ITEM(ans, i,
|
||||||
Py_BuildValue("{sN sN sI si sI}", "src_rect", R(0), "dest_rect", R(2), "group_count", r->group_count, "z_index", r->z_index, "image_id", r->image_id)
|
Py_BuildValue("{sN sN sI si sI}", "src_rect", R(0), "dest_rect", R(2), "group_count", r->group_count, "z_index", r->z_index, "image_id", r->image_id)
|
||||||
);
|
);
|
||||||
#undef R
|
#undef R
|
||||||
@ -950,10 +950,10 @@ PyTypeObject GraphicsManager_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.GraphicsManager",
|
.tp_name = "fast_data_types.GraphicsManager",
|
||||||
.tp_basicsize = sizeof(GraphicsManager),
|
.tp_basicsize = sizeof(GraphicsManager),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "GraphicsManager",
|
.tp_doc = "GraphicsManager",
|
||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
};
|
};
|
||||||
@ -969,7 +969,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
bool
|
bool
|
||||||
init_graphics(PyObject *module) {
|
init_graphics(PyObject *module) {
|
||||||
if (PyType_Ready(&GraphicsManager_Type) < 0) return false;
|
if (PyType_Ready(&GraphicsManager_Type) < 0) return false;
|
||||||
if (PyModule_AddObject(module, "GraphicsManager", (PyObject *)&GraphicsManager_Type) != 0) return false;
|
if (PyModule_AddObject(module, "GraphicsManager", (PyObject *)&GraphicsManager_Type) != 0) return false;
|
||||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||||
Py_INCREF(&GraphicsManager_Type);
|
Py_INCREF(&GraphicsManager_Type);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -58,7 +58,7 @@ dealloc(HistoryBuf* self) {
|
|||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline index_type
|
static inline index_type
|
||||||
index_of(HistoryBuf *self, index_type lnum) {
|
index_of(HistoryBuf *self, index_type lnum) {
|
||||||
// The index (buffer position) of the line with line number lnum
|
// The index (buffer position) of the line with line number lnum
|
||||||
// This is reverse indexing, i.e. lnum = 0 corresponds to the *last* line in the buffer.
|
// This is reverse indexing, i.e. lnum = 0 corresponds to the *last* line in the buffer.
|
||||||
@ -67,7 +67,7 @@ index_of(HistoryBuf *self, index_type lnum) {
|
|||||||
return (self->start_of_data + idx) % self->ynum;
|
return (self->start_of_data + idx) % self->ynum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
init_line(HistoryBuf *self, index_type num, Line *l) {
|
init_line(HistoryBuf *self, index_type num, Line *l) {
|
||||||
// Initialize the line l, setting its pointer to the offsets for the line at index (buffer position) num
|
// Initialize the line l, setting its pointer to the offsets for the line at index (buffer position) num
|
||||||
l->cells = lineptr(self, num);
|
l->cells = lineptr(self, num);
|
||||||
@ -75,22 +75,22 @@ init_line(HistoryBuf *self, index_type num, Line *l) {
|
|||||||
l->has_dirty_text = self->line_attrs[num] & TEXT_DIRTY_MASK ? true : false;
|
l->has_dirty_text = self->line_attrs[num] & TEXT_DIRTY_MASK ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
historybuf_init_line(HistoryBuf *self, index_type lnum, Line *l) {
|
historybuf_init_line(HistoryBuf *self, index_type lnum, Line *l) {
|
||||||
init_line(self, index_of(self, lnum), l);
|
init_line(self, index_of(self, lnum), l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
historybuf_mark_line_clean(HistoryBuf *self, index_type y) {
|
historybuf_mark_line_clean(HistoryBuf *self, index_type y) {
|
||||||
self->line_attrs[index_of(self, y)] &= ~TEXT_DIRTY_MASK;
|
self->line_attrs[index_of(self, y)] &= ~TEXT_DIRTY_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
historybuf_mark_line_dirty(HistoryBuf *self, index_type y) {
|
historybuf_mark_line_dirty(HistoryBuf *self, index_type y) {
|
||||||
self->line_attrs[index_of(self, y)] |= TEXT_DIRTY_MASK;
|
self->line_attrs[index_of(self, y)] |= TEXT_DIRTY_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline index_type
|
static inline index_type
|
||||||
historybuf_push(HistoryBuf *self) {
|
historybuf_push(HistoryBuf *self) {
|
||||||
index_type idx = (self->start_of_data + self->count) % self->ynum;
|
index_type idx = (self->start_of_data + self->count) % self->ynum;
|
||||||
init_line(self, idx, self->line);
|
init_line(self, idx, self->line);
|
||||||
@ -124,7 +124,7 @@ historybuf_resize(HistoryBuf *self, index_type lines) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
historybuf_add_line(HistoryBuf *self, const Line *line) {
|
historybuf_add_line(HistoryBuf *self, const Line *line) {
|
||||||
index_type idx = historybuf_push(self);
|
index_type idx = historybuf_push(self);
|
||||||
copy_line(line, self->line);
|
copy_line(line, self->line);
|
||||||
@ -234,11 +234,11 @@ PyTypeObject HistoryBuf_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.HistoryBuf",
|
.tp_name = "fast_data_types.HistoryBuf",
|
||||||
.tp_basicsize = sizeof(HistoryBuf),
|
.tp_basicsize = sizeof(HistoryBuf),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "History buffers",
|
.tp_doc = "History buffers",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
.tp_str = (reprfunc)__str__,
|
.tp_str = (reprfunc)__str__,
|
||||||
.tp_new = new
|
.tp_new = new
|
||||||
};
|
};
|
||||||
@ -258,9 +258,9 @@ HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns) {
|
|||||||
|
|
||||||
#define is_src_line_continued(src_y) (map_src_index(src_y) < src->ynum - 1 ? (src->line_attrs[map_src_index(src_y + 1)] & CONTINUED_MASK) : false)
|
#define is_src_line_continued(src_y) (map_src_index(src_y) < src->ynum - 1 ? (src->line_attrs[map_src_index(src_y + 1)] & CONTINUED_MASK) : false)
|
||||||
|
|
||||||
#define next_dest_line(cont) dest->line_attrs[historybuf_push(dest)] = cont & CONTINUED_MASK; dest->line->continued = cont;
|
#define next_dest_line(cont) dest->line_attrs[historybuf_push(dest)] = cont & CONTINUED_MASK; dest->line->continued = cont;
|
||||||
|
|
||||||
#define first_dest_line next_dest_line(false);
|
#define first_dest_line next_dest_line(false);
|
||||||
|
|
||||||
#include "rewrap.h"
|
#include "rewrap.h"
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ static inline bool
|
|||||||
is_modifier_key(int key) {
|
is_modifier_key(int key) {
|
||||||
switch(key) {
|
switch(key) {
|
||||||
case GLFW_KEY_LEFT_SHIFT:
|
case GLFW_KEY_LEFT_SHIFT:
|
||||||
case GLFW_KEY_RIGHT_SHIFT:
|
case GLFW_KEY_RIGHT_SHIFT:
|
||||||
case GLFW_KEY_LEFT_ALT:
|
case GLFW_KEY_LEFT_ALT:
|
||||||
case GLFW_KEY_RIGHT_ALT:
|
case GLFW_KEY_RIGHT_ALT:
|
||||||
case GLFW_KEY_LEFT_CONTROL:
|
case GLFW_KEY_LEFT_CONTROL:
|
||||||
@ -83,7 +83,7 @@ get_localized_key(int key, int scancode) {
|
|||||||
// key names {{{
|
// key names {{{
|
||||||
K('A', A); K('a', A);
|
K('A', A); K('a', A);
|
||||||
K('B', B); K('b', B);
|
K('B', B); K('b', B);
|
||||||
K('C', C); K('c', C);
|
K('C', C); K('c', C);
|
||||||
K('D', D); K('d', D);
|
K('D', D); K('d', D);
|
||||||
K('E', E); K('e', E);
|
K('E', E); K('e', E);
|
||||||
K('F', F); K('f', F);
|
K('F', F); K('f', F);
|
||||||
@ -209,7 +209,7 @@ PYWRAP1(key_to_bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
M(key_to_bytes, METH_VARARGS),
|
M(key_to_bytes, METH_VARARGS),
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
20
kitty/keys.h
generated
20
kitty/keys.h
generated
@ -487,12 +487,12 @@ static inline const char*
|
|||||||
key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
switch(action & 3) { case 3: return NULL;
|
switch(action & 3) { case 3: return NULL;
|
||||||
case 0: // RELEASE
|
case 0: // RELEASE
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case 1: // PRESS
|
case 1: // PRESS
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 50: // ESCAPE
|
case 50: // ESCAPE
|
||||||
@ -1690,7 +1690,7 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
} // end switch(mods)
|
} // end switch(mods)
|
||||||
|
|
||||||
case 2: // REPEAT
|
case 2: // REPEAT
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 50: // ESCAPE
|
case 50: // ESCAPE
|
||||||
@ -2891,12 +2891,12 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
|
|
||||||
|
|
||||||
case APPLICATION:
|
case APPLICATION:
|
||||||
switch(action & 3) { case 3: return NULL;
|
switch(action & 3) { case 3: return NULL;
|
||||||
case 0: // RELEASE
|
case 0: // RELEASE
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case 1: // PRESS
|
case 1: // PRESS
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 50: // ESCAPE
|
case 50: // ESCAPE
|
||||||
@ -4094,7 +4094,7 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
} // end switch(mods)
|
} // end switch(mods)
|
||||||
|
|
||||||
case 2: // REPEAT
|
case 2: // REPEAT
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 50: // ESCAPE
|
case 50: // ESCAPE
|
||||||
@ -5295,9 +5295,9 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
|
|
||||||
|
|
||||||
case EXTENDED:
|
case EXTENDED:
|
||||||
switch(action & 3) { case 3: return NULL;
|
switch(action & 3) { case 3: return NULL;
|
||||||
case 0: // RELEASE
|
case 0: // RELEASE
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 0: // SPACE
|
case 0: // SPACE
|
||||||
@ -9061,7 +9061,7 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
} // end switch(mods)
|
} // end switch(mods)
|
||||||
|
|
||||||
case 1: // PRESS
|
case 1: // PRESS
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 0: // SPACE
|
case 0: // SPACE
|
||||||
@ -12825,7 +12825,7 @@ key_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {
|
|||||||
} // end switch(mods)
|
} // end switch(mods)
|
||||||
|
|
||||||
case 2: // REPEAT
|
case 2: // REPEAT
|
||||||
switch (mods & 0xf) {
|
switch (mods & 0xf) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch(key & 0x7f) { default: return NULL;
|
switch(key & 0x7f) { default: return NULL;
|
||||||
case 0: // SPACE
|
case 0: // SPACE
|
||||||
|
|||||||
@ -22,7 +22,7 @@ clear_chars_to(LineBuf* linebuf, index_type y, char_type ch) {
|
|||||||
clear_chars_in_line(lineptr(linebuf, y), linebuf->xnum, ch);
|
clear_chars_in_line(lineptr(linebuf, y), linebuf->xnum, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_clear(LineBuf *self, char_type ch) {
|
linebuf_clear(LineBuf *self, char_type ch) {
|
||||||
memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell));
|
memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell));
|
||||||
memset(self->line_attrs, 0, self->ynum * sizeof(line_attrs_type));
|
memset(self->line_attrs, 0, self->ynum * sizeof(line_attrs_type));
|
||||||
@ -97,8 +97,8 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
static void
|
static void
|
||||||
dealloc(LineBuf* self) {
|
dealloc(LineBuf* self) {
|
||||||
PyMem_Free(self->buf);
|
PyMem_Free(self->buf);
|
||||||
PyMem_Free(self->line_map);
|
PyMem_Free(self->line_map);
|
||||||
PyMem_Free(self->line_attrs);
|
PyMem_Free(self->line_attrs);
|
||||||
PyMem_Free(self->scratch);
|
PyMem_Free(self->scratch);
|
||||||
Py_CLEAR(self->line);
|
Py_CLEAR(self->line);
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
@ -109,7 +109,7 @@ init_line(LineBuf *lb, Line *l, index_type ynum) {
|
|||||||
l->cells = lineptr(lb, ynum);
|
l->cells = lineptr(lb, ynum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_init_line(LineBuf *self, index_type idx) {
|
linebuf_init_line(LineBuf *self, index_type idx) {
|
||||||
self->line->ynum = idx;
|
self->line->ynum = idx;
|
||||||
self->line->xnum = self->xnum;
|
self->line->xnum = self->xnum;
|
||||||
@ -131,12 +131,12 @@ line(LineBuf *self, PyObject *y) {
|
|||||||
return (PyObject*)self->line;
|
return (PyObject*)self->line;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
linebuf_char_width_at(LineBuf *self, index_type x, index_type y) {
|
linebuf_char_width_at(LineBuf *self, index_type x, index_type y) {
|
||||||
return (lineptr(self, self->line_map[y])[x].attrs) & WIDTH_MASK;
|
return (lineptr(self, self->line_map[y])[x].attrs) & WIDTH_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_set_attribute(LineBuf *self, unsigned int shift, unsigned int val) {
|
linebuf_set_attribute(LineBuf *self, unsigned int shift, unsigned int val) {
|
||||||
for (index_type y = 0; y < self->ynum; y++) {
|
for (index_type y = 0; y < self->ynum; y++) {
|
||||||
set_attribute_on_line(lineptr(self, y), shift, val, self->xnum);
|
set_attribute_on_line(lineptr(self, y), shift, val, self->xnum);
|
||||||
@ -192,7 +192,7 @@ allocate_line_storage(Line *line, bool initialize) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PyObject*
|
static inline PyObject*
|
||||||
create_line_copy_inner(LineBuf* self, index_type y) {
|
create_line_copy_inner(LineBuf* self, index_type y) {
|
||||||
Line src, *line;
|
Line src, *line;
|
||||||
line = alloc_line();
|
line = alloc_line();
|
||||||
@ -237,7 +237,7 @@ clear_line_(Line *l, index_type xnum) {
|
|||||||
l->has_dirty_text = false;
|
l->has_dirty_text = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_clear_line(LineBuf *self, index_type y) {
|
linebuf_clear_line(LineBuf *self, index_type y) {
|
||||||
Line l;
|
Line l;
|
||||||
init_line(self, &l, self->line_map[y]);
|
init_line(self, &l, self->line_map[y]);
|
||||||
@ -254,7 +254,7 @@ clear_line(LineBuf *self, PyObject *val) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_index(LineBuf* self, index_type top, index_type bottom) {
|
linebuf_index(LineBuf* self, index_type top, index_type bottom) {
|
||||||
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
|
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
|
||||||
index_type old_top = self->line_map[top];
|
index_type old_top = self->line_map[top];
|
||||||
@ -276,7 +276,7 @@ pyw_index(LineBuf *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_reverse_index(LineBuf *self, index_type top, index_type bottom) {
|
linebuf_reverse_index(LineBuf *self, index_type top, index_type bottom) {
|
||||||
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
|
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
|
||||||
index_type old_bottom = self->line_map[bottom];
|
index_type old_bottom = self->line_map[bottom];
|
||||||
@ -308,7 +308,7 @@ is_continued(LineBuf *self, PyObject *val) {
|
|||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom) {
|
linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom) {
|
||||||
index_type i;
|
index_type i;
|
||||||
if (y >= self->ynum || y > bottom || bottom >= self->ynum) return;
|
if (y >= self->ynum || y > bottom || bottom >= self->ynum) return;
|
||||||
@ -344,7 +344,7 @@ insert_lines(LineBuf *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom) {
|
linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom) {
|
||||||
index_type i;
|
index_type i;
|
||||||
index_type ylimit = bottom + 1;
|
index_type ylimit = bottom + 1;
|
||||||
@ -368,7 +368,7 @@ linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bot
|
|||||||
self->line_attrs[i] = 0;
|
self->line_attrs[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
delete_lines(LineBuf *self, PyObject *args) {
|
delete_lines(LineBuf *self, PyObject *args) {
|
||||||
#define delete_lines_doc "delete_lines(num, y, bottom) -> Delete num lines at y, only changing lines in the range [y, bottom]."
|
#define delete_lines_doc "delete_lines(num, y, bottom) -> Delete num lines at y, only changing lines in the range [y, bottom]."
|
||||||
@ -377,7 +377,7 @@ delete_lines(LineBuf *self, PyObject *args) {
|
|||||||
linebuf_delete_lines(self, num, y, bottom);
|
linebuf_delete_lines(self, num, y, bottom);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
as_ansi(LineBuf *self, PyObject *callback) {
|
as_ansi(LineBuf *self, PyObject *callback) {
|
||||||
#define as_ansi_doc "as_ansi(callback) -> The contents of this buffer as ANSI escaped text. callback is called with each successive line."
|
#define as_ansi_doc "as_ansi(callback) -> The contents of this buffer as ANSI escaped text. callback is called with each successive line."
|
||||||
@ -453,11 +453,11 @@ PyTypeObject LineBuf_Type = {
|
|||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.LineBuf",
|
.tp_name = "fast_data_types.LineBuf",
|
||||||
.tp_basicsize = sizeof(LineBuf),
|
.tp_basicsize = sizeof(LineBuf),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "Line buffers",
|
.tp_doc = "Line buffers",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
.tp_str = (reprfunc)__str__,
|
.tp_str = (reprfunc)__str__,
|
||||||
.tp_new = new
|
.tp_new = new
|
||||||
};
|
};
|
||||||
@ -485,7 +485,7 @@ copy_old(LineBuf *self, PyObject *y) {
|
|||||||
|
|
||||||
#include "rewrap.h"
|
#include "rewrap.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_before, index_type *num_content_lines_after, HistoryBuf *historybuf) {
|
linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_before, index_type *num_content_lines_after, HistoryBuf *historybuf) {
|
||||||
index_type first, i;
|
index_type first, i;
|
||||||
bool is_empty = true;
|
bool is_empty = true;
|
||||||
@ -510,9 +510,9 @@ linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_befo
|
|||||||
} while(is_empty && first > 0);
|
} while(is_empty && first > 0);
|
||||||
|
|
||||||
if (is_empty) { // All lines are empty
|
if (is_empty) { // All lines are empty
|
||||||
*num_content_lines_after = 0;
|
*num_content_lines_after = 0;
|
||||||
*num_content_lines_before = 0;
|
*num_content_lines_before = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rewrap_inner(self, other, first + 1, historybuf);
|
rewrap_inner(self, other, first + 1, historybuf);
|
||||||
|
|||||||
28
kitty/line.c
28
kitty/line.c
@ -34,7 +34,7 @@ line_length(Line *self) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
line_text_at(char_type ch, combining_type cc) {
|
line_text_at(char_type ch, combining_type cc) {
|
||||||
PyObject *ans;
|
PyObject *ans;
|
||||||
if (LIKELY(cc == 0)) {
|
if (LIKELY(cc == 0)) {
|
||||||
@ -67,7 +67,7 @@ find_colon_slash(Line *self, index_type x, index_type limit) {
|
|||||||
if (!is_url_char(ch)) return false;
|
if (!is_url_char(ch)) return false;
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case ANY:
|
case ANY:
|
||||||
if (ch == '/') state = FIRST_SLASH;
|
if (ch == '/') state = FIRST_SLASH;
|
||||||
break;
|
break;
|
||||||
case FIRST_SLASH:
|
case FIRST_SLASH:
|
||||||
state = ch == '/' ? SECOND_SLASH : ANY;
|
state = ch == '/' ? SECOND_SLASH : ANY;
|
||||||
@ -202,7 +202,7 @@ PyObject*
|
|||||||
unicode_in_range(Line *self, index_type start, index_type limit, bool include_cc, char leading_char) {
|
unicode_in_range(Line *self, index_type start, index_type limit, bool include_cc, char leading_char) {
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
static Py_UCS4 buf[4096];
|
static Py_UCS4 buf[4096];
|
||||||
if (leading_char) buf[n++] = leading_char;
|
if (leading_char) buf[n++] = leading_char;
|
||||||
char_type previous_width = 0;
|
char_type previous_width = 0;
|
||||||
for(index_type i = start; i < limit && n < sizeof(buf)/sizeof(buf[0]) - 4; i++) {
|
for(index_type i = start; i < limit && n < sizeof(buf)/sizeof(buf[0]) - 4; i++) {
|
||||||
char_type ch = self->cells[i].ch;
|
char_type ch = self->cells[i].ch;
|
||||||
@ -241,7 +241,7 @@ write_sgr(const char *val, Py_UCS4 *buf, index_type buflen, index_type *i) {
|
|||||||
index_type
|
index_type
|
||||||
line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
||||||
#define WRITE_SGR(val) { if (!write_sgr(val, buf, buflen, &i)) return i; }
|
#define WRITE_SGR(val) { if (!write_sgr(val, buf, buflen, &i)) return i; }
|
||||||
#define WRITE_CH(val) if (i > buflen - 1) return i; buf[i++] = val;
|
#define WRITE_CH(val) if (i > buflen - 1) return i; buf[i++] = val;
|
||||||
|
|
||||||
index_type limit = xlimit_for_line(self), i=0;
|
index_type limit = xlimit_for_line(self), i=0;
|
||||||
char_type previous_width = 0;
|
char_type previous_width = 0;
|
||||||
@ -316,7 +316,7 @@ width(Line *self, PyObject *val) {
|
|||||||
return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK));
|
return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
|
line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
|
||||||
if (!self->cells[x].ch) return; // dont allow adding combining chars to a null cell
|
if (!self->cells[x].ch) return; // dont allow adding combining chars to a null cell
|
||||||
combining_type c = self->cells[x].cc;
|
combining_type c = self->cells[x].cc;
|
||||||
@ -398,7 +398,7 @@ cursor_from(Line* self, PyObject *args) {
|
|||||||
return (PyObject*)ans;
|
return (PyObject*)ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch) {
|
line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch) {
|
||||||
attrs_type width = ch ? 1 : 0;
|
attrs_type width = ch ? 1 : 0;
|
||||||
#define PREFIX \
|
#define PREFIX \
|
||||||
@ -423,13 +423,13 @@ clear_text(Line* self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
|
line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
|
||||||
char_type attrs = CURSOR_TO_ATTRS(cursor, 1);
|
char_type attrs = CURSOR_TO_ATTRS(cursor, 1);
|
||||||
color_type fg = (cursor->fg & COL_MASK), bg = (cursor->bg & COL_MASK);
|
color_type fg = (cursor->fg & COL_MASK), bg = (cursor->bg & COL_MASK);
|
||||||
color_type dfg = cursor->decoration_fg & COL_MASK;
|
color_type dfg = cursor->decoration_fg & COL_MASK;
|
||||||
if (!clear_char) attrs = attrs & ATTRS_MASK_WITHOUT_WIDTH;
|
if (!clear_char) attrs = attrs & ATTRS_MASK_WITHOUT_WIDTH;
|
||||||
|
|
||||||
for (index_type i = at; i < self->xnum && i < at + num; i++) {
|
for (index_type i = at; i < self->xnum && i < at + num; i++) {
|
||||||
if (clear_char) {
|
if (clear_char) {
|
||||||
self->cells[i].ch = BLANK_CHAR;
|
self->cells[i].ch = BLANK_CHAR;
|
||||||
@ -496,8 +496,8 @@ left_shift(Line *self, PyObject *args) {
|
|||||||
if (num > 0) left_shift_line(self, at, num);
|
if (num > 0) left_shift_line(self, at, num);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor, bool UNUSED is_second) {
|
line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor, bool UNUSED is_second) {
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
self->cells[at].attrs = (self->cells[at].attrs & ATTRS_MASK_WITHOUT_WIDTH) | width;
|
self->cells[at].attrs = (self->cells[at].attrs & ATTRS_MASK_WITHOUT_WIDTH) | width;
|
||||||
@ -556,7 +556,7 @@ richcmp(PyObject *obj1, PyObject *obj2, int op);
|
|||||||
|
|
||||||
|
|
||||||
static PySequenceMethods sequence_methods = {
|
static PySequenceMethods sequence_methods = {
|
||||||
.sq_length = __len__,
|
.sq_length = __len__,
|
||||||
.sq_item = (ssizeargfunc)text_at
|
.sq_item = (ssizeargfunc)text_at
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -577,7 +577,7 @@ static PyMethodDef methods[] = {
|
|||||||
METHOD(url_start_at, METH_O)
|
METHOD(url_start_at, METH_O)
|
||||||
METHOD(url_end_at, METH_O)
|
METHOD(url_end_at, METH_O)
|
||||||
METHOD(sprite_at, METH_O)
|
METHOD(sprite_at, METH_O)
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -590,7 +590,7 @@ PyTypeObject Line_Type = {
|
|||||||
.tp_str = (reprfunc)as_unicode,
|
.tp_str = (reprfunc)as_unicode,
|
||||||
.tp_as_sequence = &sequence_methods,
|
.tp_as_sequence = &sequence_methods,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_richcompare = richcmp,
|
.tp_richcompare = richcmp,
|
||||||
.tp_doc = "Lines",
|
.tp_doc = "Lines",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_new = new
|
.tp_new = new
|
||||||
@ -605,7 +605,7 @@ Line *alloc_line() {
|
|||||||
RICHCMP(Line)
|
RICHCMP(Line)
|
||||||
INIT_TYPE(Line)
|
INIT_TYPE(Line)
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
copy_char(Line* self, PyObject *args) {
|
copy_char(Line* self, PyObject *args) {
|
||||||
unsigned int src, dest;
|
unsigned int src, dest;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ static inline void
|
|||||||
set_attribute_on_line(Cell *cells, uint32_t shift, uint32_t val, index_type xnum) {
|
set_attribute_on_line(Cell *cells, uint32_t shift, uint32_t val, index_type xnum) {
|
||||||
// Set a single attribute on all cells in the line
|
// Set a single attribute on all cells in the line
|
||||||
attrs_type mask = shift == DECORATION_SHIFT ? 3 : 1;
|
attrs_type mask = shift == DECORATION_SHIFT ? 3 : 1;
|
||||||
attrs_type aval = (val & mask) << shift;
|
attrs_type aval = (val & mask) << shift;
|
||||||
mask = ~(mask << shift);
|
mask = ~(mask << shift);
|
||||||
for (index_type i = 0; i < xnum; i++) cells[i].attrs = (cells[i].attrs & mask) | aval;
|
for (index_type i = 0; i < xnum; i++) cells[i].attrs = (cells[i].attrs & mask) | aval;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
/* *Insert/Replace Mode*: When enabled, new display characters move
|
/* *Insert/Replace Mode*: When enabled, new display characters move
|
||||||
old display characters to the right. Characters moved past the
|
old display characters to the right. Characters moved past the
|
||||||
right margin are lost. Otherwise, new display characters replace
|
right margin are lost. Otherwise, new display characters replace
|
||||||
old display characters at the cursor position.
|
old display characters at the cursor position.
|
||||||
*/
|
*/
|
||||||
#define IRM 4
|
#define IRM 4
|
||||||
|
|
||||||
|
|||||||
@ -67,7 +67,7 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
|||||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "%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] = 'M'; mouse_event_buf[1] = cb + 32;
|
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32;
|
||||||
unsigned int sz = 2;
|
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);
|
||||||
@ -264,7 +264,7 @@ HANDLER(handle_button_event) {
|
|||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
if (!screen) return;
|
if (!screen) return;
|
||||||
bool handle_in_kitty = (
|
bool handle_in_kitty = (
|
||||||
modifiers == GLFW_MOD_SHIFT ||
|
modifiers == GLFW_MOD_SHIFT ||
|
||||||
screen->modes.mouse_tracking_mode == 0 ||
|
screen->modes.mouse_tracking_mode == 0 ||
|
||||||
button == GLFW_MOUSE_BUTTON_MIDDLE ||
|
button == GLFW_MOUSE_BUTTON_MIDDLE ||
|
||||||
(modifiers == (int)OPT(open_url_modifiers) && button == GLFW_MOUSE_BUTTON_LEFT)
|
(modifiers == (int)OPT(open_url_modifiers) && button == GLFW_MOUSE_BUTTON_LEFT)
|
||||||
@ -297,7 +297,7 @@ HANDLER(handle_event) {
|
|||||||
for (int i = 0; i < GLFW_MOUSE_BUTTON_5; i++) { if (global_state.callback_os_window->mouse_button_pressed[i]) { button = i; break; } }
|
for (int i = 0; i < GLFW_MOUSE_BUTTON_5; i++) { if (global_state.callback_os_window->mouse_button_pressed[i]) { button = i; break; } }
|
||||||
handle_move_event(w, button, modifiers, window_idx);
|
handle_move_event(w, button, modifiers, window_idx);
|
||||||
break;
|
break;
|
||||||
case GLFW_MOUSE_BUTTON_LEFT:
|
case GLFW_MOUSE_BUTTON_LEFT:
|
||||||
case GLFW_MOUSE_BUTTON_RIGHT:
|
case GLFW_MOUSE_BUTTON_RIGHT:
|
||||||
case GLFW_MOUSE_BUTTON_MIDDLE:
|
case GLFW_MOUSE_BUTTON_MIDDLE:
|
||||||
case GLFW_MOUSE_BUTTON_4:
|
case GLFW_MOUSE_BUTTON_4:
|
||||||
@ -309,7 +309,7 @@ HANDLER(handle_event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
handle_tab_bar_mouse(int button, int UNUSED modifiers) {
|
handle_tab_bar_mouse(int button, int UNUSED modifiers) {
|
||||||
if (button != GLFW_MOUSE_BUTTON_LEFT || !global_state.callback_os_window->mouse_button_pressed[button]) return;
|
if (button != GLFW_MOUSE_BUTTON_LEFT || !global_state.callback_os_window->mouse_button_pressed[button]) return;
|
||||||
call_boss(activate_tab_at, "Kd", global_state.callback_os_window->id, global_state.callback_os_window->mouse_x);
|
call_boss(activate_tab_at, "Kd", global_state.callback_os_window->id, global_state.callback_os_window->mouse_x);
|
||||||
@ -347,9 +347,9 @@ mouse_event(int button, int modifiers) {
|
|||||||
bool in_tab_bar;
|
bool in_tab_bar;
|
||||||
unsigned int window_idx = 0;
|
unsigned int window_idx = 0;
|
||||||
Window *w = window_for_event(&window_idx, &in_tab_bar);
|
Window *w = window_for_event(&window_idx, &in_tab_bar);
|
||||||
if (in_tab_bar) {
|
if (in_tab_bar) {
|
||||||
mouse_cursor_shape = HAND;
|
mouse_cursor_shape = HAND;
|
||||||
handle_tab_bar_mouse(button, modifiers);
|
handle_tab_bar_mouse(button, modifiers);
|
||||||
} else if(w) {
|
} else if(w) {
|
||||||
handle_event(w, button, modifiers, window_idx);
|
handle_event(w, button, modifiers, window_idx);
|
||||||
}
|
}
|
||||||
|
|||||||
200
kitty/parser.c
200
kitty/parser.c
@ -62,7 +62,7 @@ utf8(char_type codepoint) {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef DUMP_COMMANDS
|
#ifdef DUMP_COMMANDS
|
||||||
static void
|
static void
|
||||||
_report_error(PyObject *dump_callback, const char *fmt, ...) {
|
_report_error(PyObject *dump_callback, const char *fmt, ...) {
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, fmt);
|
va_start(argptr, fmt);
|
||||||
@ -74,7 +74,7 @@ _report_error(PyObject *dump_callback, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_report_params(PyObject *dump_callback, const char *name, unsigned int *params, unsigned int count, Region *r) {
|
_report_params(PyObject *dump_callback, const char *name, unsigned int *params, unsigned int count, Region *r) {
|
||||||
static char buf[MAX_PARAMS*3] = {0};
|
static char buf[MAX_PARAMS*3] = {0};
|
||||||
unsigned int i, p=0;
|
unsigned int i, p=0;
|
||||||
@ -126,7 +126,7 @@ _report_params(PyObject *dump_callback, const char *name, unsigned int *params,
|
|||||||
#define REPORT_ERROR(...) fprintf(stderr, "%s ", ERROR_PREFIX); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n");
|
#define REPORT_ERROR(...) fprintf(stderr, "%s ", ERROR_PREFIX); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n");
|
||||||
|
|
||||||
#define REPORT_COMMAND(...)
|
#define REPORT_COMMAND(...)
|
||||||
#define REPORT_VA_COMMAND(...)
|
#define REPORT_VA_COMMAND(...)
|
||||||
#define REPORT_DRAW(ch)
|
#define REPORT_DRAW(ch)
|
||||||
#define REPORT_PARAMS(...)
|
#define REPORT_PARAMS(...)
|
||||||
#define FLUSH_DRAW
|
#define FLUSH_DRAW
|
||||||
@ -142,7 +142,7 @@ _report_params(PyObject *dump_callback, const char *name, unsigned int *params,
|
|||||||
static inline void
|
static inline void
|
||||||
screen_nel(Screen *screen) { screen_carriage_return(screen); screen_linefeed(screen); }
|
screen_nel(Screen *screen) { screen_carriage_return(screen); screen_linefeed(screen); }
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
handle_normal_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_callback) {
|
handle_normal_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_callback) {
|
||||||
#define CALL_SCREEN_HANDLER(name) REPORT_COMMAND(name); name(screen); break;
|
#define CALL_SCREEN_HANDLER(name) REPORT_COMMAND(name); name(screen); break;
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
@ -191,11 +191,11 @@ handle_normal_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_
|
|||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
// Esc mode {{{
|
// Esc mode {{{
|
||||||
static inline void
|
static inline void
|
||||||
handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_callback) {
|
handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_callback) {
|
||||||
#define CALL_ED(name) REPORT_COMMAND(name); name(screen); SET_STATE(0);
|
#define CALL_ED(name) REPORT_COMMAND(name); name(screen); SET_STATE(0);
|
||||||
#define CALL_ED1(name, ch) REPORT_COMMAND(name, ch); name(screen, ch); SET_STATE(0);
|
#define CALL_ED1(name, ch) REPORT_COMMAND(name, ch); name(screen, ch); SET_STATE(0);
|
||||||
#define CALL_ED2(name, a, b) REPORT_COMMAND(name, a, b); name(screen, a, b); SET_STATE(0);
|
#define CALL_ED2(name, a, b) REPORT_COMMAND(name, a, b); name(screen, a, b); SET_STATE(0);
|
||||||
switch(screen->parser_buf_pos) {
|
switch(screen->parser_buf_pos) {
|
||||||
case 0:
|
case 0:
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@ -223,9 +223,9 @@ handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_cal
|
|||||||
CALL_ED(screen_save_cursor); break;
|
CALL_ED(screen_save_cursor); break;
|
||||||
case ESC_DECRC:
|
case ESC_DECRC:
|
||||||
CALL_ED(screen_restore_cursor); break;
|
CALL_ED(screen_restore_cursor); break;
|
||||||
case ESC_DECPNM:
|
case ESC_DECPNM:
|
||||||
CALL_ED(screen_normal_keypad_mode); break;
|
CALL_ED(screen_normal_keypad_mode); break;
|
||||||
case ESC_DECPAM:
|
case ESC_DECPAM:
|
||||||
CALL_ED(screen_alternate_keypad_mode); break;
|
CALL_ED(screen_alternate_keypad_mode); break;
|
||||||
case '%':
|
case '%':
|
||||||
case '(':
|
case '(':
|
||||||
@ -240,7 +240,7 @@ handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_cal
|
|||||||
screen->parser_buf[screen->parser_buf_pos++] = ch;
|
screen->parser_buf[screen->parser_buf_pos++] = ch;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("%s0x%x", "Unknown char after ESC: ", ch);
|
REPORT_ERROR("%s0x%x", "Unknown char after ESC: ", ch);
|
||||||
SET_STATE(0); break;
|
SET_STATE(0); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -363,11 +363,11 @@ dispatch_osc(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
|||||||
case '$':
|
case '$':
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
screen_cursor_up2(Screen *s, unsigned int count) { screen_cursor_up(s, count, false, -1); }
|
screen_cursor_up2(Screen *s, unsigned int count) { screen_cursor_up(s, count, false, -1); }
|
||||||
static inline void
|
static inline void
|
||||||
screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_back(s, count, -1); }
|
screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_back(s, count, -1); }
|
||||||
static inline void
|
static inline void
|
||||||
screen_tabn(Screen *s, unsigned int count) { for (index_type i=0; i < MAX(1, count); i++) screen_tab(s); }
|
screen_tabn(Screen *s, unsigned int count) { for (index_type i=0; i < MAX(1, count); i++) screen_tab(s); }
|
||||||
static inline void
|
static inline void
|
||||||
save_cursor(Screen *s, unsigned int UNUSED param, bool private) {
|
save_cursor(Screen *s, unsigned int UNUSED param, bool private) {
|
||||||
@ -481,8 +481,8 @@ parse_sgr(Screen *screen, uint32_t *buf, unsigned int num, unsigned int *params,
|
|||||||
READ_PARAM;
|
READ_PARAM;
|
||||||
num_start = i + 1;
|
num_start = i + 1;
|
||||||
break;
|
break;
|
||||||
case COLOR:
|
case COLOR:
|
||||||
case COLOR1:
|
case COLOR1:
|
||||||
case COLOR3:
|
case COLOR3:
|
||||||
REPORT_ERROR("Invalid SGR code containing disallowed character: %s", utf8(buf[i]));
|
REPORT_ERROR("Invalid SGR code containing disallowed character: %s", utf8(buf[i]));
|
||||||
return;
|
return;
|
||||||
@ -510,7 +510,7 @@ parse_sgr(Screen *screen, uint32_t *buf, unsigned int num, unsigned int *params,
|
|||||||
break;
|
break;
|
||||||
case COLOR3:
|
case COLOR3:
|
||||||
if (i > num_start && num_params < MAX_PARAMS) READ_PARAM;
|
if (i > num_start && num_params < MAX_PARAMS) READ_PARAM;
|
||||||
if (num_params != 5) {
|
if (num_params != 5) {
|
||||||
REPORT_ERROR("Invalid SGR code containing incomplete semi-colon separated color sequence");
|
REPORT_ERROR("Invalid SGR code containing incomplete semi-colon separated color sequence");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ parse_region(Region *r, uint32_t *buf, unsigned int num) {
|
|||||||
default:
|
default:
|
||||||
if (i > start) params[num_params++] = utoi(buf + start, i - start);
|
if (i > start) params[num_params++] = utoi(buf + start, i - start);
|
||||||
else if (i == start && buf[i] == ';') params[num_params++] = 0;
|
else if (i == start && buf[i] == ';') params[num_params++] = 0;
|
||||||
start = i + 1;
|
start = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,16 +541,16 @@ parse_region(Region *r, uint32_t *buf, unsigned int num) {
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
r->top = params[0];
|
r->top = params[0];
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
r->top = params[0]; r->left = params[1];
|
r->top = params[0]; r->left = params[1];
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
r->top = params[0]; r->left = params[1]; r->bottom = params[2];
|
r->top = params[0]; r->left = params[1]; r->bottom = params[2];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r->top = params[0]; r->left = params[1]; r->bottom = params[2]; r->right = params[3];
|
r->top = params[0]; r->left = params[1]; r->bottom = params[2]; r->right = params[3];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
@ -639,83 +639,83 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
|||||||
}
|
}
|
||||||
if (i > start) params[num_params++] = utoi(buf + start, i - start);
|
if (i > start) params[num_params++] = utoi(buf + start, i - start);
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case ICH:
|
case ICH:
|
||||||
CALL_CSI_HANDLER1(screen_insert_characters, 1);
|
CALL_CSI_HANDLER1(screen_insert_characters, 1);
|
||||||
case CUU:
|
case CUU:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_up2, 1);
|
CALL_CSI_HANDLER1(screen_cursor_up2, 1);
|
||||||
case CUD:
|
case CUD:
|
||||||
case VPR:
|
case VPR:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_down, 1);
|
CALL_CSI_HANDLER1(screen_cursor_down, 1);
|
||||||
case CUF:
|
case CUF:
|
||||||
case HPR:
|
case HPR:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_forward, 1);
|
CALL_CSI_HANDLER1(screen_cursor_forward, 1);
|
||||||
case CUB:
|
case CUB:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_back1, 1);
|
CALL_CSI_HANDLER1(screen_cursor_back1, 1);
|
||||||
case CNL:
|
case CNL:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_down1, 1);
|
CALL_CSI_HANDLER1(screen_cursor_down1, 1);
|
||||||
case CPL:
|
case CPL:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_up1, 1);
|
CALL_CSI_HANDLER1(screen_cursor_up1, 1);
|
||||||
case CHA:
|
case CHA:
|
||||||
case HPA:
|
case HPA:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_to_column, 1);
|
CALL_CSI_HANDLER1(screen_cursor_to_column, 1);
|
||||||
case VPA:
|
case VPA:
|
||||||
CALL_CSI_HANDLER1(screen_cursor_to_line, 1);
|
CALL_CSI_HANDLER1(screen_cursor_to_line, 1);
|
||||||
case CBT:
|
case CBT:
|
||||||
CALL_CSI_HANDLER1(screen_backtab, 1);
|
CALL_CSI_HANDLER1(screen_backtab, 1);
|
||||||
case CHT:
|
case CHT:
|
||||||
CALL_CSI_HANDLER1(screen_tabn, 1);
|
CALL_CSI_HANDLER1(screen_tabn, 1);
|
||||||
case CUP:
|
case CUP:
|
||||||
case HVP:
|
case HVP:
|
||||||
CALL_CSI_HANDLER2(screen_cursor_position, 1, 1);
|
CALL_CSI_HANDLER2(screen_cursor_position, 1, 1);
|
||||||
case ED:
|
case ED:
|
||||||
CALL_CSI_HANDLER1P(screen_erase_in_display, 0, '?');
|
CALL_CSI_HANDLER1P(screen_erase_in_display, 0, '?');
|
||||||
case EL:
|
case EL:
|
||||||
CALL_CSI_HANDLER1P(screen_erase_in_line, 0, '?');
|
CALL_CSI_HANDLER1P(screen_erase_in_line, 0, '?');
|
||||||
case IL:
|
case IL:
|
||||||
CALL_CSI_HANDLER1(screen_insert_lines, 1);
|
CALL_CSI_HANDLER1(screen_insert_lines, 1);
|
||||||
case DL:
|
case DL:
|
||||||
CALL_CSI_HANDLER1(screen_delete_lines, 1);
|
CALL_CSI_HANDLER1(screen_delete_lines, 1);
|
||||||
case DCH:
|
case DCH:
|
||||||
CALL_CSI_HANDLER1(screen_delete_characters, 1);
|
CALL_CSI_HANDLER1(screen_delete_characters, 1);
|
||||||
case ECH:
|
case ECH:
|
||||||
CALL_CSI_HANDLER1(screen_erase_characters, 1);
|
CALL_CSI_HANDLER1(screen_erase_characters, 1);
|
||||||
case DA:
|
case DA:
|
||||||
CALL_CSI_HANDLER1S(report_device_attributes, 0);
|
CALL_CSI_HANDLER1S(report_device_attributes, 0);
|
||||||
case TBC:
|
case TBC:
|
||||||
CALL_CSI_HANDLER1(screen_clear_tab_stop, 0);
|
CALL_CSI_HANDLER1(screen_clear_tab_stop, 0);
|
||||||
case SM:
|
case SM:
|
||||||
SET_MODE(screen_set_mode);
|
SET_MODE(screen_set_mode);
|
||||||
case RM:
|
case RM:
|
||||||
SET_MODE(screen_reset_mode);
|
SET_MODE(screen_reset_mode);
|
||||||
case DSR:
|
case DSR:
|
||||||
CALL_CSI_HANDLER1P(report_device_status, 0, '?');
|
CALL_CSI_HANDLER1P(report_device_status, 0, '?');
|
||||||
case SC:
|
case SC:
|
||||||
CALL_CSI_HANDLER1P(save_cursor, 0, '?');
|
CALL_CSI_HANDLER1P(save_cursor, 0, '?');
|
||||||
case RC:
|
case RC:
|
||||||
CALL_CSI_HANDLER1P(restore_cursor, 0, '?');
|
CALL_CSI_HANDLER1P(restore_cursor, 0, '?');
|
||||||
case 'r':
|
case 'r':
|
||||||
if (!start_modifier && !end_modifier) {
|
if (!start_modifier && !end_modifier) {
|
||||||
// DECSTBM
|
// DECSTBM
|
||||||
CALL_CSI_HANDLER2(screen_set_margins, 0, 0);
|
CALL_CSI_HANDLER2(screen_set_margins, 0, 0);
|
||||||
}
|
}
|
||||||
REPORT_ERROR("Unknown CSI r sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
REPORT_ERROR("Unknown CSI r sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
if (!start_modifier && end_modifier == '*') {
|
if (!start_modifier && end_modifier == '*') {
|
||||||
CALL_CSI_HANDLER1(screen_decsace, 0);
|
CALL_CSI_HANDLER1(screen_decsace, 0);
|
||||||
}
|
}
|
||||||
REPORT_ERROR("Unknown CSI x sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
REPORT_ERROR("Unknown CSI x sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
||||||
break;
|
break;
|
||||||
case DECSCUSR:
|
case DECSCUSR:
|
||||||
CALL_CSI_HANDLER1M(screen_set_cursor, 1);
|
CALL_CSI_HANDLER1M(screen_set_cursor, 1);
|
||||||
case SU:
|
case SU:
|
||||||
CALL_CSI_HANDLER1(screen_scroll, 1);
|
CALL_CSI_HANDLER1(screen_scroll, 1);
|
||||||
case SD:
|
case SD:
|
||||||
CALL_CSI_HANDLER1(screen_reverse_scroll, 1);
|
CALL_CSI_HANDLER1(screen_reverse_scroll, 1);
|
||||||
case DECSTR:
|
case DECSTR:
|
||||||
if (end_modifier == '$') {
|
if (end_modifier == '$') {
|
||||||
// DECRQM
|
// DECRQM
|
||||||
CALL_CSI_HANDLER1P(report_mode_status, 0, '?');
|
CALL_CSI_HANDLER1P(report_mode_status, 0, '?');
|
||||||
} else {
|
} else {
|
||||||
REPORT_ERROR("Unknown DECSTR CSI sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
REPORT_ERROR("Unknown DECSTR CSI sequence with start and end modifiers: '%c' '%c'", start_modifier, end_modifier);
|
||||||
}
|
}
|
||||||
@ -758,19 +758,19 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
unsigned int pos = 1;
|
unsigned int pos = 1;
|
||||||
enum GR_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD };
|
enum GR_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD };
|
||||||
enum GR_STATES state = KEY, value_state = FLAG;
|
enum GR_STATES state = KEY, value_state = FLAG;
|
||||||
enum KEYS {
|
enum KEYS {
|
||||||
action='a',
|
action='a',
|
||||||
delete_action='d',
|
delete_action='d',
|
||||||
transmission_type='t',
|
transmission_type='t',
|
||||||
compressed='o',
|
compressed='o',
|
||||||
format = 'f',
|
format = 'f',
|
||||||
more = 'm',
|
more = 'm',
|
||||||
id = 'i',
|
id = 'i',
|
||||||
width = 'w',
|
width = 'w',
|
||||||
height = 'h',
|
height = 'h',
|
||||||
x_offset = 'x',
|
x_offset = 'x',
|
||||||
y_offset = 'y',
|
y_offset = 'y',
|
||||||
data_height = 'v',
|
data_height = 'v',
|
||||||
data_width = 's',
|
data_width = 's',
|
||||||
data_sz = 'S',
|
data_sz = 'S',
|
||||||
data_offset = 'O',
|
data_offset = 'O',
|
||||||
@ -778,7 +778,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
num_lines = 'r',
|
num_lines = 'r',
|
||||||
cell_x_offset = 'X',
|
cell_x_offset = 'X',
|
||||||
cell_y_offset = 'Y',
|
cell_y_offset = 'Y',
|
||||||
z_index = 'z'
|
z_index = 'z'
|
||||||
};
|
};
|
||||||
enum KEYS key = 'a';
|
enum KEYS key = 'a';
|
||||||
static GraphicsCommand g;
|
static GraphicsCommand g;
|
||||||
@ -840,8 +840,8 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
is_negative = false;
|
is_negative = false;
|
||||||
if(screen->parser_buf[pos] == '-') { is_negative = true; pos++; }
|
if(screen->parser_buf[pos] == '-') { is_negative = true; pos++; }
|
||||||
#define U(x) case x: g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; break
|
#define U(x) case x: g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; break
|
||||||
READ_UINT;
|
READ_UINT;
|
||||||
switch(key) {
|
switch(key) {
|
||||||
U(z_index);
|
U(z_index);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -851,9 +851,9 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
case UINT:
|
case UINT:
|
||||||
READ_UINT;
|
READ_UINT;
|
||||||
#define U(x) case x: g.x = code; break
|
#define U(x) case x: g.x = code; break
|
||||||
switch(key) {
|
switch(key) {
|
||||||
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset);
|
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
state = AFTER_VALUE;
|
state = AFTER_VALUE;
|
||||||
break;
|
break;
|
||||||
@ -869,7 +869,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
state = PAYLOAD;
|
state = PAYLOAD;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Malformed graphics control block, expecting a comma or semi-colon after a value, found: 0x%x", screen->parser_buf[pos - 1]);
|
REPORT_ERROR("Malformed graphics control block, expecting a comma or semi-colon after a value, found: 0x%x", screen->parser_buf[pos - 1]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -879,7 +879,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
err = base64_decode(screen->parser_buf + pos, sz, payload, sizeof(payload), &g.payload_sz);
|
err = base64_decode(screen->parser_buf + pos, sz, payload, sizeof(payload), &g.payload_sz);
|
||||||
if (err != NULL) { REPORT_ERROR("Failed to parse graphics command payload with error: %s", err); return; }
|
if (err != NULL) { REPORT_ERROR("Failed to parse graphics command payload with error: %s", err); return; }
|
||||||
pos = screen->parser_buf_pos;
|
pos = screen->parser_buf_pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch(state) {
|
switch(state) {
|
||||||
@ -887,16 +887,16 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
REPORT_ERROR("Malformed graphics control block, no = after key"); return;
|
REPORT_ERROR("Malformed graphics control block, no = after key"); return;
|
||||||
case INT:
|
case INT:
|
||||||
case UINT:
|
case UINT:
|
||||||
REPORT_ERROR("Malformed graphics control block, expecting an integer value"); return;
|
REPORT_ERROR("Malformed graphics control block, expecting an integer value"); return;
|
||||||
case FLAG:
|
case FLAG:
|
||||||
REPORT_ERROR("Malformed graphics control block, expecting a flag value"); return;
|
REPORT_ERROR("Malformed graphics control block, expecting a flag value"); return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#define A(x) #x, g.x
|
#define A(x) #x, g.x
|
||||||
#define U(x) #x, (unsigned int)(g.x)
|
#define U(x) #x, (unsigned int)(g.x)
|
||||||
#define I(x) #x, (int)(g.x)
|
#define I(x) #x, (int)(g.x)
|
||||||
REPORT_VA_COMMAND("s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
REPORT_VA_COMMAND("s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
||||||
A(action), A(delete_action), A(transmission_type), A(compressed),
|
A(action), A(delete_action), A(transmission_type), A(compressed),
|
||||||
U(format), U(more), U(id), U(data_sz), U(data_offset),
|
U(format), U(more), U(id), U(data_sz), U(data_offset),
|
||||||
U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines), U(cell_x_offset), U(cell_y_offset),
|
U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines), U(cell_x_offset), U(cell_y_offset),
|
||||||
@ -1027,7 +1027,7 @@ accumulate_csi(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_callback)
|
|||||||
REPORT_ERROR("CSI sequence too long, ignoring"); \
|
REPORT_ERROR("CSI sequence too long, ignoring"); \
|
||||||
SET_STATE(0); \
|
SET_STATE(0); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
IS_DIGIT
|
IS_DIGIT
|
||||||
@ -1073,8 +1073,8 @@ END_ALLOW_CASE_RANGE
|
|||||||
case HTS:
|
case HTS:
|
||||||
handle_normal_mode_char(screen, ch, dump_callback);
|
handle_normal_mode_char(screen, ch, dump_callback);
|
||||||
break;
|
break;
|
||||||
case NUL:
|
case NUL:
|
||||||
case DEL:
|
case DEL:
|
||||||
break; // no-op
|
break; // no-op
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Invalid character in CSI: 0x%x, ignoring the sequence", ch);
|
REPORT_ERROR("Invalid character in CSI: 0x%x, ignoring the sequence", ch);
|
||||||
@ -1116,7 +1116,7 @@ dispatch_unicode_char(Screen *screen, uint32_t codepoint, PyObject DUMP_UNUSED *
|
|||||||
|
|
||||||
extern uint32_t *latin1_charset;
|
extern uint32_t *latin1_charset;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_parse_bytes(Screen *screen, uint8_t *buf, Py_ssize_t len, PyObject DUMP_UNUSED *dump_callback) {
|
_parse_bytes(Screen *screen, uint8_t *buf, Py_ssize_t len, PyObject DUMP_UNUSED *dump_callback) {
|
||||||
uint32_t prev = screen->utf8_state;
|
uint32_t prev = screen->utf8_state;
|
||||||
for (unsigned int i = 0; i < (unsigned int)len; i++) {
|
for (unsigned int i = 0; i < (unsigned int)len; i++) {
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef BufType
|
#ifndef BufType
|
||||||
#define BufType LineBuf
|
#define BufType LineBuf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -41,13 +41,13 @@
|
|||||||
#define is_src_line_continued(src_y) (src_y < src->ynum - 1 ? (src->line_attrs[src_y + 1] & CONTINUED_MASK) : false)
|
#define is_src_line_continued(src_y) (src_y < src->ynum - 1 ? (src->line_attrs[src_y + 1] & CONTINUED_MASK) : false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) {
|
copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) {
|
||||||
memcpy(dest->cells + dest_at, src->cells + src_at, num * sizeof(Cell));
|
memcpy(dest->cells + dest_at, src->cells + src_at, num * sizeof(Cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf UNUSED *historybuf) {
|
rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf UNUSED *historybuf) {
|
||||||
bool src_line_is_continued = false;
|
bool src_line_is_continued = false;
|
||||||
index_type src_y = 0, src_x = 0, dest_x = 0, dest_y = 0, num = 0, src_x_limit = 0;
|
index_type src_y = 0, src_x = 0, dest_x = 0, dest_y = 0, num = 0, src_x_limit = 0;
|
||||||
@ -60,7 +60,7 @@ rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf
|
|||||||
if (!src_line_is_continued) {
|
if (!src_line_is_continued) {
|
||||||
// Trim trailing blanks since there is a hard line break at the end of this line
|
// Trim trailing blanks since there is a hard line break at the end of this line
|
||||||
while(src_x_limit && (src->line->cells[src_x_limit - 1].ch) == BLANK_CHAR) src_x_limit--;
|
while(src_x_limit && (src->line->cells[src_x_limit - 1].ch) == BLANK_CHAR) src_x_limit--;
|
||||||
|
|
||||||
}
|
}
|
||||||
while (src_x < src_x_limit) {
|
while (src_x < src_x_limit) {
|
||||||
if (dest_x >= dest->xnum) { next_dest_line(true); dest_x = 0; }
|
if (dest_x >= dest->xnum) { next_dest_line(true); dest_x = 0; }
|
||||||
|
|||||||
198
kitty/screen.c
198
kitty/screen.c
@ -13,7 +13,7 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "unicode-data.h"
|
#include "unicode-data.h"
|
||||||
@ -26,7 +26,7 @@ static Selection EMPTY_SELECTION = {0};
|
|||||||
|
|
||||||
// Constructor/destructor {{{
|
// Constructor/destructor {{{
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
init_tabstops(bool *tabstops, index_type count) {
|
init_tabstops(bool *tabstops, index_type count) {
|
||||||
// In terminfo we specify the number of initial tabstops (it) as 8
|
// In terminfo we specify the number of initial tabstops (it) as 8
|
||||||
for (unsigned int t=0; t < count; t++) {
|
for (unsigned int t=0; t < count; t++) {
|
||||||
@ -40,7 +40,7 @@ init_tabstops(bool *tabstops, index_type count) {
|
|||||||
self->g_charset = self->g0_charset; \
|
self->g_charset = self->g0_charset; \
|
||||||
self->utf8_state = 0; \
|
self->utf8_state = 0; \
|
||||||
self->utf8_codepoint = 0; \
|
self->utf8_codepoint = 0; \
|
||||||
self->use_latin1 = false;
|
self->use_latin1 = false;
|
||||||
#define CALLBACK(...) \
|
#define CALLBACK(...) \
|
||||||
if (self->callbacks != Py_None) { \
|
if (self->callbacks != Py_None) { \
|
||||||
PyObject *callback_ret = PyObject_CallMethod(self->callbacks, __VA_ARGS__); \
|
PyObject *callback_ret = PyObject_CallMethod(self->callbacks, __VA_ARGS__); \
|
||||||
@ -84,7 +84,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
|
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
|
||||||
self->linebuf = self->main_linebuf;
|
self->linebuf = self->main_linebuf;
|
||||||
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns);
|
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns);
|
||||||
self->main_grman = grman_alloc();
|
self->main_grman = grman_alloc();
|
||||||
self->alt_grman = grman_alloc();
|
self->alt_grman = grman_alloc();
|
||||||
self->grman = self->main_grman;
|
self->grman = self->main_grman;
|
||||||
self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool));
|
self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool));
|
||||||
@ -99,7 +99,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
return (PyObject*) self;
|
return (PyObject*) self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reset(Screen *self) {
|
screen_reset(Screen *self) {
|
||||||
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self);
|
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self);
|
||||||
linebuf_clear(self->linebuf, BLANK_CHAR);
|
linebuf_clear(self->linebuf, BLANK_CHAR);
|
||||||
@ -121,7 +121,7 @@ screen_reset(Screen *self) {
|
|||||||
set_color_table_color(self, 104, NULL);
|
set_color_table_color(self, 104, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline HistoryBuf*
|
static inline HistoryBuf*
|
||||||
realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) {
|
realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) {
|
||||||
HistoryBuf *ans = alloc_historybuf(lines, columns);
|
HistoryBuf *ans = alloc_historybuf(lines, columns);
|
||||||
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
||||||
@ -129,7 +129,7 @@ realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline LineBuf*
|
static inline LineBuf*
|
||||||
realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb) {
|
realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *nclb, index_type *ncla, HistoryBuf *hb) {
|
||||||
LineBuf *ans = alloc_linebuf(lines, columns);
|
LineBuf *ans = alloc_linebuf(lines, columns);
|
||||||
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
||||||
@ -137,7 +137,7 @@ realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *n
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
||||||
lines = MAX(1, lines); columns = MAX(1, columns);
|
lines = MAX(1, lines); columns = MAX(1, columns);
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ screen_rescale_images(Screen *self, unsigned int old_cell_width, unsigned int ol
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
screen_change_scrollback_size(Screen *self, unsigned int size) {
|
screen_change_scrollback_size(Screen *self, unsigned int size) {
|
||||||
if (size != self->historybuf->ynum) return historybuf_resize(self->historybuf, size);
|
if (size != self->historybuf->ynum) return historybuf_resize(self->historybuf, size);
|
||||||
return true;
|
return true;
|
||||||
@ -221,13 +221,13 @@ static void
|
|||||||
dealloc(Screen* self) {
|
dealloc(Screen* self) {
|
||||||
pthread_mutex_destroy(&self->read_buf_lock);
|
pthread_mutex_destroy(&self->read_buf_lock);
|
||||||
pthread_mutex_destroy(&self->write_buf_lock);
|
pthread_mutex_destroy(&self->write_buf_lock);
|
||||||
Py_CLEAR(self->main_grman);
|
Py_CLEAR(self->main_grman);
|
||||||
Py_CLEAR(self->alt_grman);
|
Py_CLEAR(self->alt_grman);
|
||||||
PyMem_RawFree(self->write_buf);
|
PyMem_RawFree(self->write_buf);
|
||||||
Py_CLEAR(self->callbacks);
|
Py_CLEAR(self->callbacks);
|
||||||
Py_CLEAR(self->test_child);
|
Py_CLEAR(self->test_child);
|
||||||
Py_CLEAR(self->cursor);
|
Py_CLEAR(self->cursor);
|
||||||
Py_CLEAR(self->main_linebuf);
|
Py_CLEAR(self->main_linebuf);
|
||||||
Py_CLEAR(self->alt_linebuf);
|
Py_CLEAR(self->alt_linebuf);
|
||||||
Py_CLEAR(self->historybuf);
|
Py_CLEAR(self->historybuf);
|
||||||
Py_CLEAR(self->color_profile);
|
Py_CLEAR(self->color_profile);
|
||||||
@ -236,8 +236,8 @@ dealloc(Screen* self) {
|
|||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
// Draw text {{{
|
// Draw text {{{
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_change_charset(Screen *self, uint32_t which) {
|
screen_change_charset(Screen *self, uint32_t which) {
|
||||||
switch(which) {
|
switch(which) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -247,7 +247,7 @@ screen_change_charset(Screen *self, uint32_t which) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_designate_charset(Screen *self, uint32_t which, uint32_t as) {
|
screen_designate_charset(Screen *self, uint32_t which, uint32_t as) {
|
||||||
bool change_g = false;
|
bool change_g = false;
|
||||||
switch(which) {
|
switch(which) {
|
||||||
@ -267,7 +267,7 @@ screen_designate_charset(Screen *self, uint32_t which, uint32_t as) {
|
|||||||
|
|
||||||
static int (*wcwidth_impl)(wchar_t) = wcwidth;
|
static int (*wcwidth_impl)(wchar_t) = wcwidth;
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
safe_wcwidth(uint32_t ch) {
|
safe_wcwidth(uint32_t ch) {
|
||||||
int ans = wcwidth_impl(ch);
|
int ans = wcwidth_impl(ch);
|
||||||
if (ans < 0) ans = 1;
|
if (ans < 0) ans = 1;
|
||||||
@ -334,9 +334,9 @@ screen_align(Screen *self) {
|
|||||||
|
|
||||||
// Graphics {{{
|
// Graphics {{{
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_alignment_display(Screen *self) {
|
screen_alignment_display(Screen *self) {
|
||||||
// http://www.vt100.net/docs/vt510-rm/DECALN.html
|
// http://www.vt100.net/docs/vt510-rm/DECALN.html
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||||
for (unsigned int y = 0; y < self->linebuf->ynum; y++) {
|
for (unsigned int y = 0; y < self->linebuf->ynum; y++) {
|
||||||
@ -346,7 +346,7 @@ screen_alignment_display(Screen *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count, Region *region_) {
|
select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count, Region *region_) {
|
||||||
if (region_) {
|
if (region_) {
|
||||||
Region region = *region_;
|
Region region = *region_;
|
||||||
@ -418,7 +418,7 @@ screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const u
|
|||||||
if (response != NULL) write_escape_code_to_child(self, APC, 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);
|
||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -427,7 +427,7 @@ screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const u
|
|||||||
// Modes {{{
|
// Modes {{{
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_toggle_screen_buffer(Screen *self) {
|
screen_toggle_screen_buffer(Screen *self) {
|
||||||
bool to_alt = self->linebuf == self->main_linebuf;
|
bool to_alt = self->linebuf == self->main_linebuf;
|
||||||
grman_clear(self->alt_grman); // always clear the alt buffer graphics to free up resources, since it has to be cleared when switching back to it anyway
|
grman_clear(self->alt_grman); // always clear the alt buffer graphics to free up resources, since it has to be cleared when switching back to it anyway
|
||||||
@ -452,7 +452,7 @@ screen_toggle_screen_buffer(Screen *self) {
|
|||||||
void screen_normal_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
void screen_normal_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
||||||
void screen_alternate_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
void screen_alternate_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
||||||
#define SIMPLE_MODE(name) \
|
#define SIMPLE_MODE(name) \
|
||||||
case name: \
|
case name: \
|
||||||
@ -481,40 +481,40 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
case DECNRCM:
|
case DECNRCM:
|
||||||
break; // we ignore these modes
|
break; // we ignore these modes
|
||||||
case DECCKM:
|
case DECCKM:
|
||||||
self->modes.mDECCKM = val;
|
self->modes.mDECCKM = val;
|
||||||
break;
|
break;
|
||||||
case DECTCEM:
|
case DECTCEM:
|
||||||
self->modes.mDECTCEM = val;
|
self->modes.mDECTCEM = val;
|
||||||
break;
|
break;
|
||||||
case DECSCNM:
|
case DECSCNM:
|
||||||
// Render screen in reverse video
|
// Render screen in reverse video
|
||||||
if (self->modes.mDECSCNM != val) {
|
if (self->modes.mDECSCNM != val) {
|
||||||
self->modes.mDECSCNM = val;
|
self->modes.mDECSCNM = val;
|
||||||
self->is_dirty = true;
|
self->is_dirty = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DECOM:
|
case DECOM:
|
||||||
self->modes.mDECOM = val;
|
self->modes.mDECOM = val;
|
||||||
// According to `vttest`, DECOM should also home the cursor, see
|
// According to `vttest`, DECOM should also home the cursor, see
|
||||||
// vttest/main.c:303.
|
// vttest/main.c:303.
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
break;
|
break;
|
||||||
case DECAWM:
|
case DECAWM:
|
||||||
self->modes.mDECAWM = val; break;
|
self->modes.mDECAWM = val; break;
|
||||||
case DECCOLM:
|
case DECCOLM:
|
||||||
// When DECCOLM mode is set, the screen is erased and the cursor
|
// When DECCOLM mode is set, the screen is erased and the cursor
|
||||||
// moves to the home position.
|
// moves to the home position.
|
||||||
self->modes.mDECCOLM = val;
|
self->modes.mDECCOLM = val;
|
||||||
screen_erase_in_display(self, 2, false);
|
screen_erase_in_display(self, 2, false);
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
break;
|
break;
|
||||||
case CONTROL_CURSOR_BLINK:
|
case CONTROL_CURSOR_BLINK:
|
||||||
self->cursor->blink = val;
|
self->cursor->blink = val;
|
||||||
break;
|
break;
|
||||||
case ALTERNATE_SCREEN:
|
case ALTERNATE_SCREEN:
|
||||||
if (val && self->linebuf == self->main_linebuf) screen_toggle_screen_buffer(self);
|
if (val && self->linebuf == self->main_linebuf) screen_toggle_screen_buffer(self);
|
||||||
else if (!val && self->linebuf != self->main_linebuf) screen_toggle_screen_buffer(self);
|
else if (!val && self->linebuf != self->main_linebuf) screen_toggle_screen_buffer(self);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
private = mode >= 1 << 5;
|
private = mode >= 1 << 5;
|
||||||
if (private) mode >>= 5;
|
if (private) mode >>= 5;
|
||||||
@ -524,7 +524,7 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
#undef MOUSE_MODE
|
#undef MOUSE_MODE
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_set_mode(Screen *self, unsigned int mode) {
|
screen_set_mode(Screen *self, unsigned int mode) {
|
||||||
set_mode_from_const(self, mode, true);
|
set_mode_from_const(self, mode, true);
|
||||||
}
|
}
|
||||||
@ -534,7 +534,7 @@ screen_decsace(Screen *self, unsigned int val) {
|
|||||||
self->modes.mDECSACE = val == 2 ? true : false;
|
self->modes.mDECSACE = val == 2 ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reset_mode(Screen *self, unsigned int mode) {
|
screen_reset_mode(Screen *self, unsigned int mode) {
|
||||||
set_mode_from_const(self, mode, false);
|
set_mode_from_const(self, mode, false);
|
||||||
}
|
}
|
||||||
@ -561,12 +561,12 @@ screen_is_cursor_visible(Screen *self) {
|
|||||||
return self->modes.mDECTCEM;
|
return self->modes.mDECTCEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_backspace(Screen *self) {
|
screen_backspace(Screen *self) {
|
||||||
screen_cursor_back(self, 1, -1);
|
screen_cursor_back(self, 1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_tab(Screen *self) {
|
screen_tab(Screen *self) {
|
||||||
// Move to the next tab space, or the end of the screen if there aren't anymore left.
|
// Move to the next tab space, or the end of the screen if there aren't anymore left.
|
||||||
unsigned int found = 0;
|
unsigned int found = 0;
|
||||||
@ -579,7 +579,7 @@ screen_tab(Screen *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_backtab(Screen *self, unsigned int count) {
|
screen_backtab(Screen *self, unsigned int count) {
|
||||||
// Move back count tabs
|
// Move back count tabs
|
||||||
if (!count) count = 1;
|
if (!count) count = 1;
|
||||||
@ -593,7 +593,7 @@ screen_backtab(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_clear_tab_stop(Screen *self, unsigned int how) {
|
screen_clear_tab_stop(Screen *self, unsigned int how) {
|
||||||
switch(how) {
|
switch(how) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -610,13 +610,13 @@ screen_clear_tab_stop(Screen *self, unsigned int how) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_set_tab_stop(Screen *self) {
|
screen_set_tab_stop(Screen *self) {
|
||||||
if (self->cursor->x < self->columns)
|
if (self->cursor->x < self->columns)
|
||||||
self->tabstops[self->cursor->x] = true;
|
self->tabstops[self->cursor->x] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/) {
|
screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/) {
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (move_direction < 0 && count > self->cursor->x) self->cursor->x = 0;
|
if (move_direction < 0 && count > self->cursor->x) self->cursor->x = 0;
|
||||||
@ -624,12 +624,12 @@ screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=
|
|||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_forward(Screen *self, unsigned int count/*=1*/) {
|
screen_cursor_forward(Screen *self, unsigned int count/*=1*/) {
|
||||||
screen_cursor_back(self, count, 1);
|
screen_cursor_back(self, count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return/*=false*/, int move_direction/*=-1*/) {
|
screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return/*=false*/, int move_direction/*=-1*/) {
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (move_direction < 0 && count > self->cursor->y) self->cursor->y = 0;
|
if (move_direction < 0 && count > self->cursor->y) self->cursor->y = 0;
|
||||||
@ -638,22 +638,22 @@ screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return
|
|||||||
if (do_carriage_return) self->cursor->x = 0;
|
if (do_carriage_return) self->cursor->x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_up1(Screen *self, unsigned int count/*=1*/) {
|
screen_cursor_up1(Screen *self, unsigned int count/*=1*/) {
|
||||||
screen_cursor_up(self, count, true, -1);
|
screen_cursor_up(self, count, true, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_down(Screen *self, unsigned int count/*=1*/) {
|
screen_cursor_down(Screen *self, unsigned int count/*=1*/) {
|
||||||
screen_cursor_up(self, count, false, 1);
|
screen_cursor_up(self, count, false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_down1(Screen *self, unsigned int count/*=1*/) {
|
screen_cursor_down1(Screen *self, unsigned int count/*=1*/) {
|
||||||
screen_cursor_up(self, count, true, 1);
|
screen_cursor_up(self, count, true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_to_column(Screen *self, unsigned int column) {
|
screen_cursor_to_column(Screen *self, unsigned int column) {
|
||||||
unsigned int x = MAX(column, 1) - 1;
|
unsigned int x = MAX(column, 1) - 1;
|
||||||
if (x != self->cursor->x) {
|
if (x != self->cursor->x) {
|
||||||
@ -683,7 +683,7 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
|||||||
linebuf_clear_line(self->linebuf, bottom); \
|
linebuf_clear_line(self->linebuf, bottom); \
|
||||||
self->is_dirty = true;
|
self->is_dirty = true;
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_index(Screen *self) {
|
screen_index(Screen *self) {
|
||||||
// Move cursor down one line, scrolling screen if needed
|
// Move cursor down one line, scrolling screen if needed
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
@ -692,7 +692,7 @@ screen_index(Screen *self) {
|
|||||||
} else screen_cursor_down(self, 1);
|
} else screen_cursor_down(self, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_scroll(Screen *self, unsigned int count) {
|
screen_scroll(Screen *self, unsigned int count) {
|
||||||
// Scroll the screen up by count lines, not moving the cursor
|
// Scroll the screen up by count lines, not moving the cursor
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
@ -708,7 +708,7 @@ screen_scroll(Screen *self, unsigned int count) {
|
|||||||
INDEX_GRAPHICS(1) \
|
INDEX_GRAPHICS(1) \
|
||||||
self->is_dirty = true;
|
self->is_dirty = true;
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reverse_index(Screen *self) {
|
screen_reverse_index(Screen *self) {
|
||||||
// Move cursor up one line, scrolling screen if needed
|
// Move cursor up one line, scrolling screen if needed
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
@ -717,7 +717,7 @@ screen_reverse_index(Screen *self) {
|
|||||||
} else screen_cursor_up(self, 1, false, -1);
|
} else screen_cursor_up(self, 1, false, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reverse_scroll(Screen *self, unsigned int count) {
|
screen_reverse_scroll(Screen *self, unsigned int count) {
|
||||||
// Scroll the screen down by count lines, not moving the cursor
|
// Scroll the screen down by count lines, not moving the cursor
|
||||||
count = MIN(self->lines, count);
|
count = MIN(self->lines, count);
|
||||||
@ -729,21 +729,21 @@ screen_reverse_scroll(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_carriage_return(Screen *self) {
|
screen_carriage_return(Screen *self) {
|
||||||
if (self->cursor->x != 0) {
|
if (self->cursor->x != 0) {
|
||||||
self->cursor->x = 0;
|
self->cursor->x = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_linefeed(Screen *self) {
|
screen_linefeed(Screen *self) {
|
||||||
screen_index(self);
|
screen_index(self);
|
||||||
if (self->modes.mLNM) screen_carriage_return(self);
|
if (self->modes.mLNM) screen_carriage_return(self);
|
||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Savepoint*
|
static inline Savepoint*
|
||||||
savepoints_push(SavepointBuffer *self) {
|
savepoints_push(SavepointBuffer *self) {
|
||||||
Savepoint *ans = self->buf + ((self->start_of_data + self->count) % SAVEPOINTS_SZ);
|
Savepoint *ans = self->buf + ((self->start_of_data + self->count) % SAVEPOINTS_SZ);
|
||||||
if (self->count == SAVEPOINTS_SZ) self->start_of_data = (self->start_of_data + 1) % SAVEPOINTS_SZ;
|
if (self->count == SAVEPOINTS_SZ) self->start_of_data = (self->start_of_data + 1) % SAVEPOINTS_SZ;
|
||||||
@ -751,7 +751,7 @@ savepoints_push(SavepointBuffer *self) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Savepoint*
|
static inline Savepoint*
|
||||||
savepoints_pop(SavepointBuffer *self) {
|
savepoints_pop(SavepointBuffer *self) {
|
||||||
if (self->count == 0) return NULL;
|
if (self->count == 0) return NULL;
|
||||||
self->count--;
|
self->count--;
|
||||||
@ -766,7 +766,7 @@ savepoints_pop(SavepointBuffer *self) {
|
|||||||
sp->g_charset = self->g_charset; \
|
sp->g_charset = self->g_charset; \
|
||||||
sp->use_latin1 = self->use_latin1;
|
sp->use_latin1 = self->use_latin1;
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_save_cursor(Screen *self) {
|
screen_save_cursor(Screen *self) {
|
||||||
SavepointBuffer *pts = self->linebuf == self->main_linebuf ? &self->main_savepoints : &self->alt_savepoints;
|
SavepointBuffer *pts = self->linebuf == self->main_linebuf ? &self->main_savepoints : &self->alt_savepoints;
|
||||||
Savepoint *sp = savepoints_push(pts);
|
Savepoint *sp = savepoints_push(pts);
|
||||||
@ -777,7 +777,7 @@ screen_save_cursor(Screen *self) {
|
|||||||
COPY_CHARSETS(self, sp);
|
COPY_CHARSETS(self, sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_restore_cursor(Screen *self) {
|
screen_restore_cursor(Screen *self) {
|
||||||
SavepointBuffer *pts = self->linebuf == self->main_linebuf ? &self->main_savepoints : &self->alt_savepoints;
|
SavepointBuffer *pts = self->linebuf == self->main_linebuf ? &self->main_savepoints : &self->alt_savepoints;
|
||||||
Savepoint *sp = savepoints_pop(pts);
|
Savepoint *sp = savepoints_pop(pts);
|
||||||
@ -796,7 +796,7 @@ screen_restore_cursor(Screen *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_ensure_bounds(Screen *self, bool force_use_margins/*=false*/) {
|
screen_ensure_bounds(Screen *self, bool force_use_margins/*=false*/) {
|
||||||
unsigned int top, bottom;
|
unsigned int top, bottom;
|
||||||
if (force_use_margins || self->modes.mDECOM) {
|
if (force_use_margins || self->modes.mDECOM) {
|
||||||
@ -808,7 +808,7 @@ screen_ensure_bounds(Screen *self, bool force_use_margins/*=false*/) {
|
|||||||
self->cursor->y = MAX(top, MIN(self->cursor->y, bottom));
|
self->cursor->y = MAX(top, MIN(self->cursor->y, bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
||||||
line = (line == 0 ? 1 : line) - 1;
|
line = (line == 0 ? 1 : line) - 1;
|
||||||
column = (column == 0 ? 1: column) - 1;
|
column = (column == 0 ? 1: column) - 1;
|
||||||
@ -820,7 +820,7 @@ screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
|||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_cursor_to_line(Screen *self, unsigned int line) {
|
screen_cursor_to_line(Screen *self, unsigned int line) {
|
||||||
screen_cursor_position(self, line, self->cursor->x + 1);
|
screen_cursor_position(self, line, self->cursor->x + 1);
|
||||||
}
|
}
|
||||||
@ -829,7 +829,7 @@ screen_cursor_to_line(Screen *self, unsigned int line) {
|
|||||||
|
|
||||||
// Editing {{{
|
// Editing {{{
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_erase_in_line(Screen *self, unsigned int how, bool private) {
|
screen_erase_in_line(Screen *self, unsigned int how, bool private) {
|
||||||
/*Erases a line in a specific way.
|
/*Erases a line in a specific way.
|
||||||
|
|
||||||
@ -870,7 +870,7 @@ screen_erase_in_line(Screen *self, unsigned int how, bool private) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_erase_in_display(Screen *self, unsigned int how, bool private) {
|
screen_erase_in_display(Screen *self, unsigned int how, bool private) {
|
||||||
/* Erases display in a specific way.
|
/* Erases display in a specific way.
|
||||||
|
|
||||||
@ -913,7 +913,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_insert_lines(Screen *self, unsigned int count) {
|
screen_insert_lines(Screen *self, unsigned int count) {
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
@ -924,7 +924,7 @@ screen_insert_lines(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_delete_lines(Screen *self, unsigned int count) {
|
screen_delete_lines(Screen *self, unsigned int count) {
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
@ -935,7 +935,7 @@ screen_delete_lines(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_insert_characters(Screen *self, unsigned int count) {
|
screen_insert_characters(Screen *self, unsigned int count) {
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
@ -950,7 +950,7 @@ screen_insert_characters(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_delete_characters(Screen *self, unsigned int count) {
|
screen_delete_characters(Screen *self, unsigned int count) {
|
||||||
// Delete characters, later characters are moved left
|
// Delete characters, later characters are moved left
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
@ -966,7 +966,7 @@ screen_delete_characters(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_erase_characters(Screen *self, unsigned int count) {
|
screen_erase_characters(Screen *self, unsigned int count) {
|
||||||
// Delete characters replacing them by spaces
|
// Delete characters replacing them by spaces
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
@ -984,7 +984,7 @@ screen_erase_characters(Screen *self, unsigned int count) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
screen_use_latin1(Screen *self, bool on) {
|
screen_use_latin1(Screen *self, bool on) {
|
||||||
self->use_latin1 = on; self->utf8_state = 0; self->utf8_codepoint = 0;
|
self->use_latin1 = on; self->utf8_state = 0; self->utf8_codepoint = 0;
|
||||||
CALLBACK("use_utf8", "O", on ? Py_False : Py_True);
|
CALLBACK("use_utf8", "O", on ? Py_False : Py_True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,12 +999,12 @@ screen_invert_colors(Screen *self) {
|
|||||||
return inverted;
|
return inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_bell(Screen *self) {
|
screen_bell(Screen *self) {
|
||||||
request_window_attention(self->window_id, OPT(enable_audio_bell));
|
request_window_attention(self->window_id, OPT(enable_audio_bell));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
switch(start_modifier) {
|
switch(start_modifier) {
|
||||||
@ -1018,7 +1018,7 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_device_status(Screen *self, unsigned int which, bool private) {
|
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
|
||||||
@ -1042,7 +1042,7 @@ report_device_status(Screen *self, unsigned int which, bool private) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_mode_status(Screen *self, unsigned int which, bool private) {
|
report_mode_status(Screen *self, unsigned int which, bool private) {
|
||||||
unsigned int q = private ? which << 5 : which;
|
unsigned int q = private ? which << 5 : which;
|
||||||
unsigned int ans = 0;
|
unsigned int ans = 0;
|
||||||
@ -1071,7 +1071,7 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
|
|||||||
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_set_margins(Screen *self, unsigned int top, unsigned int bottom) {
|
screen_set_margins(Screen *self, unsigned int top, unsigned int bottom) {
|
||||||
if (!top) top = 1;
|
if (!top) top = 1;
|
||||||
if (!bottom) bottom = self->lines;
|
if (!bottom) bottom = self->lines;
|
||||||
@ -1089,7 +1089,7 @@ screen_set_margins(Screen *self, unsigned int top, unsigned int bottom) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_set_cursor(Screen *self, unsigned int mode, uint8_t secondary) {
|
screen_set_cursor(Screen *self, unsigned int mode, uint8_t secondary) {
|
||||||
uint8_t shape; bool blink;
|
uint8_t shape; bool blink;
|
||||||
switch(secondary) {
|
switch(secondary) {
|
||||||
@ -1110,29 +1110,29 @@ screen_set_cursor(Screen *self, unsigned int mode, uint8_t secondary) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_title(Screen *self, PyObject *title) {
|
set_title(Screen *self, PyObject *title) {
|
||||||
CALLBACK("title_changed", "O", title);
|
CALLBACK("title_changed", "O", title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_icon(Screen *self, PyObject *icon) {
|
set_icon(Screen *self, PyObject *icon) {
|
||||||
CALLBACK("icon_changed", "O", icon);
|
CALLBACK("icon_changed", "O", icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_dynamic_color(Screen *self, unsigned int code, PyObject *color) {
|
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", "Is", code, ""); }
|
||||||
else { CALLBACK("set_dynamic_color", "IO", code, color); }
|
else { CALLBACK("set_dynamic_color", "IO", code, color); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_color_table_color(Screen *self, unsigned int code, PyObject *color) {
|
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", "Is", code, ""); }
|
||||||
else { CALLBACK("set_color_table_color", "IO", code, color); }
|
else { CALLBACK("set_color_table_color", "IO", code, color); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
screen_request_capabilities(Screen *self, char c, PyObject *q) {
|
||||||
static char buf[128];
|
static char buf[128];
|
||||||
int shape = 0;
|
int shape = 0;
|
||||||
@ -1252,7 +1252,7 @@ visual_line_(Screen *self, index_type y) {
|
|||||||
if (y < self->scrolled_by) {
|
if (y < self->scrolled_by) {
|
||||||
historybuf_init_line(self->historybuf, self->scrolled_by - 1 - y, self->historybuf->line);
|
historybuf_init_line(self->historybuf, self->scrolled_by - 1 - y, self->historybuf->line);
|
||||||
return self->historybuf->line;
|
return self->historybuf->line;
|
||||||
}
|
}
|
||||||
y -= self->scrolled_by;
|
y -= self->scrolled_by;
|
||||||
}
|
}
|
||||||
linebuf_init_line(self->linebuf, y);
|
linebuf_init_line(self->linebuf, y);
|
||||||
@ -1274,11 +1274,11 @@ visual_line_(Screen *self, index_type y) {
|
|||||||
index_type xlimit = xlimit_for_line(line); \
|
index_type xlimit = xlimit_for_line(line); \
|
||||||
if (y == end->y) xlimit = MIN(end->x + 1, xlimit); \
|
if (y == end->y) xlimit = MIN(end->x + 1, xlimit); \
|
||||||
index_type x_start = y == start->y ? start->x : 0;
|
index_type x_start = y == start->y ? start->x : 0;
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
apply_selection(Screen *self, uint8_t *data, SelectionBoundary *start, SelectionBoundary *end, uint8_t set_mask, bool rectangle_select) {
|
apply_selection(Screen *self, uint8_t *data, SelectionBoundary *start, SelectionBoundary *end, uint8_t set_mask, bool rectangle_select) {
|
||||||
if (is_selection_empty(self, start->x, start->y, end->x, end->y)) return;
|
if (is_selection_empty(self, start->x, start->y, end->x, end->y)) return;
|
||||||
if (rectangle_select) {
|
if (rectangle_select) {
|
||||||
iterate_over_rectangle(start, end)
|
iterate_over_rectangle(start, end)
|
||||||
uint8_t *line_start = data + self->columns * y;
|
uint8_t *line_start = data + self->columns * y;
|
||||||
@ -1397,7 +1397,7 @@ visual_line(Screen *self, PyObject *args) {
|
|||||||
if (y >= self->lines) { Py_RETURN_NONE; }
|
if (y >= self->lines) { Py_RETURN_NONE; }
|
||||||
return Py_BuildValue("O", visual_line_(self, y));
|
return Py_BuildValue("O", visual_line_(self, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
draw(Screen *self, PyObject *src) {
|
draw(Screen *self, PyObject *src) {
|
||||||
if (!PyUnicode_Check(src)) { PyErr_SetString(PyExc_TypeError, "A unicode string is required"); return NULL; }
|
if (!PyUnicode_Check(src)) { PyErr_SetString(PyExc_TypeError, "A unicode string is required"); return NULL; }
|
||||||
@ -1418,7 +1418,7 @@ reset_mode(Screen *self, PyObject *args) {
|
|||||||
screen_reset_mode(self, mode);
|
screen_reset_mode(self, mode);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_select_graphic_rendition(Screen *self, PyObject *args) {
|
_select_graphic_rendition(Screen *self, PyObject *args) {
|
||||||
unsigned int params[256] = {0};
|
unsigned int params[256] = {0};
|
||||||
@ -1482,8 +1482,8 @@ WRAP2(rescale_images, 1, 1)
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
change_scrollback_size(Screen *self, PyObject *args) {
|
change_scrollback_size(Screen *self, PyObject *args) {
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
if (!PyArg_ParseTuple(args, "|I", &count)) return NULL;
|
if (!PyArg_ParseTuple(args, "|I", &count)) return NULL;
|
||||||
if (!screen_change_scrollback_size(self, MAX(self->lines, count))) return NULL;
|
if (!screen_change_scrollback_size(self, MAX(self->lines, count))) return NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
@ -1495,7 +1495,7 @@ text_for_selection(Screen *self) {
|
|||||||
if (is_selection_empty(self, start.x, start.y, end.x, end.y)) return PyTuple_New(0);
|
if (is_selection_empty(self, start.x, start.y, end.x, end.y)) return PyTuple_New(0);
|
||||||
return text_for_range(self, start, end, self->rectangle_select, true);
|
return text_for_range(self, start, end, self->rectangle_select, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end) {
|
screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end) {
|
||||||
if (y >= self->lines) { return false; }
|
if (y >= self->lines) { return false; }
|
||||||
@ -1526,7 +1526,7 @@ screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_
|
|||||||
} else {
|
} else {
|
||||||
start = x, end = x;
|
start = x, end = x;
|
||||||
while(start > 0 && is_ok(start - 1)) start--;
|
while(start > 0 && is_ok(start - 1)) start--;
|
||||||
while(end < self->columns - 1 && is_ok(end + 1)) end++;
|
while(end < self->columns - 1 && is_ok(end + 1)) end++;
|
||||||
}
|
}
|
||||||
*s = start; *e = end;
|
*s = start; *e = end;
|
||||||
return true;
|
return true;
|
||||||
@ -1592,7 +1592,7 @@ screen_start_selection(Screen *self, index_type x, index_type y, bool rectangle_
|
|||||||
void
|
void
|
||||||
screen_mark_url(Screen *self, index_type start_x, index_type start_y, index_type end_x, index_type end_y) {
|
screen_mark_url(Screen *self, index_type start_x, index_type start_y, index_type end_x, index_type end_y) {
|
||||||
#define A(attr, val) self->url_range.attr = val;
|
#define A(attr, val) self->url_range.attr = val;
|
||||||
A(start_x, start_x); A(end_x, end_x); A(start_y, start_y); A(end_y, end_y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by);
|
A(start_x, start_x); A(end_x, end_x); A(start_y, start_y); A(end_y, end_y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by);
|
||||||
#undef A
|
#undef A
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1602,19 +1602,19 @@ screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
|||||||
if (ended) self->selection.in_progress = false;
|
if (ended) self->selection.in_progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
mark_as_dirty(Screen *self) {
|
mark_as_dirty(Screen *self) {
|
||||||
self->is_dirty = true;
|
self->is_dirty = true;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
current_char_width(Screen *self) {
|
current_char_width(Screen *self) {
|
||||||
#define current_char_width_doc "The width of the character under the cursor"
|
#define current_char_width_doc "The width of the character under the cursor"
|
||||||
return PyLong_FromUnsignedLong(screen_current_char_width(self));
|
return PyLong_FromUnsignedLong(screen_current_char_width(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
is_main_linebuf(Screen *self) {
|
is_main_linebuf(Screen *self) {
|
||||||
PyObject *ans = (self->linebuf == self->main_linebuf) ? Py_True : Py_False;
|
PyObject *ans = (self->linebuf == self->main_linebuf) ? Py_True : Py_False;
|
||||||
Py_INCREF(ans);
|
Py_INCREF(ans);
|
||||||
@ -1743,17 +1743,17 @@ static PyMemberDef members[] = {
|
|||||||
{"history_line_added_count", T_UINT, offsetof(Screen, history_line_added_count), 0, "history_line_added_count"},
|
{"history_line_added_count", T_UINT, offsetof(Screen, history_line_added_count), 0, "history_line_added_count"},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject Screen_Type = {
|
PyTypeObject Screen_Type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = "fast_data_types.Screen",
|
.tp_name = "fast_data_types.Screen",
|
||||||
.tp_basicsize = sizeof(Screen),
|
.tp_basicsize = sizeof(Screen),
|
||||||
.tp_dealloc = (destructor)dealloc,
|
.tp_dealloc = (destructor)dealloc,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "Screen",
|
.tp_doc = "Screen",
|
||||||
.tp_methods = methods,
|
.tp_methods = methods,
|
||||||
.tp_members = members,
|
.tp_members = members,
|
||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
.tp_getset = getsetters,
|
.tp_getset = getsetters,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ typedef struct {
|
|||||||
unsigned int start_x, start_y, start_scrolled_by, end_x, end_y, end_scrolled_by;
|
unsigned int start_x, start_y, start_scrolled_by, end_x, end_y, end_scrolled_by;
|
||||||
bool in_progress;
|
bool in_progress;
|
||||||
} Selection;
|
} Selection;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
@ -75,8 +75,8 @@ void screen_erase_in_display(Screen *, unsigned int, bool);
|
|||||||
void screen_draw(Screen *screen, uint32_t codepoint);
|
void screen_draw(Screen *screen, uint32_t codepoint);
|
||||||
void screen_ensure_bounds(Screen *self, bool use_margins);
|
void screen_ensure_bounds(Screen *self, bool use_margins);
|
||||||
void screen_toggle_screen_buffer(Screen *self);
|
void screen_toggle_screen_buffer(Screen *self);
|
||||||
void screen_normal_keypad_mode(Screen *self);
|
void screen_normal_keypad_mode(Screen *self);
|
||||||
void screen_alternate_keypad_mode(Screen *self);
|
void screen_alternate_keypad_mode(Screen *self);
|
||||||
void screen_change_default_color(Screen *self, unsigned int which, uint32_t col);
|
void screen_change_default_color(Screen *self, unsigned int which, uint32_t col);
|
||||||
void screen_alignment_display(Screen *self);
|
void screen_alignment_display(Screen *self);
|
||||||
void screen_reverse_index(Screen *self);
|
void screen_reverse_index(Screen *self);
|
||||||
|
|||||||
150
kitty/shaders.c
150
kitty/shaders.c
@ -35,14 +35,14 @@ copy_image_sub_data(GLuint src_texture_id, GLuint dest_texture_id, unsigned int
|
|||||||
size_t sz = width * height * num_levels;
|
size_t sz = width * height * num_levels;
|
||||||
pixel *src = malloc(sz * sizeof(pixel));
|
pixel *src = malloc(sz * sizeof(pixel));
|
||||||
if (src == NULL) { fatal("Out of memory."); }
|
if (src == NULL) { fatal("Out of memory."); }
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, src_texture_id);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, src_texture_id);
|
||||||
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, dest_texture_id);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, dest_texture_id);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
||||||
free(src);
|
free(src);
|
||||||
} else {
|
} else {
|
||||||
glCopyImageSubData(src_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, dest_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels);
|
glCopyImageSubData(src_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, dest_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,24 +50,24 @@ copy_image_sub_data(GLuint src_texture_id, GLuint dest_texture_id, unsigned int
|
|||||||
static void
|
static void
|
||||||
realloc_sprite_texture() {
|
realloc_sprite_texture() {
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
glGenTextures(1, &tex);
|
glGenTextures(1, &tex);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||||
// We use GL_NEAREST otherwise glyphs that touch the edge of the cell
|
// We use GL_NEAREST otherwise glyphs that touch the edge of the cell
|
||||||
// often show a border between cells
|
// often show a border between cells
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
unsigned int xnum, ynum, z, znum, width, height, src_ynum;
|
unsigned int xnum, ynum, z, znum, width, height, src_ynum;
|
||||||
sprite_tracker_current_layout(&xnum, &ynum, &z);
|
sprite_tracker_current_layout(&xnum, &ynum, &z);
|
||||||
znum = z + 1;
|
znum = z + 1;
|
||||||
width = xnum * global_state.cell_width; height = ynum * global_state.cell_height;
|
width = xnum * global_state.cell_width; height = ynum * global_state.cell_height;
|
||||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, znum);
|
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, znum);
|
||||||
if (sprite_map.texture_id) {
|
if (sprite_map.texture_id) {
|
||||||
// need to re-alloc
|
// need to re-alloc
|
||||||
src_ynum = MAX(1, sprite_map.last_ynum);
|
src_ynum = MAX(1, sprite_map.last_ynum);
|
||||||
copy_image_sub_data(sprite_map.texture_id, tex, width, src_ynum * global_state.cell_height, sprite_map.last_num_of_layers);
|
copy_image_sub_data(sprite_map.texture_id, tex, width, src_ynum * global_state.cell_height, sprite_map.last_num_of_layers);
|
||||||
glDeleteTextures(1, &sprite_map.texture_id);
|
glDeleteTextures(1, &sprite_map.texture_id);
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||||
sprite_map.last_num_of_layers = znum;
|
sprite_map.last_num_of_layers = znum;
|
||||||
@ -80,40 +80,40 @@ ensure_sprite_map() {
|
|||||||
if (!sprite_map.texture_id) realloc_sprite_texture();
|
if (!sprite_map.texture_id) realloc_sprite_texture();
|
||||||
// We have to rebind since we dont know if the texture was ever bound
|
// We have to rebind since we dont know if the texture was ever bound
|
||||||
// in the context of the current OSWindow
|
// in the context of the current OSWindow
|
||||||
glActiveTexture(GL_TEXTURE0 + SPRITE_MAP_UNIT);
|
glActiveTexture(GL_TEXTURE0 + SPRITE_MAP_UNIT);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map.texture_id);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map.texture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_sprite_to_gpu(unsigned int x, unsigned int y, unsigned int z, pixel *buf) {
|
send_sprite_to_gpu(unsigned int x, unsigned int y, unsigned int z, pixel *buf) {
|
||||||
unsigned int xnum, ynum, znum;
|
unsigned int xnum, ynum, znum;
|
||||||
sprite_tracker_current_layout(&xnum, &ynum, &znum);
|
sprite_tracker_current_layout(&xnum, &ynum, &znum);
|
||||||
if ((int)znum >= sprite_map.last_num_of_layers || (znum == 0 && (int)ynum > sprite_map.last_ynum)) realloc_sprite_texture();
|
if ((int)znum >= sprite_map.last_num_of_layers || (znum == 0 && (int)ynum > sprite_map.last_ynum)) realloc_sprite_texture();
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map.texture_id);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map.texture_id);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
x *= global_state.cell_width; y *= global_state.cell_height;
|
x *= global_state.cell_width; y *= global_state.cell_height;
|
||||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, global_state.cell_width, global_state.cell_height, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf);
|
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, global_state.cell_width, global_state.cell_height, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei height, bool is_opaque, bool is_4byte_aligned) {
|
send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei height, bool is_opaque, bool is_4byte_aligned) {
|
||||||
if (!(*tex_id)) { glGenTextures(1, tex_id); }
|
if (!(*tex_id)) { glGenTextures(1, tex_id); }
|
||||||
glBindTexture(GL_TEXTURE_2D, *tex_id);
|
glBindTexture(GL_TEXTURE_2D, *tex_id);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, is_4byte_aligned ? 4 : 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, is_4byte_aligned ? 4 : 1);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, is_opaque ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, is_opaque ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool limits_updated = false;
|
static bool limits_updated = false;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
layout_sprite_map() {
|
layout_sprite_map() {
|
||||||
if (!limits_updated) {
|
if (!limits_updated) {
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &(sprite_map.max_texture_size));
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &(sprite_map.max_texture_size));
|
||||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &(sprite_map.max_array_texture_layers));
|
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &(sprite_map.max_array_texture_layers));
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// Since on Apple we could have multiple GPUs, with different capabilities,
|
// Since on Apple we could have multiple GPUs, with different capabilities,
|
||||||
// upper bound the values according to the data from http://developer.apple.com/graphicsimaging/opengl/capabilities/
|
// upper bound the values according to the data from http://developer.apple.com/graphicsimaging/opengl/capabilities/
|
||||||
@ -220,15 +220,15 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
|
|||||||
copy_color_table_to_buffer(screen->color_profile, (GLuint*)rd, cell_program_layouts[CELL_PROGRAM].color_table.offset / sizeof(GLuint), cell_program_layouts[CELL_PROGRAM].color_table.stride / sizeof(GLuint));
|
copy_color_table_to_buffer(screen->color_profile, (GLuint*)rd, cell_program_layouts[CELL_PROGRAM].color_table.offset / sizeof(GLuint), cell_program_layouts[CELL_PROGRAM].color_table.stride / sizeof(GLuint));
|
||||||
}
|
}
|
||||||
// Cursor position
|
// Cursor position
|
||||||
if (cursor->is_visible && cursor->shape == CURSOR_BLOCK) {
|
if (cursor->is_visible && cursor->shape == CURSOR_BLOCK) {
|
||||||
rd->cursor_x = screen->cursor->x, rd->cursor_y = screen->cursor->y;
|
rd->cursor_x = screen->cursor->x, rd->cursor_y = screen->cursor->y;
|
||||||
} else {
|
} else {
|
||||||
rd->cursor_x = screen->columns, rd->cursor_y = screen->lines;
|
rd->cursor_x = screen->columns, rd->cursor_y = screen->lines;
|
||||||
}
|
}
|
||||||
rd->cursor_w = rd->cursor_x + MAX(1, screen_current_char_width(screen)) - 1;
|
rd->cursor_w = rd->cursor_x + MAX(1, screen_current_char_width(screen)) - 1;
|
||||||
|
|
||||||
rd->xnum = screen->columns; rd->ynum = screen->lines;
|
rd->xnum = screen->columns; rd->ynum = screen->lines;
|
||||||
|
|
||||||
rd->xstart = xstart; rd->ystart = ystart; rd->dx = dx; rd->dy = dy;
|
rd->xstart = xstart; rd->ystart = ystart; rd->dx = dx; rd->dy = dy;
|
||||||
unsigned int x, y, z;
|
unsigned int x, y, z;
|
||||||
sprite_tracker_current_layout(&x, &y, &z);
|
sprite_tracker_current_layout(&x, &y, &z);
|
||||||
@ -285,18 +285,18 @@ draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *d
|
|||||||
bind_program(program);
|
bind_program(program);
|
||||||
bind_vertex_array(gvao_idx);
|
bind_vertex_array(gvao_idx);
|
||||||
static bool graphics_constants_set = false;
|
static bool graphics_constants_set = false;
|
||||||
if (!graphics_constants_set) {
|
if (!graphics_constants_set) {
|
||||||
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "image"), GRAPHICS_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "image"), GRAPHICS_UNIT);
|
||||||
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PREMULT_PROGRAM), "image"), GRAPHICS_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PREMULT_PROGRAM), "image"), GRAPHICS_UNIT);
|
||||||
graphics_constants_set = true;
|
graphics_constants_set = true;
|
||||||
}
|
}
|
||||||
glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT);
|
glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT);
|
||||||
|
|
||||||
GLuint base = 4 * start;
|
GLuint base = 4 * start;
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
for (GLuint i=0; i < count;) {
|
for (GLuint i=0; i < count;) {
|
||||||
ImageRenderData *rd = data + start + i;
|
ImageRenderData *rd = data + start + i;
|
||||||
glBindTexture(GL_TEXTURE_2D, rd->texture_id);
|
glBindTexture(GL_TEXTURE_2D, rd->texture_id);
|
||||||
// You could reduce the number of draw calls by using
|
// You could reduce the number of draw calls by using
|
||||||
// glDrawArraysInstancedBaseInstance but Apple chose to abandon OpenGL
|
// glDrawArraysInstancedBaseInstance but Apple chose to abandon OpenGL
|
||||||
// before implementing it.
|
// before implementing it.
|
||||||
@ -311,8 +311,8 @@ draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *d
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
||||||
bind_program(CELL_PROGRAM);
|
bind_program(CELL_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
if (screen->grman->count) {
|
if (screen->grman->count) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
BLEND_ONTO_OPAQUE;
|
BLEND_ONTO_OPAQUE;
|
||||||
@ -323,18 +323,18 @@ draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
||||||
bind_program(CELL_BG_PROGRAM);
|
bind_program(CELL_BG_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
BLEND_ONTO_OPAQUE;
|
BLEND_ONTO_OPAQUE;
|
||||||
|
|
||||||
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
|
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
|
||||||
|
|
||||||
bind_program(CELL_SPECIAL_PROGRAM);
|
bind_program(CELL_SPECIAL_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
bind_program(CELL_FG_PROGRAM);
|
bind_program(CELL_FG_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
||||||
|
|
||||||
@ -350,25 +350,25 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreen_framebuffer);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreen_framebuffer);
|
||||||
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0);
|
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0);
|
||||||
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("offscreen framebuffer not complete"); */
|
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("offscreen framebuffer not complete"); */
|
||||||
|
|
||||||
bind_program(CELL_BG_PROGRAM);
|
bind_program(CELL_BG_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
BLEND_PREMULT;
|
BLEND_PREMULT;
|
||||||
|
|
||||||
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
|
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
|
||||||
|
|
||||||
bind_program(CELL_SPECIAL_PROGRAM);
|
bind_program(CELL_SPECIAL_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
bind_program(CELL_FG_PROGRAM);
|
bind_program(CELL_FG_PROGRAM);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
||||||
|
|
||||||
@ -377,19 +377,19 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||||||
|
|
||||||
// Now render the framebuffer to the screen reversing alpha pre-multiplication
|
// Now render the framebuffer to the screen reversing alpha pre-multiplication
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
||||||
static bool blit_constants_set = false;
|
static bool blit_constants_set = false;
|
||||||
if (!blit_constants_set) {
|
if (!blit_constants_set) {
|
||||||
glUniform1i(glGetUniformLocation(program_id(BLIT_PROGRAM), "image"), BLIT_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(BLIT_PROGRAM), "image"), BLIT_UNIT);
|
||||||
blit_constants_set = true;
|
blit_constants_set = true;
|
||||||
}
|
}
|
||||||
glActiveTexture(GL_TEXTURE0 + BLIT_UNIT);
|
glActiveTexture(GL_TEXTURE0 + BLIT_UNIT);
|
||||||
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window) {
|
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window) {
|
||||||
if (os_window->clear_count < 2) {
|
if (os_window->clear_count < 2) {
|
||||||
os_window->clear_count++;
|
os_window->clear_count++;
|
||||||
@ -403,18 +403,18 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
|||||||
GLfloat w = (GLfloat)screen->columns * dx, h = (GLfloat)screen->lines * dy;
|
GLfloat w = (GLfloat)screen->columns * dx, h = (GLfloat)screen->lines * dy;
|
||||||
#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x))
|
#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x))
|
||||||
glScissor(
|
glScissor(
|
||||||
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
||||||
(GLint)(SCALE(height, ((ystart - h) + 1.0f) / 2.0f)),
|
(GLint)(SCALE(height, ((ystart - h) + 1.0f) / 2.0f)),
|
||||||
(GLsizei)(ceilf(SCALE(width, w / 2.0f))),
|
(GLsizei)(ceilf(SCALE(width, w / 2.0f))),
|
||||||
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
||||||
);
|
);
|
||||||
#undef SCALE
|
#undef SCALE
|
||||||
static bool cell_constants_set = false;
|
static bool cell_constants_set = false;
|
||||||
if (!cell_constants_set) {
|
if (!cell_constants_set) {
|
||||||
bind_program(CELL_PROGRAM);
|
bind_program(CELL_PROGRAM);
|
||||||
glUniform1i(glGetUniformLocation(program_id(CELL_PROGRAM), "sprites"), SPRITE_MAP_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(CELL_PROGRAM), "sprites"), SPRITE_MAP_UNIT);
|
||||||
glUniform1i(glGetUniformLocation(program_id(CELL_FG_PROGRAM), "sprites"), SPRITE_MAP_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(CELL_FG_PROGRAM), "sprites"), SPRITE_MAP_UNIT);
|
||||||
cell_constants_set = true;
|
cell_constants_set = true;
|
||||||
}
|
}
|
||||||
if (os_window->is_semi_transparent) {
|
if (os_window->is_semi_transparent) {
|
||||||
if (screen->grman->count) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
|
if (screen->grman->count) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
|
||||||
@ -446,12 +446,12 @@ init_cursor_program() {
|
|||||||
#undef SET_LOC
|
#undef SET_LOC
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
draw_cursor(CursorRenderInfo *cursor, bool is_focused) {
|
draw_cursor(CursorRenderInfo *cursor, bool is_focused) {
|
||||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
||||||
glUniform3f(cursor_uniform_locations[CURSOR_color], ((cursor->color >> 16) & 0xff) / 255.0, ((cursor->color >> 8) & 0xff) / 255.0, (cursor->color & 0xff) / 255.0);
|
glUniform3f(cursor_uniform_locations[CURSOR_color], ((cursor->color >> 16) & 0xff) / 255.0, ((cursor->color >> 8) & 0xff) / 255.0, (cursor->color & 0xff) / 255.0);
|
||||||
glUniform4f(cursor_uniform_locations[CURSOR_pos], cursor->left, cursor->top, cursor->right, cursor->bottom);
|
glUniform4f(cursor_uniform_locations[CURSOR_pos], cursor->left, cursor->top, cursor->right, cursor->bottom);
|
||||||
glDrawArrays(is_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
glDrawArrays(is_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
||||||
unbind_vertex_array(); unbind_program();
|
unbind_vertex_array(); unbind_program();
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
@ -522,11 +522,11 @@ compile_program(PyObject UNUSED *self, PyObject *args) {
|
|||||||
if (which < 0 || which >= NUM_PROGRAMS) { PyErr_Format(PyExc_ValueError, "Unknown program: %d", which); return NULL; }
|
if (which < 0 || which >= NUM_PROGRAMS) { PyErr_Format(PyExc_ValueError, "Unknown program: %d", which); return NULL; }
|
||||||
if (programs[which].id != 0) { PyErr_SetString(PyExc_ValueError, "program already compiled"); return NULL; }
|
if (programs[which].id != 0) { PyErr_SetString(PyExc_ValueError, "program already compiled"); return NULL; }
|
||||||
programs[which].id = glCreateProgram();
|
programs[which].id = glCreateProgram();
|
||||||
vertex_shader_id = compile_shader(GL_VERTEX_SHADER, vertex_shader);
|
vertex_shader_id = compile_shader(GL_VERTEX_SHADER, vertex_shader);
|
||||||
fragment_shader_id = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);
|
fragment_shader_id = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);
|
||||||
glAttachShader(programs[which].id, vertex_shader_id);
|
glAttachShader(programs[which].id, vertex_shader_id);
|
||||||
glAttachShader(programs[which].id, fragment_shader_id);
|
glAttachShader(programs[which].id, fragment_shader_id);
|
||||||
glLinkProgram(programs[which].id);
|
glLinkProgram(programs[which].id);
|
||||||
GLint ret = GL_FALSE;
|
GLint ret = GL_FALSE;
|
||||||
glGetProgramiv(programs[which].id, GL_LINK_STATUS, &ret);
|
glGetProgramiv(programs[which].id, GL_LINK_STATUS, &ret);
|
||||||
if (ret != GL_TRUE) {
|
if (ret != GL_TRUE) {
|
||||||
@ -550,8 +550,8 @@ end:
|
|||||||
#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 PYWRAP2(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args, PyObject *kw)
|
#define PYWRAP2(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args, PyObject *kw)
|
||||||
#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 ONE_INT(name) PYWRAP1(name) { name(PyLong_AsSsize_t(args)); Py_RETURN_NONE; }
|
#define ONE_INT(name) PYWRAP1(name) { name(PyLong_AsSsize_t(args)); Py_RETURN_NONE; }
|
||||||
#define TWO_INT(name) PYWRAP1(name) { int a, b; PA("ii", &a, &b); name(a, b); Py_RETURN_NONE; }
|
#define TWO_INT(name) PYWRAP1(name) { int a, b; PA("ii", &a, &b); name(a, b); Py_RETURN_NONE; }
|
||||||
#define NO_ARG(name) PYWRAP0(name) { name(); Py_RETURN_NONE; }
|
#define NO_ARG(name) PYWRAP0(name) { name(); Py_RETURN_NONE; }
|
||||||
#define NO_ARG_INT(name) PYWRAP0(name) { return PyLong_FromSsize_t(name()); }
|
#define NO_ARG_INT(name) PYWRAP0(name) { return PyLong_FromSsize_t(name()); }
|
||||||
|
|
||||||
@ -622,7 +622,7 @@ init_shaders(PyObject *module) {
|
|||||||
C(GL_UNPACK_ALIGNMENT);
|
C(GL_UNPACK_ALIGNMENT);
|
||||||
C(GL_R8); C(GL_RED); C(GL_UNSIGNED_BYTE); C(GL_UNSIGNED_SHORT); C(GL_R32UI); C(GL_RGB32UI); C(GL_RGBA);
|
C(GL_R8); C(GL_RED); C(GL_UNSIGNED_BYTE); C(GL_UNSIGNED_SHORT); C(GL_R32UI); C(GL_RGB32UI); C(GL_RGBA);
|
||||||
C(GL_TEXTURE_BUFFER); C(GL_STATIC_DRAW); C(GL_STREAM_DRAW); C(GL_DYNAMIC_DRAW);
|
C(GL_TEXTURE_BUFFER); C(GL_STATIC_DRAW); C(GL_STREAM_DRAW); C(GL_DYNAMIC_DRAW);
|
||||||
C(GL_SRC_ALPHA); C(GL_ONE_MINUS_SRC_ALPHA);
|
C(GL_SRC_ALPHA); C(GL_ONE_MINUS_SRC_ALPHA);
|
||||||
C(GL_WRITE_ONLY); C(GL_READ_ONLY); C(GL_READ_WRITE);
|
C(GL_WRITE_ONLY); C(GL_READ_ONLY); C(GL_READ_WRITE);
|
||||||
C(GL_BLEND); C(GL_FLOAT); C(GL_UNSIGNED_INT); C(GL_ARRAY_BUFFER); C(GL_UNIFORM_BUFFER);
|
C(GL_BLEND); C(GL_FLOAT); C(GL_UNSIGNED_INT); C(GL_ARRAY_BUFFER); C(GL_UNIFORM_BUFFER);
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,12 @@ GlobalState global_state = {{0}};
|
|||||||
(count)--; \
|
(count)--; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#define WITH_OS_WINDOW(os_window_id) \
|
#define WITH_OS_WINDOW(os_window_id) \
|
||||||
for (size_t o = 0; o < global_state.num_os_windows; o++) { \
|
for (size_t o = 0; o < global_state.num_os_windows; o++) { \
|
||||||
OSWindow *os_window = global_state.os_windows + o; \
|
OSWindow *os_window = global_state.os_windows + o; \
|
||||||
if (os_window->id == os_window_id) {
|
if (os_window->id == os_window_id) {
|
||||||
#define END_WITH_OS_WINDOW break; }}
|
#define END_WITH_OS_WINDOW break; }}
|
||||||
|
|
||||||
#define WITH_TAB(os_window_id, tab_id) \
|
#define WITH_TAB(os_window_id, tab_id) \
|
||||||
@ -50,7 +50,7 @@ GlobalState global_state = {{0}};
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
||||||
OSWindow*
|
OSWindow*
|
||||||
current_os_window() {
|
current_os_window() {
|
||||||
if (global_state.callback_os_window) return global_state.callback_os_window;
|
if (global_state.callback_os_window) return global_state.callback_os_window;
|
||||||
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
||||||
@ -187,7 +187,7 @@ remove_os_window(id_type os_window_id) {
|
|||||||
found = true;
|
found = true;
|
||||||
make_os_window_context_current(os_window);
|
make_os_window_context_current(os_window);
|
||||||
END_WITH_OS_WINDOW
|
END_WITH_OS_WINDOW
|
||||||
if (found) {
|
if (found) {
|
||||||
WITH_OS_WINDOW_REFS
|
WITH_OS_WINDOW_REFS
|
||||||
REMOVER(global_state.os_windows, os_window_id, global_state.num_os_windows, OSWindow, destroy_os_window_item, global_state.capacity);
|
REMOVER(global_state.os_windows, os_window_id, global_state.num_os_windows, OSWindow, destroy_os_window_item, global_state.capacity);
|
||||||
END_WITH_OS_WINDOW_REFS
|
END_WITH_OS_WINDOW_REFS
|
||||||
@ -337,7 +337,7 @@ PYWRAP1(set_options) {
|
|||||||
Py_DECREF(ret); if (PyErr_Occurred()) return NULL;
|
Py_DECREF(ret); if (PyErr_Occurred()) return NULL;
|
||||||
|
|
||||||
PyObject *al = PyObject_GetAttrString(opts, "adjust_line_height");
|
PyObject *al = PyObject_GetAttrString(opts, "adjust_line_height");
|
||||||
if (PyFloat_Check(al)) {
|
if (PyFloat_Check(al)) {
|
||||||
OPT(adjust_line_height_frac) = (float)PyFloat_AsDouble(al);
|
OPT(adjust_line_height_frac) = (float)PyFloat_AsDouble(al);
|
||||||
OPT(adjust_line_height_px) = 0;
|
OPT(adjust_line_height_px) = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -498,7 +498,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_state(PyObject *module) {
|
init_state(PyObject *module) {
|
||||||
global_state.cell_width = 1; global_state.cell_height = 1;
|
global_state.cell_width = 1; global_state.cell_height = 1;
|
||||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||||
|
|||||||
@ -3,18 +3,18 @@
|
|||||||
#include <unictype.h>
|
#include <unictype.h>
|
||||||
#include <uninorm.h>
|
#include <uninorm.h>
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
is_combining_char(uint32_t ch) {
|
is_combining_char(uint32_t ch) {
|
||||||
return uc_combining_class(ch) != UC_CCC_NR;
|
return uc_combining_class(ch) != UC_CCC_NR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
|
static inline bool
|
||||||
is_ignored_char(uint32_t ch) {
|
is_ignored_char(uint32_t ch) {
|
||||||
return uc_is_general_category_withtable(ch, UC_CATEGORY_MASK_Cc | UC_CATEGORY_MASK_Cf | UC_CATEGORY_MASK_Cs);
|
return uc_is_general_category_withtable(ch, UC_CATEGORY_MASK_Cc | UC_CATEGORY_MASK_Cf | UC_CATEGORY_MASK_Cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
is_word_char(uint32_t ch) {
|
is_word_char(uint32_t ch) {
|
||||||
return uc_is_general_category_withtable(ch, UC_CATEGORY_MASK_L | UC_CATEGORY_MASK_N);
|
return uc_is_general_category_withtable(ch, UC_CATEGORY_MASK_L | UC_CATEGORY_MASK_N);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user