]> git.neil.brown.name Git - edlib.git/commitdiff
Ensure we never call anything after "Close".
authorNeilBrown <neil@brown.name>
Fri, 8 Sep 2023 12:27:34 +0000 (22:27 +1000)
committerNeilBrown <neil@brown.name>
Fri, 8 Sep 2023 23:51:39 +0000 (09:51 +1000)
The only valid commands on a close pane are "Close", "Close:mark", and
"Notify:Close" and these are always pane_call.  So blocks all other
calls on DAMAGED_CLOSED panes, and block even these on DAMAGED_DEAD.

Note that "Free" is also allowed, but will soon be gone.

This requires that home_comm_call() must be supported so that a comm can
be called with a recently-closed pane as the focus (assuming it won't be
dereferenced).

Signed-off-by: NeilBrown <neil@brown.name>
core-keymap.c
core-pane.h
core.h
lib-libevent.c

index c2b6e492ae9932a507575aa716d0b3d7670fd858..d766953ed122b10960586ae51e9dbc9588a74a76 100644 (file)
@@ -558,7 +558,7 @@ int key_handle(const struct cmd_info *ci safe)
 
        while (p) {
                int ret = Efallthrough;
-               if (p->handle && !(p->damaged & DAMAGED_DEAD)) {
+               if (p->handle && !(p->damaged & DAMAGED_CLOSED)) {
                        vci->home = p;
                        vci->comm = p->handle;
                        /* Don't add this to the call stack as it
index e1d1b99db9ee1f016c9564700f8b9613cbe004e3..87f114ec613c005206acb33188ddb7d2ed12170a 100644 (file)
@@ -131,6 +131,14 @@ static inline int do_call_val(enum target_type type, struct pane *home,
                        return Efail;
                if (home)
                        ci.home = home;
+               if ((home->damaged & DAMAGED_CLOSED) &&
+                   strncmp(ci.key, "Close", 5) != 0 &&
+                   strcmp(ci.key, "Notify:Close") != 0 &&
+                   strcmp(ci.key, "Free") != 0)
+                       /* This pane cannot accept anything but
+                        * "Close" or "Close:mark" or "Free"
+                        */
+                       return Efail;
                ci.comm = home->handle;
                ret = ci.comm->func(&ci);
                break;
@@ -139,6 +147,8 @@ static inline int do_call_val(enum target_type type, struct pane *home,
                        return Efail;
                if (home)
                        ci.home = home;
+               if (ci.home->damaged & DAMAGED_CLOSED)
+                       return Efail;
                ci.comm = comm2a;
                ci.comm2 = comm2b;
                ret = ci.comm->func(&ci);
diff --git a/core.h b/core.h
index 12a19116285348e971a97b3cd5504833c1b54a23..a60b939f3bfe4d40eaa6e5ea0c706904e110d4c4 100644 (file)
--- a/core.h
+++ b/core.h
@@ -685,39 +685,44 @@ char *do_call_strsave(enum target_type type, struct pane *home,
 #define _doCALL(...) VFUNC(CALL, __VA_ARGS__)
 #define CALL15(ret, t_type, target, key, comm2a, focus, num, mark, str,        \
               num2, mark2, str2, x, y, comm2) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2,target), \
                      key, focus, num, mark, str, num2, mark2, str2, x, y, comm2)
 #define CALL14(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2, x, y) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, str, num2, mark2, str2, x, y, NULL)
 #define CALL12(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, str, num2, mark2, str2, 0, 0, NULL)
 #define CALL11(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, str, num2, mark2, NULL, 0, 0, NULL)
 #define CALL10(ret, t_type, target, key, comm2a, focus, num, mark, str, num2) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, str, num2, NULL, NULL, 0, 0, NULL)
 #define CALL9(ret, t_type, target, key, comm2a, focus, num, mark, str) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, str, 0, NULL, NULL, 0, 0, NULL)
 #define CALL8(ret, t_type, target, key, comm2a, focus, num, mark) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, mark, NULL, 0, NULL, NULL, 0, 0, NULL)
 #define CALL7(ret, t_type, target, key, comm2a, focus, num) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, num, NULL, NULL, 0, NULL, NULL, 0, 0, NULL)
 #define CALL6(ret, t_type, target, key, comm2a, focus) \
-       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \
+       do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, comm2a), CH(T_##t_type,comm2a,target), \
                      key, focus, 0, NULL, NULL, 0, NULL, NULL, 0, 0, NULL)
 
 #define CALL(ret, t_type, target, key, ...) _doCALL(ret, t_type, target, key, NULL, __VA_ARGS__)
 
 #define call(key, _focus, ...) CALL(val, focus, _focus, key, _focus, ##__VA_ARGS__)
-/* comm_call() is only for callbacks, is it doesn't allow a separate 'home' */
+/* comm_call() is only for callbacks
+ * home_comm_call must be used if the focus must be closed already.
+ */
 #define comm_call(_comm, key, ...) CALL(val, comm, _comm, key, ##__VA_ARGS__)
+#define home_comm_call(_home, _comm, key, ...) _doCALL(val, comm, _comm, key, _home, __VA_ARGS__)
+
 #define comm_call_ret(_ret, _comm, key, ...) CALL(_ret, comm, _comm, key, ##__VA_ARGS__)
+#define home_comm_call_ret(_ret, _comm, key, ...) _doCALL(_ret, comm, _comm, key, _home, ##__VA_ARGS__)
 /* pane_call() is used when a very specific pane must be informed, rather than
  * the first responder in a chain of panes.  This mostly used for notifications,
  * both generic notification, and special things like a child appearing or disappearing
index 6268f7219f34a467301a616d034b5dbe5d9c2625..e13fd6523f620b3f3e0847f877a781a33e68e7f3 100644 (file)
@@ -444,7 +444,7 @@ DEF_CMD(libevent_notify)
 {
        struct event_info *ei = ci->home->data;
 
-       comm_call(&ei->free, "free", ci->focus);
+       home_comm_call(ci->home, &ei->free, "free", ci->focus);
        return 1;
 }