From 92e6dc1d89f7187eeea1412e51598600925e23f5 Mon Sep 17 00:00:00 2001 From: David Champion Date: Sat, 28 Jan 2017 18:47:15 -0800 Subject: [PATCH] Adds capability to edit x-labels inside mutt, and to sort by label. --- copy.c | 62 ++--------- curs_main.c | 3 +- doc/manual.xml.head | 6 ++ functions.h | 4 +- hcache.c | 4 +- hdrline.c | 65 +++++------ headers.c | 258 ++++---------------------------------------- imap/imap.c | 4 +- main.c | 1 - mh.c | 6 +- mutt.h | 3 +- muttlib.c | 4 +- pager.c | 26 +++-- parse.c | 67 +----------- pattern.c | 14 +-- protos.h | 7 +- sort.c | 16 +-- 17 files changed, 94 insertions(+), 456 deletions(-) diff --git a/copy.c b/copy.c index 0b4c0344b..faf383894 100644 --- 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) diff --git a/curs_main.c b/curs_main.c index 04bfdcf11..75f61d95d 100644 --- a/curs_main.c +++ b/curs_main.c @@ -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.")); diff --git a/doc/manual.xml.head b/doc/manual.xml.head index 20bd9f88c..dcf92a1d0 100644 --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -6985,6 +6985,12 @@ field. When set to yes, the Reply-To field will be used when present. + +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. + + Lastly, Mutt has the ability to sort the mailbox into threads. A thread is a diff --git a/functions.h b/functions.h index 2d5090e0e..b09a53702 100644 --- a/functions.h +++ b/functions.h @@ -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 }, diff --git a/hcache.c b/hcache.c index 1d73c1e94..67e02c2fb 100644 --- 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); diff --git a/hdrline.c b/hdrline.c index 77e58e28e..f72cfc3be 100644 --- 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; diff --git a/headers.c b/headers.c index 13f92a0fe..e51f5b41d 100644 --- a/headers.c +++ b/headers.c @@ -28,11 +28,6 @@ #include #include -/* 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; -} diff --git a/imap/imap.c b/imap/imap.c index 39b6961b4..01427a206 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -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 94bcffe97..81ae6fea4 100644 --- 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 8384ad192..ece6818af 100644 --- 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 0b95c8fd0..4d0c7a273 100644 --- 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; diff --git a/muttlib.c b/muttlib.c index 9a875a10a..04884c55f 100644 --- 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 b3b472269..77382d231 100644 --- 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 9ce4b420c..bf47b1fff 100644 --- 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; diff --git a/pattern.c b/pattern.c index 9f4c56813..6de0b55a4 100644 --- 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: { diff --git a/protos.h b/protos.h index 7653c8254..1304e4035 100644 --- 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 11c03cf79..6418afbc2 100644 --- 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)); } -- 2.40.0