Embed vim into madmutt. Yeah _IN_ madmutt.
authorPierre Habouzit <madcoder@debian.org>
Sat, 10 Nov 2007 17:13:37 +0000 (18:13 +0100)
committerPierre Habouzit <madcoder@debian.org>
Sat, 10 Nov 2007 17:13:37 +0000 (18:13 +0100)
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
globals.h
lib-sys/mutt_signal.c
lib-ui/curs_lib.c

index f8c7a2f..3a96cae 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -131,6 +131,7 @@ WHERE short ImapBuffyTimeout;
 WHERE sig_atomic_t SigAlrm INITVAL (0);
 WHERE sig_atomic_t SigInt INITVAL (0);
 WHERE sig_atomic_t SigWinch INITVAL (0);
+WHERE sig_atomic_t SigChild INITVAL (0);
 
 WHERE int CurrentMenu;
 
index 0c53567..2728656 100644 (file)
@@ -28,11 +28,6 @@ static void exit_handler (int sig)
     exit(0);
 }
 
-static void chld_handler(int sig __attribute__((unused)))
-{
-  /* empty */
-}
-
 static void sighandler (int sig)
 {
   int save_errno = errno;
@@ -55,6 +50,10 @@ static void sighandler (int sig)
     SigWinch = 1;
     break;
 
+  case SIGCHLD:
+    SigChild = 1;
+    break;
+
   case SIGINT:
     SigInt = 1;
     break;
@@ -100,7 +99,6 @@ void mutt_signal_initialize (void)
   /* POSIX doesn't allow us to ignore SIGCHLD,
    * so we just install a dummy handler for it
    */
-  act.sa_handler = chld_handler;
   /* don't need to block any other signals here */
   sigemptyset (&act.sa_mask);
   /* we don't want to mess with stopped children */
index 5ac5dcb..619cb31 100644 (file)
@@ -117,16 +117,80 @@ void mutt_clear_error (void)
     CLEARLINE(stdscr, LINES - 1);
 }
 
+static struct timeval const slice = { 0, 1000 * 1000 / 100 };
+static struct timeval timeval_add(struct timeval a, struct timeval b)
+{
+    int usec = a.tv_usec + b.tv_usec;
+    a.tv_sec += b.tv_sec;
+    while (usec > 1000 * 1000) {
+        a.tv_sec += 1;
+        usec -= 1000 * 1000;
+    }
+    a.tv_usec = usec;
+    return a;
+}
+
+static int is_expired(struct timeval now, struct timeval expiry)
+{
+    return now.tv_sec > expiry.tv_sec
+        || (now.tv_sec == expiry.tv_sec && now.tv_usec > expiry.tv_usec);
+}
+
 void mutt_edit_file(const char *data)
 {
-  char cmd[LONG_STRING];
-
-  mutt_endwin (NULL);
-  m_quotefile_fmt(cmd, sizeof (cmd), mod_core.editor, data);
-  if (mutt_system (cmd) == -1)
-    mutt_error (_("Error running \"%s\"!"), cmd);
-  keypad (stdscr, TRUE);
-  clearok (stdscr, TRUE);
+    char cmd[STRING];
+    const char *args[] = { "/bin/sh", "-c", cmd, NULL };
+    int dirty = 0, ch, res, mh, mw, pty, pid;
+    struct timeval next;
+    madtty_t *rt;
+
+    m_quotefile_fmt(cmd, sizeof(cmd), mod_core.editor, data);
+    getmaxyx(main_w, mh, mw);
+    SigChild = 0;
+
+    rt = madtty_create(mh - 2, mw);
+    pid = madtty_forkpty(rt, args[0], args, &pty);
+    if (pid < 0) {
+        madtty_destroy(rt);
+        mutt_error(_("unable to start editor"));
+        return;
+    }
+
+    nodelay(stdscr, true);
+    gettimeofday(&next, NULL);
+    while (!SigChild) {
+        struct timeval tv = { 0, 1000 * 1000 / 100 };
+        fd_set rfds;
+
+        FD_ZERO(&rfds);
+        FD_SET(0, &rfds);
+        FD_SET(pty, &rfds);
+
+        if (select(pty + 1, &rfds, NULL, NULL, &tv) < 0)
+            break;
+
+        if (FD_ISSET(pty, &rfds)) {
+            madtty_process(rt);
+            dirty = 1;
+        }
+
+        while ((ch = getch()) != ERR) {
+            madtty_keypress(rt, ch); /* pass the keypress for handling */
+            dirty = 1;
+        }
+
+        gettimeofday(&tv, NULL);
+        if (dirty && is_expired(tv, next)) {
+            madtty_draw(rt, main_w, 1, 0);
+            wrefresh(main_w);
+            dirty = 0;
+            next = timeval_add(tv, slice);
+        }
+    }
+    while (waitpid(pid, &res, 0) < 0 && errno == EINTR);
+    nodelay(stdscr, false);
+    close(pty);
+    madtty_destroy(rt);
 }
 
 int mutt_yesorno (const char *msg, int def)