Bugs to be fixed
----------------
+- [ ] notmuch reply should interpolate the first *visible* text part
- [X] multipart must handle Notify:Close better. It should NULL out the
pointer to the pane, and always check it isn't NULL.
- [X] I cannot dup a mark in a mark:moving handler. That is too
scaling.
- [ ] stop consistency checking a text doc when it gets "big" ??
- [ ] auto-sign emails..
-- [ ] be sure to wait for xdg-open etc.
+- [X] be sure to wait for xdg-open etc.
- [ ] things slow down after lots of edits. Maybe track
number of chunk, marks, undos etc and display them somewhere
- [?] Make doesn't follow llog_reader.c:723:6: when it have seen
#include <ctype.h>
#include <signal.h>
#include <sys/ioctl.h>
+#include <sys/wait.h>
#include <netdb.h>
#include <wand/MagickWand.h>
char *paste_latest;
int paste_pending;
+ struct pids {
+ pid_t pid;
+ struct pids *next;
+ } *pids;
+
char *rs1, *rs2, *rs3, *clear;
char attr_buf[1024];
#ifdef RECORD_REPLAY
return ret ?: "_";
}
+static void wait_for(struct display_data *dd safe)
+{
+ struct pids **pp = &dd->pids;
+
+ while (*pp) {
+ struct pids *p = *pp;
+ if (waitpid(p->pid, NULL, WNOHANG) > 0) {
+ *pp = p->next;
+ free(p);
+ } else
+ pp = &p->next;
+ }
+}
+
DEF_CMD(nc_external_viewer)
{
struct pane *p = ci->home;
if (!path)
return Enoarg;
if (disp && *disp) {
+ struct pids *pds;
switch (pid = fork()) {
case -1:
return Efail;
execlp("xdg-open", "xdg-open", path, NULL);
exit(1);
default: /* parent */
- /* FIXME record pid?? */
+ pds = malloc(sizeof(*pds));
+ pds->pid = pid;
+ pds->next = dd->pids;
+ dd->pids = pds;
break;
}
+ wait_for(dd);
return 1;
}
/* handle no-display case */
if (!(void*)p->data)
/* already closed */
return 0;
+ wait_for(dd);
set_screen(p);
while ((is_keycode = get_wch(&c)) != ERR) {
if (paste_recv(p, is_keycode, c))
#include <string.h>
#include <xcb/xcb.h>
#include <stdarg.h>
+#include <sys/wait.h>
#ifndef __CHECKER__
#include <xcb/xkb.h>
#else
struct xkb_compose_table *compose_table;
struct xkb_keymap *xkb_keymap;
+ struct pids {
+ pid_t pid;
+ struct pids *next;
+ } *pids;
+
/* FIXME use hash?? */
struct panes {
struct panes *next;
return 1;
}
+static void wait_for(struct xcb_data *xd safe)
+{
+ struct pids **pp = &xd->pids;
+
+ while (*pp) {
+ struct pids *p = *pp;
+ if (waitpid(p->pid, NULL, WNOHANG) > 0) {
+ *pp = p->next;
+ free(p);
+ } else
+ pp = &p->next;
+ }
+}
+
DEF_CMD(xcb_external_viewer)
{
struct xcb_data *xd = ci->home->data;
const char *path = ci->str;
+ struct pids *p;
int pid;
int fd;
execlp("xdg-open", "xdg-open", path, NULL);
exit(1);
default: /* parent */
+ p = malloc(sizeof(*p));
+ p->pid = pid;
+ p->next = xd->pids;
+ xd->pids = p;
break;
}
+ wait_for(xd);
return 1;
}
xcb_generic_event_t *ev;
int ret = 1;
+ wait_for(xd);
if (ci->num < 0)
/* This is a poll - only return 1 on something happening */
ret = Efalse;
gi.require_foreign("cairo")
from gi.repository import Gtk, Gdk, Pango, PangoCairo, GdkPixbuf, Gio
+def wait_for(p):
+ try:
+ r = os.read(p.stdout.fileno(), 4096)
+ except IOError:
+ # nothing to read yet
+ return 1
+ if r:
+ # not eof yet
+ return 1
+ p.communicate()
+ # stop waiting
+ return edlib.Efalse
+
+def wait_on(self, p):
+ # wait on pipe for exit
+ fd = self.pipe.stdout.fileno()
+ fl = fcntl.fcntl(fd, fcntl.F_GETFL);
+ fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
+ self.call("event:read", fd, lambda key, **a: wait_for(p))
+
class EdDisplay(edlib.Pane):
def __init__(self, focus, display):
edlib.Pane.__init__(self, focus, z=1)
env = os.environ.copy()
env['DISPLAY'] = disp
- subprocess.Popen(["xdg-open", str], env=env,
+ p = subprocess.Popen(["xdg-open", str], env=env,
+ stdin = subprocess.DEVNULL,
+ stdout = subprocess.PIPE,
stderr = subprocess.DEVNULL)
+ if p:
+ wait_on(self, p)
return 1
def handle_close(self, key, **a):
# "query.misc-list" is a subset of current-list for which query:current should not
# be assumed.
-from subprocess import Popen, PIPE, DEVNULL
+from subprocess import Popen, PIPE, DEVNULL, TimeoutExpired
import re
import os
import os.path