]> git.neil.brown.name Git - edlib.git/commitdiff
use new notifiers to notify changes to render-lines.
authorNeilBrown <neil@brown.name>
Fri, 11 Dec 2015 04:21:30 +0000 (15:21 +1100)
committerNeilBrown <neil@brown.name>
Fri, 11 Dec 2015 04:21:30 +0000 (15:21 +1100)
Signed-off-by: NeilBrown <neil@brown.name>
core-doc.c
core-mark.c
core.h
render-lines.c

index f25e1f48b794e012da5cecb8fdd060b4371a91b9..9493969b984f2f5b6dca08df0b516f2cfdba8386 100644 (file)
@@ -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);
        }
index 6b5506fcc3819335b6f04e82d4f1c261ed784a99..cf81a33ee6e6ddf48e4b4cf9f97fdbd53df52a35 100644 (file)
@@ -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 19c5c0de231d87c2817039a023db11b990fd70fe..a614608c17fbbfa9b15e36343dcf30e801b2d4c6 100644 (file)
--- 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)
index 096ef938065586bf5e2b0f4579e22c181905612e..ff4470ed3839bf2652301ad3a0b39ccaa0542c4d 100644 (file)
@@ -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);