FREE (&Context);
}
- if (Labels)
- hash_destroy(&Labels, NULL);
-
mutt_sleep (0);
/* Set CurrentMenu to MENU_MAIN before executing any folder
(option (OPTREADONLY) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ?
MUTT_READONLY : 0, NULL)) != NULL)
{
- Labels = hash_create(131, 0);
- mutt_scan_labels(Context);
menu->current = ci_first_message ();
}
else
WHERE const char *ReleaseDate;
WHERE HASH *Groups;
-WHERE HASH *Labels;
WHERE HASH *ReverseAlias;
WHERE LIST *AutoViewList INITVAL(0);
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
+#include <stdint.h>
void mutt_edit_headers (const char *editor,
const char *body,
}
}
-static void label_ref_dec(char *label)
+static void label_ref_dec(CONTEXT *ctx, char *label)
{
+ struct hash_elem *elem;
uintptr_t count;
- count = (uintptr_t)hash_find(Labels, label);
- if (count)
+ elem = hash_find_elem (ctx->label_hash, label);
+ if (!elem)
+ return;
+
+ count = (uintptr_t)elem->data;
+ if (count <= 1)
{
- hash_delete(Labels, label, NULL, NULL);
- count--;
- if (count > 0)
- hash_insert(Labels, label, (void *)count, 0);
+ hash_delete(ctx->label_hash, label, NULL, NULL);
+ return;
}
+
+ count--;
+ elem->data = (void *)count;
}
-static void label_ref_inc(char *label)
+static void label_ref_inc(CONTEXT *ctx, char *label)
{
+ struct hash_elem *elem;
uintptr_t count;
- count = (uintptr_t)hash_find(Labels, label);
- if (count)
- hash_delete(Labels, label, NULL, NULL);
- count++; /* was zero if not found */
- hash_insert(Labels, label, (void *)count, 0);
+ elem = hash_find_elem (ctx->label_hash, label);
+ if (!elem)
+ {
+ count = 1;
+ hash_insert(ctx->label_hash, label, (void *)count, 0);
+ return;
+ }
+
+ count = (uintptr_t)elem->data;
+ count++;
+ elem->data = (void *)count;
}
/*
* add an X-Label: field.
*/
-static int label_message(HEADER *hdr, char *new)
+static int label_message(CONTEXT *ctx, HEADER *hdr, char *new)
{
if (hdr == NULL)
return 0;
if (mutt_strcmp (hdr->env->x_label, new) == 0)
return 0;
+
if (hdr->env->x_label != NULL)
- label_ref_dec(hdr->env->x_label);
+ label_ref_dec(ctx, hdr->env->x_label);
mutt_str_replace (&hdr->env->x_label, new);
if (hdr->env->x_label != NULL)
- label_ref_inc(hdr->env->x_label);
+ label_ref_inc(ctx, hdr->env->x_label);
+
return hdr->changed = hdr->xlabel_changed = 1;
}
int i;
int changed;
+ if (!Context || !Context->label_hash)
+ return 0;
+
*buf = '\0';
if (hdr != NULL && hdr->env->x_label != NULL) {
strncpy(buf, hdr->env->x_label, LONG_STRING);
changed = 0;
if (hdr != NULL) {
- changed += label_message(hdr, new);
+ changed += label_message(Context, 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)) {
+ if (label_message(Context, 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)
+void mutt_make_label_hash (CONTEXT *ctx)
{
- int i;
+ /* 131 is just a rough prime estimate of how many distinct
+ * labels someone might have in a mailbox.
+ */
+ ctx->label_hash = hash_create(131, MUTT_HASH_STRDUP_KEYS);
+}
- for (i = 0; i < ctx->msgcount; i++)
- if (ctx->hdrs[i]->env->x_label)
- label_ref_inc(ctx->hdrs[i]->env->x_label);
+void mutt_label_hash_add (CONTEXT *ctx, HEADER *hdr)
+{
+ if (!ctx || !ctx->label_hash)
+ return;
+ if (hdr->env->x_label)
+ label_ref_inc (ctx, hdr->env->x_label);
}
+void mutt_label_hash_remove (CONTEXT *ctx, HEADER *hdr)
+{
+ if (!ctx || !ctx->label_hash)
+ return;
+ if (hdr->env->x_label)
+ label_ref_dec (ctx, hdr->env->x_label);
+}
char *pt = buffer;
int spaces; /* keep track of the number of leading spaces on the line */
+ if (!Context || !Context->label_hash)
+ return 0;
+
SKIPWS (buffer);
spaces = buffer - pt;
memset (Matches, 0, Matches_listsize);
memset (Completed, 0, sizeof (Completed));
memset (&state, 0, sizeof(state));
- while ((entry = hash_walk(Labels, &state)))
+ while ((entry = hash_walk(Context->label_hash, &state)))
candidate (Completed, User_typed, entry->key.strkey, sizeof (Completed));
matches_ensure_morespace (Num_matched);
qsort(Matches, Num_matched, sizeof(char *), (sort_t *) mutt_strcasecmp);
if((Context = mx_open_mailbox (folder, ((flags & MUTT_RO) || option (OPTREADONLY)) ? MUTT_READONLY : 0, NULL))
|| !explicit_folder)
{
- Labels = hash_create (131, 0);
- mutt_scan_labels(Context);
#ifdef USE_SIDEBAR
mutt_sb_set_open_buffy ();
#endif
mutt_index_menu ();
if (Context)
FREE (&Context);
- if (Labels)
- hash_destroy(&Labels, NULL);
}
#ifdef USE_IMAP
imap_logout_all ();
hash_destroy (&ctx->id_hash, NULL);
if (ctx->subj_hash)
hash_destroy (&ctx->subj_hash, NULL);
+ hash_destroy (&ctx->label_hash, NULL);
mutt_clear_threads (ctx);
FREE (&ctx->v2r);
if (ctx->readonly)
ctx->changed = 0;
ctx->id_hash = NULL;
ctx->subj_hash = NULL;
+ mutt_make_label_hash (ctx);
switch (ctx->magic)
{
HASH *id_hash; /* hash table by msg id */
HASH *subj_hash; /* hash table by subject */
HASH *thread_hash; /* hash table for threading */
+ HASH *label_hash; /* hash table for x-labels */
int *v2r; /* mapping from virtual to real msgno */
int hdrmax; /* number of pointers in hdrs */
int msgcount; /* number of messages in the mailbox */
FREE (&ctx);
return (NULL);
}
-
+
+ mutt_make_label_hash (ctx);
+
/* if the user has a `push' command in their .muttrc, or in a folder-hook,
* it will cause the progress messages not to be displayed because
* mutt_refresh() will think we are in the middle of a macro. so set a
hash_destroy (&ctx->subj_hash, NULL);
if (ctx->id_hash)
hash_destroy (&ctx->id_hash, NULL);
+ hash_destroy (&ctx->label_hash, NULL);
mutt_clear_threads (ctx);
for (i = 0; i < ctx->msgcount; i++)
mutt_free_header (&ctx->hdrs[i]);
hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, ctx->hdrs[i], NULL);
if (ctx->id_hash && ctx->hdrs[i]->env->message_id)
hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id, ctx->hdrs[i], NULL);
+ mutt_label_hash_remove (ctx, ctx->hdrs[i]);
/* The path mx_check_mailbox() -> imap_check_mailbox() ->
* imap_expunge_mailbox() -> mx_update_tables()
* can occur before a call to mx_sync_mailbox(), resulting in
hash_insert (ctx->id_hash, h->env->message_id, h, 0);
if (ctx->subj_hash && h->env->real_subj)
hash_insert (ctx->subj_hash, h->env->real_subj, h, 1);
+ mutt_label_hash_add (ctx, h);
if (option (OPTSCORE))
mutt_score_message (ctx, h, 0);
/* we replace envelop, key in subj_hash has to be updated as well */
if (ctx->subj_hash && h->env->real_subj)
hash_delete (ctx->subj_hash, h->env->real_subj, h, NULL);
+ mutt_label_hash_remove (ctx, h);
mutt_free_envelope (&h->env);
h->env = mutt_read_rfc822_header (msg->fp, h, 0, 0);
if (ctx->subj_hash && h->env->real_subj)
hash_insert (ctx->subj_hash, h->env->real_subj, h, 1);
+ mutt_label_hash_add (ctx, h);
h->data = uidl;
h->lines = 0;
void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);
int mutt_filter_unprintable (char **);
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);
void mutt_curses_error (const char *, ...);
void mutt_curses_message (const char *, ...);