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);
}
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;
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.
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;
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;
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)
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;
}
/* 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)
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);