From: NeilBrown Date: Fri, 11 Dec 2015 04:21:30 +0000 (+1100) Subject: use new notifiers to notify changes to render-lines. X-Git-Tag: lca2016~57 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=68e4f5e8f707fdad921b4cbd14e7d782a1776a4f;p=edlib.git use new notifiers to notify changes to render-lines. Signed-off-by: NeilBrown --- diff --git a/core-doc.c b/core-doc.c index f25e1f48..9493969b 100644 --- a/core-doc.c +++ b/core-doc.c @@ -488,6 +488,8 @@ DEF_CMD(doc_handle) ci->numeric); if (ci->extra == 2) m2 = doc_new_mark(dd->doc, ci->numeric); + if (ci->extra == 3) + m2 = do_vmark_at_or_before(dd->doc, ci->mark, ci->numeric); return comm_call7(ci->comm2, "callback:vmark", ci->focus, 0, m, NULL, 0, NULL, m2); } diff --git a/core-mark.c b/core-mark.c index 6b5506fc..cf81a33e 100644 --- a/core-mark.c +++ b/core-mark.c @@ -913,6 +913,24 @@ struct mark *vmark_at_point(struct pane *p, int view) return point; } +struct mark *vmark_at_or_before(struct pane *p, struct mark *m, int view) +{ + struct cmd_info ci = {0}; + struct call_return cr; + + ci.key = "doc:vmark-get"; + ci.focus = p; + ci.numeric = view; + ci.extra = 3; + ci.mark = m; + cr.c = take_marks; + cr.m = cr.m2 = NULL; + ci.comm2 = &cr.c; + if (key_handle_focus(&ci) == 0) + return NULL; + return cr.m2; +} + struct mark *vmark_new(struct pane *p, int view) { struct mark *new = NULL; @@ -952,6 +970,40 @@ struct mark *do_vmark_at_point(struct doc *d, struct mark *pt, int view) return NULL; } +struct mark *do_vmark_at_or_before(struct doc *d, struct mark *m, int view) +{ + struct mark *vm = m; + + /* might need to hunt along 'all' list for something suitable */ + while (vm && vm->viewnum != MARK_POINT && vm->viewnum != view) + vm = doc_next_mark_all(vm); + if (!vm) { + vm = m; + while (vm && vm->viewnum != MARK_POINT && vm->viewnum != view) + vm = doc_prev_mark_all(vm); + } + if (vm->viewnum == MARK_POINT) { + struct point_links *lnk = vm->mdata; + struct tlist_head *tl = &lnk->lists[view]; + vm = __vmark_next(tl); + if (vm && mark_same(d, vm, m)) { + /* maybe there are even more */ + struct mark *vm2; + while ((vm2 = vmark_next(vm)) != NULL && + mark_same(d, vm, vm2)) + vm = vm2; + } else + vm = __vmark_prev(tl); + } else if (vm->viewnum == view) { + /* Just use this, or nearby */ + struct mark *vm2; + while ((vm2 = vmark_next(vm)) != NULL && + mark_same(d, vm, vm2)) + vm = vm2; + } + return vm; +} + static void point_notify_change(struct doc *d, struct mark *p, struct mark *m) { /* Notify of changes from m (might be NULL) to p. @@ -963,7 +1015,6 @@ static void point_notify_change(struct doc *d, struct mark *p, struct mark *m) int i; struct point_links *lnk = p->mdata; - pane_notify(d->home, "Notify:Replace", p, m); ci.key = "Notify:Replace"; ci.numeric = 1; ci.x = ci.y = -1; @@ -1021,6 +1072,8 @@ void doc_notify_change(struct doc *d, struct mark *m, struct mark *m2) int i; int remaining = d->nviews; + pane_notify(d->home, "Notify:Replace", m, m2); + if (m->viewnum == MARK_POINT) { point_notify_change(d, m, m2); return; diff --git a/core.h b/core.h index 19c5c0de..a614608c 100644 --- a/core.h +++ b/core.h @@ -202,9 +202,11 @@ struct mark *do_vmark_first(struct doc *d, int view); struct mark *do_vmark_last(struct doc *d, int view); struct mark *vmark_matching(struct pane *p, struct mark *m); struct mark *do_vmark_at_point(struct doc *d, struct mark *pt, int view); +struct mark *do_vmark_at_or_before(struct doc *d, struct mark *m, int view); struct mark *vmark_first(struct pane *p, int view); struct mark *vmark_last(struct pane *p, int view); struct mark *vmark_at_point(struct pane *p, int view); +struct mark *vmark_at_or_before(struct pane *p, struct mark *m, int view); struct mark *vmark_new(struct pane *p, int view); static inline int mark_ordered(struct mark *m1, struct mark *m2) diff --git a/render-lines.c b/render-lines.c index 096ef938..ff4470ed 100644 --- a/render-lines.c +++ b/render-lines.c @@ -862,43 +862,47 @@ DEF_CMD(render_lines_move_line) DEF_CMD(render_lines_notify) { - struct rl_data *rl = container_of(ci->comm, struct rl_data, type); - - if (strcmp(ci->key, "Notify:Replace") == 0) { - if (ci->mark) { - struct mark *rm = ci->mark; - struct mark *vm; - struct cmd_info ci2 = {0}; - struct pane *p = rl->pane; - - if (rm->mdata) { - free(rm->mdata); - rm->mdata = NULL; - } - /* If an adjacent mark is for the same location, - * delete it - marks must remain distinct - */ - while ((vm = vmark_prev(rm)) != NULL && - mark_same_pane(p, rm, vm, &ci2)) { - free(vm->mdata); - vm->mdata = NULL; - mark_free(vm); - } - while ((vm = vmark_next(rm)) != NULL && mark_same_pane(p, rm, vm, &ci2)) { - free(vm->mdata); - vm->mdata = NULL; - mark_free(vm); - } - pane_damaged(rl->pane, DAMAGED_CONTENT); - } + return 1; +} + +DEF_CMD(render_lines_notify_replace) +{ + struct rl_data *rl = ci->home->data; + struct mark *start = ci->mark2; + struct mark *end, *t; + struct pane *p = ci->home; + + if (!start) + start = ci->mark; + if (!ci->mark) return 1; - } - if (strcmp(ci->key, "Release") == 0) { - if (rl->pane) - pane_close(rl->pane); + + end = vmark_at_or_before(ci->home, ci->mark, rl->typenum); + + if (!end) + /* Change before visible region */ return 1; + + t = end; + while (t && mark_ordered_or_same_pane(p, start, t)) { + struct mark *t2; + if (t->mdata) { + free(t->mdata); + t->mdata = NULL; + } + t2 = doc_prev_mark_view(t); + if (t2 && mark_same_pane(p, t, t2, NULL)) + /* Marks must be distinct! */ + mark_free(t); + t = t2; } - return 0; + if (t && t->mdata) { + free(t->mdata); + t->mdata = NULL; + } + pane_damaged(rl->pane, DAMAGED_CONTENT); + + return 1; } @@ -957,6 +961,8 @@ static void render_lines_register_map(void) /* force full refresh */ key_add(rl_map, "render-lines:redraw", &render_lines_redraw); + + key_add(rl_map, "Notify:Replace", &render_lines_notify_replace); } REDEF_CMD(render_lines_attach) @@ -978,6 +984,7 @@ REDEF_CMD(render_lines_attach) rl->type = render_lines_notify; rl->typenum = doc_add_view(ci->focus, &rl->type, 0); rl->pane = pane_register(ci->focus, 0, &render_lines_handle.c, rl, NULL); + call3("Request:Notify:Replace", rl->pane, 0, NULL); return comm_call(ci->comm2, "callback:attach", rl->pane, 0, NULL, NULL, 0);