📄 compose.c
字号:
/* * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org> * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_curses.h"#include "mutt_idna.h"#include "mutt_menu.h"#include "rfc1524.h"#include "mime.h"#include "attach.h"#include "mapping.h"#include "mailbox.h"#include "sort.h"#include "charset.h"#ifdef MIXMASTER#include "remailer.h"#endif#include <errno.h>#include <string.h>#include <sys/stat.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.h>static const char* There_are_no_attachments = N_("There are no attachments.");#define CHECK_COUNT if (idxlen == 0) { mutt_error _(There_are_no_attachments); break; }enum{ HDR_FROM = 1, HDR_TO, HDR_CC, HDR_BCC, HDR_SUBJECT, HDR_REPLYTO, HDR_FCC,#ifdef MIXMASTER HDR_MIX,#endif HDR_CRYPT, HDR_CRYPTINFO, HDR_ATTACH = (HDR_FCC + 5) /* where to start printing the attachments */};#define HDR_XOFFSET 10#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */#define W (COLS - HDR_XOFFSET)static char *Prompts[] ={ "From: ", "To: ", "Cc: ", "Bcc: ", "Subject: ", "Reply-To: ", "Fcc: "};static struct mapping_t ComposeHelp[] = { { N_("Send"), OP_COMPOSE_SEND_MESSAGE }, { N_("Abort"), OP_EXIT }, { "To", OP_COMPOSE_EDIT_TO }, { "CC", OP_COMPOSE_EDIT_CC }, { "Subj", OP_COMPOSE_EDIT_SUBJECT }, { N_("Attach file"), OP_COMPOSE_ATTACH_FILE }, { N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION }, { N_("Help"), OP_HELP }, { NULL }};static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num){ mutt_FormatString (b, blen, NONULL (AttachFormat), mutt_attach_fmt, (unsigned long)(((ATTACHPTR **) menu->data)[num]), M_FORMAT_STAT_FILE | M_FORMAT_ARROWCURSOR);}#include "mutt_crypt.h"static void redraw_crypt_lines (HEADER *msg){ int off = 0; if ((WithCrypto & APPLICATION_PGP) && (WithCrypto & APPLICATION_SMIME)) { if (!msg->security) mvaddstr (HDR_CRYPT, 0, "Security: "); else if (msg->security & APPLICATION_SMIME) mvaddstr (HDR_CRYPT, 0, " S/MIME: "); else if (msg->security & APPLICATION_PGP) mvaddstr (HDR_CRYPT, 0, " PGP: "); } else if ((WithCrypto & APPLICATION_SMIME)) mvaddstr (HDR_CRYPT, 0, " S/MIME: "); else if ((WithCrypto & APPLICATION_PGP)) mvaddstr (HDR_CRYPT, 0, " PGP: "); else return; if ((msg->security & (ENCRYPT | SIGN)) == (ENCRYPT | SIGN)) addstr (_("Sign, Encrypt")); else if (msg->security & ENCRYPT) addstr (_("Encrypt")); else if (msg->security & SIGN) addstr (_("Sign")); else addstr (_("Clear")); if ((WithCrypto & APPLICATION_PGP)) if ((msg->security & APPLICATION_PGP) && (msg->security & (ENCRYPT | SIGN))) { if ((msg->security & INLINE)) addstr (_(" (inline)")); else addstr (_(" (PGP/MIME)")); } clrtoeol (); move (HDR_CRYPTINFO, 0); clrtoeol (); if ((WithCrypto & APPLICATION_PGP) && msg->security & APPLICATION_PGP && msg->security & SIGN) printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("<default>")); if ((WithCrypto & APPLICATION_SMIME) && msg->security & APPLICATION_SMIME && msg->security & SIGN) { printw ("%s%s", _(" sign as: "), SmimeDefaultKey ? SmimeDefaultKey : _("<default>")); } if ((WithCrypto & APPLICATION_SMIME) && (msg->security & APPLICATION_SMIME) && (msg->security & ENCRYPT) && SmimeCryptAlg && *SmimeCryptAlg) { mvprintw (HDR_CRYPTINFO, 40, "%s%s", _("Encrypt with: "), NONULL(SmimeCryptAlg)); off = 20; }}#ifdef MIXMASTERstatic void redraw_mix_line (LIST *chain){ int c; char *t; mvaddstr (HDR_MIX, 0, " Mix: "); if (!chain) { addstr ("<no chain defined>"); clrtoeol (); return; } for (c = 12; chain; chain = chain->next) { t = chain->data; if (t && t[0] == '0' && t[1] == '\0') t = "<random>"; if (c + mutt_strlen (t) + 2 >= COLS) break; addstr (NONULL(t)); if (chain->next) addstr (", "); c += mutt_strlen (t) + 2; }}#endif /* MIXMASTER */static intcheck_attachments(ATTACHPTR **idx, short idxlen){ int i, r; struct stat st; char pretty[_POSIX_PATH_MAX], msg[_POSIX_PATH_MAX + SHORT_STRING]; for (i = 0; i < idxlen; i++) { strfcpy(pretty, idx[i]->content->filename, sizeof(pretty)); if(stat(idx[i]->content->filename, &st) != 0) { mutt_pretty_mailbox(pretty); mutt_error(_("%s [#%d] no longer exists!"), pretty, i+1); return -1; } if(idx[i]->content->stamp < st.st_mtime) { mutt_pretty_mailbox(pretty); snprintf(msg, sizeof(msg), _("%s [#%d] modified. Update encoding?"), pretty, i+1); if((r = mutt_yesorno(msg, M_YES)) == M_YES) mutt_update_encoding(idx[i]->content); else if(r == -1) return -1; } } return 0;}static void draw_envelope_addr (int line, ADDRESS *addr){ char buf[STRING]; buf[0] = 0; rfc822_write_address (buf, sizeof (buf), addr, 1); mvprintw (line, 0, TITLE_FMT, Prompts[line - 1]); mutt_paddstr (W, buf);}static void draw_envelope (HEADER *msg, char *fcc){ draw_envelope_addr (HDR_FROM, msg->env->from); draw_envelope_addr (HDR_TO, msg->env->to); draw_envelope_addr (HDR_CC, msg->env->cc); 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)); draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to); mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]); mutt_paddstr (W, fcc); if (WithCrypto) redraw_crypt_lines (msg);#ifdef MIXMASTER redraw_mix_line (msg->chain);#endif SETCOLOR (MT_COLOR_STATUS); mvaddstr (HDR_ATTACH - 1, 0, _("-- Attachments")); BKGDSET (MT_COLOR_STATUS); clrtoeol (); BKGDSET (MT_COLOR_NORMAL); SETCOLOR (MT_COLOR_NORMAL);}static int edit_address_list (int line, ADDRESS **addr){ char buf[HUGE_STRING] = ""; /* needs to be large for alias expansion */ char *err = NULL; mutt_addrlist_to_local (*addr); rfc822_write_address (buf, sizeof (buf), *addr, 0); if (mutt_get_field (Prompts[line - 1], buf, sizeof (buf), M_ALIAS) == 0) { rfc822_free_address (addr); *addr = mutt_parse_adrlist (*addr, buf); *addr = mutt_expand_aliases (*addr); } if (option (OPTNEEDREDRAW)) { unset_option (OPTNEEDREDRAW); return (REDRAW_FULL); } if (mutt_addrlist_to_idna (*addr, &err) != 0) { mutt_error (_("Warning: '%s' is a bad IDN."), err); mutt_refresh(); FREE (&err); } /* redraw the expanded list so the user can see the result */ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), *addr, 1); move (line, HDR_XOFFSET); mutt_paddstr (W, buf); return 0;}static int delete_attachment (MUTTMENU *menu, short *idxlen, int x){ ATTACHPTR **idx = (ATTACHPTR **) menu->data; int y; menu->redraw = REDRAW_INDEX | REDRAW_STATUS; if (x == 0 && menu->max == 1) { mutt_error _("You may not delete the only attachment."); idx[x]->content->tagged = 0; return (-1); } for (y = 0; y < *idxlen; y++) { if (idx[y]->content->next == idx[x]->content) { idx[y]->content->next = idx[x]->content->next; break; } } idx[x]->content->next = NULL; idx[x]->content->parts = NULL; mutt_free_body (&(idx[x]->content)); FREE (&idx[x]->tree); FREE (&idx[x]); for (; x < *idxlen - 1; x++) idx[x] = idx[x+1]; menu->max = --(*idxlen); return (0);}static void update_idx (MUTTMENU *menu, ATTACHPTR **idx, short idxlen){ idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0; if (idxlen) idx[idxlen - 1]->content->next = idx[idxlen]->content; idx[idxlen]->content->aptr = idx[idxlen]; menu->current = idxlen++; mutt_update_tree (idx, idxlen); menu->max = idxlen; return;}/* * cum_attachs_size: Cumulative Attachments Size * * Returns the total number of bytes used by the attachments in the * attachment list _after_ content-transfer-encodings have been * applied. * */static unsigned long cum_attachs_size (MUTTMENU *menu){ size_t s; unsigned short i; ATTACHPTR **idx = menu->data; CONTENT *info; BODY *b; for (i = 0, s = 0; i < menu->max; i++) { b = idx[i]->content; if (!b->content) b->content = mutt_get_content_info (b->filename, b); if ((info = b->content)) { switch (b->encoding) { case ENCQUOTEDPRINTABLE: s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf; break; case ENCBASE64: s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3; break; default: s += info->lobin + info->hibin + info->ascii + info->crlf; break; } } } return s;}/* prototype for use below */static void compose_status_line (char *buf, size_t buflen, MUTTMENU *menu, const char *p);/* * compose_format_str() * * %a = total number of attachments * %h = hostname [option] * %l = approx. length of current message (in bytes) * %v = Mutt version * * This function is similar to status_format_str(). Look at that function for * help when modifying this function. */static const char *compose_format_str (char *buf, size_t buflen, char op, const char *src, const char *prefix, const char *ifstring, const char *elsestring, unsigned long data, format_flag flags){ char fmt[SHORT_STRING], tmp[SHORT_STRING]; int optional = (flags & M_FORMAT_OPTIONAL); MUTTMENU *menu = (MUTTMENU *) data; *buf = 0; switch (op) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -