--- globals.h.orig	Sat Aug 24 10:10:36 2002
+++ globals.h	Thu May 30 23:13:46 2002
@@ -171,6 +171,8 @@
 WHERE ALIAS *Aliases INITVAL (0);
 WHERE LIST *UserHeader INITVAL (0);
 
+WHERE int slrnface_fd INITVAL (-1);
+
 #ifdef DEBUG
 WHERE FILE *debugfile INITVAL (0);
 WHERE int debuglevel INITVAL (0);
--- init.c.orig	Mon Feb 11 10:58:54 2002
+++ init.c	Sat Aug 24 07:28:13 2002
@@ -47,6 +47,8 @@
 #include <string.h>
 #include <sys/utsname.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <sys/wait.h>
 
 void toggle_quadoption (int opt)
@@ -1966,4 +1968,132 @@
     if (c->func == mutt_parse_hook && ascii_strcasecmp (c->name, name) == 0)
       return c->data;
   return 0;
+}
+
+void mutt_start_slrnface(void)
+{
+  char *fifo;
+  int pathlen, status;
+  pid_t pid, pidst;
+  struct utsname u;
+
+  if (!option(OPTXFACE))
+    return;
+
+  /*
+   * If we don't have display, there's no point. The user probably knows,
+   * so fail silently.
+   */
+  if (!getenv("DISPLAY"))
+    return;
+  /* If there is no WINDOWID, complain. */
+  if (!getenv ("WINDOWID"))
+  {
+    mutt_error (_("Cannot run slrnface: WINDOWID not found in environment."));
+    return;
+  }
+
+  uname (&u);
+  pathlen = strlen (Homedir) + sizeof("/.slrnfaces/")
+            + strlen (u.nodename) + 30;
+  fifo = safe_malloc (pathlen);
+  sprintf (fifo, "%s/.slrnfaces", Homedir);
+  if (mkdir (fifo, 0700))
+  {
+    if (errno != EEXIST)
+    {
+      mutt_error (_("Cannot run slrnface: failed to create %s: %s."),
+	  	  fifo, strerror(errno));
+      return;
+    }
+  }
+  else
+  {
+    FILE *fp;
+
+    /* We'll abuse fifo filename memory here. It's long enough. */
+    sprintf (fifo, "%s/.slrnfaces/README", Homedir);
+    if ((fp = fopen (fifo, "w")) != NULL)
+    {
+      fputs (_(
+"This directory is used to create named pipes for communication between\n"
+"slrnface and its parent process. It should normally be empty because\n"
+"the pipe is deleted right after it has been opened by both processes.\n\n"
+"File names generated by slrnface have the form \"hostname.pid\". It is\n"
+"probably an error if they linger here longer than a fraction of a second.\n\n"
+"However, if the directory is mounted from an NFS server, you might see\n"
+"special files created by your NFS server while slrnface is running.\n"
+"Do not try to remove them.\n"), fp);
+      fclose (fp);
+    }
+  }
+
+  status = snprintf (fifo, pathlen, "%s/.slrnfaces/%s.%ld", Homedir,
+	  	     u.nodename, (long)getpid());
+  if (status < 0)
+    goto clean_face;
+
+  unlink (fifo);
+  if (mkfifo (fifo, 0600) < 0)
+  {
+    mutt_error (_("Cannot run slrnface, failed to create %s: %s."), fifo,
+		strerror(errno));
+    goto clean_face;
+  }
+
+  pid = fork();
+  switch (pid)
+  {
+    case -1: break;
+    case 0:  execlp ("slrnface", "slrnface", fifo, (char *)0);
+	     /* This is child, exit on error. */
+	     _exit (10);
+    default: do {
+	       pidst = waitpid (pid, &status, 0);
+	     } while (pidst == -1 && errno == EINTR);
+
+	     if (!WIFEXITED (status))
+	       mutt_error (_("Slrnface abnormaly exited, code %d."), status);
+	     else
+	     {
+	       char *message;
+
+	       switch (WEXITSTATUS (status))
+	       {
+		 case 0: /* All fine, open the pipe */
+			 slrnface_fd = open (fifo, O_WRONLY, 0600);
+			 write (slrnface_fd, "start\n", sizeof "start");
+			 goto clean_face;
+		 case 1: message = "couldn't connect to display";
+			 break;
+		 case 2: message = "WINDOWID not found in environment";
+			 break;
+		 case 3: message = "couldn't find controlling terminal";
+			 break;
+		 case 4: message = "terminal doesn't export width and height";
+			 break;
+		 case 5: message = "cannot open FIFO";
+			 break;
+		 case 6: message = "fork() failed";
+			 break;
+		 case 10: message = "executable not found";
+			  break;
+		 default: message = "unknown error";
+	       }
+	       mutt_error (_("Slrnface failed: %s."), message);
+	     }
+  }
+
+clean_face:
+  unlink (fifo);
+  free (fifo);
+}
+
+void mutt_stop_slrnface(void)
+{
+  if (slrnface_fd >= 0)
+    close(slrnface_fd);
+  slrnface_fd = -1;
+
+  /* FIFO has been unlinked in the startup function. */
 }
--- init.h.orig	Thu Apr 25 15:26:37 2002
+++ init.h	Thu May 30 23:13:46 2002
@@ -2366,6 +2366,12 @@
   ** Controls whether mutt writes out the Bcc header when preparing
   ** messages to be sent.  Exim users may wish to use this.
   */
+  { "xface",		DT_BOOL, R_NONE, OPTXFACE, 0 },
+  /*
+  ** .pp
+  ** Controls whether mutt uses slrnface to display X-Faces when run
+  ** in an X11 terminal emulator.
+  */
   /*--*/
   { NULL }
 };
--- main.c.orig	Sat Aug 24 10:11:53 2002
+++ main.c	Thu May 30 23:13:46 2002
@@ -835,6 +835,8 @@
 
     mutt_folder_hook (folder);
 
+    mutt_start_slrnface();
+
     if((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL))
        || !explicit_folder)
     {
@@ -843,6 +845,8 @@
 	safe_free ((void **)&Context);
     }
     mutt_endwin (Errorbuf);
+
+    mutt_stop_slrnface();
   }
 
   exit (0);
--- mutt.h.orig	Sat Aug 24 10:12:08 2002
+++ mutt.h	Thu May 30 23:13:46 2002
@@ -410,6 +410,7 @@
   OPTWRAP,
   OPTWRAPSEARCH,
   OPTWRITEBCC,		/* write out a bcc header? */
+  OPTXFACE,
   OPTXMAILER,
 
   /* PGP options */
@@ -526,6 +527,7 @@
   char *x_label;
   LIST *references;		/* message references (in reverse order) */
   LIST *in_reply_to;		/* in-reply-to header content */
+  LIST *x_face;			/* X-Face header content */
   LIST *userhdrs;		/* user defined headers */
 } ENVELOPE;
 
--- muttlib.c.orig	Sat Aug 24 10:12:24 2002
+++ muttlib.c	Thu May 30 23:13:47 2002
@@ -650,6 +650,7 @@
   safe_free ((void **) &(*p)->date);
   mutt_free_list (&(*p)->references);
   mutt_free_list (&(*p)->in_reply_to);
+  mutt_free_list (&(*p)->x_face);
   mutt_free_list (&(*p)->userhdrs);
   safe_free ((void **) p);
 }
--- pager.c.orig	Sat Aug 24 10:12:57 2002
+++ pager.c	Sat Aug 24 23:39:17 2002
@@ -1431,6 +1431,66 @@
   return cur;
 }
 
+static void
+mutt_display_xface (HEADER *hdr)
+{
+  LIST *face;
+  char buf[2000];
+
+  if (slrnface_fd < 0)
+    return;
+
+  if (!hdr)
+    return;
+
+  face = hdr->env->x_face;
+
+  if (face == NULL || face->data == NULL)
+    write(slrnface_fd, "clear\n", sizeof "clear");
+  else
+    do {
+      int len;
+
+      len = snprintf (buf, sizeof (buf), "xface %s\n", face->data);
+      if (len <= sizeof (buf))
+      {
+	write (slrnface_fd, buf, len);
+	break;
+      }
+      /*
+       * slrnface will ignore X-Faces larger than approx. 2000 chars, so
+       * try the next one, if it exists.
+       */
+    } while (face = face->next);
+}
+
+static void
+mutt_clear_xface (void)
+{
+  if (slrnface_fd < 0)
+    return;
+
+  write(slrnface_fd, "clear\n", sizeof "clear");
+}
+
+static void
+mutt_suppress_xface (void)
+{
+  if (slrnface_fd < 0)
+    return;
+
+  write(slrnface_fd, "suppress\n", sizeof "suppress");
+}
+
+static void
+mutt_show_xface (void)
+{
+  if (slrnface_fd < 0)
+    return;
+
+  write(slrnface_fd, "show\n", sizeof "show");
+}
+
 static struct mapping_t PagerHelp[] = {
   { N_("Exit"),	OP_EXIT },
   { N_("PrevPg"), OP_PREV_PAGE },
@@ -1535,6 +1595,9 @@
     snprintf (helpstr, sizeof (helpstr), "%s %s", tmphelp, buffer);
   }
 
+  if (IsHeader (extra))
+    mutt_display_xface(extra->hdr);
+
   while (ch != -1)
   {
     mutt_curs_set (0);
@@ -2035,7 +2098,9 @@
 	if (! InHelp)
 	{
 	  InHelp = 1;
+	  mutt_suppress_xface ();
 	  mutt_help (MENU_PAGER);
+	  mutt_show_xface ();
 	  redraw = REDRAW_FULL;
 	  InHelp = 0;
 	}
@@ -2327,59 +2392,71 @@
       case OP_MAIL:
 	CHECK_MODE(IsHeader (extra) && !IsAttach (extra));
         CHECK_ATTACH;      
+	mutt_suppress_xface ();
 	ci_send_message (0, NULL, NULL, NULL, NULL);
+	mutt_show_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
       case OP_REPLY:
 	CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
         CHECK_ATTACH;      
+	mutt_suppress_xface();
         if (IsMsgAttach (extra)) 
 	  mutt_attach_reply (extra->fp, extra->hdr, extra->idx,
 			     extra->idxlen, extra->bdy,
 			     SENDREPLY);
 	else
 	  ci_send_message (SENDREPLY, NULL, NULL, extra->ctx, extra->hdr);
+	mutt_show_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
       case OP_RECALL_MESSAGE:
 	CHECK_MODE(IsHeader (extra));
         CHECK_ATTACH;
+	mutt_suppress_xface();
 	ci_send_message (SENDPOSTPONED, NULL, NULL, extra->ctx, extra->hdr);
+	mutt_show_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
       case OP_GROUP_REPLY:
 	CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
         CHECK_ATTACH;
+	mutt_suppress_xface();
         if (IsMsgAttach (extra))
 	  mutt_attach_reply (extra->fp, extra->hdr, extra->idx,
 			     extra->idxlen, extra->bdy, SENDREPLY|SENDGROUPREPLY);
         else
 	  ci_send_message (SENDREPLY | SENDGROUPREPLY, NULL, NULL, extra->ctx, extra->hdr);
+	mutt_suppress_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
       case OP_LIST_REPLY:
 	CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
         CHECK_ATTACH;        
+	mutt_suppress_xface();
         if (IsMsgAttach (extra))
 	  mutt_attach_reply (extra->fp, extra->hdr, extra->idx,
 			     extra->idxlen, extra->bdy, SENDREPLY|SENDLISTREPLY);
         else
 	  ci_send_message (SENDREPLY | SENDLISTREPLY, NULL, NULL, extra->ctx, extra->hdr);
+	mutt_show_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
       case OP_FORWARD_MESSAGE:
 	CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
         CHECK_ATTACH;
+	mutt_suppress_xface();
         if (IsMsgAttach (extra))
 	  mutt_attach_forward (extra->fp, extra->hdr, extra->idx,
 			       extra->idxlen, extra->bdy);
         else
 	  ci_send_message (SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr);
+	mutt_show_xface ();
 	redraw = REDRAW_FULL;
 	break;
 
@@ -2428,7 +2505,9 @@
 	break;
 
       case OP_SHELL_ESCAPE:
+	mutt_suppress_xface ();
 	mutt_shell_escape ();
+	mutt_show_xface ();
 	MAYBE_REDRAW (redraw);
 	break;
 
@@ -2563,5 +2642,6 @@
   safe_free ((void **) &lineInfo);
   if (index)
     mutt_menuDestroy(&index);
+  mutt_clear_xface ();
   return (rc != -1 ? rc : 0);
 }
--- parse.c.orig	Tue Jan 29 11:05:20 2002
+++ parse.c	Thu May 30 23:13:47 2002
@@ -90,6 +90,27 @@
   /* not reached */
 }
 
+static LIST *mutt_add_x_face (LIST *lst, char *face)
+{
+  LIST *n;
+
+  n = safe_malloc(sizeof(LIST));
+  n->data = safe_strdup(face);
+  n->next = NULL;
+
+  if (lst)
+  {
+    LIST *l;
+
+    for(l = lst; l->next; l = l->next);
+    l->next = n;
+  }
+  else
+    lst = n;
+
+  return lst;
+}
+
 static LIST *mutt_parse_references (char *s, int in_reply_to)
 {
   LIST *t, *lst = NULL;
@@ -1205,6 +1226,11 @@
     else if (ascii_strcasecmp (line+1, "-label") == 0)
     {
       e->x_label = safe_strdup(p);
+      matched = 1;
+    }
+    else if (ascii_strcasecmp (line+1, "-face") == 0)
+    {
+      e->x_face = mutt_add_x_face (e->x_face, p);
       matched = 1;
     }
     
--- sendlib.c.orig	Sat Aug 24 00:05:52 2002
+++ sendlib.c	Sat Aug 24 00:16:54 2002
@@ -1663,6 +1663,15 @@
     fputc ('\n', fp);
   }
   
+  /* Add X-Face headers */
+  if (env->x_face)
+  {
+    LIST *face;
+
+    for (face = env->x_face; face; face = face->next)
+      fprintf (fp, "X-Face: %s\n", face->data);
+  }
+
   if (mode == 0 && !privacy && option (OPTXMAILER))
   {
     /* Add a vanity header */
