Preserve the mouse selection even when the contents of the screen are scrolled or overwritten provided the new text does not intersect the selected lines.
Requires a small CPU usage overhead when scrolling/drawing characters even in the absence of a selection. I couldn't isolate the overhead from statistical noise in my testing.
This commit is contained in:
parent
57871e1983
commit
d72098bdf8
@ -6,6 +6,10 @@ Changelog
|
||||
0.12.0 [future]
|
||||
------------------------------
|
||||
|
||||
- Preserve the mouse selection even when the contents of the screen are
|
||||
scrolled or overwritten provided the new text does not intersect the
|
||||
selected lines.
|
||||
|
||||
- Linux: Implement support for Input Method Extensions (multilingual input
|
||||
using standard keyboards) via `IBus
|
||||
<https://github.com/ibus/ibus/wiki/ReadMe>`_ (:iss:`469`)
|
||||
|
||||
@ -146,6 +146,7 @@ screen_reset(Screen *self) {
|
||||
init_tabstops(self->alt_tabstops, self->columns);
|
||||
cursor_reset(self->cursor);
|
||||
self->is_dirty = true;
|
||||
self->selection = EMPTY_SELECTION;
|
||||
screen_cursor_position(self, 1, 1);
|
||||
set_dynamic_color(self, 110, NULL);
|
||||
set_dynamic_color(self, 111, NULL);
|
||||
@ -332,6 +333,14 @@ move_widened_char(Screen *self, CPUCell* cpu_cell, GPUCell *gpu_cell, index_type
|
||||
*dest_gpu = src_gpu;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
selection_has_screen_line(Selection *s, int y) {
|
||||
if (s->start_scrolled_by == s->end_scrolled_by && s->start_x == s->end_x && s->start_y == s->end_y) return false;
|
||||
int top = (int)s->start_y - s->start_scrolled_by;
|
||||
int bottom = (int)s->end_y - s->end_scrolled_by;
|
||||
return top <= y && y <= bottom;
|
||||
}
|
||||
|
||||
static inline void
|
||||
draw_combining_char(Screen *self, char_type ch) {
|
||||
bool has_prev_char = false;
|
||||
@ -350,6 +359,7 @@ draw_combining_char(Screen *self, char_type ch) {
|
||||
if (has_prev_char) {
|
||||
line_add_combining_char(self->linebuf->line, ch, xpos);
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, ypos)) self->selection = EMPTY_SELECTION;
|
||||
linebuf_mark_line_dirty(self->linebuf, ypos);
|
||||
if (ch == 0xfe0f) { // emoji presentation variation marker makes default text presentation emoji (narrow emoji) into wide emoji
|
||||
CPUCell *cpu_cell = self->linebuf->line->cpu_cells + xpos;
|
||||
@ -398,6 +408,7 @@ screen_draw(Screen *self, uint32_t och) {
|
||||
self->cursor->x++;
|
||||
}
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, self->cursor->y)) self->selection = EMPTY_SELECTION;
|
||||
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
|
||||
}
|
||||
|
||||
@ -563,6 +574,7 @@ screen_toggle_screen_buffer(Screen *self) {
|
||||
}
|
||||
screen_history_scroll(self, SCROLL_FULL, false);
|
||||
self->is_dirty = true;
|
||||
self->selection = EMPTY_SELECTION;
|
||||
}
|
||||
|
||||
void screen_normal_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
||||
@ -782,6 +794,22 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
index_selection(Screen *self, Selection *s, bool up) {
|
||||
if (s->start_scrolled_by == s->end_scrolled_by && s->start_x == s->end_x && s->start_y == s->end_y) return;
|
||||
if (up) {
|
||||
if (s->start_y == 0) s->start_scrolled_by += 1;
|
||||
else s->start_y--;
|
||||
if (s->end_y == 0) s->end_scrolled_by += 1;
|
||||
else s->end_y--;
|
||||
} else {
|
||||
if (s->start_y >= self->lines - 1) s->start_scrolled_by -= 1;
|
||||
else s->start_y++;
|
||||
if (s->end_y >= self->lines - 1) s->end_scrolled_by -= 1;
|
||||
else s->end_y++;
|
||||
}
|
||||
}
|
||||
|
||||
#define INDEX_GRAPHICS(amtv) { \
|
||||
bool is_main = self->linebuf == self->main_linebuf; \
|
||||
static ScrollData s; \
|
||||
@ -802,7 +830,8 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
||||
self->history_line_added_count++; \
|
||||
} \
|
||||
linebuf_clear_line(self->linebuf, bottom); \
|
||||
self->is_dirty = true;
|
||||
self->is_dirty = true; \
|
||||
index_selection(self, &self->selection, true);
|
||||
|
||||
void
|
||||
screen_index(Screen *self) {
|
||||
@ -828,7 +857,8 @@ screen_scroll(Screen *self, unsigned int count) {
|
||||
linebuf_reverse_index(self->linebuf, top, bottom); \
|
||||
linebuf_clear_line(self->linebuf, top); \
|
||||
INDEX_GRAPHICS(1) \
|
||||
self->is_dirty = true;
|
||||
self->is_dirty = true; \
|
||||
index_selection(self, &self->selection, false);
|
||||
|
||||
void
|
||||
screen_reverse_index(Screen *self) {
|
||||
@ -1012,6 +1042,7 @@ screen_erase_in_line(Screen *self, unsigned int how, bool private) {
|
||||
line_apply_cursor(self->linebuf->line, self->cursor, s, n, true);
|
||||
}
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, self->cursor->y)) self->selection = EMPTY_SELECTION;
|
||||
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
|
||||
}
|
||||
}
|
||||
@ -1055,6 +1086,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) {
|
||||
linebuf_mark_line_dirty(self->linebuf, i);
|
||||
}
|
||||
self->is_dirty = true;
|
||||
self->selection = EMPTY_SELECTION;
|
||||
}
|
||||
if (how != 2) {
|
||||
screen_erase_in_line(self, how, private);
|
||||
@ -1075,6 +1107,7 @@ screen_insert_lines(Screen *self, unsigned int count) {
|
||||
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
||||
linebuf_insert_lines(self->linebuf, count, self->cursor->y, bottom);
|
||||
self->is_dirty = true;
|
||||
self->selection = EMPTY_SELECTION;
|
||||
screen_carriage_return(self);
|
||||
}
|
||||
}
|
||||
@ -1086,6 +1119,7 @@ screen_delete_lines(Screen *self, unsigned int count) {
|
||||
if (top <= self->cursor->y && self->cursor->y <= bottom) {
|
||||
linebuf_delete_lines(self->linebuf, count, self->cursor->y, bottom);
|
||||
self->is_dirty = true;
|
||||
self->selection = EMPTY_SELECTION;
|
||||
screen_carriage_return(self);
|
||||
}
|
||||
}
|
||||
@ -1102,6 +1136,7 @@ screen_insert_characters(Screen *self, unsigned int count) {
|
||||
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
||||
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, self->cursor->y)) self->selection = EMPTY_SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1118,6 +1153,7 @@ screen_delete_characters(Screen *self, unsigned int count) {
|
||||
line_apply_cursor(self->linebuf->line, self->cursor, self->columns - num, num, true);
|
||||
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, self->cursor->y)) self->selection = EMPTY_SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1131,6 +1167,7 @@ screen_erase_characters(Screen *self, unsigned int count) {
|
||||
line_apply_cursor(self->linebuf->line, self->cursor, x, num, true);
|
||||
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, self->cursor->y)) self->selection = EMPTY_SELECTION;
|
||||
}
|
||||
|
||||
// }}}
|
||||
@ -1423,7 +1460,7 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat
|
||||
update_line_data(self->linebuf->line, y, address);
|
||||
}
|
||||
if (was_dirty) {
|
||||
self->selection = EMPTY_SELECTION; self->url_range = EMPTY_SELECTION;
|
||||
self->url_range = EMPTY_SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user