diff options
| -rw-r--r-- | array.c | 18 | ||||
| -rw-r--r-- | array.h | 21 | ||||
| -rw-r--r-- | test/core/array-test.c | 8 | ||||
| -rw-r--r-- | vis-core.h | 14 | ||||
| -rw-r--r-- | vis-marks.c | 108 | ||||
| -rw-r--r-- | vis.c | 8 | ||||
| -rw-r--r-- | vis.h | 6 |
7 files changed, 41 insertions, 142 deletions
@@ -141,21 +141,3 @@ void array_sort(Array *arr, int (*compar)(const void*, const void*)) { if (arr->items) qsort(arr->items, arr->len, arr->elem_size, compar); } - -bool array_push(Array *arr, void *item) { - return array_add(arr, item); -} - -void *array_pop(Array *arr) { - void *item = array_peek(arr); - if (!item) - return NULL; - arr->len--; - return item; -} - -void *array_peek(const Array *arr) { - if (arr->len == 0) - return NULL; - return array_get(arr, arr->len - 1); -} @@ -101,26 +101,5 @@ VIS_INTERNAL bool array_resize(Array*, size_t length); * Sort array, the comparision function works as for `qsort(3)`. */ VIS_INTERNAL void array_sort(Array*, int (*compar)(const void*, const void*)); -/** - * Push item onto the top of the stack. - * @rst - * .. note:: Is equivalent to ``array_add(arr, item)``. - * @endrst - */ -VIS_INTERNAL bool array_push(Array*, void *item); -/** - * Get and remove item at the top of the stack. - * @rst - * .. warning:: The same ownership rules as for ``array_get`` apply. - * @endrst - */ -VIS_INTERNAL void *array_pop(Array*); -/** - * Get item at the top of the stack without removing it. - * @rst - * .. warning:: The same ownership rules as for ``array_get`` apply. - * @endrst - */ -VIS_INTERNAL void *array_peek(const Array*); #endif diff --git a/test/core/array-test.c b/test/core/array-test.c index 5944904..77d9d36 100644 --- a/test/core/array-test.c +++ b/test/core/array-test.c @@ -22,8 +22,6 @@ static void test_small_objects(void) { ok(arr.len == 0, "Initialization"); ok(!array_set(&arr, 0, NULL) && errno == EINVAL, "Set with invalid index"); ok(array_get(&arr, 0) == NULL && errno == EINVAL, "Get with invalid index"); - ok(array_peek(&arr) == NULL && arr.len == 0, "Peek empty array"); - ok(array_pop(&arr) == NULL && arr.len == 0, "Pop empty array"); for (size_t i = 0; i < len; i++) { int *v; @@ -44,11 +42,6 @@ static void test_small_objects(void) { "Get array element: %zu = %d", i, *v); } - int *v; - ok((v = array_peek(&arr)) && *v == values[0] && arr.len == len, "Peek populated array"); - ok((v = array_pop(&arr)) && *v == values[0] && arr.len == len-1, "Pop populated array"); - ok((v = array_peek(&arr)) && *v == values[1] && arr.len == len-1, "Peek after pop"); - array_clear(&arr); ok(arr.len == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear"); @@ -66,6 +59,7 @@ static void test_small_objects(void) { ok(!array_remove(&arr, arr.len) && errno == EINVAL, "Remove past end of array"); + int *v; size_t len_before = arr.len; ok(array_remove(&arr, 2) && arr.len == len_before-1 && (v = array_get(&arr, 0)) && *v == values[0] && @@ -131,12 +131,6 @@ typedef struct { enum SamError error; /* non-zero in case something went wrong */ } Transcript; -typedef struct { - Array prev; - Array next; - size_t max; -} MarkList; - struct File { /* shared state among windows displaying the same file */ Text *text; /* data structure holding the file content */ const char *name; /* file name used when loading/saving */ @@ -161,12 +155,15 @@ struct Win { bool expandtab; /* whether typed tabs should be converted to spaces in this window*/ Vis *vis; /* editor instance to which this window belongs */ File *file; /* file being displayed in this window */ - MarkList jumplist; /* LRU jump management */ Array saved_selections; /* register used to store selections */ Mode modes[VIS_MODE_INVALID]; /* overlay mods used for per window key bindings */ Win *parent; /* window which was active when showing the command prompt */ Mode *parent_mode; /* mode which was active when showing the command prompt */ Win *prev, *next; /* neighbouring windows */ + + /* Jumplist LRU */ + size_t mark_set_lru_cursor; + Array mark_set_lru[32]; }; struct Vis { @@ -283,9 +280,6 @@ VIS_INTERNAL void register_release(Register*); VIS_INTERNAL void mark_init(Array*); VIS_INTERNAL void mark_release(Array*); -VIS_INTERNAL void marklist_init(MarkList*, size_t max); -VIS_INTERNAL void marklist_release(MarkList*); - VIS_INTERNAL const char *register_get(Vis*, Register*, size_t *len); VIS_INTERNAL const char *register_slot_get(Vis*, Register*, size_t slot, size_t *len); diff --git a/vis-marks.c b/vis-marks.c index 6d63877..a44e727 100644 --- a/vis-marks.c +++ b/vis-marks.c @@ -104,115 +104,61 @@ void vis_mark_set(Win *win, enum VisMark id, Array *sel) { mark_set(win, mark_from(win->vis, id), sel); } -void marklist_init(MarkList *list, size_t max) { - Array mark; - mark_init(&mark); - array_init_sized(&list->prev, sizeof(Array)); - array_reserve(&list->prev, max); - array_add(&list->prev, &mark); - array_init_sized(&list->next, sizeof(Array)); - array_reserve(&list->next, max); -} - -void marklist_release(MarkList *list) { - for (size_t i = 0, len = list->prev.len; i < len; i++) - array_release(array_get(&list->prev, i)); - array_release(&list->prev); - for (size_t i = 0, len = list->next.len; i < len; i++) - array_release(array_get(&list->next, i)); - array_release(&list->next); -} - -static bool marklist_push(Win *win, MarkList *list, Array *sel) { - Array *top = array_peek(&list->prev); - if (top) { +void vis_jumplist_save(Vis *vis) +{ + Win *win = vis->win; + Array sel = view_selections_get_all(&win->view); + Array *top = win->mark_set_lru + (win->mark_set_lru_cursor % LENGTH(win->mark_set_lru)); + bool done = false; + if (top->len) { Array top_sel = mark_get(win, top); - bool eq = vis_mark_equal(&top_sel, sel); + /* NOTE: avoid pushing duplicate sets into cache */ + done = vis_mark_equal(&top_sel, &sel); array_release(&top_sel); - if (eq) - return true; } - for (size_t i = 0, len = list->next.len; i < len; i++) - array_release(array_get(&list->next, i)); - array_clear(&list->next); - Array arr; - mark_init(&arr); - if (list->prev.len >= list->prev.count) { - Array *tmp = array_get(&list->prev, 0); - arr = *tmp; - array_remove(&list->prev, 0); + if (!done) { + Array *arr = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); + mark_set(win, arr, &sel); } - mark_set(win, &arr, sel); - return array_push(&list->prev, &arr); -} -bool vis_jumplist_save(Vis *vis) { - Array sel = view_selections_get_all(&vis->win->view); - bool ret = marklist_push(vis->win, &vis->win->jumplist, &sel); array_release(&sel); - return ret; } -static bool marklist_prev(Win *win, MarkList *list) { +void vis_jumplist_prev(Vis *vis) +{ + Win *win = vis->win; View *view = &win->view; - bool restore = false; Array cur = view_selections_get_all(view); bool anchored = view_selections_primary_get(view)->anchored; - Array *top = array_peek(&list->prev); - if (!top) - goto out; - Array top_sel = mark_get(win, top); - restore = !vis_mark_equal(&top_sel, &cur); - if (restore) - view_selections_set_all(view, &top_sel, anchored); - array_release(&top_sel); - if (restore) - goto out; - - while (list->prev.len > 1) { - Array *prev = array_pop(&list->prev); - array_push(&list->next, prev); - prev = array_peek(&list->prev); - Array sel = mark_get(win, prev); - restore = sel.len > 0; - if (restore) + + Array *top = win->mark_set_lru + (--win->mark_set_lru_cursor % LENGTH(win->mark_set_lru)); + if (top->len) { + Array sel = mark_get(win, top); + if (!vis_mark_equal(top, &cur)) { view_selections_set_all(view, &sel, anchored); + } array_release(&sel); - if (restore) - goto out; } -out: array_release(&cur); - return restore; } -static bool marklist_next(Win *win, MarkList *list) { +void vis_jumplist_next(Vis *vis) +{ + Win *win = vis->win; View *view = &win->view; bool anchored = view_selections_primary_get(view)->anchored; - for (;;) { - Array *next = array_pop(&list->next); - if (!next) - return false; + Array *next = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); + + if (next->len) { Array sel = mark_get(win, next); if (sel.len > 0) { view_selections_set_all(view, &sel, anchored); array_release(&sel); - array_push(&list->prev, next); - return true; } - array_release(next); } } -bool vis_jumplist_prev(Vis *vis) { - return marklist_prev(vis->win, &vis->win->jumplist); -} - -bool vis_jumplist_next(Vis *vis) { - return marklist_next(vis->win, &vis->win->jumplist); -} - enum VisMark vis_mark_from(Vis *vis, char mark) { if (mark >= 'a' && mark <= 'z') return VIS_MARK_a + mark - 'a'; @@ -204,7 +204,8 @@ static void window_free(Win *win) { view_free(&win->view); for (size_t i = 0; i < LENGTH(win->modes); i++) map_free(win->modes[i].bindings); - marklist_release(&win->jumplist); + for (int i = 0; i < LENGTH(win->mark_set_lru); i++) + free(win->mark_set_lru[i].items); mark_release(&win->saved_selections); free(win); } @@ -383,7 +384,10 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { window_free(win); return NULL; } - marklist_init(&win->jumplist, 32); + + for (int i = 0; i < LENGTH(win->mark_set_lru); i++) + win->mark_set_lru[i].elem_size = sizeof(SelectionRegion); + mark_init(&win->saved_selections); file->refcount++; win_options_set(win, win->options); @@ -960,17 +960,17 @@ VIS_EXPORT void vis_mark_normalize(Array *array); * Add selections of focused window to jump list. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_save(Vis*); +VIS_EXPORT void vis_jumplist_save(Vis*); /** * Navigate jump list backwards. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_prev(Vis*); +VIS_EXPORT void vis_jumplist_prev(Vis*); /** * Navigate jump list forwards. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_next(Vis*); +VIS_EXPORT void vis_jumplist_next(Vis*); /** @} */ /* |
