Index: owl.c
===================================================================
--- owl.c	(revision 23fddadbb7a375688e9be9627f1f5ca39aaa54d0)
+++ owl.c	(revision 18fdd5f9be6de827a19aceb95d4769058b145869)
@@ -315,5 +315,5 @@
 }
 
-void owl_process_input(owl_dispatch *d)
+void owl_process_input(const owl_io_dispatch *d, void *data)
 {
   owl_input j;
@@ -444,5 +444,5 @@
 
 /* Sends stderr (read from rfd) messages to the error console */
-void stderr_redirect_handler(owl_dispatch *d)
+void stderr_redirect_handler(const owl_io_dispatch *d, void *data)
 {
   int navail, bread;
@@ -521,25 +521,12 @@
   owl_global_set_haveaim(&g);
 
-  /* prepare stdin dispatch */
-  {
-    owl_dispatch *d = owl_malloc(sizeof(owl_dispatch));
-    d->fd = STDIN;
-    d->cfunc = &owl_process_input;
-    d->destroy = NULL;
-    owl_select_add_dispatch(d);
-  }
-
+  /* register STDIN dispatch; throw away return, we won't need it */
+  owl_select_add_io_dispatch(STDIN, OWL_IO_READ, &owl_process_input, NULL, NULL);
   owl_zephyr_initialize();
 
 #if OWL_STDERR_REDIR
   /* Do this only after we've started curses up... */
-  {
-    owl_dispatch *d = owl_malloc(sizeof(owl_dispatch));
-    owl_function_debugmsg("startup: doing stderr redirection");
-    d->fd = stderr_replace();
-    d->cfunc = stderr_redirect_handler;
-    d->destroy = NULL;
-    owl_select_add_dispatch(d);
-  }
+  owl_function_debugmsg("startup: doing stderr redirection");
+  owl_select_add_io_dispatch(stderr_replace(), OWL_IO_READ, &stderr_redirect_handler, NULL, NULL);
 #endif
 
Index: owl.h
===================================================================
--- owl.h	(revision df0138f05e0bae986f09d167195c6ce676bac37d)
+++ owl.h	(revision 18fdd5f9be6de827a19aceb95d4769058b145869)
@@ -530,5 +530,5 @@
   int winactive;
   pid_t pid;			/* or 0 if it has terminated */
-  owl_dispatch dispatch;
+  const owl_io_dispatch *dispatch;
 } owl_popexec;
 
Index: popexec.c
===================================================================
--- popexec.c	(revision 0e5afa2bbf43713baa4056d267c8f99c4104238a)
+++ popexec.c	(revision 18fdd5f9be6de827a19aceb95d4769058b145869)
@@ -53,9 +53,5 @@
     pe->pid=pid;
     pe->winactive=1;
-    pe->dispatch.fd = parent_read_fd;
-    pe->dispatch.cfunc = owl_popexec_inputhandler;
-    pe->dispatch.destroy = owl_popexec_free_dispatch;
-    pe->dispatch.data = pe;
-    owl_select_add_dispatch(&pe->dispatch);
+    pe->dispatch = owl_select_add_io_dispatch(parent_read_fd, OWL_IO_READ|OWL_IO_EXCEPT, &owl_popexec_inputhandler, &owl_popexec_delete_dispatch, pe);
     pe->refcount++;
   } else {
@@ -78,7 +74,7 @@
 }
 
-void owl_popexec_inputhandler(owl_dispatch *d)
+void owl_popexec_inputhandler(const owl_io_dispatch *d, void *data)
 {
-  owl_popexec *pe = d->data;
+  owl_popexec *pe = data;
   int navail, bread, rv_navail;
   char *buf;
@@ -99,5 +95,5 @@
   /* the viewwin has closed */
   if (!pe->pid && !pe->winactive) {
-    owl_select_remove_dispatch(d->fd);
+    owl_select_remove_io_dispatch(d);
     return;
   }
@@ -116,5 +112,5 @@
       owl_viewwin_redisplay(pe->vwin, 1);
     }
-    owl_select_remove_dispatch(d->fd);
+    owl_select_remove_io_dispatch(d);
     return;
   }
@@ -146,5 +142,5 @@
 }
 
-void owl_popexec_free_dispatch(owl_dispatch *d)
+void owl_popexec_delete_dispatch(const owl_io_dispatch *d)
 {
   owl_popexec *pe = d->data;
@@ -159,6 +155,6 @@
 
   pe->winactive = 0;
-  if (pe->dispatch.fd>0) {
-    owl_select_remove_dispatch(pe->dispatch.fd);
+  if (pe->dispatch->fd > 0) {
+    owl_select_remove_io_dispatch(pe->dispatch);
   }
   if (pe->pid) {
Index: zephyr.c
===================================================================
--- zephyr.c	(revision 12e291a330f117a61b8b222315c1f39822010a2a)
+++ zephyr.c	(revision 18fdd5f9be6de827a19aceb95d4769058b145869)
@@ -36,5 +36,4 @@
   ZNotice_t req;
   Code_t code;
-  owl_dispatch *dispatch;
 
   /*
@@ -80,17 +79,12 @@
   }
 
-  dispatch = owl_malloc(sizeof(*dispatch));
-  dispatch->fd = ZGetFD();
-  dispatch->cfunc = owl_zephyr_finish_initialization;
-  dispatch->destroy = (void(*)(owl_dispatch*))owl_free;
-
-  owl_select_add_dispatch(dispatch);
-}
-
-void owl_zephyr_finish_initialization(owl_dispatch *d) {
+  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_finish_initialization, NULL, NULL);
+}
+
+void owl_zephyr_finish_initialization(const owl_io_dispatch *d, void *data) {
   Code_t code;
   char *perl;
 
-  owl_select_remove_dispatch(d->fd);
+  owl_select_remove_io_dispatch(d);
 
   ZClosePort();
@@ -106,9 +100,6 @@
   }
 
-  d = owl_malloc(sizeof(owl_dispatch));
-  d->fd = ZGetFD();
-  d->cfunc = &owl_zephyr_process_events;
-  d->destroy = NULL;
-  owl_select_add_dispatch(d);
+  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL);
+
   owl_global_set_havezephyr(&g);
 
@@ -1350,5 +1341,5 @@
 }
 
-void owl_zephyr_process_events(owl_dispatch *d)
+void owl_zephyr_process_events(const owl_io_dispatch *d, void *data)
 {
   _owl_zephyr_process_events();
