Implement Screen.resize
This commit is contained in:
parent
a120b25286
commit
6c39b07552
@ -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_delete_lines(LineBuf *self, index_type num, index_type y, index_type bottom);
|
||||
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_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) {\
|
||||
if (dest_y >= dest->ynum - 1) { \
|
||||
linebuf_index(dest, 0, dest->ynum - 1); \
|
||||
PyObject *l = create_line_copy_inner(dest, dest_y); \
|
||||
if (l == NULL) return false; \
|
||||
if (PyList_Append(extra_lines, l) != 0) { Py_CLEAR(l); return false; } \
|
||||
Py_CLEAR(l); \
|
||||
if (extra_lines != NULL) {\
|
||||
PyObject *l = create_line_copy_inner(dest, dest_y); \
|
||||
if (l == NULL) return false; \
|
||||
if (PyList_Append(extra_lines, l) != 0) { Py_CLEAR(l); return false; } \
|
||||
Py_CLEAR(l); \
|
||||
}\
|
||||
} else dest_y++; \
|
||||
INIT_LINE(dest, dest->line, dest->line_map[dest_y]); \
|
||||
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) {
|
||||
// TODO: Change this to put the extra lines into the history buf
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
rewrap(LineBuf *self, PyObject *val) {
|
||||
LineBuf* other;
|
||||
bool linebuf_rewrap(LineBuf *self, LineBuf *other, int *cursor_y_out, PyObject *extra_lines) {
|
||||
index_type first, i;
|
||||
int cursor_y = -1;
|
||||
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
|
||||
if (other->xnum == self->xnum && other->ynum == self->ynum) {
|
||||
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->buf, self->buf, self->xnum * self->ynum * CELL_SIZE);
|
||||
Py_END_ALLOW_THREADS;
|
||||
goto end;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find the first line that contains some content
|
||||
@ -485,16 +480,27 @@ rewrap(LineBuf *self, PyObject *val) {
|
||||
}
|
||||
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)) {
|
||||
Py_CLEAR(ret);
|
||||
return PyErr_NoMemory();
|
||||
if (!rewrap_inner(self, other, first + 1, extra_lines)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +66,41 @@ void screen_reset(Screen *self) {
|
||||
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
|
||||
dealloc(Screen* self) {
|
||||
@ -555,6 +590,8 @@ void screen_restore_cursor(Screen *self) {
|
||||
self->utf8_state = sp->utf8_state;
|
||||
if (sp->mDECOM) screen_set_mode(self, DECOM);
|
||||
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);
|
||||
} else {
|
||||
screen_cursor_position(self, 1, 1);
|
||||
@ -935,6 +972,14 @@ reverse_index(Screen *self) {
|
||||
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) \
|
||||
static PyObject* name(Screen *self, PyObject *args) { \
|
||||
unsigned int count = 1; \
|
||||
@ -978,6 +1023,7 @@ static PyMethodDef methods[] = {
|
||||
MND(cursor_forward, METH_VARARGS)
|
||||
MND(index, METH_NOARGS)
|
||||
MND(reverse_index, METH_NOARGS)
|
||||
MND(resize, METH_VARARGS)
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@ -51,3 +51,4 @@ static inline void tracker_reset(ChangeTracker *self) {
|
||||
}
|
||||
|
||||
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
||||
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user