parent
c81a8216dc
commit
d097403a12
@ -107,11 +107,11 @@ cell_for_pos(Window *w, unsigned int *x, unsigned int *y) {
|
|||||||
#define HANDLER(name) static inline void name(Window UNUSED *w, int UNUSED button, int UNUSED modifiers, unsigned int UNUSED window_idx)
|
#define HANDLER(name) static inline void name(Window UNUSED *w, int UNUSED button, int UNUSED modifiers, unsigned int UNUSED window_idx)
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
update_drag(bool from_button, Window *w, bool is_release) {
|
update_drag(bool from_button, Window *w, bool is_release, int modifiers) {
|
||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
if (from_button) {
|
if (from_button) {
|
||||||
if (is_release) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true);
|
if (is_release) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true);
|
||||||
else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y);
|
else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
} else if (screen->selection.in_progress) {
|
} else if (screen->selection.in_progress) {
|
||||||
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
||||||
call_boss(set_primary_selection, NULL);
|
call_boss(set_primary_selection, NULL);
|
||||||
@ -130,7 +130,7 @@ drag_scroll(Window *w, OSWindow *frame) {
|
|||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
if (screen->linebuf == screen->main_linebuf) {
|
if (screen->linebuf == screen->main_linebuf) {
|
||||||
screen_history_scroll(screen, SCROLL_LINE, upwards);
|
screen_history_scroll(screen, SCROLL_LINE, upwards);
|
||||||
update_drag(false, w, false);
|
update_drag(false, w, false, 0);
|
||||||
frame->last_mouse_activity_at = monotonic();
|
frame->last_mouse_activity_at = monotonic();
|
||||||
if (mouse_cursor_shape != ARROW) {
|
if (mouse_cursor_shape != ARROW) {
|
||||||
mouse_cursor_shape = ARROW;
|
mouse_cursor_shape = ARROW;
|
||||||
@ -199,7 +199,7 @@ HANDLER(handle_move_event) {
|
|||||||
if (screen->selection.in_progress && button == GLFW_MOUSE_BUTTON_LEFT) {
|
if (screen->selection.in_progress && button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
if ((now - w->last_drag_scroll_at) >= 0.02 || mouse_cell_changed) {
|
if ((now - w->last_drag_scroll_at) >= 0.02 || mouse_cell_changed) {
|
||||||
update_drag(false, w, false);
|
update_drag(false, w, false, 0);
|
||||||
w->last_drag_scroll_at = monotonic();
|
w->last_drag_scroll_at = monotonic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ multi_click(Window *w, unsigned int count) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (found_selection) {
|
if (found_selection) {
|
||||||
screen_start_selection(screen, start, w->mouse_cell_y);
|
screen_start_selection(screen, start, w->mouse_cell_y, false);
|
||||||
screen_update_selection(screen, end, w->mouse_cell_y, true);
|
screen_update_selection(screen, end, w->mouse_cell_y, true);
|
||||||
call_boss(set_primary_selection, NULL);
|
call_boss(set_primary_selection, NULL);
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ HANDLER(handle_button_event) {
|
|||||||
if (handle_in_kitty) {
|
if (handle_in_kitty) {
|
||||||
switch(button) {
|
switch(button) {
|
||||||
case GLFW_MOUSE_BUTTON_LEFT:
|
case GLFW_MOUSE_BUTTON_LEFT:
|
||||||
update_drag(true, w, is_release);
|
update_drag(true, w, is_release, modifiers);
|
||||||
if (is_release) {
|
if (is_release) {
|
||||||
if (modifiers == (int)OPT(open_url_modifiers)) {
|
if (modifiers == (int)OPT(open_url_modifiers)) {
|
||||||
open_url(w);
|
open_url(w);
|
||||||
|
|||||||
@ -1226,15 +1226,36 @@ visual_line_(Screen *self, index_type y) {
|
|||||||
return self->linebuf->line;
|
return self->linebuf->line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define iterate_over_rectangle(start, end) { \
|
||||||
|
index_type min_y = MIN(start->y, end->y), max_y = MAX(start->y, end->y); \
|
||||||
|
index_type min_x = MIN(start->x, end->x), max_x = MAX(start->x, end->x); \
|
||||||
|
for (index_type y = min_y; y <= max_y; y++) { \
|
||||||
|
Line *line = visual_line_(self, y); \
|
||||||
|
index_type xlimit = xlimit_for_line(line); \
|
||||||
|
xlimit = MIN(max_x + 1, xlimit); \
|
||||||
|
index_type x_start = min_x; \
|
||||||
|
|
||||||
|
#define iterate_over_region(start, end) { \
|
||||||
|
for (index_type y = start->y; y <= end->y; y++) { \
|
||||||
|
Line *line = visual_line_(self, y); \
|
||||||
|
index_type xlimit = xlimit_for_line(line); \
|
||||||
|
if (y == end->y) xlimit = MIN(end->x + 1, xlimit); \
|
||||||
|
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) {
|
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;
|
||||||
for (index_type y = start->y; y <= end->y; y++) {
|
if (rectangle_select) {
|
||||||
Line *line = visual_line_(self, y);
|
iterate_over_rectangle(start, end)
|
||||||
index_type xlimit = xlimit_for_line(line);
|
uint8_t *line_start = data + self->columns * y;
|
||||||
if (y == end->y) xlimit = MIN(end->x + 1, xlimit);
|
for (index_type x = x_start; x < xlimit; x++) line_start[x] |= set_mask;
|
||||||
uint8_t *line_start = data + self->columns * y;
|
}}
|
||||||
for (index_type x = (y == start->y ? start->x : 0); x < xlimit; x++) line_start[x] |= set_mask;
|
} else {
|
||||||
|
iterate_over_region(start, end)
|
||||||
|
uint8_t *line_start = data + self->columns * y;
|
||||||
|
for (index_type x = x_start; x < xlimit; x++) line_start[x] |= set_mask;
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1245,26 +1266,30 @@ screen_apply_selection(Screen *self, void *address, size_t size) {
|
|||||||
self->last_selection_scrolled_by = self->scrolled_by;
|
self->last_selection_scrolled_by = self->scrolled_by;
|
||||||
self->selection_updated_once = true;
|
self->selection_updated_once = true;
|
||||||
selection_limits_(selection, &self->last_rendered_selection_start, &self->last_rendered_selection_end);
|
selection_limits_(selection, &self->last_rendered_selection_start, &self->last_rendered_selection_end);
|
||||||
apply_selection(self, address, &self->last_rendered_selection_start, &self->last_rendered_selection_end, 1);
|
apply_selection(self, address, &self->last_rendered_selection_start, &self->last_rendered_selection_end, 1, self->rectangle_select);
|
||||||
selection_limits_(url_range, &self->last_rendered_url_start, &self->last_rendered_url_end);
|
selection_limits_(url_range, &self->last_rendered_url_start, &self->last_rendered_url_end);
|
||||||
apply_selection(self, address, &self->last_rendered_url_start, &self->last_rendered_url_end, 2);
|
apply_selection(self, address, &self->last_rendered_url_start, &self->last_rendered_url_end, 2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PyObject*
|
static inline PyObject*
|
||||||
text_for_range(Screen *self, SelectionBoundary start, SelectionBoundary end) {
|
text_for_range(Screen *self, SelectionBoundary start, SelectionBoundary end, bool rectangle_select, bool insert_newlines) {
|
||||||
Py_ssize_t i = 0, num_of_lines = end.y - start.y + 1;
|
int num_of_lines = end.y - start.y + 1, i = 0;
|
||||||
PyObject *ans = PyTuple_New(num_of_lines);
|
PyObject *ans = PyTuple_New(num_of_lines);
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
for (index_type y = start.y; y <= end.y; y++, i++) {
|
#define action \
|
||||||
Line *line = visual_line_(self, y);
|
char leading_char = (i > 0 && insert_newlines && !line->continued) ? '\n' : 0; \
|
||||||
index_type xlimit = xlimit_for_line(line);
|
PyObject *text = unicode_in_range(line, x_start, xlimit, true, leading_char); \
|
||||||
if (y == end.y) xlimit = MIN(end.x + 1, xlimit);
|
if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); } \
|
||||||
index_type xstart = (y == start.y ? start.x : 0);
|
PyTuple_SET_ITEM(ans, i++, text);
|
||||||
char leading_char = i > 0 && !line->continued ? '\n' : 0;
|
|
||||||
PyObject *text = unicode_in_range(line, xstart, xlimit, true, leading_char);
|
if (rectangle_select) {
|
||||||
if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); }
|
iterate_over_rectangle((&start), (&end))
|
||||||
PyTuple_SET_ITEM(ans, i, text);
|
action
|
||||||
}
|
}}} else {
|
||||||
|
iterate_over_region((&start), (&end))
|
||||||
|
action
|
||||||
|
}}}
|
||||||
|
#undef action
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1273,7 +1298,7 @@ screen_open_url(Screen *self) {
|
|||||||
SelectionBoundary start, end;
|
SelectionBoundary start, end;
|
||||||
selection_limits_(url_range, &start, &end);
|
selection_limits_(url_range, &start, &end);
|
||||||
if (is_selection_empty(self, start.x, start.y, end.x, end.y)) return false;
|
if (is_selection_empty(self, start.x, start.y, end.x, end.y)) return false;
|
||||||
PyObject *text = text_for_range(self, start, end);
|
PyObject *text = text_for_range(self, start, end, false, false);
|
||||||
if (text) { call_boss(open_url_lines, "(O)", text); Py_CLEAR(text); }
|
if (text) { call_boss(open_url_lines, "(O)", text); Py_CLEAR(text); }
|
||||||
else PyErr_Print();
|
else PyErr_Print();
|
||||||
return true;
|
return true;
|
||||||
@ -1435,7 +1460,7 @@ text_for_selection(Screen *self) {
|
|||||||
SelectionBoundary start, end;
|
SelectionBoundary start, end;
|
||||||
selection_limits_(selection, &start, &end);
|
selection_limits_(selection, &start, &end);
|
||||||
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);
|
return text_for_range(self, start, end, self->rectangle_select, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1524,7 +1549,8 @@ screen_is_selection_dirty(Screen *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_start_selection(Screen *self, index_type x, index_type y) {
|
screen_start_selection(Screen *self, index_type x, index_type y, bool rectangle_select) {
|
||||||
|
self->rectangle_select = rectangle_select;
|
||||||
#define A(attr, val) self->selection.attr = val;
|
#define A(attr, val) self->selection.attr = val;
|
||||||
A(start_x, x); A(end_x, x); A(start_y, y); A(end_y, y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by); A(in_progress, true);
|
A(start_x, x); A(end_x, x); A(start_y, y); A(end_y, y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by); A(in_progress, true);
|
||||||
#undef A
|
#undef A
|
||||||
|
|||||||
@ -36,7 +36,7 @@ typedef struct {
|
|||||||
Selection selection;
|
Selection selection;
|
||||||
SelectionBoundary last_rendered_selection_start, last_rendered_selection_end, last_rendered_url_start, last_rendered_url_end;
|
SelectionBoundary last_rendered_selection_start, last_rendered_selection_end, last_rendered_url_start, last_rendered_url_end;
|
||||||
Selection url_range;
|
Selection url_range;
|
||||||
bool use_latin1, selection_updated_once, is_dirty, scroll_changed;
|
bool use_latin1, selection_updated_once, is_dirty, scroll_changed, rectangle_select;
|
||||||
Cursor *cursor;
|
Cursor *cursor;
|
||||||
SavepointBuffer main_savepoints, alt_savepoints;
|
SavepointBuffer main_savepoints, alt_savepoints;
|
||||||
PyObject *callbacks, *test_child;
|
PyObject *callbacks, *test_child;
|
||||||
@ -125,7 +125,7 @@ void screen_update_cell_data(Screen *self, void *address, size_t sz);
|
|||||||
bool screen_is_cursor_visible(Screen *self);
|
bool screen_is_cursor_visible(Screen *self);
|
||||||
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end);
|
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end);
|
||||||
bool screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_type *start, index_type *end);
|
bool screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_type *start, index_type *end);
|
||||||
void screen_start_selection(Screen *self, index_type x, index_type y);
|
void screen_start_selection(Screen *self, index_type x, index_type y, bool);
|
||||||
void screen_update_selection(Screen *self, index_type x, index_type y, bool ended);
|
void screen_update_selection(Screen *self, index_type x, index_type y, bool ended);
|
||||||
bool screen_history_scroll(Screen *self, int amt, bool upwards);
|
bool screen_history_scroll(Screen *self, int amt, bool upwards);
|
||||||
Line* screen_visual_line(Screen *self, index_type y);
|
Line* screen_visual_line(Screen *self, index_type y);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user