When double-clicking select words that continue onto next/prev line as well. Fixes #444

This commit is contained in:
Kovid Goyal
2018-04-09 09:47:18 +05:30
parent 49c375ae0f
commit e90df0ca95
4 changed files with 54 additions and 12 deletions

View File

@@ -1676,17 +1676,31 @@ is_opt_word_char(char_type ch) {
}
bool
screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_type *s, index_type *e) {
if (y >= self->lines || x >= self->columns) return false;
screen_selection_range_for_word(Screen *self, index_type x, index_type *y1, index_type *y2, index_type *s, index_type *e) {
if (*y1 >= self->lines || x >= self->columns) return false;
index_type start, end;
Line *line = visual_line_(self, y);
Line *line = visual_line_(self, *y1);
*y2 = *y1;
#define is_ok(x) (is_word_char((line->cells[x].ch)) || is_opt_word_char(line->cells[x].ch))
if (!is_ok(x)) {
start = x; end = x + 1;
} else {
start = x, end = x;
while(start > 0 && is_ok(start - 1)) start--;
while(end < self->columns - 1 && is_ok(end + 1)) end++;
while(true) {
while(start > 0 && is_ok(start - 1)) start--;
if (start > 0 || !line->continued || *y1 == 0) break;
line = visual_line_(self, *y1 - 1);
if (!is_ok(self->columns - 1)) break;
(*y1)--; start = self->columns - 1;
}
line = visual_line_(self, *y2);
while(true) {
while(end < self->columns - 1 && is_ok(end + 1)) end++;
if (end < self->columns - 1 || *y2 >= self->lines - 1) break;
line = visual_line_(self, *y2 + 1);
if (!line->continued || !is_ok(0)) break;
(*y2)++; end = 0;
}
}
*s = start; *e = end;
return true;
@@ -1763,16 +1777,40 @@ screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
index_type start, end;
bool found = false;
switch(self->selection.extend_mode) {
case EXTEND_WORD:
found = screen_selection_range_for_word(self, x, y, &start, &end);
case EXTEND_WORD: {
index_type y1 = y, y2;
found = screen_selection_range_for_word(self, x, &y1, &y2, &start, &end);
if (found) {
#define SMALLER(x1, y1, x2, y2) (y1 < y2 || (y1 == y2 && x1 < x2))
if (SMALLER(self->selection.end_x, self->selection.end_y, self->selection.start_x, self->selection.start_y)) {
// extend 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);
if (found) {
self->selection.start_x = end; self->selection.start_y = y2;
}
} else {
// extend rightwards
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);
if (found) {
self->selection.start_x = start; self->selection.start_y = y1;
}
}
#undef SMALLER
}
break;
}
case EXTEND_LINE:
found = screen_selection_range_for_line(self, y, &start, &end);
if (found) self->selection.end_x = end;
break;
case EXTEND_CELL:
break;
}
if (found) self->selection.end_x = end;
call_boss(set_primary_selection, NULL);
}