]> granicus.if.org Git - neomutt/commitdiff
Adds capability to edit x-labels inside mutt, and to sort by label.
authorDavid Champion <dgc@bikeshed.us>
Sun, 29 Jan 2017 02:47:15 +0000 (18:47 -0800)
committerRichard Russon <rich@flatcap.org>
Fri, 10 Feb 2017 03:32:55 +0000 (03:32 +0000)
17 files changed:
copy.c
curs_main.c
doc/manual.xml.head
functions.h
hcache.c
hdrline.c
headers.c
imap/imap.c
main.c
mh.c
mutt.h
muttlib.c
pager.c
parse.c
pattern.c
protos.h
sort.c

diff --git a/copy.c b/copy.c
index 0b4c0344bc6899815deff9249bf66542c34a568b..faf383894b981a9c9a17ed97cc1f648bde528c16 100644 (file)
--- a/copy.c
+++ b/copy.c
@@ -124,6 +124,10 @@ mutt_copy_hdr (FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end, int flags,
          continue;
       }
 
+      if (flags & CH_UPDATE_LABEL &&
+         mutt_strncasecmp ("X-Label:", buf, 8) == 0)
+       continue;
+
       if (!ignore && fputs (buf, out) == EOF)
        return (-1);
     }
@@ -451,59 +455,13 @@ mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix)
   }
 #endif
 
-  if (flags & CH_UPDATE_LABEL && h->label_changed)
+  if (flags & CH_UPDATE_LABEL && h->xlabel_changed)
   {
-    h->label_changed = 0;
-    if (h->env->labels != NULL)
-    {
-      char buf[HUGE_STRING];
-      char *tmp = NULL;
-      int fail = 0;
-
-      if (fail == 0 &&
-          ((h->env->kwtypes & MUTT_X_LABEL) || (h->env->kwtypes == 0)) &&
-          (option(OPTKEYWORDSLEGACY) || option(OPTKEYWORDSSTANDARD) == 0))
-      {
-        mutt_labels(buf, sizeof(buf), h->env, XlabelDelim);
-        tmp = safe_strdup(buf);
-        rfc2047_encode_string(&tmp);
-        fail = fprintf(out, "X-Label: %s\n", tmp) != 10 + strlen(tmp);
-        FREE(&tmp);
-      }
-
-      if (fail == 0 && (h->env->kwtypes & MUTT_X_KEYWORDS) &&
-          (option(OPTKEYWORDSLEGACY) || option(OPTKEYWORDSSTANDARD) == 0))
-      {
-        mutt_labels(buf, sizeof(buf), h->env, " ");
-        tmp = safe_strdup(buf);
-        rfc2047_encode_string(&tmp);
-        fail = fprintf(out, "X-Keywords: %s\n", tmp) != 13 + strlen(tmp);
-        FREE(&tmp);
-      }
-
-      if (fail == 0 && (h->env->kwtypes & MUTT_X_MOZILLA_KEYS) &&
-          (option(OPTKEYWORDSLEGACY) || option(OPTKEYWORDSSTANDARD) == 0))
-      {
-        mutt_labels(buf, sizeof(buf), h->env, " ");
-        tmp = safe_strdup(buf);
-        rfc2047_encode_string(&tmp);
-        fail = fprintf(out, "X-Mozilla-Keys: %s\n", tmp) != 17 + strlen(tmp);
-        FREE(&tmp);
-      }
-
-      if (fail == 0 && ((h->env->kwtypes & MUTT_KEYWORDS) ||
-                        option(OPTKEYWORDSSTANDARD)))
-      {
-        mutt_labels(buf, sizeof(buf), h->env, NULL);
-        tmp = safe_strdup(buf);
-        rfc2047_encode_string(&tmp);
-        fail = fprintf(out, "Keywords: %s\n", tmp) != 11 + strlen(tmp);
-        FREE(&tmp);
-      }
-
-      if (fail)
+    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)
@@ -586,7 +544,7 @@ _mutt_copy_message (FILE *fpout, FILE *fpin, HEADER *hdr, BODY *body,
       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context, hdr, 0);
   }
 
-  if (hdr->label_changed)
+  if (hdr->xlabel_changed)
     chflags |= CH_UPDATE_LABEL;
 
   if ((flags & MUTT_CM_NOHEADER) == 0)
index 04bfdcf110422697d27e327bc96788c780daa181..75f61d95da3a55b2994fa8a0e5d27963d1a1ac4a 100644 (file)
@@ -772,7 +772,6 @@ static int main_change_folder(MUTTMENU *menu, int op, char *buf, size_t bufsz,
                MUTT_READONLY : 0, NULL)) != NULL)
   {
     Labels = hash_create(131, 0);
-    mutt_scan_labels(Context);
     menu->current = ci_first_message ();
   }
   else
@@ -2844,7 +2843,7 @@ int mutt_index_menu (void)
        if (rc > 0) {
          Context->changed = 1;
          menu->redraw = REDRAW_FULL;
-         mutt_message ("%d label%s changed.", rc, rc == 1 ? "" : "s");
+         mutt_message (_("%d labels changed."), rc);
        }
        else {
          mutt_message (_("No labels changed."));
index 20bd9f88c0ec49f7dd5821da52be462c43869d08..dcf92a1d004fc7cd74b4522c68d7279f46e24776 100644 (file)
@@ -6985,6 +6985,12 @@ field.  When set to <emphasis>yes</emphasis>, the
 <quote>Reply-To</quote> field will be used when present.
 </para>
 
+<para>
+You can change or delete the <quote>X-Label:</quote> field within
+Mutt using the <quote>edit-label</quote> command, bound to the
+<quote>y</quote> 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
index 2d5090e0ee8cadda026f6c3eaf553699e11f6268..b09a537023b06d9af924fb84210da87f7f9dbd9e 100644 (file)
@@ -101,7 +101,7 @@ const struct binding_t OpMain[] = { /* map: index */
   { "delete-thread",           OP_DELETE_THREAD,               "\004" },
   { "delete-subthread",                OP_DELETE_SUBTHREAD,            "\033d" },
   { "edit",                    OP_EDIT_MESSAGE,                "e" },
-  { "edit-label",              OP_EDIT_LABEL,                  NULL },
+  { "edit-label",              OP_EDIT_LABEL,                  "Y" },
   { "edit-type",               OP_EDIT_TYPE,                   "\005" },
   { "forward-message",         OP_FORWARD_MESSAGE,             "f" },
 #ifdef USE_NNTP
@@ -237,7 +237,7 @@ const struct binding_t OpPager[] = { /* map: pager */
   { "set-flag",        OP_MAIN_SET_FLAG,               "w" },
   { "clear-flag",       OP_MAIN_CLEAR_FLAG,            "W" },
   { "edit",            OP_EDIT_MESSAGE,                "e" },
-  { "edit-label",      OP_EDIT_LABEL,                  NULL },
+  { "edit-label",      OP_EDIT_LABEL,                  "Y" },
   { "edit-type",       OP_EDIT_TYPE,                   "\005" },
 #ifdef USE_NNTP
   { "followup-message",        OP_FOLLOWUP,                    NULL },
index 1d73c1e949008a4b0f59e525e5c0c421d0e7e812..67e02c2fb772b26c125aced0871d699cfef0998d 100644 (file)
--- a/hcache.c
+++ b/hcache.c
@@ -454,13 +454,13 @@ dump_envelope(ENVELOPE * e, unsigned char *d, int *off, int convert)
   d = dump_char(e->message_id, d, off, 0);
   d = dump_char(e->supersedes, d, off, 0);
   d = dump_char(e->date, d, off, 0);
+  d = dump_char(e->x_label, d, off, convert);
 
   d = dump_buffer(e->spam, d, off, convert);
 
   d = dump_list(e->references, d, off, 0);
   d = dump_list(e->in_reply_to, d, off, 0);
   d = dump_list(e->userhdrs, d, off, convert);
-  d = dump_list(e->labels, d, off, convert);
 
 #ifdef USE_NNTP
   d = dump_char(e->xref, d, off, 0);
@@ -497,13 +497,13 @@ restore_envelope(ENVELOPE * e, const unsigned char *d, int *off, int convert)
   restore_char(&e->message_id, d, off, 0);
   restore_char(&e->supersedes, d, off, 0);
   restore_char(&e->date, d, off, 0);
+  restore_char(&e->x_label, d, off, convert);
 
   restore_buffer(&e->spam, d, off, convert);
 
   restore_list(&e->references, d, off, 0);
   restore_list(&e->in_reply_to, d, off, 0);
   restore_list(&e->userhdrs, d, off, convert);
-  restore_list(&e->labels, d, off, convert);
 
 #ifdef USE_NNTP
   restore_char(&e->xref, d, off, 0);
index 77e58e28e70f38f7b84131e382ac6d83de52b553..f72cfc3be7f0a108980b53564a0e5208c88c4c91 100644 (file)
--- a/hdrline.c
+++ b/hdrline.c
@@ -1135,57 +1135,42 @@ hdr_format_str (char *dest,
 
      case 'y':
        if (optional)
-        optional = hdr->env->labels ? 1 : 0;
+        optional = hdr->env->x_label ? 1 : 0;
 
        colorlen = add_index_color (dest, destlen, flags, MT_COLOR_INDEX_LABEL);
-       mutt_format_s (dest + colorlen, destlen - colorlen, prefix, mutt_labels(NULL, 0, hdr->env, NULL));
+       mutt_format_s (dest + colorlen, destlen - colorlen, prefix, NONULL (hdr->env->x_label));
        add_index_color (dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX);
        break;
  
     case 'Y':
-      if (hdr->env->labels == NULL)
+      if (hdr->env->x_label)
       {
-        if (optional)
-          optional = 0;
-        mutt_format_s(dest, destlen, prefix, "");
-        break;
+       i = 1;  /* reduce reuse recycle */
+       htmp = NULL;
+       if (flags & MUTT_FORMAT_TREE
+           && (hdr->thread->prev && hdr->thread->prev->message
+               && hdr->thread->prev->message->env->x_label))
+         htmp = hdr->thread->prev->message;
+       else if (flags & MUTT_FORMAT_TREE
+                && (hdr->thread->parent && hdr->thread->parent->message
+                    && hdr->thread->parent->message->env->x_label))
+         htmp = hdr->thread->parent->message;
+       if (htmp && mutt_strcasecmp (hdr->env->x_label,
+                                    htmp->env->x_label) == 0)
+         i = 0;
       }
       else
-      {
-        char labels[HUGE_STRING];
-        char labelstmp[HUGE_STRING];
-
-        i = 1;  /* reduce reuse recycle */
-        htmp = NULL;
-        if ((flags & MUTT_FORMAT_TREE) &&
-            hdr->thread->prev &&
-            hdr->thread->prev->message &&
-            hdr->thread->prev->message->env->labels)
-          htmp = hdr->thread->prev->message;
-        else if ((flags & MUTT_FORMAT_TREE) &&
-                 hdr->thread->parent &&
-                 hdr->thread->parent->message &&
-                 hdr->thread->parent->message->env->labels)
-          htmp = hdr->thread->parent->message;
-
-        mutt_labels(labels, sizeof(labels), hdr->env, NULL);
-        if (htmp)
-        {
-          mutt_labels(labelstmp, sizeof(labelstmp), htmp->env, NULL);
-          if (htmp && mutt_strcasecmp (labels, labelstmp) == 0)
-            i = 0;
-        }
+       i = 0;
 
-        if (optional)
-         optional = i;
+      if (optional)
+       optional = i;
 
-        colorlen = add_index_color (dest, destlen, flags, MT_COLOR_INDEX_LABEL);
-        if (i)
-         mutt_format_s (dest + colorlen, destlen - colorlen, prefix, labels);
-        else
-          mutt_format_s (dest + colorlen, destlen - colorlen, prefix, "");
-        add_index_color (dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX);
-      }
+      colorlen = add_index_color (dest, destlen, flags, MT_COLOR_INDEX_LABEL);
+      if (i)
+        mutt_format_s (dest + colorlen, destlen - colorlen, prefix, NONULL (hdr->env->x_label));
+      else
+        mutt_format_s (dest + colorlen, destlen - colorlen, prefix, "");
+      add_index_color (dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX);
 
       break;
 
index 13f92a0fe6f2a69ed5e58618eb18ae54c0c693a5..e51f5b41d462c853d938f499870698b177afb8c1 100644 (file)
--- a/headers.c
+++ b/headers.c
 #include <string.h>
 #include <ctype.h>
 
-/* The labels are used as keys in the Labels hash.
- * The keys must have a longer lifespan than the hash.
- */
-static LIST *LabelList = NULL;
-
 void mutt_edit_headers (const char *editor,
                        const char *body,
                        HEADER *msg,
@@ -220,176 +215,25 @@ void mutt_edit_headers (const char *editor,
   }
 }
 
-/**
- * label_add - Add to a list of all labels
- * @label: Label name to keep
- *
- * Add an item to our LIST of all labels.
- *
- * The keys in the Label HASH must have a longer lifespan than the HASH itself.
- * We keep them in an (inefficient) linked list.
- *
- * Note: We don't check for duplicates.
- *
- * Returns:
- *      NULL  on error
- *      LIST* new LIST item, on success
- */
-static LIST *label_add (const char *label)
-{
-  if (!label)
-    return NULL;
-
-  LIST *n = mutt_new_list();
-
-  /* Insert our new LIST item at the front */
-  n->data = safe_strdup (label);
-  n->next = LabelList;
-  LabelList = n;
-
-  return n;
-}
-
-/**
- * label_delete - Delete from a list of all labels
- * @label: Label name to remove
- *
- * Delete an item from our LIST of all labels.
- *
- * The keys in the Label HASH must have a longer lifespan than the HASH itself.
- * We keep them in an (inefficient) linked list.
- */
-static void label_delete (const char *label)
-{
-  if (!label || !LabelList)
-    return;
-
-  LIST *l;
-  LIST **prev;
-
-  for (l = LabelList, prev = &LabelList; l; prev = &l->next, l = l->next)
-  {
-    if (mutt_strcmp (label, l->data) == 0)
-    {
-      *prev = l->next;
-      FREE(&l->data);
-      FREE(&l);
-      break;
-    }
-  }
-}
-
-void mutt_label_ref_dec(ENVELOPE *env)
-{
-  uintptr_t count;
-  LIST *label;
-
-  if (!env || !env->labels || !Labels)
-    return;
-
-  for (label = env->labels; label; label = label->next)
-  {
-    if (label->data == NULL)
-      continue;
-
-    count = (uintptr_t)hash_find(Labels, label->data);
-    count--;
-    if (count > 0)
-    {
-      /* Existing label, decrease refcount */
-      hash_set_data (Labels, label->data, (void*) count);
-    }
-    else
-    {
-      /* Old label */
-      hash_delete(Labels, label->data, NULL, NULL);
-      label_delete (label->data);
-    }
-
-    mutt_debug (1, "--label %s: %d\n", label->data, count);
-  }
-}
-
-void mutt_label_ref_inc(ENVELOPE *env)
-{
-  uintptr_t count;
-  LIST *label;
-
-  if (!env || !env->labels || !Labels)
-    return;
-
-  for (label = env->labels; label; label = label->next)
-  {
-    if (label->data == NULL)
-      continue;
-
-    count = (uintptr_t) hash_find(Labels, label->data);
-    count++;
-    if (count > 1)
-    {
-      /* Existing label, increase refcount */
-      hash_set_data (Labels, label->data, (void*) count);
-    }
-    else
-    {
-      /* New label */
-      const char *dup_label = safe_strdup (label->data);
-      label_add (dup_label);
-      hash_insert(Labels, dup_label, (void *) count, 0);
-    }
-
-    mutt_debug (1, "++label %s: %d\n", label->data, count);
-  }
-}
-
 /*
- * set labels on a message
+ * add an X-Label: field.
  */
-static int label_message(HEADER *hdr, const char *new)
+static int label_message(HEADER *hdr, char *new)
 {
   if (hdr == NULL)
     return 0;
-  if (hdr->env->labels == NULL && new == NULL)
+  if (hdr->env->x_label == NULL && new == NULL)
     return 0;
-  if (hdr->env->labels != NULL && new != NULL)
-  {
-    char old[HUGE_STRING];
-    mutt_labels(old, sizeof(old), hdr->env, NULL);
-    if (!strcmp(old, new))
-      return 0;
-  }
-
-  if (hdr->env->labels != NULL)
-  {
-    mutt_label_ref_dec(hdr->env);
-    mutt_free_list(&hdr->env->labels);
-  }
-
-  if ((new != NULL) && (*new != '\0'))
-  {
-    char *last, *label;
-    char copy[LONG_STRING];
-
-    /* We take a copy because we're going to alter it */
-    strfcpy (copy, new, sizeof(copy));
-
-    for (label = strtok_r(copy, ",", &last); label;
-         label = strtok_r(NULL, ",", &last)) 
-    {
-      SKIPWS(label);
-      if (mutt_find_list(hdr->env->labels, label))
-        continue;
-      if (hdr->env->labels == NULL)
-      {
-        hdr->env->labels = mutt_new_list();
-        hdr->env->labels->data = safe_strdup(label);
-      }
-      else
-        mutt_add_list(hdr->env->labels, label);
-    }
-    mutt_label_ref_inc(hdr->env);
-  }
-  return hdr->changed = hdr->label_changed = 1;
+  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)
@@ -399,31 +243,15 @@ int mutt_label_message(HEADER *hdr)
   int changed;
 
   *buf = '\0';
-  if (hdr != NULL && hdr->env->labels != NULL)
-    mutt_labels(buf, sizeof(buf)-2, hdr->env, NULL);
-
-  /* add a comma-space so that new typing is a new keyword */
-  if (buf[0])
-    strcat(buf, ", ");    /* __STRCAT_CHECKED__ */
+  if (hdr != NULL && hdr->env->x_label != NULL) {
+    strncpy(buf, hdr->env->x_label, LONG_STRING);
+  }
 
-  if (mutt_get_field("Label: ", buf, sizeof(buf), MUTT_LABEL /* | MUTT_CLEAR */) != 0)
+  if (mutt_get_field("Label: ", buf, sizeof(buf), 0 /* | MUTT_CLEAR */) != 0)
     return 0;
 
   new = buf;
   SKIPWS(new);
-  if (new && *new)
-  {
-    char *p;
-    int len = strlen(new);
-    p = &new[len]; /* '\0' */
-    while (p > new)
-    {
-      if (!isspace((unsigned char)*(p-1)) && *(p-1) != ',')
-        break;
-      p--;
-    }
-    *p = '\0';
-  }
   if (*new == '\0')
     new = NULL;
 
@@ -436,59 +264,11 @@ int mutt_label_message(HEADER *hdr)
       if (HDR_OF(i)->tagged)
         if (label_message(HDR_OF(i), new)) {
           ++changed;
+          mutt_set_flag(Context, HDR_OF(i),
+            MUTT_TAG, 0);
         }
     }
   }
 
   return changed;
 }
-
-/* scan a context (mailbox) and hash all labels we find */
-void mutt_scan_labels(CONTEXT *ctx)
-{
-  int i;
-
-  if (!ctx)
-    return;
-
-  for (i = 0; i < ctx->msgcount; i++)
-    if (ctx->hdrs[i]->env->labels)
-      mutt_label_ref_inc(ctx->hdrs[i]->env);
-}
-
-
-char *mutt_labels(char *dst, int sz, ENVELOPE *env, char *sep)
-{
-  static char sbuf[HUGE_STRING];
-  int off = 0;
-  int len;
-  LIST *label;
-
-  if (sep == NULL)
-    sep = ", ";
-
-  if (dst == NULL)
-  {
-    dst = sbuf;
-    sz = sizeof(sbuf);
-  }
-
-  *dst = '\0';
-
-  for (label = env->labels; label; label = label->next)
-  {
-    if (label->data == NULL)
-      continue;
-    len = MIN(mutt_strlen(label->data), sz-off);
-    strfcpy(&dst[off], label->data, len+1);
-    off += len;
-    if (label->next)
-    {
-      len = MIN(mutt_strlen(sep), sz-off);
-      strfcpy(&dst[off], sep, len+1);
-      off += len;
-    }
-  }
-
-  return dst;
-}
index 39b6961b4db164afe6049f5af006e82af693447b..01427a206d4ff294f4112cb34ef6bc811d26ae4f 100644 (file)
@@ -1240,7 +1240,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge)
        * 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->label_changed)
+         h->attach_del || h->xlabel_changed)
       {
         mutt_message (_("Saving changed messages... [%d/%d]"), n+1,
                       ctx->msgcount);
@@ -1250,7 +1250,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge)
          mutt_debug (1, "imap_sync_mailbox: Error opening mailbox in append mode\n");
        else
          _mutt_save_message (h, appendctx, 1, 0, 0);
-       h->label_changed = 0;
+       h->xlabel_changed = 0;
       }
     }
   }
diff --git a/main.c b/main.c
index 94bcffe9784d85dfeefc33024fe1459f752ce7d5..81ae6fea4d8ef07db16fa599de88bf08ec78450c 100644 (file)
--- a/main.c
+++ b/main.c
@@ -899,7 +899,6 @@ int main (int argc, char **argv, char **environ)
       mutt_sb_set_open_buffy ();
 #endif
       Labels = hash_create (131, 0);
-      mutt_scan_labels(Context);
       mutt_index_menu ();
       if (Context)
        FREE (&Context);
diff --git a/mh.c b/mh.c
index 8384ad19233de8ea319102bc1758720b14b0ce46..ece6818aff28160199ba4d98b06cbde646bb00cb 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -1842,7 +1842,7 @@ static int mh_sync_message (CONTEXT * ctx, int msgno)
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || h->label_changed ||
+  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;
@@ -1854,7 +1854,7 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || h->label_changed ||
+  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. */
@@ -1961,7 +1961,7 @@ int mh_sync_mailbox_message (CONTEXT * ctx, int msgno)
       }
     }
     else if (h->changed || h->attach_del ||
-            h->label_changed ||
+            h->xlabel_changed ||
             (ctx->magic == MUTT_MAILDIR
              && (option (OPTMAILDIRTRASH) || h->trash)
              && (h->deleted != h->trash)))
diff --git a/mutt.h b/mutt.h
index 0b95c8fd09fc4fec34b73bfafceafc68ab126a98..4d0c7a2734f6d98578c9c60ebccf4d0f3fc94857 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -730,7 +730,6 @@ typedef struct envelope
   LIST *references;            /* message references (in reverse order) */
   LIST *in_reply_to;           /* in-reply-to header content */
   LIST *userhdrs;              /* user defined headers */
-  LIST *labels;
   int kwtypes;
 
   unsigned int irt_changed : 1; /* In-Reply-To changed to link/break threads */
@@ -876,7 +875,7 @@ typedef struct header
                                         * This flag is used by the maildir_trash
                                         * option.
                                         */
-  unsigned int label_changed : 1;      /* editable - used for syncing */
+  unsigned int xlabel_changed : 1;     /* editable - used for syncing */
   
   /* timezone of the sender of this message */
   unsigned int zhours : 5;
index 9a875a10a0ec2bf142d8aeb22028f5ddcf9d8d90..04884c55f74097fc65782bbe02a93bc30106aee6 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -823,8 +823,6 @@ void mutt_free_envelope (ENVELOPE **p)
   mutt_free_list (&(*p)->references);
   mutt_free_list (&(*p)->in_reply_to);
   mutt_free_list (&(*p)->userhdrs);
-  mutt_label_ref_dec ((*p));
-  mutt_free_list (&(*p)->labels);
   FREE (p);            /* __FREE_CHECKED__ */
 }
 
@@ -847,7 +845,7 @@ void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra)
   MOVE_ELEM(message_id);
   MOVE_ELEM(supersedes);
   MOVE_ELEM(date);
-  MOVE_ELEM(labels);
+  MOVE_ELEM(x_label);
   MOVE_ELEM(x_original_to);
   if (!base->refs_changed)
   {
diff --git a/pager.c b/pager.c
index b3b472269b62caa0b9155493ae45dd3034998fd9..77382d23186f8b8a5d671d6e18aad318da4225ef 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -3071,20 +3071,6 @@ search_next:
        redraw = REDRAW_FULL;
        break;
 
-     case OP_EDIT_LABEL:
-        CHECK_MODE(IsHeader (extra));
-        rc = mutt_label_message(extra->hdr);
-        if (rc > 0) {
-         if (Context)
-           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))
         {
@@ -3097,6 +3083,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 labels changed."), rc);
+        }
+        else {
+          mutt_message (_("No labels changed."));
+        }
+        break;
 
       case OP_FORGET_PASSPHRASE:
        crypt_forget_passphrase ();
diff --git a/parse.c b/parse.c
index 9ce4b420c0737deff6fa2a756f83c4f983c70ea3..bf47b1fff04fc0a80c70246c7072290104580f94 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -982,7 +982,6 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short
 {
   int matched = 0;
   LIST *last = NULL;
-  int kwtype = 0;
   
   if (lastp)
     last = *lastp;
@@ -1101,13 +1100,6 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short
     }
     break;
 
-    case 'k':
-    if (!ascii_strcasecmp (line+1, "eywords"))
-    {
-      kwtype = MUTT_KEYWORDS;
-    }
-    break;
-
     case 'l':
     if (!ascii_strcasecmp (line + 1, "ines"))
     {
@@ -1308,15 +1300,9 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short
     }
     else if (ascii_strcasecmp (line+1, "-label") == 0)
     {
-      kwtype = MUTT_X_LABEL;
-    }
-    else if (!ascii_strcasecmp (line+1, "-keywords"))
-    {
-      kwtype = MUTT_X_KEYWORDS;
-    }
-    else if (!ascii_strcasecmp (line+1, "-mozilla-keys"))
-    {
-      kwtype = MUTT_X_MOZILLA_KEYS;
+      FREE(&e->x_label);
+      e->x_label = safe_strdup(p);
+      matched = 1;
     }
 #ifdef USE_NNTP
     else if (!ascii_strcasecmp (line + 1, "-comment-to"))
@@ -1363,53 +1349,6 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short
       rfc2047_decode (&last->data);
   }
 
-  if (kwtype)
-  {
-    char *last, *label;
-    char *text = safe_strdup(p);
-    char *sep;
-
-    if (kwtype == MUTT_KEYWORDS)
-      sep = ",";
-    else if (kwtype == MUTT_X_LABEL)
-      sep = XlabelDelim;
-    else
-      sep = " ";
-
-    rfc2047_decode(&text);
-    if (sep == NULL || *sep == '\0')
-    {
-      SKIPWS(text);
-      if (!mutt_find_list(e->labels, text))
-      {
-        if (e->labels)
-          mutt_add_list(e->labels, text);
-        else
-        {
-          e->labels = mutt_new_list();
-          e->labels->data = safe_strdup(text);
-        }
-      }
-    }
-    else for (label = strtok_r(text, sep, &last); label;
-              label = strtok_r(NULL, sep, &last))
-    {
-      SKIPWS(label);
-      if (mutt_find_list(e->labels, label))
-        continue;
-      if (e->labels)
-        mutt_add_list(e->labels, label);
-      else
-      {
-        e->labels = mutt_new_list();
-        e->labels->data = safe_strdup(label);
-      }
-    }
-    e->kwtypes |= kwtype;
-    kwtype = 0;
-    matched = 1;
-  }
-
   done:
   
   *lastp = last;
index 9f4c5681374cbd89cf25898d7db3e5938b12af0a..6de0b55a4d28c3ef65ecffdf36cbe6eca410dec0 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1638,19 +1638,7 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx,
        break;
      return (pat->not ^ ((h->security & APPLICATION_PGP) && (h->security & PGPKEY)));
     case MUTT_XLABEL:
-      {
-        LIST *label;
-        int result = 0;
-        for (label = h->env->labels; label; label = label->next)
-        {
-          if (label->data == NULL)
-            continue;
-          result = patmatch (pat, label->data) == 0;
-          if (result)
-            break;
-        }
-        return pat->not ^ result;
-      }
+      return (pat->not ^ (h->env->x_label && patmatch (pat, h->env->x_label) == 0));
 #ifdef USE_NOTMUCH
     case MUTT_NOTMUCH_LABEL:
       {
index 7653c82548e1569ea6ed21c17547fc538e5d3797..1304e40351b9b6756c52a836870147bc29ae2409 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -196,12 +196,11 @@ void mutt_edit_content_type (HEADER *, BODY *, FILE *);
 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 **);
-void mutt_label_ref_dec(ENVELOPE *);
-void mutt_label_ref_inc(ENVELOPE *);
 int mutt_label_message (HEADER *);
-void mutt_scan_labels (CONTEXT *);
+void mutt_make_label_hash (CONTEXT *);
+void mutt_label_hash_add (CONTEXT *ctx, HEADER *hdr);
+void mutt_label_hash_remove (CONTEXT *ctx, HEADER *hdr);
 int mutt_label_complete (char *, size_t, int, int);
-char *mutt_labels(char *, int, ENVELOPE *, char *);
 void mutt_curses_error (const char *, ...);
 void mutt_curses_message (const char *, ...);
 void mutt_encode_descriptions (BODY *, short);
diff --git a/sort.c b/sort.c
index 11c03cf79084931ef623e5d40a74504c50d5b6f0..6418afbc24779f3fafd4eb7f911db3b9573b88fe 100644 (file)
--- a/sort.c
+++ b/sort.c
@@ -233,13 +233,12 @@ int compare_label (const void *a, const void *b)
   HEADER **ppa = (HEADER **) a;
   HEADER **ppb = (HEADER **) b;
   int     ahas, bhas, result = 0;
-  LIST *la, *lb;
 
   /* 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->labels;
-  bhas = (*ppb)->env && (*ppb)->env->labels;
+  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)
@@ -255,16 +254,7 @@ int compare_label (const void *a, const void *b)
   }
 
   /* If both have a label, we just do a lexical compare. */
-  for (la = (*ppa)->env->labels, lb = (*ppb)->env->labels;
-       la && la->data && lb && lb->data && result == 0;
-       la = la->next, lb = lb->next)
-  {
-    result = mutt_strcasecmp(la->data, lb->data);
-  }
-  if (result == 0 && la == NULL)
-    return (SORTCODE(-1));
-  if (result == 0 && lb == NULL)
-    return (SORTCODE(1));
+  result = mutt_strcasecmp((*ppa)->env->x_label, (*ppb)->env->x_label);
   return (SORTCODE(result));
 }