diff options
| -rw-r--r-- | main.c | 31 | ||||
| -rw-r--r-- | sam.c | 31 | ||||
| -rw-r--r-- | view.c | 196 | ||||
| -rw-r--r-- | view.h | 22 | ||||
| -rw-r--r-- | vis-prompt.c | 2 | ||||
| -rw-r--r-- | vis.c | 33 |
6 files changed, 86 insertions, 229 deletions
@@ -1309,12 +1309,8 @@ static const char *cursors_align_indent(Vis *vis, const char *keys, const Arg *a for (int i = 0; i < columns; i++) { int mincol = INT_MAX, maxcol = 0; for (Cursor *c = view_cursors_column(view, i); c; c = view_cursors_column_next(c, i)) { - size_t pos; Filerange sel = view_cursors_selection_get(c); - if (text_range_valid(&sel)) - pos = left_align ? sel.start : sel.end; - else - pos = view_cursors_pos(c); + size_t pos = left_align ? sel.start : sel.end; int col = text_line_width_get(txt, pos); if (col < mincol) mincol = col; @@ -1329,15 +1325,9 @@ static const char *cursors_align_indent(Vis *vis, const char *keys, const Arg *a memset(buf, ' ', len); for (Cursor *c = view_cursors_column(view, i); c; c = view_cursors_column_next(c, i)) { - size_t pos, ipos; Filerange sel = view_cursors_selection_get(c); - if (text_range_valid(&sel)) { - pos = left_align ? sel.start : sel.end; - ipos = sel.start; - } else { - pos = view_cursors_pos(c); - ipos = pos; - } + size_t pos = left_align ? sel.start : sel.end; + size_t ipos = sel.start; int col = text_line_width_get(txt, pos); if (col < maxcol) { size_t off = maxcol - col; @@ -1366,12 +1356,9 @@ static const char *cursors_select(Vis *vis, const char *keys, const Arg *arg) { Text *txt = vis_text(vis); View *view = vis_view(vis); for (Cursor *cursor = view_cursors(view); cursor; cursor = view_cursors_next(cursor)) { - Filerange sel = view_cursors_selection_get(cursor); Filerange word = text_object_word(txt, view_cursors_pos(cursor)); - if (!text_range_valid(&sel) && text_range_valid(&word)) { + if (text_range_valid(&word)) view_cursors_selection_set(cursor, &word); - view_cursors_to(cursor, text_char_prev(txt, word.end)); - } } vis_mode_switch(vis, VIS_MODE_VISUAL); return keys; @@ -1476,12 +1463,8 @@ static const char *cursors_remove_column_except(Vis *vis, const char *keys, cons static const char *cursors_navigate(Vis *vis, const char *keys, const Arg *arg) { View *view = vis_view(vis); - if (!view_cursors_multiple(view)) { - Filerange sel = view_selection_get(view); - if (!text_range_valid(&sel)) - return wscroll(vis, keys, arg); - return keys; - } + if (!view_cursors_multiple(view)) + return wscroll(vis, keys, arg); Cursor *c = view_cursors_primary_get(view); VisCountIterator it = vis_count_iterator_get(vis, 1); while (vis_count_iterator_next(&it)) { @@ -1558,7 +1541,6 @@ static const char *selections_rotate(Vis *vis, const char *keys, const Arg *arg) continue; newsel.end = newsel.start + oldrot->len; view_cursors_selection_set(newrot->cursor, &newsel); - view_cursors_selection_sync(newrot->cursor); free(oldrot->data); } array_clear(&arr); @@ -1585,7 +1567,6 @@ static const char *selections_trim(Vis *vis, const char *keys, const Arg *arg) { && isspace((unsigned char)b); sel.start++); if (sel.start < sel.end) { view_cursors_selection_set(c, &sel); - view_cursors_selection_sync(c); } else if (!view_cursors_dispose(c)) { vis_mode_switch(vis, VIS_MODE_NORMAL); } @@ -1213,7 +1213,7 @@ enum SamError sam_cmd(Vis *vis, const char *s) { if (c->cursor) { if (visual) { view_cursors_selection_set(c->cursor, &sel); - view_cursors_selection_sync(c->cursor); + view_cursors_selection_start(c->cursor); } else { if (memchr(c->data, '\n', c->len)) view_cursors_to(c->cursor, sel.start); @@ -1224,7 +1224,7 @@ enum SamError sam_cmd(Vis *vis, const char *s) { Cursor *cursor = view_cursors_new(c->win->view, sel.start); if (cursor) { view_cursors_selection_set(cursor, &sel); - view_cursors_selection_sync(cursor); + view_cursors_selection_start(cursor); } } } @@ -1239,8 +1239,7 @@ enum SamError sam_cmd(Vis *vis, const char *s) { view_cursors_primary_set(view_cursors(vis->win->view)); bool completed = true; for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) { - Filerange sel = view_cursors_selection_get(c); - if (text_range_valid(&sel)) { + if (view_selection_anchored(c)) { completed = false; break; } @@ -1504,10 +1503,12 @@ static bool cmd_print(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs else cur = view_cursors_new_force(view, pos); if (cur) { - if (range->start != range->end) + if (range->start != range->end) { view_cursors_selection_set(cur, range); - else + view_cursors_selection_start(cur); + } else { view_cursors_selection_clear(cur); + } } return cur != NULL; } @@ -1559,17 +1560,16 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs return false; } + bool visual = vis->mode->visual; + for (Cursor *c = view_cursors(win->view); c; c = view_cursors_next(c)) { - Filerange range = view_cursors_selection_get(c); - bool invalid_range = !text_range_valid(&range); - if (invalid_range) - range = *r; + Filerange range = visual ? view_cursors_selection_get(c) : *r; ssize_t written = text_write_range(text, &range, file->fd); if (written == -1 || (size_t)written != text_range_size(&range)) { vis_info_show(vis, "Can not write to stdout"); return false; } - if (invalid_range) + if (!visual) break; } @@ -1612,13 +1612,10 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs } bool failure = false; + bool visual = vis->mode->visual; for (Cursor *c = view_cursors(win->view); c; c = view_cursors_next(c)) { - Filerange range = view_cursors_selection_get(c); - bool invalid_range = !text_range_valid(&range); - if (invalid_range) - range = *r; - + Filerange range = visual ? view_cursors_selection_get(c) : *r; ssize_t written = text_save_write_range(ctx, &range); failure = (written == -1 || (size_t)written != text_range_size(&range)); if (failure) { @@ -1626,7 +1623,7 @@ static bool cmd_write(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs break; } - if (invalid_range) + if (!visual) break; } @@ -37,26 +37,23 @@ enum { * 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 */ - View *view; /* associated view to which this selection belongs */ - Cursor *cur; /* cursor whose movement will affect this selection */ - Selection *prev, *next; /* previsous/next selections in no particular order */ -}; + +typedef struct { + Mark anchor; + Mark cursor; +} SelectionRegion; struct Cursor { /* cursor position */ + Mark cursor; /* other selection endpoint where it changes */ + Mark anchor; /* position where the selection was created */ + bool anchored; /* whether anchor remains fixed */ size_t pos; /* in bytes from the start of the file */ int row, col; /* in terms of zero based screen coordinates */ int lastcol; /* remembered column used when moving across lines */ Line *line; /* screen line on which cursor currently resides */ - Mark mark; /* mark used to keep track of current cursor position */ - Mark mark_old; /* previous value of the mark, used to recover cursor position */ - Selection *sel; /* selection (if any) which folows the cursor upon movement */ - Mark lastsel_anchor;/* previously used selection data, */ - Mark lastsel_cursor;/* used to restore it */ int generation; /* used to filter out newly created cursors during iteration */ int number; /* how many cursors are located before this one */ + SelectionRegion region; /* saved selection region */ View *view; /* associated view to which this cursor belongs */ Cursor *prev, *next;/* previous/next cursors ordered by location at creation time */ }; @@ -86,7 +83,6 @@ struct View { const SyntaxSymbol *symbols[SYNTAX_SYMBOL_LAST]; /* symbols to use for white spaces etc */ int tabwidth; /* how many spaces should be used to display a tab character */ Cursor *cursors; /* all cursors currently active */ - Selection *selections; /* all selected regions */ int cursor_generation; /* used to filter out newly created cursors during iteration */ bool need_update; /* whether view has been redrawn */ bool large_file; /* optimize for displaying large files */ @@ -261,13 +257,12 @@ static bool view_addch(View *view, Cell *cell) { static void cursor_to(Cursor *c, size_t pos) { Text *txt = c->view->text; - c->mark_old = c->mark; - c->mark = text_mark_set(txt, pos); + c->cursor = text_mark_set(txt, pos); + if (!c->anchored) + c->anchor = c->cursor; if (pos != c->pos) c->lastcol = 0; c->pos = pos; - if (c->sel) - c->sel->cursor = text_mark_set(txt, pos); if (!view_coord_get(c->view, pos, &c->line, &c->row, &c->col)) { if (c->view->cursor == c) { c->line = c->view->topline; @@ -484,8 +479,6 @@ void view_free(View *view) { return; while (view->cursors) view_cursors_free(view->cursors); - while (view->selections) - view_selections_free(view->selections); free(view->lines); free(view); } @@ -1028,7 +1021,6 @@ bool view_cursors_dispose(Cursor *c) { View *view = c->view; if (!view->cursors || !view->cursors->next) return false; - view_selections_free(c->sel); view_cursors_free(c); view_cursors_primary_set(view->cursor); return true; @@ -1064,11 +1056,7 @@ Cursor *view_cursors_primary_get(View *view) { void view_cursors_primary_set(Cursor *c) { if (!c) return; - View *view = c->view; - view->cursor = c; - Filerange sel = view_cursors_selection_get(c); - view_cursors_to(c, view_cursors_pos(c)); - view_cursors_selection_set(c, &sel); + c->view->cursor = c; } Cursor *view_cursors_prev(Cursor *c) { @@ -1092,8 +1080,7 @@ Cursor *view_cursors_next(Cursor *c) { } size_t view_cursors_pos(Cursor *c) { - size_t pos = text_mark_get(c->view->text, c->mark); - return pos != EPOS ? pos : text_mark_get(c->view->text, c->mark_old); + return text_mark_get(c->view->text, c->cursor); } size_t view_cursors_line(Cursor *c) { @@ -1171,147 +1158,46 @@ void view_cursors_place(Cursor *c, size_t line, size_t col) { } void view_cursors_selection_start(Cursor *c) { - if (c->sel) - return; - size_t pos = view_cursors_pos(c); - if (pos == EPOS || !(c->sel = view_selections_new(c->view, c))) - return; - Text *txt = c->view->text; - c->sel->anchor = text_mark_set(txt, pos); - c->sel->cursor = c->sel->anchor; - c->view->need_update = true; -} - -void view_cursors_selection_restore(Cursor *c) { - Text *txt = c->view->text; - if (c->sel) - return; - Filerange sel = text_range_new( - text_mark_get(txt, c->lastsel_anchor), - text_mark_get(txt, c->lastsel_cursor) - ); - if (!text_range_valid(&sel)) - return; - view_cursors_to(c, sel.end); - sel.end = text_char_next(txt, sel.end); - if (!(c->sel = view_selections_new(c->view, c))) - return; - view_selections_set(c->sel, &sel); -} - -void view_cursors_selection_stop(Cursor *c) { - c->sel = NULL; + c->anchored = true; } void view_cursors_selection_clear(Cursor *c) { - view_selections_free(c->sel); + c->anchored = false; + c->anchor = c->cursor; c->view->need_update = true; } -void view_cursors_selection_swap(Cursor *c) { - if (!c->sel) - return; - view_selections_swap(c->sel); - view_cursors_selection_sync(c); -} - -void view_cursors_selection_sync(Cursor *c) { - if (!c->sel) - return; - Text *txt = c->view->text; - size_t pos = text_mark_get(txt, c->sel->cursor); - view_cursors_to(c, pos); -} - -Filerange view_cursors_selection_get(Cursor *c) { - return view_selections_get(c->sel); -} - -void view_cursors_selection_set(Cursor *c, const Filerange *r) { - if (!text_range_valid(r)) - return; - bool new = !c->sel; - if (new && !(c->sel = view_selections_new(c->view, c))) - return; - view_selections_set(c->sel, r); - if (!new) { - size_t pos = view_cursors_pos(c); - if (!text_range_contains(r, pos)) - view_cursors_selection_sync(c); - } -} - -Selection *view_selections_new(View *view, Cursor *c) { - Selection *s = calloc(1, sizeof(*s)); - if (!s) - return NULL; - s->view = view; - s->next = view->selections; - if (view->selections) - view->selections->prev = s; - view->selections = s; - s->cur = c; - return s; +void view_cursors_selection_swap(Cursor *s) { + Mark temp = s->anchor; + s->anchor = s->cursor; + s->cursor = temp; + view_cursors_to(s, text_mark_get(s->view->text, s->cursor)); } -void view_selections_free(Selection *s) { - if (!s) - return; - if (s->prev) - s->prev->next = s->next; - if (s->next) - s->next->prev = s->prev; - if (s->view->selections == s) - s->view->selections = s->next; - Cursor *c = s->cur; - if (c) { - c->lastsel_anchor = s->anchor; - c->lastsel_cursor = s->cursor; - c->sel = NULL; - } - free(s); +bool view_selection_anchored(Selection *s) { + return s->anchored; } void view_selections_clear(View *view) { - while (view->selections) - view_selections_free(view->selections); + for (Cursor *c = view->cursors; c; c = c->next) + view_cursors_selection_clear(c); view_draw(view); } void view_cursors_clear(View *view) { for (Cursor *c = view->cursors, *next; c; c = next) { next = c->next; - if (c != view->cursor) { - view_selections_free(c->sel); + if (c != view->cursor) view_cursors_free(c); - } } view_draw(view); } -void view_selections_swap(Selection *s) { - Mark temp = s->anchor; - s->anchor = s->cursor; - s->cursor = temp; -} - -Selection *view_selections(View *view) { - return view->selections; -} - -Selection *view_selections_prev(Selection *s) { - return s->prev; -} - -Selection *view_selections_next(Selection *s) { - return s->next; -} - Filerange view_selection_get(View *view) { - return view_selections_get(view->cursor->sel); + return view_cursors_selection_get(view->cursor); } -Filerange view_selections_get(Selection *s) { +Filerange view_cursors_selection_get(Selection *s) { if (!s) return text_range_empty(); Text *txt = s->view->text; @@ -1323,7 +1209,7 @@ Filerange view_selections_get(Selection *s) { return sel; } -void view_selections_set(Selection *s, const Filerange *r) { +void view_cursors_selection_set(Selection *s, const Filerange *r) { if (!text_range_valid(r)) return; Text *txt = s->view->text; @@ -1340,7 +1226,27 @@ void view_selections_set(Selection *s, const Filerange *r) { s->anchor = text_mark_set(txt, r->start); s->cursor = text_mark_set(txt, end); } - s->view->need_update = true; + s->anchored = true; + view_cursors_to(s, text_mark_get(s->view->text, s->cursor)); +} + +void view_cursors_selection_save(Selection *s) { + s->region.cursor = s->cursor; + s->region.anchor = s->anchor; +} + +bool view_cursors_selection_restore(Selection *s) { + Text *txt = s->view->text; + size_t pos = text_mark_get(txt, s->region.cursor); + if (pos == EPOS) + return false; + if (s->region.anchor != s->region.cursor && text_mark_get(txt, s->region.anchor) == EPOS) + return false; + s->cursor = s->region.cursor; + s->anchor = s->region.anchor; + s->anchored = true; + view_cursors_to(s, pos); + return true; } Text *view_text(View *view) { @@ -6,7 +6,7 @@ typedef struct View View; typedef struct Cursor Cursor; -typedef struct Selection Selection; +typedef Cursor Selection; #include "text.h" #include "ui.h" @@ -162,30 +162,20 @@ void view_cursors_place(Cursor*, size_t line, size_t col); /* start selected area at current cursor position. further cursor movements * will affect the selected region. */ void view_cursors_selection_start(Cursor*); -/* detach cursor from selection, further cursor movements will not affect - * the selected region. */ -void view_cursors_selection_stop(Cursor*); /* clear selection associated with this cursor (if any) */ void view_cursors_selection_clear(Cursor*); /* move cursor position from one end of the selection to the other */ void view_cursors_selection_swap(Cursor*); -/* move cursor to the end/boundary of the associated selection */ -void view_cursors_selection_sync(Cursor*); -/* restore previous used selection of this cursor */ -void view_cursors_selection_restore(Cursor*); /* get/set the selected region associated with this cursor */ Filerange view_cursors_selection_get(Cursor*); void view_cursors_selection_set(Cursor*, const Filerange*); -Selection *view_selections_new(View*, Cursor*); -void view_selections_free(Selection*); +void view_cursors_selection_save(Selection*); +bool view_cursors_selection_restore(Selection*); + +bool view_selection_anchored(Cursor*); + void view_selections_clear(View*); -void view_selections_swap(Selection*); -Selection *view_selections(View*); -Selection *view_selections_prev(Selection*); -Selection *view_selections_next(Selection*); -Filerange view_selections_get(Selection*); -void view_selections_set(Selection*, const Filerange*); Text *view_text(View*); /* get number of columns, that is maximal number of cursors on a line */ diff --git a/vis-prompt.c b/vis-prompt.c index a08a19f..c37f093 100644 --- a/vis-prompt.c +++ b/vis-prompt.c @@ -55,7 +55,7 @@ static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) { char *cmd = NULL; Filerange range = view_selection_get(view); - if (!text_range_valid(&range)) { + if (!vis->mode->visual) { const char *pattern = NULL; Regex *regex = text_regex_new(); size_t pos = view_cursor_get(view); @@ -245,10 +245,15 @@ void vis_window_status(Win *win, const char *status) { } void window_selection_save(Win *win) { + Vis *vis = win->vis; File *file = win->file; Filerange sel = view_cursors_selection_get(view_cursors(win->view)); file->marks[VIS_MARK_SELECTION_START] = text_mark_set(file->text, sel.start); file->marks[VIS_MARK_SELECTION_END] = text_mark_set(file->text, sel.end); + if (!vis->action.op) { + for (Selection *s = view_cursors(win->view); s; s = view_cursors_next(s)) + view_cursors_selection_save(s); + } } static void window_free(Win *win) { @@ -966,39 +971,17 @@ void vis_do(Vis *vis) { if (linewise && vis->mode != &vis_modes[VIS_MODE_VISUAL]) c.range = text_range_linewise(txt, &c.range); - if (vis->mode->visual) { + if (vis->mode->visual) view_cursors_selection_set(cursor, &c.range); - if (vis->mode == &vis_modes[VIS_MODE_VISUAL] || a->textobj) - view_cursors_selection_sync(cursor); - } if (a->op) { size_t pos = a->op->func(vis, txt, &c); if (pos == EPOS) { view_cursors_dispose(cursor); } else if (pos <= text_size(txt)) { - /* moving the cursor will affect the selection. - * because we want to be able to later restore - * the old selection we update it again before - * leaving visual mode. - */ - Filerange sel = view_cursors_selection_get(cursor); + if (vis->mode->visual) + view_cursors_selection_save(cursor); view_cursors_to(cursor, pos); - if (vis->mode->visual) { - if (sel.start == EPOS && sel.end == EPOS) - sel = c.range; - else if (sel.start == EPOS) - sel = text_range_new(c.range.start, sel.end); - else if (sel.end == EPOS) - sel = text_range_new(c.range.start, sel.start); - if (vis->mode == &vis_modes[VIS_MODE_VISUAL_LINE]) - sel = text_range_linewise(txt, &sel); - if (!text_range_contains(&sel, pos)) { - Filerange cur = text_range_new(pos, pos); - sel = text_range_union(&sel, &cur); - } - view_cursors_selection_set(cursor, &sel); - } } } } |
