Store cell half information in selection objects
This commit is contained in:
parent
c00b486864
commit
6f1fda0a48
@ -174,14 +174,14 @@ update_drag(bool from_button, Window *w, bool is_release, int modifiers) {
|
||||
global_state.active_drag_in_window = 0;
|
||||
w->last_drag_scroll_at = 0;
|
||||
if (screen->selection.in_progress)
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, true);
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, w->mouse_pos.in_left_half_of_cell, true);
|
||||
}
|
||||
else {
|
||||
global_state.active_drag_in_window = w->id;
|
||||
screen_start_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | (int)OPT(terminal_select_modifiers)), EXTEND_CELL);
|
||||
screen_start_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, w->mouse_pos.in_left_half_of_cell, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | (int)OPT(terminal_select_modifiers)), EXTEND_CELL);
|
||||
}
|
||||
} else if (screen->selection.in_progress) {
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, false);
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, w->mouse_pos.in_left_half_of_cell, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ static inline void
|
||||
extend_selection(Window *w) {
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (screen_has_selection(screen)) {
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, true);
|
||||
screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, w->mouse_pos.in_left_half_of_cell, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,21 +335,22 @@ multi_click(Window *w, unsigned int count) {
|
||||
bool found_selection = false;
|
||||
SelectionExtendMode mode = EXTEND_CELL;
|
||||
unsigned int y1 = w->mouse_pos.cell_y, y2 = w->mouse_pos.cell_y;
|
||||
bool start_in_left_half = w->mouse_pos.in_left_half_of_cell, end_in_left_half = w->mouse_pos.in_left_half_of_cell;
|
||||
switch(count) {
|
||||
case 2:
|
||||
found_selection = screen_selection_range_for_word(screen, w->mouse_pos.cell_x, &y1, &y2, &start, &end, true);
|
||||
found_selection = screen_selection_range_for_word(screen, w->mouse_pos.cell_x, &y1, &y2, &start, &end, &start_in_left_half, &end_in_left_half, true);
|
||||
mode = EXTEND_WORD;
|
||||
break;
|
||||
case 3:
|
||||
found_selection = screen_selection_range_for_line(screen, w->mouse_pos.cell_y, &start, &end);
|
||||
found_selection = screen_selection_range_for_line(screen, w->mouse_pos.cell_y, &start, &end, &start_in_left_half, &end_in_left_half);
|
||||
mode = EXTEND_LINE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (found_selection) {
|
||||
screen_start_selection(screen, start, y1, false, mode);
|
||||
screen_update_selection(screen, end, y2, false);
|
||||
screen_start_selection(screen, start, y1, start_in_left_half, false, mode);
|
||||
screen_update_selection(screen, end, y2, end_in_left_half, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1996,6 +1996,15 @@ cursor_up(Screen *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
update_selection(Screen *self, PyObject *args) {
|
||||
unsigned int x, y;
|
||||
int in_left_half_of_cell = 0, ended = 1;
|
||||
if (!PyArg_ParseTuple(args, "II|pp", &x, &y, &in_left_half_of_cell, &ended)) return NULL;
|
||||
screen_update_selection(self, x, y, in_left_half_of_cell, ended);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
WRAP0x(index)
|
||||
WRAP0(reverse_index)
|
||||
WRAP0(reset)
|
||||
@ -2008,14 +2017,13 @@ WRAP0(carriage_return)
|
||||
WRAP2(resize, 1, 1)
|
||||
WRAP2(set_margins, 1, 1)
|
||||
WRAP0(rescale_images)
|
||||
WRAP2B(update_selection)
|
||||
|
||||
static PyObject*
|
||||
start_selection(Screen *self, PyObject *args) {
|
||||
unsigned int x, y;
|
||||
int rectangle_select = 0, extend_mode = EXTEND_CELL;
|
||||
if (!PyArg_ParseTuple(args, "II|pi", &x, &y, &rectangle_select, &extend_mode)) return NULL;
|
||||
screen_start_selection(self, x, y, rectangle_select, extend_mode);
|
||||
screen_start_selection(self, x, y, false, rectangle_select, extend_mode);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@ -2045,13 +2053,15 @@ text_for_selection(Screen *self, PyObject *a UNUSED) {
|
||||
}
|
||||
|
||||
bool
|
||||
screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end) {
|
||||
screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end, bool* start_in_left_half, bool* end_in_left_half) {
|
||||
if (y >= self->lines) { return false; }
|
||||
Line *line = visual_line_(self, y);
|
||||
index_type xlimit = line->xnum, xstart = 0;
|
||||
while (xlimit > 0 && CHAR_IS_BLANK(line->cpu_cells[xlimit - 1].ch)) xlimit--;
|
||||
while (xstart < xlimit && CHAR_IS_BLANK(line->cpu_cells[xstart].ch)) xstart++;
|
||||
*start = xstart; *end = xlimit > 0 ? xlimit - 1 : 0;
|
||||
*start_in_left_half = true;
|
||||
*end_in_left_half = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2064,8 +2074,9 @@ is_opt_word_char(char_type ch) {
|
||||
}
|
||||
|
||||
bool
|
||||
screen_selection_range_for_word(Screen *self, index_type x, index_type *y1, index_type *y2, index_type *s, index_type *e, bool initial_selection) {
|
||||
screen_selection_range_for_word(Screen *self, index_type x, index_type *y1, index_type *y2, index_type *s, index_type *e, bool *start_in_left_half, bool *end_in_left_half, bool initial_selection) {
|
||||
if (*y1 >= self->lines || x >= self->columns) return false;
|
||||
*start_in_left_half = true; *end_in_left_half = false;
|
||||
index_type start, end;
|
||||
Line *line = visual_line_(self, *y1);
|
||||
*y2 = *y1;
|
||||
@ -2145,10 +2156,10 @@ screen_is_selection_dirty(Screen *self) {
|
||||
}
|
||||
|
||||
void
|
||||
screen_start_selection(Screen *self, index_type x, index_type y, bool rectangle_select, SelectionExtendMode extend_mode) {
|
||||
screen_start_selection(Screen *self, index_type x, index_type y, bool in_left_half_of_cell, bool rectangle_select, SelectionExtendMode extend_mode) {
|
||||
#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(rectangle_select, rectangle_select); A(extend_mode, extend_mode);
|
||||
A(in_progress, true); A(rectangle_select, rectangle_select); A(extend_mode, extend_mode); A(start_in_left_half, in_left_half_of_cell); A(end_in_left_half, in_left_half_of_cell);
|
||||
#undef A
|
||||
}
|
||||
|
||||
@ -2156,13 +2167,15 @@ void
|
||||
screen_mark_url(Screen *self, index_type start_x, index_type start_y, index_type end_x, index_type end_y) {
|
||||
#define A(attr, val) self->url_range.attr = val;
|
||||
A(start_x, start_x); A(end_x, end_x); A(start_y, start_y); A(end_y, end_y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by);
|
||||
A(start_in_left_half, true); A(end_in_left_half, false);
|
||||
#undef A
|
||||
}
|
||||
|
||||
void
|
||||
screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
||||
screen_update_selection(Screen *self, index_type x, index_type y, bool in_left_half_of_cell, bool ended) {
|
||||
index_type orig_x = self->selection.end_x, orig_y = self->selection.end_y, orig_scrolled_by = self->selection.end_scrolled_by;
|
||||
self->selection.end_x = x; self->selection.end_y = y; self->selection.end_scrolled_by = self->scrolled_by;
|
||||
self->selection.end_in_left_half = in_left_half_of_cell;
|
||||
if (ended) self->selection.in_progress = false;
|
||||
index_type start, end;
|
||||
bool found = false;
|
||||
@ -2170,19 +2183,19 @@ screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
||||
switch(self->selection.extend_mode) {
|
||||
case EXTEND_WORD: {
|
||||
index_type y1 = y, y2;
|
||||
found = screen_selection_range_for_word(self, x, &y1, &y2, &start, &end, false);
|
||||
found = screen_selection_range_for_word(self, x, &y1, &y2, &start, &end, &self->selection.start_in_left_half, &self->selection.end_in_left_half, false);
|
||||
if (found) {
|
||||
if (extending_leftwards) {
|
||||
self->selection.end_x = start; self->selection.end_y = y1;
|
||||
y1 = self->selection.start_y;
|
||||
found = screen_selection_range_for_word(self, self->selection.start_x, &y1, &y2, &start, &end, false);
|
||||
found = screen_selection_range_for_word(self, self->selection.start_x, &y1, &y2, &start, &end, &self->selection.start_in_left_half, &self->selection.end_in_left_half, false);
|
||||
if (found) {
|
||||
self->selection.start_x = end; self->selection.start_y = y2;
|
||||
}
|
||||
} else {
|
||||
self->selection.end_x = end; self->selection.end_y = y2;
|
||||
y1 = self->selection.start_y;
|
||||
found = screen_selection_range_for_word(self, self->selection.start_x, &y1, &y2, &start, &end, false);
|
||||
found = screen_selection_range_for_word(self, self->selection.start_x, &y1, &y2, &start, &end, &self->selection.start_in_left_half, &self->selection.end_in_left_half, false);
|
||||
if (found) {
|
||||
self->selection.start_x = start; self->selection.start_y = y1;
|
||||
}
|
||||
@ -2199,7 +2212,7 @@ screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
||||
while(top_line > 0 && visual_line_(self, top_line)->continued) top_line--;
|
||||
while(bottom_line < self->lines - 1 && visual_line_(self, bottom_line + 1)->continued) bottom_line++;
|
||||
bool multiline = self->selection.end_y != self->selection.start_y;
|
||||
found = screen_selection_range_for_line(self, top_line, &start, &end);
|
||||
found = screen_selection_range_for_line(self, top_line, &start, &end, &self->selection.start_in_left_half, &self->selection.end_in_left_half);
|
||||
if (found) {
|
||||
if (extending_leftwards) {
|
||||
self->selection.end_x = multiline ? 0 : start; self->selection.end_y = top_line;
|
||||
@ -2207,7 +2220,7 @@ screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
||||
self->selection.start_x = multiline ? 0 : start; self->selection.start_y = top_line;
|
||||
}
|
||||
}
|
||||
found = screen_selection_range_for_line(self, bottom_line, &start, &end);
|
||||
found = screen_selection_range_for_line(self, bottom_line, &start, &end, &self->selection.start_in_left_half, &self->selection.end_in_left_half);
|
||||
if (found) {
|
||||
if (extending_leftwards) {
|
||||
self->selection.start_x = end; self->selection.start_y = bottom_line;
|
||||
|
||||
@ -29,6 +29,7 @@ typedef struct {
|
||||
unsigned int start_x, start_y, start_scrolled_by, end_x, end_y, end_scrolled_by;
|
||||
bool in_progress, rectangle_select;
|
||||
SelectionExtendMode extend_mode;
|
||||
bool start_in_left_half, end_in_left_half;
|
||||
} Selection;
|
||||
|
||||
#define SAVEPOINTS_SZ 256
|
||||
@ -181,10 +182,10 @@ bool screen_has_selection(Screen*);
|
||||
bool screen_invert_colors(Screen *self);
|
||||
void screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE, bool cursor_has_moved);
|
||||
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_word(Screen *self, index_type x, index_type *, index_type *, index_type *start, index_type *end, bool);
|
||||
void screen_start_selection(Screen *self, index_type x, index_type y, bool, SelectionExtendMode);
|
||||
void screen_update_selection(Screen *self, index_type x, index_type y, bool ended);
|
||||
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end, bool*, bool*);
|
||||
bool screen_selection_range_for_word(Screen *self, index_type x, index_type *, index_type *, index_type *start, index_type *end, bool*, bool*, bool);
|
||||
void screen_start_selection(Screen *self, index_type x, index_type y, bool, bool, SelectionExtendMode);
|
||||
void screen_update_selection(Screen *self, index_type x, index_type y, bool in_left_half, bool ended);
|
||||
bool screen_history_scroll(Screen *self, int amt, bool upwards);
|
||||
Line* screen_visual_line(Screen *self, index_type y);
|
||||
unsigned long screen_current_char_width(Screen *self);
|
||||
|
||||
@ -421,7 +421,7 @@ class TestScreen(BaseTest):
|
||||
s.carriage_return(), s.linefeed()
|
||||
s.draw(str(i) * s.columns)
|
||||
s.start_selection(0, 0, False)
|
||||
s.update_selection(4, 4, True)
|
||||
s.update_selection(4, 4)
|
||||
expected = ('55555', '\n66666', '\n77777', '\n88888', '\n99999')
|
||||
self.ae(s.text_for_selection(), expected)
|
||||
s.scroll(2, True)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user