diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2016-03-30 13:05:50 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2016-03-30 14:03:12 +0200 |
| commit | 1cd15a982a47cf9c7a2beade17987f8303df85bf (patch) | |
| tree | b6b0690270fd8454d12181584df4fda0fb098b71 /view.c | |
| parent | 8bd6650245d050e455cd4d26f6e59e7dd9b80392 (diff) | |
| download | vis-1cd15a982a47cf9c7a2beade17987f8303df85bf.tar.gz vis-1cd15a982a47cf9c7a2beade17987f8303df85bf.tar.xz | |
view: change internal representation of selections
We place the end mark inside the selection as opposted to on the character
immediately following it. This is better when selections are touching each
other. Previously for two seletions [a][b] the end mark for selection
a would be at the same location as the start mark of selection b. Thus
when for example the content of selection b is deleted it would also
destroy selection a, because the end mark would no longer be valid.
Diffstat (limited to 'view.c')
| -rw-r--r-- | view.c | 50 |
1 files changed, 27 insertions, 23 deletions
@@ -26,6 +26,21 @@ enum { SYNTAX_SYMBOL_LAST, }; +/* A selection is made up of two marks named cursor and anchor. + * While the anchor remains fixed the cursor mark follows cursor motions. + * For a selection (indicated by []), the marks (^) are placed as follows: + * + * [some text] [!] + * ^ ^ ^ + * ^ + * + * That is the marks point to the *start* of the first and last character + * of the selection. In particular for a single character selection (as + * depicted on the right above) both marks point to the same location. + * + * The view_selections_{get,set} functions take care of adding/removing + * the necessary offset for the last character. + */ struct Selection { Mark anchor; /* position where the selection was created */ Mark cursor; /* other selection endpoint where it changes */ @@ -432,20 +447,6 @@ static void cursor_to(Cursor *c, size_t pos) { c->lastcol = 0; c->pos = pos; if (c->sel) { - size_t anchor = text_mark_get(txt, c->sel->anchor); - size_t cursor = text_mark_get(txt, c->sel->cursor); - /* do we have to change the orientation of the selection? */ - if (pos < anchor && anchor < cursor) { - /* right extend -> left extend */ - anchor = text_char_next(txt, anchor); - c->sel->anchor = text_mark_set(txt, anchor); - } else if (cursor < anchor && anchor <= pos) { - /* left extend -> right extend */ - anchor = text_char_prev(txt, anchor); - c->sel->anchor = text_mark_set(txt, anchor); - } - if (anchor <= pos) - pos = text_char_next(txt, pos); c->sel->cursor = text_mark_set(txt, pos); } if (!view_coord_get(c->view, pos, &c->line, &c->row, &c->col)) { @@ -1297,7 +1298,7 @@ void view_cursors_selection_start(Cursor *c) { return; Text *txt = c->view->text; c->sel->anchor = text_mark_set(txt, pos); - c->sel->cursor = text_mark_set(txt, text_char_next(txt, pos)); + c->sel->cursor = c->sel->anchor; view_draw(c->view); } @@ -1311,6 +1312,7 @@ void view_cursors_selection_restore(Cursor *c) { ); if (!text_range_valid(&sel)) return; + sel.end = text_char_next(txt, sel.end); if (!(c->sel = view_selections_new(c->view))) return; view_selections_set(c->sel, &sel); @@ -1338,11 +1340,7 @@ void view_cursors_selection_sync(Cursor *c) { if (!c->sel) return; Text *txt = c->view->text; - size_t anchor = text_mark_get(txt, c->sel->anchor); size_t cursor = text_mark_get(txt, c->sel->cursor); - bool right_extending = anchor < cursor; - if (right_extending) - cursor = text_char_prev(txt, cursor); view_cursors_to(c, cursor); } @@ -1439,7 +1437,10 @@ Filerange view_selections_get(Selection *s) { Text *txt = s->view->text; size_t anchor = text_mark_get(txt, s->anchor); size_t cursor = text_mark_get(txt, s->cursor); - return text_range_new(anchor, cursor); + Filerange sel = text_range_new(anchor, cursor); + if (text_range_valid(&sel)) + sel.end = text_char_next(txt, sel.end); + return sel; } void view_selections_set(Selection *s, Filerange *r) { @@ -1448,13 +1449,16 @@ void view_selections_set(Selection *s, Filerange *r) { Text *txt = s->view->text; size_t anchor = text_mark_get(txt, s->anchor); size_t cursor = text_mark_get(txt, s->cursor); - bool left_extending = anchor > cursor; + bool left_extending = anchor != EPOS && anchor > cursor; + size_t end = r->end; + if (r->start != end) + end = text_char_prev(txt, end); if (left_extending) { - s->anchor = text_mark_set(txt, r->end); + s->anchor = text_mark_set(txt, end); s->cursor = text_mark_set(txt, r->start); } else { s->anchor = text_mark_set(txt, r->start); - s->cursor = text_mark_set(txt, r->end); + s->cursor = text_mark_set(txt, end); } view_draw(s->view); } |
