Remove the now useless change tracking code
This commit is contained in:
parent
906937149e
commit
f5dbe36cf3
@ -357,7 +357,7 @@ class CharGrid:
|
|||||||
def prepare_for_render(self, cell_program):
|
def prepare_for_render(self, cell_program):
|
||||||
if self.vao_id is None:
|
if self.vao_id is None:
|
||||||
self.vao_id = cell_program.create_sprite_map()
|
self.vao_id = cell_program.create_sprite_map()
|
||||||
if self.scroll_changed or self.screen.is_dirty():
|
if self.scroll_changed or self.screen.is_dirty:
|
||||||
self.update_cell_data(cell_program)
|
self.update_cell_data(cell_program)
|
||||||
self.scroll_changed = False
|
self.scroll_changed = False
|
||||||
sg = self.render_data
|
sg = self.render_data
|
||||||
|
|||||||
@ -114,7 +114,6 @@ PyInit_fast_data_types(void) {
|
|||||||
if (!init_Timers(m)) return NULL;
|
if (!init_Timers(m)) return NULL;
|
||||||
if (!init_ChildMonitor(m)) return NULL;
|
if (!init_ChildMonitor(m)) return NULL;
|
||||||
if (!init_ColorProfile(m)) return NULL;
|
if (!init_ColorProfile(m)) return NULL;
|
||||||
if (!init_ChangeTracker(m)) return NULL;
|
|
||||||
if (!init_Screen(m)) return NULL;
|
if (!init_Screen(m)) return NULL;
|
||||||
if (!add_module_gl_constants(m)) return NULL;
|
if (!add_module_gl_constants(m)) return NULL;
|
||||||
if (!init_glfw(m)) return NULL;
|
if (!init_glfw(m)) return NULL;
|
||||||
|
|||||||
@ -195,21 +195,6 @@ typedef struct {
|
|||||||
} ColorProfile;
|
} ColorProfile;
|
||||||
PyTypeObject ColorProfile_Type;
|
PyTypeObject ColorProfile_Type;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
|
|
||||||
index_type xnum, ynum;
|
|
||||||
bool screen_changed;
|
|
||||||
bool cursor_changed;
|
|
||||||
bool dirty;
|
|
||||||
bool *changed_lines;
|
|
||||||
bool *lines_with_changed_cells;
|
|
||||||
bool *changed_cells;
|
|
||||||
unsigned int history_line_added_count;
|
|
||||||
} ChangeTracker;
|
|
||||||
PyTypeObject ChangeTracker_Type;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
||||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
||||||
@ -245,11 +230,11 @@ typedef struct {
|
|||||||
bool use_latin1;
|
bool use_latin1;
|
||||||
Cursor *cursor;
|
Cursor *cursor;
|
||||||
SavepointBuffer main_savepoints, alt_savepoints;
|
SavepointBuffer main_savepoints, alt_savepoints;
|
||||||
PyObject *callbacks;
|
PyObject *callbacks, *is_dirty, *cursor_changed;
|
||||||
LineBuf *linebuf, *main_linebuf, *alt_linebuf;
|
LineBuf *linebuf, *main_linebuf, *alt_linebuf;
|
||||||
HistoryBuf *historybuf;
|
HistoryBuf *historybuf;
|
||||||
|
unsigned int history_line_added_count;
|
||||||
bool *tabstops, *main_tabstops, *alt_tabstops;
|
bool *tabstops, *main_tabstops, *alt_tabstops;
|
||||||
ChangeTracker *change_tracker;
|
|
||||||
ScreenModes modes;
|
ScreenModes modes;
|
||||||
ColorProfile *color_profile;
|
ColorProfile *color_profile;
|
||||||
|
|
||||||
@ -307,7 +292,6 @@ Line* alloc_line();
|
|||||||
Cursor* alloc_cursor();
|
Cursor* alloc_cursor();
|
||||||
LineBuf* alloc_linebuf(unsigned int, unsigned int);
|
LineBuf* alloc_linebuf(unsigned int, unsigned int);
|
||||||
HistoryBuf* alloc_historybuf(unsigned int, unsigned int);
|
HistoryBuf* alloc_historybuf(unsigned int, unsigned int);
|
||||||
ChangeTracker* alloc_change_tracker(unsigned int, unsigned int);
|
|
||||||
ColorProfile* alloc_color_profile();
|
ColorProfile* alloc_color_profile();
|
||||||
int init_LineBuf(PyObject *);
|
int init_LineBuf(PyObject *);
|
||||||
int init_HistoryBuf(PyObject *);
|
int init_HistoryBuf(PyObject *);
|
||||||
@ -316,7 +300,6 @@ int init_Timers(PyObject *);
|
|||||||
int init_ChildMonitor(PyObject *);
|
int init_ChildMonitor(PyObject *);
|
||||||
int init_Line(PyObject *);
|
int init_Line(PyObject *);
|
||||||
int init_ColorProfile(PyObject *);
|
int init_ColorProfile(PyObject *);
|
||||||
int init_ChangeTracker(PyObject *);
|
|
||||||
int init_Screen(PyObject *);
|
int init_Screen(PyObject *);
|
||||||
int init_Face(PyObject *);
|
int init_Face(PyObject *);
|
||||||
int init_Window(PyObject *);
|
int init_Window(PyObject *);
|
||||||
|
|||||||
104
kitty/screen.c
104
kitty/screen.c
@ -9,7 +9,6 @@
|
|||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "unicode-data.h"
|
#include "unicode-data.h"
|
||||||
#include "tracker.h"
|
|
||||||
#include "modes.h"
|
#include "modes.h"
|
||||||
#include "wcwidth9.h"
|
#include "wcwidth9.h"
|
||||||
|
|
||||||
@ -59,17 +58,18 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->columns = columns; self->lines = lines;
|
self->columns = columns; self->lines = lines;
|
||||||
self->write_buf = NULL;
|
self->write_buf = NULL;
|
||||||
self->modes = empty_modes;
|
self->modes = empty_modes;
|
||||||
|
self->cursor_changed = Py_True; self->is_dirty = Py_True;
|
||||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||||
|
self->history_line_added_count = 0;
|
||||||
RESET_CHARSETS;
|
RESET_CHARSETS;
|
||||||
self->callbacks = callbacks; Py_INCREF(callbacks);
|
self->callbacks = callbacks; Py_INCREF(callbacks);
|
||||||
self->cursor = alloc_cursor();
|
self->cursor = alloc_cursor();
|
||||||
self->color_profile = alloc_color_profile();
|
self->color_profile = alloc_color_profile();
|
||||||
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->change_tracker = alloc_change_tracker(lines, columns);
|
|
||||||
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns);
|
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns);
|
||||||
self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool));
|
self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool));
|
||||||
if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->change_tracker == NULL || self->main_tabstops == NULL || self->historybuf == NULL || self->color_profile == NULL) {
|
if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->main_tabstops == NULL || self->historybuf == NULL || self->color_profile == NULL) {
|
||||||
Py_CLEAR(self); return NULL;
|
Py_CLEAR(self); return NULL;
|
||||||
}
|
}
|
||||||
self->alt_tabstops = self->main_tabstops + self->columns * sizeof(bool);
|
self->alt_tabstops = self->main_tabstops + self->columns * sizeof(bool);
|
||||||
@ -94,12 +94,12 @@ screen_reset(Screen *self) {
|
|||||||
init_tabstops(self->main_tabstops, self->columns);
|
init_tabstops(self->main_tabstops, self->columns);
|
||||||
init_tabstops(self->alt_tabstops, self->columns);
|
init_tabstops(self->alt_tabstops, self->columns);
|
||||||
cursor_reset(self->cursor);
|
cursor_reset(self->cursor);
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
|
self->is_dirty = Py_True;
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
set_dynamic_color(self, 110, NULL);
|
set_dynamic_color(self, 110, NULL);
|
||||||
set_dynamic_color(self, 111, NULL);
|
set_dynamic_color(self, 111, NULL);
|
||||||
set_color_table_color(self, 104, NULL);
|
set_color_table_color(self, 104, NULL);
|
||||||
tracker_update_screen(self->change_tracker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline HistoryBuf*
|
static inline HistoryBuf*
|
||||||
@ -150,7 +150,6 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
|||||||
self->linebuf = is_main ? self->main_linebuf : self->alt_linebuf;
|
self->linebuf = is_main ? self->main_linebuf : self->alt_linebuf;
|
||||||
if (is_x_shrink && cursor_x >= columns) self->cursor->x = columns - 1;
|
if (is_x_shrink && cursor_x >= columns) self->cursor->x = columns - 1;
|
||||||
|
|
||||||
if (!tracker_resize(self->change_tracker, lines, columns)) return false;
|
|
||||||
self->lines = lines; self->columns = columns;
|
self->lines = lines; self->columns = columns;
|
||||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||||
|
|
||||||
@ -161,8 +160,7 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
|||||||
self->tabstops = self->main_tabstops;
|
self->tabstops = self->main_tabstops;
|
||||||
init_tabstops(self->main_tabstops, self->columns);
|
init_tabstops(self->main_tabstops, self->columns);
|
||||||
init_tabstops(self->alt_tabstops, self->columns);
|
init_tabstops(self->alt_tabstops, self->columns);
|
||||||
tracker_update_screen(self->change_tracker);
|
self->cursor_changed = Py_True; self->is_dirty = Py_True;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
|
||||||
if (index_after_resize) screen_index(self);
|
if (index_after_resize) screen_index(self);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -200,7 +198,6 @@ dealloc(Screen* self) {
|
|||||||
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->change_tracker);
|
|
||||||
Py_CLEAR(self->historybuf);
|
Py_CLEAR(self->historybuf);
|
||||||
Py_CLEAR(self->color_profile);
|
Py_CLEAR(self->color_profile);
|
||||||
PyMem_Free(self->main_tabstops);
|
PyMem_Free(self->main_tabstops);
|
||||||
@ -268,7 +265,6 @@ screen_draw(Screen *self, uint32_t och) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (char_width > 0) {
|
if (char_width > 0) {
|
||||||
unsigned int cx = self->cursor->x;
|
|
||||||
linebuf_init_line(self->linebuf, self->cursor->y);
|
linebuf_init_line(self->linebuf, self->cursor->y);
|
||||||
if (self->modes.mIRM) {
|
if (self->modes.mIRM) {
|
||||||
line_right_shift(self->linebuf->line, self->cursor->x, char_width);
|
line_right_shift(self->linebuf->line, self->cursor->x, char_width);
|
||||||
@ -279,20 +275,19 @@ screen_draw(Screen *self, uint32_t och) {
|
|||||||
line_set_char(self->linebuf->line, self->cursor->x, 0, 0, self->cursor);
|
line_set_char(self->linebuf->line, self->cursor->x, 0, 0, self->cursor);
|
||||||
self->cursor->x++;
|
self->cursor->x++;
|
||||||
}
|
}
|
||||||
unsigned int right = self->modes.mIRM ? self->columns - 1 : MIN((MAX(self->cursor->x, 1) - 1), self->columns - 1);
|
self->is_dirty = Py_True;
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, cx, right);
|
|
||||||
} else if (is_combining_char(ch)) {
|
} else if (is_combining_char(ch)) {
|
||||||
if (self->cursor->x > 0) {
|
if (self->cursor->x > 0) {
|
||||||
linebuf_init_line(self->linebuf, self->cursor->y);
|
linebuf_init_line(self->linebuf, self->cursor->y);
|
||||||
line_add_combining_char(self->linebuf->line, ch, self->cursor->x - 1);
|
line_add_combining_char(self->linebuf->line, ch, self->cursor->x - 1);
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, self->cursor->x - 1, self->cursor->x - 1);
|
self->is_dirty = Py_True;
|
||||||
} else if (self->cursor->y > 0) {
|
} else if (self->cursor->y > 0) {
|
||||||
linebuf_init_line(self->linebuf, self->cursor->y - 1);
|
linebuf_init_line(self->linebuf, self->cursor->y - 1);
|
||||||
line_add_combining_char(self->linebuf->line, ch, self->columns - 1);
|
line_add_combining_char(self->linebuf->line, ch, self->columns - 1);
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y - 1, self->columns - 1, self->columns - 1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (x != self->cursor->x || y != self->cursor->y) tracker_cursor_changed(self->change_tracker);
|
if (x != self->cursor->x || y != self->cursor->y) self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -414,7 +409,7 @@ screen_toggle_screen_buffer(Screen *self) {
|
|||||||
screen_restore_cursor(self);
|
screen_restore_cursor(self);
|
||||||
}
|
}
|
||||||
CALLBACK("buf_toggled", "O", self->linebuf == self->main_linebuf ? Py_True : Py_False);
|
CALLBACK("buf_toggled", "O", self->linebuf == self->main_linebuf ? Py_True : Py_False);
|
||||||
tracker_update_screen(self->change_tracker);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -453,13 +448,13 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
break;
|
break;
|
||||||
case DECTCEM:
|
case DECTCEM:
|
||||||
self->modes.mDECTCEM = val;
|
self->modes.mDECTCEM = val;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
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;
|
||||||
tracker_update_screen(self->change_tracker);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DECOM:
|
case DECOM:
|
||||||
@ -479,7 +474,7 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
break;
|
break;
|
||||||
case CONTROL_CURSOR_BLINK:
|
case CONTROL_CURSOR_BLINK:
|
||||||
self->cursor->blink = val;
|
self->cursor->blink = val;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
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);
|
||||||
@ -521,7 +516,7 @@ screen_tab(Screen *self) {
|
|||||||
if (!found) found = self->columns - 1;
|
if (!found) found = self->columns - 1;
|
||||||
if (found != self->cursor->x) {
|
if (found != self->cursor->x) {
|
||||||
self->cursor->x = found;
|
self->cursor->x = found;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +533,7 @@ screen_backtab(Screen *self, unsigned int count) {
|
|||||||
}
|
}
|
||||||
if (i <= 0) self->cursor->x = 0;
|
if (i <= 0) self->cursor->x = 0;
|
||||||
}
|
}
|
||||||
if (before != self->cursor->x) tracker_cursor_changed(self->change_tracker);
|
if (before != self->cursor->x) self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -571,7 +566,7 @@ screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=
|
|||||||
if (move_direction < 0 && count > self->cursor->x) self->cursor->x = 0;
|
if (move_direction < 0 && count > self->cursor->x) self->cursor->x = 0;
|
||||||
else self->cursor->x += move_direction * count;
|
else self->cursor->x += move_direction * count;
|
||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
if (x != self->cursor->x) tracker_cursor_changed(self->change_tracker);
|
if (x != self->cursor->x) self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -587,7 +582,7 @@ screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return
|
|||||||
else self->cursor->y += move_direction * count;
|
else self->cursor->y += move_direction * count;
|
||||||
screen_ensure_bounds(self, true);
|
screen_ensure_bounds(self, true);
|
||||||
if (do_carriage_return) self->cursor->x = 0;
|
if (do_carriage_return) self->cursor->x = 0;
|
||||||
if (x != self->cursor->x || y != self->cursor->y) tracker_cursor_changed(self->change_tracker);
|
if (x != self->cursor->x || y != self->cursor->y) self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -611,7 +606,7 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
|||||||
if (x != self->cursor->x) {
|
if (x != self->cursor->x) {
|
||||||
self->cursor->x = x;
|
self->cursor->x = x;
|
||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,11 +616,10 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
|||||||
/* Only add to history when no page margins have been set */ \
|
/* Only add to history when no page margins have been set */ \
|
||||||
linebuf_init_line(self->linebuf, bottom); \
|
linebuf_init_line(self->linebuf, bottom); \
|
||||||
historybuf_add_line(self->historybuf, self->linebuf->line); \
|
historybuf_add_line(self->historybuf, self->linebuf->line); \
|
||||||
tracker_line_added_to_history(self->change_tracker); \
|
self->history_line_added_count++; \
|
||||||
} \
|
} \
|
||||||
linebuf_clear_line(self->linebuf, bottom); \
|
linebuf_clear_line(self->linebuf, bottom); \
|
||||||
if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); \
|
self->is_dirty = Py_True;
|
||||||
else tracker_update_line_range(self->change_tracker, top, bottom);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_index(Screen *self) {
|
screen_index(Screen *self) {
|
||||||
@ -650,8 +644,7 @@ screen_scroll(Screen *self, unsigned int count) {
|
|||||||
#define INDEX_DOWN \
|
#define INDEX_DOWN \
|
||||||
linebuf_reverse_index(self->linebuf, top, bottom); \
|
linebuf_reverse_index(self->linebuf, top, bottom); \
|
||||||
linebuf_clear_line(self->linebuf, top); \
|
linebuf_clear_line(self->linebuf, top); \
|
||||||
if (bottom - top > self->lines - 1) tracker_update_screen(self->change_tracker); \
|
self->is_dirty = Py_True;
|
||||||
else tracker_update_line_range(self->change_tracker, top, bottom);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_reverse_index(Screen *self) {
|
screen_reverse_index(Screen *self) {
|
||||||
@ -678,7 +671,7 @@ 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;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,7 +722,7 @@ screen_restore_cursor(Screen *self) {
|
|||||||
Savepoint *sp = savepoints_pop(pts);
|
Savepoint *sp = savepoints_pop(pts);
|
||||||
if (sp == NULL) {
|
if (sp == NULL) {
|
||||||
screen_cursor_position(self, 1, 1);
|
screen_cursor_position(self, 1, 1);
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
screen_reset_mode(self, DECOM);
|
screen_reset_mode(self, DECOM);
|
||||||
RESET_CHARSETS;
|
RESET_CHARSETS;
|
||||||
screen_reset_mode(self, DECSCNM);
|
screen_reset_mode(self, DECSCNM);
|
||||||
@ -766,7 +759,7 @@ screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
|||||||
unsigned int x = self->cursor->x, y = self->cursor->y;
|
unsigned int x = self->cursor->x, y = self->cursor->y;
|
||||||
self->cursor->x = column; self->cursor->y = line;
|
self->cursor->x = column; self->cursor->y = line;
|
||||||
screen_ensure_bounds(self, false);
|
screen_ensure_bounds(self, false);
|
||||||
if (x != self->cursor->x || y != self->cursor->y) tracker_cursor_changed(self->change_tracker);
|
if (x != self->cursor->x || y != self->cursor->y) self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -813,7 +806,7 @@ void screen_erase_in_line(Screen *self, unsigned int how, bool private) {
|
|||||||
} else {
|
} else {
|
||||||
line_apply_cursor(self->linebuf->line, self->cursor, s, n, true);
|
line_apply_cursor(self->linebuf->line, self->cursor, s, n, true);
|
||||||
}
|
}
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, s, MIN(s+n, self->columns) - 1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,7 +843,7 @@ void screen_erase_in_display(Screen *self, unsigned int how, bool private) {
|
|||||||
line_apply_cursor(self->linebuf->line, self->cursor, 0, self->columns, true);
|
line_apply_cursor(self->linebuf->line, self->cursor, 0, self->columns, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracker_update_line_range(self->change_tracker, a, b-1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
if (how != 2) {
|
if (how != 2) {
|
||||||
screen_erase_in_line(self, how, private);
|
screen_erase_in_line(self, how, private);
|
||||||
@ -862,7 +855,7 @@ void screen_insert_lines(Screen *self, unsigned int count) {
|
|||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
||||||
linebuf_insert_lines(self->linebuf, count, self->cursor->y, bottom);
|
linebuf_insert_lines(self->linebuf, count, self->cursor->y, bottom);
|
||||||
tracker_update_line_range(self->change_tracker, self->cursor->y, bottom);
|
self->is_dirty = Py_True;
|
||||||
screen_carriage_return(self);
|
screen_carriage_return(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -872,7 +865,7 @@ void screen_delete_lines(Screen *self, unsigned int count) {
|
|||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
||||||
linebuf_delete_lines(self->linebuf, count, self->cursor->y, bottom);
|
linebuf_delete_lines(self->linebuf, count, self->cursor->y, bottom);
|
||||||
tracker_update_line_range(self->change_tracker, self->cursor->y, bottom);
|
self->is_dirty = Py_True;
|
||||||
screen_carriage_return(self);
|
screen_carriage_return(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -886,7 +879,7 @@ void screen_insert_characters(Screen *self, unsigned int count) {
|
|||||||
linebuf_init_line(self->linebuf, self->cursor->y);
|
linebuf_init_line(self->linebuf, self->cursor->y);
|
||||||
line_right_shift(self->linebuf->line, x, num);
|
line_right_shift(self->linebuf->line, x, num);
|
||||||
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, x, self->columns - 1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,7 +893,7 @@ void screen_delete_characters(Screen *self, unsigned int count) {
|
|||||||
linebuf_init_line(self->linebuf, self->cursor->y);
|
linebuf_init_line(self->linebuf, self->cursor->y);
|
||||||
left_shift_line(self->linebuf->line, x, num);
|
left_shift_line(self->linebuf->line, x, num);
|
||||||
line_apply_cursor(self->linebuf->line, self->cursor, self->columns - num, num, true);
|
line_apply_cursor(self->linebuf->line, self->cursor, self->columns - num, num, true);
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, x, self->columns - 1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +904,7 @@ void screen_erase_characters(Screen *self, unsigned int count) {
|
|||||||
unsigned int num = MIN(self->columns - x, count);
|
unsigned int num = MIN(self->columns - x, count);
|
||||||
linebuf_init_line(self->linebuf, self->cursor->y);
|
linebuf_init_line(self->linebuf, self->cursor->y);
|
||||||
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
||||||
tracker_update_cell_range(self->change_tracker, self->cursor->y, x, MIN(x + num, self->columns) - 1);
|
self->is_dirty = Py_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -1034,7 +1027,7 @@ screen_set_cursor(Screen *self, unsigned int mode, uint8_t secondary) {
|
|||||||
}
|
}
|
||||||
if (shape != self->cursor->shape || blink != self->cursor->blink) {
|
if (shape != self->cursor->shape || blink != self->cursor->blink) {
|
||||||
self->cursor->shape = shape; self->cursor->blink = blink;
|
self->cursor->shape = shape; self->cursor->blink = blink;
|
||||||
tracker_cursor_changed(self->change_tracker);
|
self->cursor_changed = Py_True;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1124,15 +1117,12 @@ set_mode(Screen *self, PyObject *args) {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
reset_dirty(Screen *self) {
|
reset_dirty(Screen *self) {
|
||||||
tracker_reset(self->change_tracker);
|
self->is_dirty = Py_False;
|
||||||
|
self->cursor_changed = Py_False;
|
||||||
|
self->history_line_added_count = 0;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
consolidate_changes(Screen *self) {
|
|
||||||
return tracker_consolidate_changes(self->change_tracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRAP1E(cursor_back, 1, -1)
|
WRAP1E(cursor_back, 1, -1)
|
||||||
WRAP1B(erase_in_line, 0)
|
WRAP1B(erase_in_line, 0)
|
||||||
WRAP1B(erase_in_display, 0)
|
WRAP1B(erase_in_display, 0)
|
||||||
@ -1194,12 +1184,12 @@ screen_update_cell_data(Screen *self, PyObject *args) {
|
|||||||
unsigned int *data;
|
unsigned int *data;
|
||||||
int force_screen_refresh;
|
int force_screen_refresh;
|
||||||
unsigned int scrolled_by;
|
unsigned int scrolled_by;
|
||||||
unsigned int history_line_added_count = self->change_tracker->history_line_added_count;
|
unsigned int history_line_added_count = self->history_line_added_count;
|
||||||
if (!PyArg_ParseTuple(args, "O!Ip", &PyLong_Type, &dp, &scrolled_by, &force_screen_refresh)) return NULL;
|
if (!PyArg_ParseTuple(args, "O!Ip", &PyLong_Type, &dp, &scrolled_by, &force_screen_refresh)) return NULL;
|
||||||
data = PyLong_AsVoidPtr(dp);
|
data = PyLong_AsVoidPtr(dp);
|
||||||
PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False;
|
PyObject *cursor_changed = self->cursor_changed;
|
||||||
if (scrolled_by) scrolled_by = MIN(scrolled_by + history_line_added_count, self->historybuf->count);
|
if (scrolled_by) scrolled_by = MIN(scrolled_by + history_line_added_count, self->historybuf->count);
|
||||||
tracker_reset(self->change_tracker);
|
reset_dirty(self);
|
||||||
for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) {
|
for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) {
|
||||||
historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line);
|
historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line);
|
||||||
self->historybuf->line->ynum = y;
|
self->historybuf->line->ynum = y;
|
||||||
@ -1227,14 +1217,9 @@ apply_selection(Screen *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* is_dirty(Screen *self) {
|
static
|
||||||
PyObject *ans = self->change_tracker->dirty ? Py_True : Py_False;
|
PyObject* mark_as_dirty(Screen *self) {
|
||||||
Py_INCREF(ans);
|
self->is_dirty = Py_True;
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject* mark_as_dirty(Screen *self) {
|
|
||||||
tracker_update_screen(self->change_tracker);
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1286,7 +1271,6 @@ static PyMethodDef methods[] = {
|
|||||||
MND(reset, METH_NOARGS)
|
MND(reset, METH_NOARGS)
|
||||||
MND(reset_dirty, METH_NOARGS)
|
MND(reset_dirty, METH_NOARGS)
|
||||||
MND(is_main_linebuf, METH_NOARGS)
|
MND(is_main_linebuf, METH_NOARGS)
|
||||||
MND(consolidate_changes, METH_NOARGS)
|
|
||||||
MND(cursor_back, METH_VARARGS)
|
MND(cursor_back, METH_VARARGS)
|
||||||
MND(erase_in_line, METH_VARARGS)
|
MND(erase_in_line, METH_VARARGS)
|
||||||
MND(erase_in_display, METH_VARARGS)
|
MND(erase_in_display, METH_VARARGS)
|
||||||
@ -1313,7 +1297,6 @@ static PyMethodDef methods[] = {
|
|||||||
MND(clear_tab_stop, METH_VARARGS)
|
MND(clear_tab_stop, METH_VARARGS)
|
||||||
MND(reverse_index, METH_NOARGS)
|
MND(reverse_index, METH_NOARGS)
|
||||||
MND(refresh_sprite_positions, METH_NOARGS)
|
MND(refresh_sprite_positions, METH_NOARGS)
|
||||||
MND(is_dirty, METH_NOARGS)
|
|
||||||
MND(mark_as_dirty, METH_NOARGS)
|
MND(mark_as_dirty, METH_NOARGS)
|
||||||
MND(resize, METH_VARARGS)
|
MND(resize, METH_VARARGS)
|
||||||
MND(set_margins, METH_VARARGS)
|
MND(set_margins, METH_VARARGS)
|
||||||
@ -1346,6 +1329,8 @@ static PyGetSetDef getsetters[] = {
|
|||||||
|
|
||||||
static PyMemberDef members[] = {
|
static PyMemberDef members[] = {
|
||||||
{"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"},
|
{"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"},
|
||||||
|
{"cursor_changed", T_OBJECT_EX, offsetof(Screen, cursor_changed), 0, "cursor_changed"},
|
||||||
|
{"is_dirty", T_OBJECT_EX, offsetof(Screen, is_dirty), 0, "is_dirty"},
|
||||||
{"cursor", T_OBJECT_EX, offsetof(Screen, cursor), READONLY, "cursor"},
|
{"cursor", T_OBJECT_EX, offsetof(Screen, cursor), READONLY, "cursor"},
|
||||||
{"color_profile", T_OBJECT_EX, offsetof(Screen, color_profile), READONLY, "color_profile"},
|
{"color_profile", T_OBJECT_EX, offsetof(Screen, color_profile), READONLY, "color_profile"},
|
||||||
{"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), READONLY, "linebuf"},
|
{"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), READONLY, "linebuf"},
|
||||||
@ -1354,6 +1339,7 @@ static PyMemberDef members[] = {
|
|||||||
{"columns", T_UINT, offsetof(Screen, columns), READONLY, "columns"},
|
{"columns", T_UINT, offsetof(Screen, columns), READONLY, "columns"},
|
||||||
{"margin_top", T_UINT, offsetof(Screen, margin_top), READONLY, "margin_top"},
|
{"margin_top", T_UINT, offsetof(Screen, margin_top), READONLY, "margin_top"},
|
||||||
{"margin_bottom", T_UINT, offsetof(Screen, margin_bottom), READONLY, "margin_bottom"},
|
{"margin_bottom", T_UINT, offsetof(Screen, margin_bottom), READONLY, "margin_bottom"},
|
||||||
|
{"history_line_added_count", T_UINT, offsetof(Screen, history_line_added_count), 0, "history_line_added_count"},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
265
kitty/tracker.c
265
kitty/tracker.c
@ -1,265 +0,0 @@
|
|||||||
/*
|
|
||||||
* tracker.c
|
|
||||||
* Copyright (C) 2016 Kovid Goyal <kovid at kovidgoyal.net>
|
|
||||||
*
|
|
||||||
* Distributed under terms of the GPL3 license.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "data-types.h"
|
|
||||||
#include "tracker.h"
|
|
||||||
|
|
||||||
|
|
||||||
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum) {
|
|
||||||
#define ALLOC_VAR(name, sz) \
|
|
||||||
bool *name = PyMem_Calloc(sz, sizeof(bool)); \
|
|
||||||
if (name == NULL) { PyErr_NoMemory(); return false; } \
|
|
||||||
PyMem_Free(self->name); self->name = name;
|
|
||||||
|
|
||||||
self->ynum = ynum; self->xnum = xnum;
|
|
||||||
ALLOC_VAR(changed_lines, self->ynum);
|
|
||||||
ALLOC_VAR(changed_cells, self->xnum * self->ynum);
|
|
||||||
ALLOC_VAR(lines_with_changed_cells, self->ynum);
|
|
||||||
RESET_STATE_VARS(self);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
resize(ChangeTracker *self, PyObject *args) {
|
|
||||||
#define resize_doc "Resize this change tracker must be called when the screen it is tracking for is resized"
|
|
||||||
unsigned int ynum=1, xnum=1;
|
|
||||||
if (!PyArg_ParseTuple(args, "|II", &ynum, &xnum)) return NULL;
|
|
||||||
if (!tracker_resize(self, ynum, xnum)) return NULL;
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|
||||||
ChangeTracker *self;
|
|
||||||
self = (ChangeTracker *)type->tp_alloc(type, 0);
|
|
||||||
if (self != NULL) {
|
|
||||||
PyObject *ret = resize(self, args);
|
|
||||||
if (ret == NULL) { Py_CLEAR(self); return NULL; }
|
|
||||||
Py_CLEAR(ret);
|
|
||||||
}
|
|
||||||
return (PyObject*) self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dealloc(ChangeTracker* self) {
|
|
||||||
PyMem_Free(self->changed_lines); PyMem_Free(self->changed_cells); PyMem_Free(self->lines_with_changed_cells);
|
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
reset(ChangeTracker *self) {
|
|
||||||
#define reset_doc "Reset all changes"
|
|
||||||
tracker_reset(self);
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
cursor_changed(ChangeTracker *self) {
|
|
||||||
#define cursor_changed_doc ""
|
|
||||||
tracker_cursor_changed(self);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
line_added_to_history(ChangeTracker *self) {
|
|
||||||
#define line_added_to_history_doc ""
|
|
||||||
tracker_line_added_to_history(self);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
update_screen(ChangeTracker *self) {
|
|
||||||
#define update_screen_doc ""
|
|
||||||
tracker_update_screen(self);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
update_line_range(ChangeTracker *self, PyObject *args) {
|
|
||||||
#define update_line_range_doc ""
|
|
||||||
unsigned int f, l;
|
|
||||||
if (!PyArg_ParseTuple(args, "II", &f, &l)) return NULL;
|
|
||||||
tracker_update_line_range(self, f, l);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
update_cell_range(ChangeTracker *self, PyObject *args) {
|
|
||||||
#define update_cell_range_doc ""
|
|
||||||
unsigned int line, f, l;
|
|
||||||
if (!PyArg_ParseTuple(args, "III", &line, &f, &l)) return NULL;
|
|
||||||
tracker_update_cell_range(self, line, f, l);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tracker_update_cell_data(ScreenModes *modes, ChangeTracker *self, LineBuf *lb, unsigned int *data, bool force_screen_refresh) {
|
|
||||||
unsigned int y;
|
|
||||||
Py_ssize_t start;
|
|
||||||
|
|
||||||
#define UPDATE_RANGE(xstart, xmax) \
|
|
||||||
linebuf_init_line(lb, y); \
|
|
||||||
if (!update_cell_range_data(modes, lb->line, (xstart), (xmax), data)) return false;
|
|
||||||
|
|
||||||
if (self->screen_changed || force_screen_refresh) {
|
|
||||||
for (y = 0; y < self->ynum; y++) {
|
|
||||||
UPDATE_RANGE(0, self->xnum - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (y = 0; y < self->ynum; y++) {
|
|
||||||
if (self->changed_lines[y]) {
|
|
||||||
UPDATE_RANGE(0, self->xnum - 1);
|
|
||||||
} else if (self->lines_with_changed_cells[y]) {
|
|
||||||
start = -1;
|
|
||||||
bool *line = self->changed_cells + y * self->xnum;
|
|
||||||
for (unsigned int i = 0; i < self->xnum; i++) {
|
|
||||||
if (line[i]) {
|
|
||||||
if (start == -1) {
|
|
||||||
start = i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (start != -1) {
|
|
||||||
UPDATE_RANGE(start, i - 1);
|
|
||||||
start = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (start != -1) {
|
|
||||||
UPDATE_RANGE(start, self->xnum - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tracker_reset(self);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline PyObject*
|
|
||||||
get_ranges(bool *line, unsigned int xnum) {
|
|
||||||
PyObject *ans = PyList_New(0), *t;
|
|
||||||
Py_ssize_t start = -1;
|
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
|
||||||
|
|
||||||
#define APPEND_RANGE(x) \
|
|
||||||
t = Py_BuildValue("nI", start, x); \
|
|
||||||
if (t == NULL) { Py_CLEAR(ans); return NULL; } \
|
|
||||||
if (PyList_Append(ans, t) != 0) { Py_CLEAR(ans); Py_CLEAR(t); return NULL; } \
|
|
||||||
Py_CLEAR(t);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < xnum; i++) {
|
|
||||||
if (line[i]) {
|
|
||||||
if (start == -1) {
|
|
||||||
start = i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (start != -1) {
|
|
||||||
APPEND_RANGE(i - 1);
|
|
||||||
start = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (start != -1) {
|
|
||||||
APPEND_RANGE(xnum - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject*
|
|
||||||
tracker_consolidate_changes(ChangeTracker *self) {
|
|
||||||
PyObject *ans = PyDict_New();
|
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
|
||||||
if (PyDict_SetItemString(ans, "screen", self->screen_changed ? Py_True : Py_False) != 0) { Py_CLEAR(ans); return NULL; }
|
|
||||||
if (PyDict_SetItemString(ans, "cursor", self->cursor_changed ? Py_True : Py_False) != 0) { Py_CLEAR(ans); return NULL; }
|
|
||||||
PyObject *t = PyLong_FromUnsignedLong((unsigned long)self->history_line_added_count);
|
|
||||||
if (t == NULL) { Py_CLEAR(ans); return NULL; }
|
|
||||||
if (PyDict_SetItemString(ans, "history_line_added_count", t) != 0) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; }
|
|
||||||
Py_CLEAR(t);
|
|
||||||
|
|
||||||
// Changed lines
|
|
||||||
Py_ssize_t num = 0;
|
|
||||||
if (!self->screen_changed) {
|
|
||||||
for (unsigned int i = 0; i < self->ynum; i++) { num += self->changed_lines[i]; }
|
|
||||||
}
|
|
||||||
t = PyTuple_New(num);
|
|
||||||
if (t == NULL) { Py_CLEAR(ans); return NULL; }
|
|
||||||
if (num > 0) {
|
|
||||||
for (unsigned int i = 0, j=0; i < self->ynum; i++) {
|
|
||||||
if (self->changed_lines[i]) {
|
|
||||||
PyObject *n = PyLong_FromUnsignedLong(i);
|
|
||||||
if (n == NULL) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; }
|
|
||||||
PyTuple_SET_ITEM(t, j++, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (PyDict_SetItemString(ans, "lines", t) != 0) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; }
|
|
||||||
Py_CLEAR(t);
|
|
||||||
|
|
||||||
// Changed cells
|
|
||||||
t = PyDict_New();
|
|
||||||
if (t == NULL) { Py_CLEAR(ans); return PyErr_NoMemory(); }
|
|
||||||
if (!self->screen_changed) {
|
|
||||||
for (unsigned int i = 0; i < self->ynum; i++) {
|
|
||||||
if (self->lines_with_changed_cells[i] && !self->changed_lines[i]) {
|
|
||||||
PyObject *ranges = get_ranges(self->changed_cells + i * self->xnum, self->xnum);
|
|
||||||
if (ranges == NULL) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; }
|
|
||||||
PyObject *key = PyLong_FromUnsignedLong(i);
|
|
||||||
if (key == NULL) { Py_CLEAR(t); Py_CLEAR(ans); Py_CLEAR(ranges); return NULL; }
|
|
||||||
if (PyDict_SetItem(t, key, ranges) != 0) { Py_CLEAR(key); Py_CLEAR(t); Py_CLEAR(ans); Py_CLEAR(ranges); return NULL; }
|
|
||||||
Py_CLEAR(key); Py_CLEAR(ranges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyDict_SetItemString(ans, "cells", t) != 0) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; }
|
|
||||||
Py_CLEAR(t);
|
|
||||||
|
|
||||||
tracker_reset(self);
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boilerplate {{{
|
|
||||||
|
|
||||||
BOOL_GETSET(ChangeTracker, dirty)
|
|
||||||
static PyGetSetDef getseters[] = {
|
|
||||||
GETSET(dirty)
|
|
||||||
{NULL} /* Sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
static PyMethodDef methods[] = {
|
|
||||||
METHOD(resize, METH_VARARGS)
|
|
||||||
METHOD(reset, METH_NOARGS)
|
|
||||||
METHOD(cursor_changed, METH_NOARGS)
|
|
||||||
{"consolidate_changes", (PyCFunction)tracker_consolidate_changes, METH_NOARGS, ""},
|
|
||||||
METHOD(line_added_to_history, METH_NOARGS)
|
|
||||||
METHOD(update_screen, METH_NOARGS)
|
|
||||||
METHOD(update_line_range, METH_VARARGS)
|
|
||||||
METHOD(update_cell_range, METH_VARARGS)
|
|
||||||
{NULL} /* Sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
PyTypeObject ChangeTracker_Type = {
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
.tp_name = "fast_data_types.ChangeTracker",
|
|
||||||
.tp_basicsize = sizeof(ChangeTracker),
|
|
||||||
.tp_dealloc = (destructor)dealloc,
|
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
|
||||||
.tp_doc = "ChangeTracker",
|
|
||||||
.tp_methods = methods,
|
|
||||||
.tp_getset = getseters,
|
|
||||||
.tp_new = new,
|
|
||||||
};
|
|
||||||
|
|
||||||
INIT_TYPE(ChangeTracker)
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
ChangeTracker* alloc_change_tracker(unsigned int ynum, unsigned int xnum) {
|
|
||||||
ChangeTracker *self = (ChangeTracker *)(&ChangeTracker_Type)->tp_alloc((&ChangeTracker_Type), 0);
|
|
||||||
if (!tracker_resize(self, ynum, xnum)) { Py_CLEAR(self); return NULL; }
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* tracker.h
|
|
||||||
* Copyright (C) 2016 Kovid Goyal <kovid at kovidgoyal.net>
|
|
||||||
*
|
|
||||||
* Distributed under terms of the GPL3 license.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
static inline void tracker_cursor_changed(ChangeTracker *self) {
|
|
||||||
self->cursor_changed = true;
|
|
||||||
self->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tracker_line_added_to_history(ChangeTracker *self) {
|
|
||||||
self->history_line_added_count++;
|
|
||||||
self->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tracker_update_screen(ChangeTracker *self) {
|
|
||||||
self->screen_changed = true;
|
|
||||||
self->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tracker_update_line_range(ChangeTracker *self, unsigned int first_line, unsigned int last_line) {
|
|
||||||
if (!self->screen_changed) {
|
|
||||||
for (unsigned int i = first_line; i <= MIN(self->ynum - 1, last_line); i++) self->changed_lines[i] = true;
|
|
||||||
self->dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tracker_update_cell_range(ChangeTracker *self, unsigned int line, unsigned int first_cell, unsigned int last_cell) {
|
|
||||||
if (!self->screen_changed && line < self->ynum && !self->changed_lines[line]) {
|
|
||||||
self->lines_with_changed_cells[line] = true;
|
|
||||||
unsigned int base = line * self->xnum;
|
|
||||||
for (unsigned int i = first_cell; i <= MIN(self->xnum - 1, last_cell); i++) self->changed_cells[base + i] = true;
|
|
||||||
self->dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RESET_STATE_VARS(self) \
|
|
||||||
self->screen_changed = false; self->cursor_changed = false; self->dirty = false; self->history_line_added_count = 0;
|
|
||||||
|
|
||||||
static inline void tracker_reset(ChangeTracker *self) {
|
|
||||||
self->screen_changed = false; self->cursor_changed = false; self->dirty = false;
|
|
||||||
self->history_line_added_count = 0;
|
|
||||||
memset(self->changed_lines, 0, self->ynum * sizeof(bool));
|
|
||||||
memset(self->changed_cells, 0, self->ynum * self->xnum * sizeof(bool));
|
|
||||||
memset(self->lines_with_changed_cells, 0, self->ynum * sizeof(bool));
|
|
||||||
RESET_STATE_VARS(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
|
||||||
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
|
|
||||||
bool tracker_update_cell_data(ScreenModes*, ChangeTracker *, LineBuf *, unsigned int *, bool);
|
|
||||||
Loading…
x
Reference in New Issue
Block a user