<<< Date Index >>>     <<< Thread Index >>>

Re: xlabel request



Here's a freshened-up version of
http://home.uchicago.edu/~dgc/sw/mutt/patch-dgc.label_ext.9  dated 25-Apr-2008

merged with email to mutt-dev from Thomas Roessler as of 11-Jan-2007 for
displaying/editing X-Labels during message composition (also, replies
start with the same X-Labels as the originals),

and with a bug fix or two of my own thrown in...


Roessler's patch prompted some discussion along the lines of "I don't
want to see other people's X-Labels (or them to see mine)". I fully
agree; however, I want to be able to label my own copies of outgoing
mail when I'm composing it. (Rather than after the fact, when I've
usually lost track of it or forgotten what it's about.) The solution is
to set your
    sendmail=xlabel_stripping_wrapper REAL_SENDMAIL_AND_OPTIONS

Where xlabel_stripping_wrapper is a script that does merely this:
    SENDMAIL="$1"
    shift
    sed -r '1,/^$/{/^X-Label:/d}' | $SENDMAIL "$@"
(Note that will break your messages if your X-Labels ever wrap to a second
line. A more complex sed script would be needed to catch such cases.)

This way, X-Labels never pollute the mail that really gets sent from
your machine, but your own saved copies of outgoing messages do have the
X-Labels you specified.




diff -Naurp mutt-1.5.18/OPS mutt-1.5.18.xlabel.new/OPS
--- mutt-1.5.18/OPS     2008-01-29 23:26:49.000000000 -0500
+++ mutt-1.5.18.xlabel.new/OPS  2008-09-16 20:49:32.000000000 -0400
@@ -24,6 +24,7 @@ OP_COMPOSE_EDIT_FCC "enter a file to sav
 OP_COMPOSE_EDIT_FILE "edit the file to be attached"
 OP_COMPOSE_EDIT_FROM "edit the from field"
 OP_COMPOSE_EDIT_HEADERS "edit the message with headers"
+OP_COMPOSE_EDIT_LABEL "edit the message's x-label header"
 OP_COMPOSE_EDIT_MESSAGE "edit the message"
 OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry"
 OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
@@ -56,6 +57,7 @@ OP_DELETE_THREAD "delete all messages in
 OP_DISPLAY_ADDRESS "display full address of sender"
 OP_DISPLAY_HEADERS "display message and toggle header weeding"
 OP_DISPLAY_MESSAGE "display a message"
+OP_EDIT_LABEL "add, change, or delete a message's label"
 OP_EDIT_MESSAGE "edit the raw message"
 OP_EDITOR_BACKSPACE "delete the char in front of the cursor"
 OP_EDITOR_BACKWARD_CHAR "move the cursor one character to the left"
diff -Naurp mutt-1.5.18/PATCHES mutt-1.5.18.xlabel.new/PATCHES
--- mutt-1.5.18/PATCHES 2008-01-27 21:20:20.000000000 -0500
+++ mutt-1.5.18.xlabel.new/PATCHES      2008-09-16 20:49:28.000000000 -0400
@@ -0,0 +1 @@
+patch-1.5.16.dgc.xlabel_ext.9
diff -Naurp mutt-1.5.18/commands.c mutt-1.5.18.xlabel.new/commands.c
--- mutt-1.5.18/commands.c      2008-01-29 23:26:49.000000000 -0500
+++ mutt-1.5.18.xlabel.new/commands.c   2008-09-16 20:49:28.000000000 -0400
@@ -509,9 +509,9 @@ int mutt_select_sort (int reverse)
   int method = Sort; /* save the current method in case of abort */
 
   switch (mutt_multi_choice (reverse ?
-                            _("Rev-Sort 
(d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(u)nsort/si(z)e/s(c)ore/s(p)am?: ") :
-                            _("Sort 
(d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(u)nsort/si(z)e/s(c)ore/s(p)am?: "),
-                            _("dfrsotuzcp")))
+                            _("Rev-Sort 
(d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(l)abel/(u)nsort/si(z)e/s(c)ore/s(p)am?:
 ") :
+                            _("Sort 
(d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(l)abel/(u)nsort/si(z)e/s(c)ore/s(p)am?:
 "),
+                            _("dfrsotuzcpl")))
   {
   case -1: /* abort - don't resort */
     return -1;
@@ -555,6 +555,10 @@ int mutt_select_sort (int reverse)
   case 10: /* s(p)am */
     Sort = SORT_SPAM;
     break;
+
+  case 11: /* (l)abel */
+    Sort = SORT_LABEL;
+    break;
   }
   if (reverse)
     Sort |= SORT_REVERSE;
diff -Naurp mutt-1.5.18/compose.c mutt-1.5.18.xlabel.new/compose.c
--- mutt-1.5.18/compose.c       2008-03-09 16:52:24.000000000 -0400
+++ mutt-1.5.18.xlabel.new/compose.c    2008-09-16 20:49:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include "remailer.h"
 #endif
 
+#include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -57,6 +58,7 @@ enum
   HDR_CC,
   HDR_BCC,
   HDR_SUBJECT,
+  HDR_LABEL,
   HDR_REPLYTO,
   HDR_FCC,
 
@@ -81,6 +83,7 @@ static char *Prompts[] =
   "Cc: ",
   "Bcc: ",
   "Subject: ",
+  "Label: ",
   "Reply-To: ",
   "Fcc: "
 };
@@ -257,6 +260,8 @@ static void draw_envelope (HEADER *msg, 
   draw_envelope_addr (HDR_BCC, msg->env->bcc);
   mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
   mutt_paddstr (W, NONULL (msg->env->subject));
+  mvprintw (HDR_LABEL, 0, TITLE_FMT, Prompts[HDR_LABEL - 1]);
+  mutt_paddstr (W, NONULL (msg->env->x_label));
   draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
   mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]);
   mutt_paddstr (W, fcc);
@@ -560,6 +565,20 @@ int mutt_compose_menu (HEADER *msg,   /*
        }
         mutt_message_hook (NULL, msg, M_SEND2HOOK);
         break;
+      case OP_COMPOSE_EDIT_LABEL:
+       if (msg->env->x_label)
+         strfcpy (buf, msg->env->x_label, sizeof (buf));
+       else
+         buf[0] = 0;
+       if (mutt_get_field ("Label: ", buf, sizeof (buf), 0) == 0)
+       {
+         mutt_str_replace (&msg->env->x_label, buf);
+         move (HDR_LABEL, HDR_XOFFSET);
+         clrtoeol ();
+         if (msg->env->x_label)
+           mutt_paddstr (W, msg->env->x_label);
+       }
+        break;
       case OP_COMPOSE_EDIT_REPLY_TO:
        menu->redraw = edit_address_list (HDR_REPLYTO, &msg->env->reply_to);
         mutt_message_hook (NULL, msg, M_SEND2HOOK);
diff -Naurp mutt-1.5.18/copy.c mutt-1.5.18.xlabel.new/copy.c
--- mutt-1.5.18/copy.c  2008-01-29 23:26:49.000000000 -0500
+++ mutt-1.5.18.xlabel.new/copy.c       2008-09-16 20:49:32.000000000 -0400
@@ -108,6 +108,9 @@ mutt_copy_hdr (FILE *in, FILE *out, LOFF
        if ((flags & CH_UPDATE_IRT) &&
            ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
          continue;
+       if (flags & CH_UPDATE_LABEL &&
+           ascii_strncasecmp ("X-Label:", buf, 8) == 0)
+         continue;
        ignore = 0;
       }
 
@@ -214,6 +217,9 @@ mutt_copy_hdr (FILE *in, FILE *out, LOFF
       if ((flags & CH_UPDATE_IRT) &&
          ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
        continue;
+      if (flags & CH_UPDATE_LABEL &&
+         ascii_strncasecmp ("X-Label:", buf, 8) == 0)
+        continue;
 
       /* Find x -- the array entry where this header is to be saved */
       if (flags & CH_REORDER)
@@ -333,6 +339,7 @@ mutt_copy_hdr (FILE *in, FILE *out, LOFF
        CH_NOQFROM      ignore ">From " line
        CH_UPDATE_IRT   update the In-Reply-To: header
        CH_UPDATE_REFS  update the References: header
+       CH_UPDATE_LABEL update X-Label: from hdr->env->x_label?
 
    prefix
        string to use if CH_PREFIX is set
@@ -464,6 +471,15 @@ mutt_copy_header (FILE *in, HEADER *h, F
       fprintf (out, "Lines: %d\n", h->lines);
   }
 
+  if (flags & CH_UPDATE_LABEL && h->xlabel_changed)
+  {
+    /* h->xlabel_changed = 0; */
+    if (h->env->x_label != NULL)
+      if (fprintf(out, "X-Label: %s\n", h->env->x_label) !=
+                 10 + strlen(h->env->x_label))
+        return -1;
+  }
+
   if ((flags & CH_NONEWLINE) == 0)
   {
     if (flags & CH_PREFIX)
@@ -545,6 +561,9 @@ _mutt_copy_message (FILE *fpout, FILE *f
       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context, 
hdr, 0);
   }
 
+  if (hdr->xlabel_changed)
+    chflags |= CH_UPDATE_LABEL;
+
   if ((flags & M_CM_NOHEADER) == 0)
   {
     if (flags & M_CM_PREFIX)
@@ -599,6 +618,7 @@ _mutt_copy_message (FILE *fpout, FILE *f
       if (flags & M_CM_UPDATE)
       {
        hdr->attach_del = 0;
+       hdr->xlabel_changed = 0;
        hdr->lines = new_lines;
        body->offset = new_offset;
 
diff -Naurp mutt-1.5.18/curs_main.c mutt-1.5.18.xlabel.new/curs_main.c
--- mutt-1.5.18/curs_main.c     2008-05-15 01:48:37.000000000 -0400
+++ mutt-1.5.18.xlabel.new/curs_main.c  2008-09-16 20:49:28.000000000 -0400
@@ -1923,6 +1923,21 @@ int mutt_index_menu (void)
        menu->redraw = REDRAW_FULL;
        break;
 
+      case OP_EDIT_LABEL:
+
+       CHECK_MSGCOUNT;
+       CHECK_READONLY;
+       rc = mutt_label_message(tag ? NULL : CURHDR);
+       if (rc > 0) {
+         Context->changed = 1;
+         menu->redraw = REDRAW_FULL;
+         mutt_message ("%d label%s changed.", rc, rc == 1 ? "" : "s");
+       }
+       else {
+         mutt_message _("No labels changed.");
+       }
+       break;
+
       case OP_LIST_REPLY:
 
        CHECK_ATTACH;
diff -Naurp mutt-1.5.18/doc/manual.xml.head 
mutt-1.5.18.xlabel.new/doc/manual.xml.head
--- mutt-1.5.18/doc/manual.xml.head     2008-05-16 01:50:13.000000000 -0400
+++ mutt-1.5.18.xlabel.new/doc/manual.xml.head  2008-09-16 20:49:28.000000000 
-0400
@@ -4661,6 +4661,18 @@ and other mail filtering agents.
 </para>
 
 <para>
+You can change or delete the ``X-Label:'' field within Mutt using the
+``edit-label'' command, bound to the ``y'' key by default.  This works
+for tagged messages, too.
+</para>
+
+<para>
+You can change or delete the ``X-Label:'' field within Mutt using the
+``edit-label'' command, bound to the ``y'' key by default.  This works
+for tagged messages, too.
+</para>
+
+<para>
 Lastly, Mutt has the ability to <link linkend="sort">sort</link> the mailbox 
into
 <link linkend="threads">threads</link>.  A thread is a group of messages which 
all relate to the same
 subject.  This is usually organized into a tree-like structure where a
diff -Naurp mutt-1.5.18/functions.h mutt-1.5.18.xlabel.new/functions.h
--- mutt-1.5.18/functions.h     2008-01-29 23:26:50.000000000 -0500
+++ mutt-1.5.18.xlabel.new/functions.h  2008-09-16 20:49:32.000000000 -0400
@@ -99,6 +99,7 @@ struct binding_t OpMain[] = { /* map: in
   { "delete-thread",           OP_DELETE_THREAD,               "\004" },
   { "delete-subthread",                OP_DELETE_SUBTHREAD,            "\033d" 
},
   { "edit",                    OP_EDIT_MESSAGE,                "e" },
+  { "edit-label",              OP_EDIT_LABEL,                  "y" },
   { "edit-type",               OP_EDIT_TYPE,                   "\005" },
   { "forward-message",         OP_FORWARD_MESSAGE,             "f" },
   { "flag-message",            OP_FLAG_MESSAGE,                "F" },
@@ -184,6 +185,7 @@ struct binding_t OpPager[] = { /* map: p
   { "delete-thread",   OP_DELETE_THREAD,               "\004" },
   { "delete-subthread",        OP_DELETE_SUBTHREAD,            "\033d" },
   { "edit",            OP_EDIT_MESSAGE,                "e" },
+  { "edit-label",      OP_EDIT_LABEL,                  "y" },
   { "edit-type",       OP_EDIT_TYPE,                   "\005" },
   { "forward-message", OP_FORWARD_MESSAGE,             "f" },
   { "flag-message",    OP_FLAG_MESSAGE,                "F" },
@@ -314,6 +316,7 @@ struct binding_t OpCompose[] = { /* map:
   { "display-toggle-weed",     OP_DISPLAY_HEADERS,             "h" },
   { "ispell",          OP_COMPOSE_ISPELL,              "i" },
   { "print-entry",     OP_PRINT,                       "l" },
+  { "edit-label",       OP_COMPOSE_EDIT_LABEL,         "L" },
   { "edit-mime",       OP_COMPOSE_EDIT_MIME,           "m" },
   { "new-mime",                OP_COMPOSE_NEW_MIME,            "n" },
   { "postpone-message",        OP_COMPOSE_POSTPONE_MESSAGE,    "P" },
diff -Naurp mutt-1.5.18/headers.c mutt-1.5.18.xlabel.new/headers.c
--- mutt-1.5.18/headers.c       2008-01-27 21:20:22.000000000 -0500
+++ mutt-1.5.18.xlabel.new/headers.c    2008-09-16 20:49:28.000000000 -0400
@@ -205,3 +205,59 @@ void mutt_edit_headers (const char *edit
     }
   }
 }
+
+/*
+ * dgc: Add an X-Label: field.
+ */
+static int label_message(HEADER *hdr, char *new)
+{
+       if (hdr == NULL)
+               return 0;
+       if (hdr->env->x_label == NULL && new == NULL)
+               return 0;
+       if (hdr->env->x_label != NULL && new != NULL &&
+                       strcmp(hdr->env->x_label, new) == 0)
+               return 0;
+       if (hdr->env->x_label != NULL)
+               FREE(&hdr->env->x_label);
+       if (new == NULL)
+               hdr->env->x_label = NULL;
+       else
+               hdr->env->x_label = safe_strdup(new);
+       return hdr->changed = hdr->xlabel_changed = 1;
+}
+
+int mutt_label_message(HEADER *hdr)
+{
+       char buf[LONG_STRING], *new;
+       int i;
+       int changed;
+
+       *buf = '\0';
+       if (hdr != NULL && hdr->env->x_label != NULL) {
+               strncpy(buf, hdr->env->x_label, LONG_STRING);
+       }
+
+       if (mutt_get_field("Label: ", buf, sizeof(buf), 0 /* | M_CLEAR */) == 
-1) return 0;
+       new = buf;
+       SKIPWS(new);
+       if (*new == '\0')
+               new = NULL;
+
+       changed = 0;
+       if (hdr != NULL) {
+               changed += label_message(hdr, new);
+       } else {
+#define HDR_OF(index)  Context->hdrs[Context->v2r[(index)]]
+               for (i = 0; i < Context->vcount; ++i) {
+                       if (HDR_OF(i)->tagged)
+                               if (label_message(HDR_OF(i), new)) {
+                                       ++changed;
+                                       mutt_set_flag(Context, HDR_OF(i),
+                                               M_TAG, 0);
+                               }
+               }
+       }
+
+       return changed;
+}
diff -Naurp mutt-1.5.18/imap/imap.c mutt-1.5.18.xlabel.new/imap/imap.c
--- mutt-1.5.18/imap/imap.c     2008-05-13 02:13:38.000000000 -0400
+++ mutt-1.5.18.xlabel.new/imap/imap.c  2008-09-16 20:49:28.000000000 -0400
@@ -1169,7 +1169,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int
        * we delete the message and reupload it.
        * This works better if we're expunging, of course. */
       if ((h->env && (h->env->refs_changed || h->env->irt_changed)) ||
-         h->attach_del)
+         h->attach_del || h->xlabel_changed)
       {
         mutt_message (_("Saving changed messages... [%d/%d]"), n+1,
                       ctx->msgcount);
@@ -1181,6 +1181,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int
        }
        else
          _mutt_save_message (h, appendctx, 1, 0, 0);
+       h->xlabel_changed = 0;
       }
     }
   }
diff -Naurp mutt-1.5.18/imap/message.c mutt-1.5.18.xlabel.new/imap/message.c
--- mutt-1.5.18/imap/message.c  2008-01-29 23:26:50.000000000 -0500
+++ mutt-1.5.18.xlabel.new/imap/message.c       2008-09-16 20:49:28.000000000 
-0400
@@ -365,6 +365,7 @@ int imap_fetch_message (MESSAGE *msg, CO
   IMAP_CACHE *cache;
   int read;
   int rc;
+  char *x_label = NULL;
   /* Sam's weird courier server returns an OK response even when FETCH
    * fails. Thanks Sam. */
   short fetched = 0;
diff -Naurp mutt-1.5.18/init.h mutt-1.5.18.xlabel.new/init.h
--- mutt-1.5.18/init.h  2008-01-29 23:26:50.000000000 -0500
+++ mutt-1.5.18.xlabel.new/init.h       2008-09-16 20:49:32.000000000 -0400
@@ -169,6 +169,12 @@ struct option_t MuttVars[] = {
   ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before
   ** editing the body of an outgoing message.
   */  
+  { "asklabel",         DT_BOOL, R_NONE, OPTASKLABEL, 0 },
+  /*
+  ** .pp
+  ** If set, Mutt will prompt you for an X-Label header to be put on
+  ** your outgoing message.
+  */
   { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL 0},
   /*
   ** .pp
@@ -3110,6 +3116,7 @@ const struct mapping_t SortMethods[] = {
   { "to",              SORT_TO },
   { "score",           SORT_SCORE },
   { "spam",            SORT_SPAM },
+  { "label",           SORT_LABEL },
   { NULL,              0 }
 };
 
@@ -3129,6 +3136,7 @@ const struct mapping_t SortAuxMethods[] 
   { "to",              SORT_TO },
   { "score",           SORT_SCORE },
   { "spam",            SORT_SPAM },
+  { "label",           SORT_LABEL },
   { NULL,              0 }
 };
   
diff -Naurp mutt-1.5.18/mh.c mutt-1.5.18.xlabel.new/mh.c
--- mutt-1.5.18/mh.c    2008-03-11 20:08:24.000000000 -0400
+++ mutt-1.5.18.xlabel.new/mh.c 2008-09-16 20:49:28.000000000 -0400
@@ -1537,7 +1537,7 @@ static int mh_sync_message (CONTEXT * ct
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || 
+  if (h->attach_del || h->xlabel_changed ||
       (h->env && (h->env->refs_changed || h->env->irt_changed)))
     if (mh_rewrite_message (ctx, msgno) != 0)
       return -1;
@@ -1549,7 +1549,7 @@ static int maildir_sync_message (CONTEXT
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || 
+  if (h->attach_del || h->xlabel_changed ||
       (h->env && (h->env->refs_changed || h->env->irt_changed)))
   {
     /* when doing attachment deletion/rethreading, fall back to the MH case. */
@@ -1671,6 +1671,7 @@ int mh_sync_mailbox (CONTEXT * ctx, int 
       }
     }
     else if (ctx->hdrs[i]->changed || ctx->hdrs[i]->attach_del ||
+            ctx->hdrs[i]->xlabel_changed ||
             (ctx->magic == M_MAILDIR
              && (option (OPTMAILDIRTRASH) || ctx->hdrs[i]->trash)
              && (ctx->hdrs[i]->deleted != ctx->hdrs[i]->trash)))
diff -Naurp mutt-1.5.18/mutt.h mutt-1.5.18.xlabel.new/mutt.h
--- mutt-1.5.18/mutt.h  2008-01-29 23:26:50.000000000 -0500
+++ mutt-1.5.18.xlabel.new/mutt.h       2008-09-16 20:49:32.000000000 -0400
@@ -94,6 +94,7 @@
 #define CH_NOQFROM     (1<<15) /* give CH_FROM precedence over CH_WEED? */
 #define CH_UPDATE_IRT  (1<<16) /* update In-Reply-To: */
 #define CH_UPDATE_REFS (1<<17) /* update References: */
+#define CH_UPDATE_LABEL        (1<<18) /* update X-Label: from 
hdr->env->x_label? */
 
 /* flags for mutt_enter_string() */
 #define  M_ALIAS   1      /* do alias "completion" by calling up the 
alias-menu */
@@ -332,6 +333,7 @@ enum
   OPTASCIICHARS,
   OPTASKBCC,
   OPTASKCC,
+  OPTASKLABEL,
   OPTATTACHSPLIT,
   OPTAUTOEDIT,
   OPTAUTOTAG,
@@ -728,6 +730,7 @@ typedef struct header
                                         * This flag is used by the 
maildir_trash
                                         * option.
                                         */
+  unsigned int xlabel_changed : 1;     /* editable - used for syncing */
   
   /* timezone of the sender of this message */
   unsigned int zhours : 5;
diff -Naurp mutt-1.5.18/pager.c mutt-1.5.18.xlabel.new/pager.c
--- mutt-1.5.18/pager.c 2008-01-29 23:26:51.000000000 -0500
+++ mutt-1.5.18.xlabel.new/pager.c      2008-09-16 20:49:28.000000000 -0400
@@ -2629,6 +2629,18 @@ search_next:
        redraw = REDRAW_FULL;
        break;
 
+     case OP_EDIT_LABEL:
+        CHECK_MODE(IsHeader (extra));
+        rc = mutt_label_message(extra->hdr);
+        if (rc > 0) {
+          Context->changed = 1;
+          redraw = REDRAW_FULL;
+          mutt_message ("%d label%s changed.", rc, rc == 1 ? "" : "s");
+        }
+        else {
+          mutt_message _("No labels changed.");
+        }
+        break;
 
       case OP_MAIL_KEY:
         if (!(WithCrypto & APPLICATION_PGP))
diff -Naurp mutt-1.5.18/parse.c mutt-1.5.18.xlabel.new/parse.c
--- mutt-1.5.18/parse.c 2008-01-29 23:26:51.000000000 -0500
+++ mutt-1.5.18.xlabel.new/parse.c      2008-09-16 20:49:32.000000000 -0400
@@ -1257,7 +1257,8 @@ int mutt_parse_rfc822_line (ENVELOPE *e,
     }
     else if (ascii_strcasecmp (line+1, "-label") == 0)
     {
-      e->x_label = safe_strdup(p);
+      /* e->x_label = safe_strdup(p); */
+      mutt_str_replace(&e->x_label, p);
       matched = 1;
     }
     
diff -Naurp mutt-1.5.18/protos.h mutt-1.5.18.xlabel.new/protos.h
--- mutt-1.5.18/protos.h        2008-05-16 01:50:13.000000000 -0400
+++ mutt-1.5.18.xlabel.new/protos.h     2008-09-16 20:49:28.000000000 -0400
@@ -188,6 +188,7 @@ void mutt_edit_content_type (HEADER *, B
 void mutt_edit_file (const char *, const char *);
 void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);
 int mutt_filter_unprintable (char **);
+int mutt_label_message (HEADER *);
 void mutt_curses_error (const char *, ...);
 void mutt_curses_message (const char *, ...);
 void mutt_enter_command (void);
diff -Naurp mutt-1.5.18/send.c mutt-1.5.18.xlabel.new/send.c
--- mutt-1.5.18/send.c  2008-01-29 23:26:53.000000000 -0500
+++ mutt-1.5.18.xlabel.new/send.c       2008-09-16 20:49:32.000000000 -0400
@@ -238,7 +238,7 @@ static int edit_envelope (ENVELOPE *en)
     char *p;
 
     buf[0] = 0;
-    for (; uh; uh = uh->next)
+    for (uh = UserHeader; uh; uh = uh->next)
     {
       if (ascii_strncasecmp ("subject:", uh->data, 8) == 0)
       {
@@ -257,6 +257,17 @@ static int edit_envelope (ENVELOPE *en)
   }
   mutt_str_replace (&en->subject, buf);
 
+  if(option(OPTASKLABEL))
+  {
+    if (en->x_label)
+      strfcpy (buf, en->x_label, sizeof (buf));
+    else
+      buf[0] = 0;
+    if (mutt_get_field ("Label: ", buf, sizeof (buf), 0) == -1)
+       return(-1);
+    mutt_str_replace (&en->x_label, buf);
+  }
+
   return 0;
 }
 
@@ -310,6 +321,7 @@ static void process_user_header (ENVELOP
     else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 &&
             ascii_strncasecmp ("cc:", uh->data, 3) != 0 &&
             ascii_strncasecmp ("bcc:", uh->data, 4) != 0 &&
+            ascii_strncasecmp ("x-label:", uh->data, 8) != 0 &&
             ascii_strncasecmp ("subject:", uh->data, 8) != 0)
     {
       if (last)
@@ -627,6 +639,22 @@ void mutt_make_misc_reply_headers (ENVEL
   }
   else if (!env->subject)
     env->subject = safe_strdup ("Re: your mail");
+
+  if (curenv->x_label)
+    mutt_str_replace (&env->x_label, curenv->x_label);
+  /* are any X-Label headers supplied in my_hdrs? if so, they override */
+  LIST *uh = UserHeader;
+  char *p;
+  for (; uh; uh = uh->next)
+  {
+    if (ascii_strncasecmp ("x-label:", uh->data, 8) == 0)
+    {
+      p = uh->data + 8;
+      SKIPWS (p);
+      mutt_str_replace(&env->x_label, p);
+      /* break  // no break, will use last my_hdr X-Label:... */
+    }
+  }
 }
 
 void mutt_add_to_reference_headers (ENVELOPE *env, ENVELOPE *curenv, LIST 
***pp, LIST ***qq)
diff -Naurp mutt-1.5.18/sendlib.c mutt-1.5.18.xlabel.new/sendlib.c
--- mutt-1.5.18/sendlib.c       2008-01-29 23:26:53.000000000 -0500
+++ mutt-1.5.18.xlabel.new/sendlib.c    2008-09-16 20:49:32.000000000 -0400
@@ -1841,6 +1841,9 @@ int mutt_write_rfc822_header (FILE *fp, 
     fputc ('\n', fp);
   }
   
+  if (env->x_label)
+    mutt_write_one_header (fp, "X-Label", env->x_label, NULL, 0);
+  
   /* Add any user defined headers */
   for (; tmp; tmp = tmp->next)
   {
diff -Naurp mutt-1.5.18/sort.c mutt-1.5.18.xlabel.new/sort.c
--- mutt-1.5.18/sort.c  2008-01-29 23:26:53.000000000 -0500
+++ mutt-1.5.18.xlabel.new/sort.c       2008-09-16 20:49:28.000000000 -0400
@@ -210,6 +210,36 @@ int compare_spam (const void *a, const v
   return (SORTCODE(result));
 }
 
+int compare_label (const void *a, const void *b)
+{
+  HEADER **ppa = (HEADER **) a;
+  HEADER **ppb = (HEADER **) b;
+  int     ahas, bhas, result;
+
+  /* As with compare_spam, not all messages will have the x-label
+   * property.  Blank X-Labels are treated as null in the index
+   * display, so we'll consider them as null for sort, too.       */
+  ahas = (*ppa)->env && (*ppa)->env->x_label && *((*ppa)->env->x_label);
+  bhas = (*ppb)->env && (*ppb)->env->x_label && *((*ppb)->env->x_label);
+
+  /* First we bias toward a message with a label, if the other does not. */
+  if (ahas && !bhas)
+    return (SORTCODE(-1));
+  if (!ahas && bhas)
+    return (SORTCODE(1));
+
+  /* If neither has a label, use aux sort. */
+  if (!ahas && !bhas)
+  {
+    AUXSORT(result, a, b);
+    return (SORTCODE(result));
+  }
+
+  /* If both have a label, we just do a lexical compare. */
+  result = mutt_strcasecmp((*ppa)->env->x_label, (*ppb)->env->x_label);
+  return (SORTCODE(result));
+}
+
 sort_t *mutt_get_sort_func (int method)
 {
   switch (method & SORT_MASK)
@@ -232,6 +262,8 @@ sort_t *mutt_get_sort_func (int method)
       return (compare_score);
     case SORT_SPAM:
       return (compare_spam);
+    case SORT_LABEL:
+      return (compare_label);
     default:
       return (NULL);
   }
diff -Naurp mutt-1.5.18/sort.h mutt-1.5.18.xlabel.new/sort.h
--- mutt-1.5.18/sort.h  2008-01-27 21:20:25.000000000 -0500
+++ mutt-1.5.18.xlabel.new/sort.h       2008-09-16 20:49:28.000000000 -0400
@@ -31,6 +31,7 @@
 #define SORT_KEYID     12
 #define SORT_TRUST     13
 #define SORT_SPAM      14
+#define SORT_LABEL     15
 /* dgc: Sort & SortAux are shorts, so I'm bumping these bitflags up from
  * bits 4 & 5 to bits 8 & 9 to make room for more sort keys in the future. */
 #define SORT_MASK      0xff