mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Implement Screen.resize
This commit is contained in:
@@ -295,6 +295,7 @@ void linebuf_clear_line(LineBuf *self, index_type y);
|
|||||||
void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom);
|
void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom);
|
||||||
void linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom);
|
void linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom);
|
||||||
void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int );
|
void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int );
|
||||||
|
bool linebuf_rewrap(LineBuf *self, LineBuf *other, int *cursor_y_out, PyObject *extra_lines);
|
||||||
|
|
||||||
void screen_restore_cursor(Screen *);
|
void screen_restore_cursor(Screen *);
|
||||||
void screen_save_cursor(Screen *);
|
void screen_save_cursor(Screen *);
|
||||||
|
|||||||
@@ -415,10 +415,12 @@ static inline void copy_range(Line *src, index_type src_at, Line* dest, index_ty
|
|||||||
#define next_dest_line(continued) {\
|
#define next_dest_line(continued) {\
|
||||||
if (dest_y >= dest->ynum - 1) { \
|
if (dest_y >= dest->ynum - 1) { \
|
||||||
linebuf_index(dest, 0, dest->ynum - 1); \
|
linebuf_index(dest, 0, dest->ynum - 1); \
|
||||||
PyObject *l = create_line_copy_inner(dest, dest_y); \
|
if (extra_lines != NULL) {\
|
||||||
if (l == NULL) return false; \
|
PyObject *l = create_line_copy_inner(dest, dest_y); \
|
||||||
if (PyList_Append(extra_lines, l) != 0) { Py_CLEAR(l); return false; } \
|
if (l == NULL) return false; \
|
||||||
Py_CLEAR(l); \
|
if (PyList_Append(extra_lines, l) != 0) { Py_CLEAR(l); return false; } \
|
||||||
|
Py_CLEAR(l); \
|
||||||
|
}\
|
||||||
} else dest_y++; \
|
} else dest_y++; \
|
||||||
INIT_LINE(dest, dest->line, dest->line_map[dest_y]); \
|
INIT_LINE(dest, dest->line, dest->line_map[dest_y]); \
|
||||||
dest->continued_map[dest_y] = continued; \
|
dest->continued_map[dest_y] = continued; \
|
||||||
@@ -426,6 +428,7 @@ static inline void copy_range(Line *src, index_type src_at, Line* dest, index_ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool rewrap_inner(LineBuf *src, LineBuf *dest, const index_type src_limit, PyObject *extra_lines) {
|
static bool rewrap_inner(LineBuf *src, LineBuf *dest, const index_type src_limit, PyObject *extra_lines) {
|
||||||
|
// TODO: Change this to put the extra lines into the history buf
|
||||||
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;
|
||||||
INIT_LINE(dest, dest->line, dest->line_map[dest_y]);
|
INIT_LINE(dest, dest->line, dest->line_map[dest_y]);
|
||||||
@@ -452,18 +455,10 @@ static bool rewrap_inner(LineBuf *src, LineBuf *dest, const index_type src_limit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
bool linebuf_rewrap(LineBuf *self, LineBuf *other, int *cursor_y_out, PyObject *extra_lines) {
|
||||||
rewrap(LineBuf *self, PyObject *val) {
|
|
||||||
LineBuf* other;
|
|
||||||
index_type first, i;
|
index_type first, i;
|
||||||
int cursor_y = -1;
|
|
||||||
bool is_empty = true;
|
bool is_empty = true;
|
||||||
|
|
||||||
if (!PyObject_TypeCheck(val, &LineBuf_Type)) { PyErr_SetString(PyExc_TypeError, "Not a LineBuf object"); return NULL; }
|
|
||||||
other = (LineBuf*) val;
|
|
||||||
PyObject *ret = PyList_New(0);
|
|
||||||
if (ret == NULL) return PyErr_NoMemory();
|
|
||||||
|
|
||||||
// Fast path
|
// Fast path
|
||||||
if (other->xnum == self->xnum && other->ynum == self->ynum) {
|
if (other->xnum == self->xnum && other->ynum == self->ynum) {
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
@@ -471,7 +466,7 @@ rewrap(LineBuf *self, PyObject *val) {
|
|||||||
memcpy(other->continued_map, self->continued_map, sizeof(bool) * self->ynum);
|
memcpy(other->continued_map, self->continued_map, sizeof(bool) * self->ynum);
|
||||||
memcpy(other->buf, self->buf, self->xnum * self->ynum * CELL_SIZE);
|
memcpy(other->buf, self->buf, self->xnum * self->ynum * CELL_SIZE);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
goto end;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the first line that contains some content
|
// Find the first line that contains some content
|
||||||
@@ -485,16 +480,27 @@ rewrap(LineBuf *self, PyObject *val) {
|
|||||||
}
|
}
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
if (first == 0) { cursor_y = 0; goto end; } // All lines are empty
|
if (first == 0) { *cursor_y_out = 0; return true; } // All lines are empty
|
||||||
|
|
||||||
if (!rewrap_inner(self, other, first + 1, ret)) {
|
if (!rewrap_inner(self, other, first + 1, extra_lines)) {
|
||||||
Py_CLEAR(ret);
|
PyErr_NoMemory();
|
||||||
return PyErr_NoMemory();
|
return false;
|
||||||
}
|
}
|
||||||
|
*cursor_y_out = other->line->ynum;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
cursor_y = other->line->ynum;
|
static PyObject*
|
||||||
|
rewrap(LineBuf *self, PyObject *val) {
|
||||||
|
LineBuf* other;
|
||||||
|
int cursor_y = -1;
|
||||||
|
|
||||||
|
if (!PyObject_TypeCheck(val, &LineBuf_Type)) { PyErr_SetString(PyExc_TypeError, "Not a LineBuf object"); return NULL; }
|
||||||
|
other = (LineBuf*) val;
|
||||||
|
PyObject *ret = PyList_New(0);
|
||||||
|
if (ret == NULL) return PyErr_NoMemory();
|
||||||
|
if(!linebuf_rewrap(self, other, &cursor_y, ret)) return NULL;
|
||||||
|
|
||||||
end:
|
|
||||||
return Py_BuildValue("Ni", ret, cursor_y);
|
return Py_BuildValue("Ni", ret, cursor_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,41 @@ void screen_reset(Screen *self) {
|
|||||||
tracker_update_screen(self->change_tracker);
|
tracker_update_screen(self->change_tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline LineBuf* realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, int *cursor_y) {
|
||||||
|
LineBuf *ans = alloc_linebuf(lines, columns);
|
||||||
|
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
||||||
|
if(!linebuf_rewrap(old, ans, cursor_y, NULL)) return NULL;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
||||||
|
lines = MAX(1, lines); columns = MAX(1, columns);
|
||||||
|
|
||||||
|
bool is_main = self->linebuf == self->main_linebuf;
|
||||||
|
int cursor_y = -1;
|
||||||
|
LineBuf *n = realloc_lb(self->main_linebuf, lines, columns, &cursor_y);
|
||||||
|
if (n == NULL) return false;
|
||||||
|
Py_CLEAR(self->main_linebuf); self->main_linebuf = n;
|
||||||
|
if (is_main) self->cursor->y = MAX(0, cursor_y);
|
||||||
|
cursor_y = -1;
|
||||||
|
n = realloc_lb(self->alt_linebuf, lines, columns, &cursor_y);
|
||||||
|
if (n == NULL) return false;
|
||||||
|
Py_CLEAR(self->alt_linebuf); self->alt_linebuf = n;
|
||||||
|
if (!is_main) self->cursor->y = MAX(0, cursor_y);
|
||||||
|
self->linebuf = is_main ? self->main_linebuf : self->alt_linebuf;
|
||||||
|
|
||||||
|
if (!tracker_resize(self->change_tracker, lines, columns)) return false;
|
||||||
|
|
||||||
|
PyMem_Free(self->tabstops);
|
||||||
|
self->tabstops = PyMem_Calloc(self->columns, sizeof(bool));
|
||||||
|
if (self->tabstops == NULL) { PyErr_NoMemory(); return false; }
|
||||||
|
|
||||||
|
self->lines = lines; self->columns = columns;
|
||||||
|
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||||
|
screen_reset_mode(self, DECOM);
|
||||||
|
// TODO: resize history buf
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dealloc(Screen* self) {
|
dealloc(Screen* self) {
|
||||||
@@ -555,6 +590,8 @@ void screen_restore_cursor(Screen *self) {
|
|||||||
self->utf8_state = sp->utf8_state;
|
self->utf8_state = sp->utf8_state;
|
||||||
if (sp->mDECOM) screen_set_mode(self, DECOM);
|
if (sp->mDECOM) screen_set_mode(self, DECOM);
|
||||||
if (sp->mDECAWM) screen_set_mode(self, DECAWM);
|
if (sp->mDECAWM) screen_set_mode(self, DECAWM);
|
||||||
|
self->cursor = cursor_copy(sp->cursor);
|
||||||
|
screen_ensure_bounds(self, false);
|
||||||
PyList_SetSlice(self->savepoints, sz-1, sz, NULL);
|
PyList_SetSlice(self->savepoints, sz-1, sz, NULL);
|
||||||
} else {
|
} else {
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
@@ -935,6 +972,14 @@ reverse_index(Screen *self) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
resize(Screen *self, PyObject *args) {
|
||||||
|
unsigned int lines = 1, columns = 1;
|
||||||
|
if (!PyArg_ParseTuple(args, "II", &lines, &columns)) return NULL;
|
||||||
|
if (!screen_resize(self, lines, columns)) return NULL;
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
#define COUNT_WRAP(name) \
|
#define COUNT_WRAP(name) \
|
||||||
static PyObject* name(Screen *self, PyObject *args) { \
|
static PyObject* name(Screen *self, PyObject *args) { \
|
||||||
unsigned int count = 1; \
|
unsigned int count = 1; \
|
||||||
@@ -978,6 +1023,7 @@ static PyMethodDef methods[] = {
|
|||||||
MND(cursor_forward, METH_VARARGS)
|
MND(cursor_forward, METH_VARARGS)
|
||||||
MND(index, METH_NOARGS)
|
MND(index, METH_NOARGS)
|
||||||
MND(reverse_index, METH_NOARGS)
|
MND(reverse_index, METH_NOARGS)
|
||||||
|
MND(resize, METH_VARARGS)
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,3 +51,4 @@ static inline void tracker_reset(ChangeTracker *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
||||||
|
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
|
||||||
|
|||||||
Reference in New Issue
Block a user