📄 mx.c
字号:
{ mutt_perror (tmp); snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); rmdir (tmp); snprintf (tmp, sizeof (tmp), "%s/new", ctx->path); rmdir (tmp); rmdir (ctx->path); return (-1); } } else { int i; snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", ctx->path); if ((i = creat (tmp, S_IRWXU)) == -1) { mutt_perror (tmp); rmdir (ctx->path); return (-1); } close (i); } } } else { mutt_perror (ctx->path); return (-1); } switch (ctx->magic) { case M_MBOX: case M_MMDF: if ((ctx->fp = safe_fopen (ctx->path, flags & M_NEWFOLDER ? "w" : "a")) == NULL || mbox_lock_mailbox (ctx, 1, 1) != 0) { if (!ctx->fp) mutt_perror (ctx->path); else { mutt_error (_("Couldn't lock %s\n"), ctx->path); safe_fclose (&ctx->fp); } return (-1); } fseek (ctx->fp, 0, 2); break; case M_MH: case M_MAILDIR: /* nothing to do */ break; default: return (-1); } return 0;}/* * open a mailbox and parse it * * Args: * flags M_NOSORT do not sort mailbox * M_APPEND open mailbox for appending * M_READONLY open mailbox in read-only mode * M_QUIET only print error messages * ctx if non-null, context struct to use */CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx){ CONTEXT *ctx = pctx; int rc; if (!ctx) ctx = safe_malloc (sizeof (CONTEXT)); memset (ctx, 0, sizeof (CONTEXT)); ctx->path = safe_strdup (path); ctx->msgnotreadyet = -1; ctx->collapsed = 0; if (flags & M_QUIET) ctx->quiet = 1; if (flags & M_READONLY) ctx->readonly = 1; if (flags & (M_APPEND|M_NEWFOLDER)) { if (mx_open_mailbox_append (ctx, flags) != 0) { mx_fastclose_mailbox (ctx); if (!pctx) FREE (&ctx); return NULL; } return ctx; } ctx->magic = mx_get_magic (path); if(ctx->magic == 0) mutt_error (_("%s is not a mailbox."), path); if(ctx->magic == -1) mutt_perror(path); if(ctx->magic <= 0) { mx_fastclose_mailbox (ctx); if (!pctx) FREE (&ctx); return (NULL); } /* 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 * flag to indicate that we should really refresh the screen. */ set_option (OPTFORCEREFRESH); if (!ctx->quiet) mutt_message (_("Reading %s..."), ctx->path); switch (ctx->magic) { case M_MH: rc = mh_read_dir (ctx, NULL); break; case M_MAILDIR: rc = maildir_read_dir (ctx); break; case M_MMDF: case M_MBOX: rc = mbox_open_mailbox (ctx); break;#ifdef USE_IMAP case M_IMAP: rc = imap_open_mailbox (ctx); break;#endif /* USE_IMAP */#ifdef USE_POP case M_POP: rc = pop_open_mailbox (ctx); break;#endif /* USE_POP */ default: rc = -1; break; } if (rc == 0) { if ((flags & M_NOSORT) == 0) { /* avoid unnecessary work since the mailbox is completely unthreaded to begin with */ unset_option (OPTSORTSUBTHREADS); unset_option (OPTNEEDRESCORE); mutt_sort_headers (ctx, 1); } if (!ctx->quiet) mutt_clear_error (); } else { mx_fastclose_mailbox (ctx); if (!pctx) FREE (&ctx); } unset_option (OPTFORCEREFRESH); return (ctx);}/* free up memory associated with the mailbox context */void mx_fastclose_mailbox (CONTEXT *ctx){ int i; if(!ctx) return; #ifdef USE_IMAP if (ctx->magic == M_IMAP) imap_close_mailbox (ctx);#endif /* USE_IMAP */#ifdef USE_POP if (ctx->magic == M_POP) pop_close_mailbox (ctx);#endif /* USE_POP */ if (ctx->subj_hash) hash_destroy (&ctx->subj_hash, NULL); if (ctx->id_hash) hash_destroy (&ctx->id_hash, NULL); mutt_clear_threads (ctx); for (i = 0; i < ctx->msgcount; i++) mutt_free_header (&ctx->hdrs[i]); FREE (&ctx->hdrs); FREE (&ctx->v2r); FREE (&ctx->path); FREE (&ctx->pattern); if (ctx->limit_pattern) mutt_pattern_free (&ctx->limit_pattern); safe_fclose (&ctx->fp); memset (ctx, 0, sizeof (CONTEXT));}/* save changes to disk */static int sync_mailbox (CONTEXT *ctx, int *index_hint){#ifdef BUFFY_SIZE BUFFY *tmp = NULL;#endif int rc = -1; if (!ctx->quiet) mutt_message (_("Writing %s..."), ctx->path); switch (ctx->magic) { case M_MBOX: case M_MMDF: rc = mbox_sync_mailbox (ctx, index_hint);#ifdef BUFFY_SIZE tmp = mutt_find_mailbox (ctx->path);#endif break; case M_MH: case M_MAILDIR: rc = mh_sync_mailbox (ctx, index_hint); break; #ifdef USE_IMAP case M_IMAP: /* extra argument means EXPUNGE */ rc = imap_sync_mailbox (ctx, 1, index_hint); break;#endif /* USE_IMAP */#ifdef USE_POP case M_POP: rc = pop_sync_mailbox (ctx, index_hint); break;#endif /* USE_POP */ }#if 0 if (!ctx->quiet && !ctx->shutup && rc == -1) mutt_error ( _("Could not synchronize mailbox %s!"), ctx->path);#endif #ifdef BUFFY_SIZE if (tmp && tmp->new == 0) mutt_update_mailbox (tmp);#endif return rc;}/* save changes and close mailbox */int mx_close_mailbox (CONTEXT *ctx, int *index_hint){ int i, move_messages = 0, purge = 1, read_msgs = 0; int check; int isSpool = 0; CONTEXT f; char mbox[_POSIX_PATH_MAX]; char buf[SHORT_STRING]; if (!ctx) return 0; ctx->closing = 1; if (ctx->readonly || ctx->dontwrite) { /* mailbox is readonly or we don't want to write */ mx_fastclose_mailbox (ctx); return 0; } if (ctx->append) { /* mailbox was opened in write-mode */ if (ctx->magic == M_MBOX || ctx->magic == M_MMDF) mbox_close_mailbox (ctx); else mx_fastclose_mailbox (ctx); return 0; } for (i = 0; i < ctx->msgcount; i++) { if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) read_msgs++; } if (read_msgs && quadoption (OPT_MOVE) != M_NO) { char *p; if ((p = mutt_find_hook (M_MBOXHOOK, ctx->path))) { isSpool = 1; strfcpy (mbox, p, sizeof (mbox)); } else { strfcpy (mbox, NONULL(Inbox), sizeof (mbox)); isSpool = mutt_is_spool (ctx->path) && !mutt_is_spool (mbox); } mutt_expand_path (mbox, sizeof (mbox)); if (isSpool) { snprintf (buf, sizeof (buf), _("Move read messages to %s?"), mbox); if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1) { ctx->closing = 0; return (-1); } } } /* * There is no point in asking whether or not to purge if we are * just marking messages as "trash". */ if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) { snprintf (buf, sizeof (buf), ctx->deleted == 1 ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"), ctx->deleted); if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) { ctx->closing = 0; return (-1); } } if (option (OPTMARKOLD)) { for (i = 0; i < ctx->msgcount; i++) { if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old && !ctx->hdrs[i]->read) mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1); } } if (move_messages) { mutt_message (_("Moving read messages to %s..."), mbox);#ifdef USE_IMAP /* try to use server-side copy first */ i = 1; if (ctx->magic == M_IMAP && mx_is_imap (mbox)) { /* tag messages for moving, and clear old tags, if any */ for (i = 0; i < ctx->msgcount; i++) if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) ctx->hdrs[i]->tagged = 1; else ctx->hdrs[i]->tagged = 0; i = imap_copy_messages (ctx, NULL, mbox, 1); } if (i == 0) /* success */ mutt_clear_error (); else if (i == -1) /* horrible error, bail */ { ctx->closing=0; return -1; } else /* use regular append-copy mode */#endif { if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL) { ctx->closing = 0; return -1; } for (i = 0; i < ctx->msgcount; i++) { if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) { if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0) { mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1); } else { mx_close_mailbox (&f, NULL); ctx->closing = 0; return -1; } } } mx_close_mailbox (&f, NULL); } } else if (!ctx->changed && ctx->deleted == 0) { mutt_message _("Mailbox is unchanged."); mx_fastclose_mailbox (ctx); return 0; } #ifdef USE_IMAP /* allow IMAP to preserve the deleted flag across sessions */ if (ctx->magic == M_IMAP) { if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0) { ctx->closing = 0; return check; } } else#endif { if (!purge) { for (i = 0; i < ctx->msgcount; i++) ctx->hdrs[i]->deleted = 0; ctx->deleted = 0; } if (ctx->changed || ctx->deleted) { if ((check = sync_mailbox (ctx, index_hint)) != 0) { ctx->closing = 0; return check; } } } if (move_messages) mutt_message (_("%d kept, %d moved, %d deleted."), ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted); else mutt_message (_("%d kept, %d deleted."), ctx->msgcount - ctx->deleted, ctx->deleted); if (ctx->msgcount == ctx->deleted && (ctx->magic == M_MMDF || ctx->magic == M_MBOX) && !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) mx_unlink_empty (ctx->path); mx_fastclose_mailbox (ctx); return 0;}/* update a Context structure's internal tables. */void mx_update_tables(CONTEXT *ctx, int committing){ int i, j; /* update memory to reflect the new state of the mailbox */ ctx->vcount = 0; ctx->vsize = 0; ctx->tagged = 0; ctx->deleted = 0; ctx->new = 0; ctx->unread = 0; ctx->changed = 0; ctx->flagged = 0;#define this_body ctx->hdrs[j]->content for (i = 0, j = 0; i < ctx->msgcount; i++) { if ((committing && (!ctx->hdrs[i]->deleted || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))) || (!committing && ctx->hdrs[i]->active)) { if (i != j) { ctx->hdrs[j] = ctx->hdrs[i]; ctx->hdrs[i] = NULL; } ctx->hdrs[j]->msgno = j; if (ctx->hdrs[j]->virtual != -1) { ctx->v2r[ctx->vcount] = j; ctx->hdrs[j]->virtual = ctx->vcount++; ctx->vsize += this_body->length + this_body->offset - this_body->hdr_offset; } if (committing) ctx->hdrs[j]->changed = 0; else if (ctx->hdrs[j]->changed) ctx->changed++; if (!committing || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) { if (ctx->hdrs[j]->deleted) ctx->deleted++; } if (ctx->hdrs[j]->tagged) ctx->tagged++; if (ctx->hdrs[j]->flagged) ctx->flagged++; if (!ctx->hdrs[j]->read) { ctx->unread++; if (!ctx->hdrs[j]->old) ctx->new++; } j++; } else { if (ctx->magic == M_MH || ctx->magic == M_MAILDIR) ctx->size -= (ctx->hdrs[i]->content->length + ctx->hdrs[i]->content->offset - ctx->hdrs[i]->content->hdr_offset); /* remove message from the hash tables */ if (ctx->subj_hash && ctx->hdrs[i]->env->real_subj) 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_free_header (&ctx->hdrs[i]); } }#undef this_body ctx->msgcount = j;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -