key_handle should be used most often.
It uses the focus given, but moves 'home' out to a leaf and
searches in from there.
key_handle_filter should be used only when calling a function with
the same name as self. It uses focus and home as given and
only searches home towards root
key_handle_focus should be used when simulting keyboard input. It
moves focus out to a leaf, and then sets home from there.
key_handle_xy should be used when simulatiing mouse input. it follows
focus out to a root tracking x,y and starts home from there.
key_handle_focus and key_handle_xy also pick-up ->point if it is set on
any pane on the way out.
Signed-off-by: NeilBrown <neil@brown.name>
ci2.focus = p;
ci2.extra = -1;
ci2.misc = &stb;
- if (key_handle_focus(&ci2) > 0)
+ if (key_handle(&ci2) > 0)
return p;
}
cr.c = doc_str_callback;
cr.s = NULL;
ci.comm2 = &cr.c;
- ret = key_handle_focus(&ci);
+ ret = key_handle(&ci);
if (!ret)
return NULL;
return cr.s;
return key_lookup(*l->m, ci);
}
-int key_handle(const struct cmd_info *ci)
+/* key_handle_filter is simplest. It just searches towards root for the pane
+ * which handles the command.
+ */
+int key_handle_filter(const struct cmd_info *ci)
{
struct cmd_info *vci = (struct cmd_info*)ci;
struct pane *p;
- int ret = 0;
if (ci->comm)
return ci->comm->func(ci);
if (!p)
p = ci->focus;
- while (ret == 0 && p) {
+ while (p) {
+ int ret = 0;
if (p->handle) {
vci->home = p;
vci->comm = p->handle;
}
if (ret)
/* 'p' might have been destroyed */
- break;
+ return ret;
p = p->parent;
}
- return ret;
+ return 0;
}
-static int __key_handle_focus(struct cmd_info *ci, int savepoint)
+/* key_handle move 'home' out to a leaf and searches from there */
+int key_handle(const struct cmd_info *ci)
+{
+ struct pane *p;
+ if (ci->comm)
+ return ci->comm->func(ci);
+ p = ci->home;
+ if (!p)
+ p = ci->focus;
+ while (p->focus)
+ p = p->focus;
+ ((struct cmd_info*)ci)->home = p;
+ return key_handle_filter(ci);
+}
+
+int key_handle_focus(struct cmd_info *ci)
{
- /* Handle this in the focus pane, so x,y are irrelevant */
struct pane *p = ci->home;
if (!p)
p = ci->focus;
if (!p)
return -1;
+ /* Handle this in the focus pane, so x,y are irrelevant */
ci->x = -1;
ci->y = -1;
while (p->focus) {
p = p->focus;
- if (savepoint && p->pointer)
+ if (!ci->mark)
ci->mark = p->pointer;
}
- if (!ci->home || !ci->focus)
- ci->focus = p;
+ ci->focus = p;
ci->home = p;
ci->comm = NULL;
return key_handle(ci);
}
-int key_handle_focus(struct cmd_info *ci)
-{
- return __key_handle_focus(ci, 0);
-}
-
-int key_handle_focus_point(struct cmd_info *ci)
-{
- int ret = __key_handle_focus(ci, 1);
- if (ret < 0)
- call5("Message", ci->focus, 0, NULL, "** Command Failed **", 1);
- return ret;
-}
-
-static int __key_handle_xy(struct cmd_info *ci, int savepoint)
+int key_handle_xy(struct cmd_info *ci)
{
/* Handle this in child with x,y co-ords */
- struct pane *p = ci->focus;
+ struct pane *p = ci->home;
int x = ci->x;
int y = ci->y;
+ if (!p)
+ p = ci->focus;
while (1) {
struct pane *t, *chld = NULL;
x -= chld->x;
y -= chld->y;
p = chld;
- if (savepoint && p->pointer)
+ if (!ci->mark)
ci->mark = p->pointer;
}
ci->x = x;
ci->y = y;
ci->focus = p;
+ ci->home = p;
ci->comm = NULL;
return key_handle(ci);
}
-
-int key_handle_xy(struct cmd_info *ci)
-{
- return __key_handle_xy(ci, 0);
-}
-int key_handle_xy_point(struct cmd_info *ci)
-{
- return __key_handle_xy(ci, 1);
-}
ci->mark = m1;
ci->mark2 = m2;
ci->focus = p;
- return key_handle_focus(ci) == 1;
+ return key_handle(ci) == 1;
}
/* A 'vmark' is a mark in a particular view. We can walk around those
ci.extra = 1;
else if (new)
ci.extra = 2;
- if (key_handle_focus(&ci) == 0)
+ if (key_handle(&ci) == 0)
return 0;
if (first)
*first = cr.m;
cr.c = take_marks;
cr.m = cr.m2 = NULL;
ci.comm2 = &cr.c;
- if (key_handle_focus(&ci) == 0)
+ if (key_handle(&ci) == 0)
return NULL;
return cr.m2;
}
cr.c = take_pane;
cr.p = NULL;
ci.comm2 = &cr.c;
- if (!key_handle_focus(&ci))
+ if (!key_handle(&ci))
return NULL;
return cr.p;
}
struct map *key_alloc(void);
void key_free(struct map *m);
+int key_handle_filter(const struct cmd_info *ci);
int key_handle(const struct cmd_info *ci);
int key_handle_focus(struct cmd_info *ci);
int key_handle_xy(struct cmd_info *ci);
-int key_handle_focus_point(struct cmd_info *ci);
-int key_handle_xy_point(struct cmd_info *ci);
int key_lookup(struct map *m, const const struct cmd_info *ci);
struct command *key_lookup_cmd(struct map *m, char *c);
void key_add(struct map *map, char *k, struct command *comm);
ci.str = str;
ci.extra = *first;
ci.numeric = 1;
- ret = key_handle_focus(&ci);
+ ret = key_handle(&ci);
if (ret == 1)
*first = 1;
}
ci.focus = p;
ci.numeric = redo ? 1 : 0;
ci.key = "doc:reundo";
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int doc_load_file(struct pane *p, int fd, char *name)
{
ci.extra = fd;
ci.str = name;
ci.key = "doc:load-file";
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int doc_set_attr(struct pane *p, struct mark *pt,
ci.mark = pt;
ci.str = attr;
ci.str2 = val;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
ci.key = "doc:add-view";
ci.comm2 = c;
ci.extra = size;
- ret = key_handle_focus(&ci);
+ ret = key_handle(&ci);
if (ret <= 0)
return -1;
return ret - 1;
ci.focus = p;
ci.key = "doc:del-view";
ci.comm2 = c;
- key_handle_focus(&ci);
+ key_handle(&ci);
}
static inline int doc_find_view(struct pane *p, struct command *c)
ci.focus = p;
ci.key = "doc:find-view";
ci.comm2 = c;
- ret = key_handle_focus(&ci);
+ ret = key_handle(&ci);
if (ret <= 0)
return -1;
return ret - 1;
ci.focus = focus;
ci.numeric = numeric;
ci.mark = m;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int call_home(struct pane *home, char *key, struct pane *focus,
ci.numeric = numeric;
ci.mark = m;
ci.comm2 = comm;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int call5(char *key, struct pane *focus, int numeric, struct mark *m,
ci.mark = m;
ci.str = str;
ci.extra = extra;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int call7(char *key, struct pane *focus, int numeric, struct mark *m,
ci.str = str;
ci.str2 = str2;
ci.extra = extra;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
struct call_return {
ci.str = str;
ci.extra = extra;
ci.comm2 = comm;
- return key_handle_focus(&ci);
+ return key_handle(&ci);
}
static inline int comm_call(struct command *comm, char *key, struct pane *focus,
ci.focus = p;
ci.x = x;
ci.y = y;
- key_handle_xy(&ci);
+ key_handle(&ci);
}
static void send_mouse(MEVENT *mev, struct pane *p)
char *ret;
int l = 0, head, tail;
- if (ci->mark) {
+ if (ci->mark && ci->mark2) {
if (mark_ordered(ci->mark2, ci->mark)) {
from = ci->mark2;
to = ci->mark;
struct cmd_info ci2 = {0};
struct input_mode *im = ci->home->data;
int l;
+ int ret;
l = strlen(im->mode) + strlen(ci->str) + 1;
ci2.key = malloc(l);
im->mode = "";
im->numeric = NO_NUMERIC;
im->extra = 0;
- key_handle_focus_point(&ci2);
+ ret = key_handle_focus(&ci2);
free(ci2.key);
+ if (ret < 0)
+ call5("Message", ci2.focus, 0, NULL, "** Command Failed **", 1);
return 0;
}
im->numeric = NO_NUMERIC;
im->extra = 0;
- key_handle_xy_point(&ci2);
+ key_handle_xy(&ci2);
return 0;
}
if (ppi->doc)
ci2.str = doc_getstr(ppi->popup, NULL);
ci2.mark = NULL;
- key_handle_focus(&ci2);
+ key_handle(&ci2);
if (ppi->doc)
free(ci2.str);
d = ppi->doc; ppi->doc = NULL;
ci2.numeric = ci->numeric;
ci2.extra = ci->extra;
ci2.mark = ci->mark;
- return key_handle_focus(&ci2);
+ return key_handle(&ci2);
}
DEF_CMD(popup_attach)
ci2.focus = p;
ci2.str = "popup:quote";
ci2.str2 = "Return";
- key_handle_focus(&ci2);
+ key_handle(&ci2);
ci2.str2 = "Abort";
- key_handle_focus(&ci2);
+ key_handle(&ci2);
return comm_call(ci->comm2, "callback:attach", ppi->popup, 0, NULL, NULL, 0);
}
ci2.numeric = ci->numeric;
ci2.extra = ci->extra;
ci2.mark = ci->mark;
- return key_handle_focus(&ci2);
+ return key_handle(&ci2);
}
DEF_CMD(emacs_insert)
ci2.focus = p;
ci2.str = "emacs:file-complete";
ci2.str2 = "Tab";
- key_handle_focus(&ci2);
+ key_handle(&ci2);
return 1;
}
cr.c = save_str;
cr.s = NULL;
ci2.comm2 = &cr.c;
- ret = key_handle_focus(&ci2);
+ ret = key_handle(&ci2);
free(d);
if (cr.s && (strlen(cr.s) <= strlen(b) && ret-1 > 1)) {
/* We need the dropdown */
ci2.focus = p;
ci2.str = "emacs:doc-complete";
ci2.str2 = "Tab";
- key_handle_focus(&ci2);
+ key_handle(&ci2);
return 1;
}
cr.c = save_str;
cr.s = NULL;
ci2.comm2= &cr.c;
- ret = key_handle_focus(&ci2);
+ ret = key_handle(&ci2);
if (cr.s && (strlen(cr.s) <= strlen(str) && ret - 1 > 1)) {
/* We need the dropdown */
pane_damaged(par, DAMAGED_CONTENT);
ci2.str = "Search String";
ci2.str2 = ci->str;
ci2.focus = ci->home;
- key_handle_focus(&ci2);
+ key_handle(&ci2);
memset(&ci2, 0, sizeof(ci2));
ci2.focus = ci->home;
cr.i = plen;
cr.s = NULL;
ci2.comm2 = &cr.c;
- if (key_handle(&ci2) == 0)
+ if (key_handle_filter(&ci2) == 0)
return 0;
ret = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL, cr.s, 0);
cb.prefix = cd->prefix;
cb.cmp = 0;
ci2.comm2 = &cb.c;
- key_handle(&ci2);
+ key_handle_filter(&ci2);
if (cb.cmp == 0)
break;
cb.plen = strlen(cb.prefix);
ci3.comm2 = &cb.c;
while (1) {
- ret = key_handle(&ci2);
+ ret = key_handle_filter(&ci2);
if (ret <= 0 || ci->numeric == 0)
/* Either hit start-of-file, or have what we need */
break;
ci3.numeric = NO_NUMERIC;
cb.keep = ci2.numeric == 1 && ci->extra == 42;
cb.str = NULL;
- if (key_handle(&ci3) != 1) {
+ if (key_handle_filter(&ci3) != 1) {
mark_free(ci3.mark);
break;
}
ci2.focus = ci->home->parent;
ci2.str = cr.s + strlen(cd->prefix);
ci2.numeric = NO_NUMERIC;
- key_handle(&ci2);
+ key_handle_filter(&ci2);
free(cr.s);
return 1;
}
ci.mark = m;
ci.focus = p;
ci.numeric = n;
- ret = key_handle_focus(&ci);
+ ret = key_handle(&ci);
if (ret == 0) {
mark_free(m);
return NULL;
* 'used' can be negative if the mark is before the start
* of the pane
*/
- if (key_handle_focus(&ci) == 0) {
+ if (key_handle(&ci) == 0) {
mark_free(ci.mark);
return NULL;
}
ci.mark = mark_dup(start, 0);
ci.numeric = offset;
ci.comm2 = &no_save;
- if (key_handle_focus(&ci) == 0) {
+ if (key_handle(&ci) == 0) {
mark_free(ci.mark);
return NULL;
}
ci.mark = mark_dup(start, 0);
ci.numeric = -1;
ci.comm2 = &get_len;
- len = key_handle_focus(&ci);
+ len = key_handle(&ci);
if (len <= 0) {
mark_free(ci.mark);
return 0;
else
ci2.numeric += 1;
ci2.mark = ci->mark;
- if (!key_handle_focus(&ci2))
+ if (!key_handle(&ci2))
return -1;
if (RPT_NUM(ci) > 0) {
/* at end of target line, move to start */
ci2.numeric = -1;
- if (!key_handle_focus(&ci2))
+ if (!key_handle(&ci2))
return -1;
}