Get rid of the ugly macro used for iteration over selections

This commit is contained in:
Kovid Goyal 2020-02-23 20:53:02 +05:30
parent 71b6e8f12a
commit 6f5968eeb0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -1733,30 +1733,33 @@ iteration_data(const Screen *self, Selection *sel, const bool rectangle) {
return ans; return ans;
} }
#define iterate_over_selection(screen, sel, line_func, rectangular) { \ static inline XRange
IterationData idata = iteration_data(screen, sel, rectangular); \ xrange_for_iteration(IterationData *idata, index_type y, Line *line) {
for (index_type y = idata.y; y < idata.y_limit; y++) { \ XRange ans = {.x_limit=xlimit_for_line(line)};
Line *line = line_func(self, y); \ if (y == idata->y) {
index_type xlimit = xlimit_for_line(line), x_start = 0; \ ans.x_limit = MIN(idata->first.x_limit, ans.x_limit);
if (y == idata.y) { \ ans.x = idata->first.x;
xlimit = MIN(idata.first.x_limit, xlimit); \ } else if (y == idata->y_limit - 1) {
x_start = idata.first.x; \ ans.x_limit = MIN(idata->last.x_limit, ans.x_limit);
} else if (y == idata.y_limit - 1) { \ ans.x = idata->last.x;
xlimit = MIN(idata.last.x_limit, xlimit); \ } else {
x_start = idata.last.x; \ ans.x_limit = MIN(idata->body.x_limit, ans.x_limit);
} else { \ ans.x = idata->body.x;
xlimit = MIN(idata.body.x_limit, xlimit); \ }
x_start = idata.body.x; \ return ans;
} \ }
static inline void static inline void
apply_selection(Screen *self, uint8_t *data, Selection *s, uint8_t set_mask, bool rectangle_select) { apply_selection(Screen *self, uint8_t *data, Selection *s, uint8_t set_mask, bool rectangle_select) {
if (is_selection_empty_or_out_of_bounds(self, s)) return; if (is_selection_empty_or_out_of_bounds(self, s)) return;
iterate_over_selection(self, s, visual_line_, rectangle_select) IterationData idata = iteration_data(self, s, rectangle_select);
for (index_type y = idata.y; y < idata.y_limit; y++) {
Line *line = visual_line_(self, y);
uint8_t *line_start = data + self->columns * y; uint8_t *line_start = data + self->columns * y;
for (index_type x = x_start; x < xlimit; x++) line_start[x] |= set_mask; XRange xr = xrange_for_iteration(&idata, y, line);
}} for (index_type x = xr.x; x < xr.x_limit; x++) line_start[x] |= set_mask;
}
} }
bool bool
@ -1779,15 +1782,17 @@ screen_apply_selection(Screen *self, void *address, size_t size) {
static inline PyObject* static inline PyObject*
text_for_range(Screen *self, Selection *sel, bool rectangle_select, bool insert_newlines, linefunc_t line_func) { text_for_range(Screen *self, Selection *sel, bool rectangle_select, bool insert_newlines, linefunc_t line_func) {
int num_of_lines = sel->end.y - sel->start.y + 1, i = 0; IterationData idata = iteration_data(self, sel, rectangle_select);
PyObject *ans = PyTuple_New(num_of_lines); PyObject *ans = PyTuple_New(idata.y_limit - idata.y);
if (!ans) return NULL; if (!ans) return NULL;
iterate_over_selection(self, sel, line_func, rectangle_select) for (index_type y = idata.y, i = 0; y < idata.y_limit; y++, i++) {
char leading_char = (i > 0 && insert_newlines && !line->continued) ? '\n' : 0; \ Line *line = line_func(self, y);
PyObject *text = unicode_in_range(line, x_start, xlimit, true, leading_char); \ XRange xr = xrange_for_iteration(&idata, y, line);
if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); } \ char leading_char = (i > 0 && insert_newlines && !line->continued) ? '\n' : 0;
PyTuple_SET_ITEM(ans, i++, text); \ PyObject *text = unicode_in_range(line, xr.x, xr.x_limit, true, leading_char);
}} if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(ans, i, text);
}
return ans; return ans;
} }