NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
Compose Function API

Prototype for a Compose Function. More...

+ Collaboration diagram for Compose Function API:

Functions

static int op_attach_attach_file (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Attach files to this message - Implements compose_function_t -.
 
static int op_attach_attach_key (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Attach a PGP public key - Implements compose_function_t -.
 
static int op_attach_attach_message (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Attach messages to this message - Implements compose_function_t -.
 
static int op_attach_detach (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Delete the current entry - Implements compose_function_t -.
 
static int op_attach_edit_content_id (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit the 'Content-ID' of the attachment - Implements compose_function_t -.
 
static int op_attach_edit_description (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit attachment description - Implements compose_function_t -.
 
static int op_attach_edit_encoding (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit attachment transfer-encoding - Implements compose_function_t -.
 
static int op_attach_edit_language (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit the 'Content-Language' of the attachment - Implements compose_function_t -.
 
static int op_attach_edit_mime (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit attachment using mailcap entry - Implements compose_function_t -.
 
static int op_attach_edit_type (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit attachment content type - Implements compose_function_t -.
 
static int op_attach_filter (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Filter attachment through a shell command - Implements compose_function_t -.
 
static int op_attach_get_attachment (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Get a temporary copy of an attachment - Implements compose_function_t -.
 
static int op_attach_group_alts (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Group selected attachments as 'multipart/alternative' - Implements compose_function_t -.
 
static int op_attach_group_lingual (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Group selected attachments as 'multipart/multilingual' - Implements compose_function_t -.
 
static int op_attach_group_related (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Group selected attachments as 'multipart/related' - Implements compose_function_t -.
 
static int op_attach_move_down (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Move an attachment down in the attachment list - Implements compose_function_t -.
 
static int op_attach_move_up (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Move an attachment up in the attachment list - Implements compose_function_t -.
 
static int op_attach_new_mime (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Compose new attachment using mailcap entry - Implements compose_function_t -.
 
static int op_attach_print (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Print the current entry - Implements compose_function_t -.
 
static int op_attach_rename_attachment (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Send attachment with a different name - Implements compose_function_t -.
 
static int op_attach_save (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Save message/attachment to a mailbox/file - Implements compose_function_t -.
 
static int op_attach_toggle_disposition (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Toggle disposition between inline/attachment - Implements compose_function_t -.
 
static int op_attach_toggle_recode (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Toggle recoding of this attachment - Implements compose_function_t -.
 
static int op_attach_toggle_unlink (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Toggle whether to delete file after sending it - Implements compose_function_t -.
 
static int op_attach_ungroup (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Ungroup a 'multipart' attachment - Implements compose_function_t -.
 
static int op_attach_update_encoding (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Update an attachment's encoding info - Implements compose_function_t -.
 
static int op_envelope_edit_headers (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit the message with headers - Implements compose_function_t -.
 
static int op_compose_edit_file (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit the file to be attached - Implements compose_function_t -.
 
static int op_compose_edit_message (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Edit the message - Implements compose_function_t -.
 
static int op_compose_ispell (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Run ispell on the message - Implements compose_function_t -.
 
static int op_compose_postpone_message (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Save this message to send later - Implements compose_function_t -.
 
static int op_compose_rename_file (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Rename/move an attached file - Implements compose_function_t -.
 
static int op_compose_send_message (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Send the message - Implements compose_function_t -.
 
static int op_compose_write_message (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Write the message to a folder - Implements compose_function_t -.
 
static int op_display_headers (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Display message and toggle header weeding - Implements compose_function_t -.
 
static int op_quit (struct ComposeFunctionData *fdata, const struct KeyEvent *event)
 Save changes and exit this dialog - Implements compose_function_t -.
 

Detailed Description

Prototype for a Compose Function.

Parameters
fdataCompose Function context data
eventEvent to process
Return values
enumFunctionRetval
Precondition
fdata is not NULL
event is not NULL

Function Documentation

◆ op_attach_attach_file()

static int op_attach_attach_file ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Attach files to this message - Implements compose_function_t -.

Definition at line 1023 of file functions.c.

1024{
1025 struct ComposeSharedData *shared = fdata->shared;
1026 char *prompt = _("Attach file");
1027 int numfiles = 0;
1028 char **files = NULL;
1029
1030 struct Buffer *fname = buf_pool_get();
1031 if ((mw_enter_fname(prompt, fname, false, NULL, true, &files, &numfiles,
1032 MUTT_SEL_MULTI) == -1) ||
1033 buf_is_empty(fname))
1034 {
1035 for (int i = 0; i < numfiles; i++)
1036 FREE(&files[i]);
1037
1038 FREE(&files);
1039 buf_pool_release(&fname);
1040 return FR_NO_ACTION;
1041 }
1042
1043 bool error = false;
1044 bool added_attachment = false;
1045 if (numfiles > 1)
1046 {
1047 mutt_message(ngettext("Attaching selected file...",
1048 "Attaching selected files...", numfiles));
1049 }
1050 for (int i = 0; i < numfiles; i++)
1051 {
1052 char *att = files[i];
1053 if (!att)
1054 continue;
1055
1056 struct AttachPtr *ap = mutt_aptr_new();
1057 ap->unowned = true;
1058 ap->body = mutt_make_file_attach(att, shared->sub);
1059 if (ap->body)
1060 {
1061 added_attachment = true;
1062 update_idx(shared->adata->menu, shared->adata->actx, ap);
1063 }
1064 else
1065 {
1066 error = true;
1067 mutt_error(_("Unable to attach %s"), att);
1068 mutt_aptr_free(&ap);
1069 }
1070 FREE(&files[i]);
1071 }
1072
1073 FREE(&files);
1074 buf_pool_release(&fname);
1075
1076 if (!error)
1078
1081 if (added_attachment)
1082 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1083 return added_attachment ? FR_SUCCESS : (error ? FR_ERROR : FR_NO_ACTION);
1084}
struct AttachPtr * mutt_aptr_new(void)
Create a new Attachment Pointer.
Definition attach.c:40
void mutt_aptr_free(struct AttachPtr **ptr)
Free an Attachment Pointer.
Definition attach.c:49
@ MUTT_SEL_MULTI
Multi-selection is enabled.
Definition lib.h:61
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
@ CMD_SEND2_HOOK
:send2-hook
Definition command.h:109
static void update_idx(struct Menu *menu, struct AttachCtx *actx, struct AttachPtr *ap)
Add a new attachment to the message.
Definition functions.c:466
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
@ NT_EMAIL_CHANGE_ATTACH
Email's Attachments have changed.
Definition email.h:188
int mw_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file -.
Definition curs_lib.c:237
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
void exec_message_hook(struct Mailbox *m, struct Email *e, enum CommandId id)
Perform a message hook.
Definition exec.c:137
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition menu.c:177
@ MENU_REDRAW_INDEX
Redraw the index.
Definition lib.h:61
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
@ NT_EMAIL
Email has changed, NotifyEmail, EventEmail.
Definition notify_type.h:44
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition sendlib.c:617
An email to which things will be attached.
Definition attach.h:36
struct Body * body
Attachment.
Definition attach.h:37
bool unowned
Don't unlink on detach.
Definition attach.h:43
String manipulation buffer.
Definition buffer.h:36
struct Menu * menu
Menu displaying the attachments.
Definition attach_data.h:35
struct AttachCtx * actx
Set of attachments.
Definition attach_data.h:34
struct ComposeSharedData * shared
Shared Compose data.
Definition functions.h:36
Shared Compose Data.
Definition shared_data.h:35
struct ConfigSubset * sub
Config set to use.
Definition shared_data.h:36
struct ComposeAttachData * adata
Attachments.
Definition shared_data.h:39
struct Email * email
Email being composed.
Definition shared_data.h:38
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition email.h:73
+ Here is the call graph for this function:

◆ op_attach_attach_key()

static int op_attach_attach_key ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Attach a PGP public key - Implements compose_function_t -.

Definition at line 1089 of file functions.c.

1090{
1091 struct ComposeSharedData *shared = fdata->shared;
1092 if (!(WithCrypto & APPLICATION_PGP))
1093 return FR_NOT_IMPL;
1094 struct AttachPtr *ap = mutt_aptr_new();
1096 if (ap->body)
1097 {
1098 update_idx(shared->adata->menu, shared->adata->actx, ap);
1100 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1101 }
1102 else
1103 {
1104 mutt_aptr_free(&ap);
1105 }
1106
1108 return FR_SUCCESS;
1109}
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition cryptglue.c:349
@ FR_NOT_IMPL
Invalid function - feature not enabled.
Definition dispatcher.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define WithCrypto
Definition lib.h:132
+ Here is the call graph for this function:

◆ op_attach_attach_message()

static int op_attach_attach_message ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Attach messages to this message - Implements compose_function_t -.

This function handles:

  • OP_ATTACH_ATTACH_MESSAGE
  • OP_ATTACH_ATTACH_NEWS_MESSAGE

Definition at line 1118 of file functions.c.

1120{
1122 struct ComposeSharedData *shared = fdata->shared;
1123 char *prompt = _("Open mailbox to attach message from");
1124
1125 OptNews = false;
1126 const int op = event->op;
1127 if (shared->mailbox && (op == OP_ATTACH_ATTACH_NEWS_MESSAGE))
1128 {
1129 const char *const c_news_server = cs_subset_string(shared->sub, "news_server");
1130 mod_data->current_news_srv = nntp_select_server(shared->mailbox, c_news_server, false);
1131 if (!mod_data->current_news_srv)
1132 return FR_NO_ACTION;
1133
1134 prompt = _("Open newsgroup to attach message from");
1135 OptNews = true;
1136 }
1137
1138 struct Buffer *fname = buf_pool_get();
1139 if (shared->mailbox)
1140 {
1141 if ((op == OP_ATTACH_ATTACH_MESSAGE) ^ (shared->mailbox->type == MUTT_NNTP))
1142 {
1143 buf_strcpy(fname, mailbox_path(shared->mailbox));
1144 pretty_mailbox(fname);
1145 }
1146 }
1147
1148 if ((mw_enter_fname(prompt, fname, true, shared->mailbox, false, NULL, NULL,
1149 MUTT_SEL_NONE) == -1) ||
1150 buf_is_empty(fname))
1151 {
1152 buf_pool_release(&fname);
1153 return FR_NO_ACTION;
1154 }
1155
1156 if (OptNews)
1157 nntp_expand_path(fname->data, fname->dsize,
1158 &mod_data->current_news_srv->conn->account);
1159 else
1160 expand_path(fname, false);
1161
1162 if (imap_path_probe(buf_string(fname), NULL) != MUTT_IMAP)
1163 {
1164 if (pop_path_probe(buf_string(fname), NULL) != MUTT_POP)
1165 {
1166 if (!OptNews && (nntp_path_probe(buf_string(fname), NULL) != MUTT_NNTP))
1167 {
1168 if (mx_path_probe(buf_string(fname)) != MUTT_NOTMUCH)
1169 {
1170 /* check to make sure the file exists and is readable */
1171 if (access(buf_string(fname), R_OK) == -1)
1172 {
1173 mutt_perror("%s", buf_string(fname));
1174 buf_pool_release(&fname);
1175 return FR_ERROR;
1176 }
1177 }
1178 }
1179 }
1180 }
1181
1183
1184 struct Mailbox *m_attach = mx_path_resolve(buf_string(fname));
1185 const bool old_readonly = m_attach->readonly;
1186 if (!mx_mbox_open(m_attach, MUTT_READONLY))
1187 {
1188 mutt_error(_("Unable to open mailbox %s"), buf_string(fname));
1189 mx_fastclose_mailbox(m_attach, false);
1190 m_attach = NULL;
1191 buf_pool_release(&fname);
1192 return FR_ERROR;
1193 }
1194 buf_pool_release(&fname);
1195
1196 if (m_attach->msg_count == 0)
1197 {
1198 mx_mbox_close(m_attach);
1199 mutt_error(_("No messages in that folder"));
1200 return FR_ERROR;
1201 }
1202
1203 /* `$sort`, `$sort_aux`, `$use_threads` could be changed in dlg_index() */
1204 const enum EmailSortType old_sort = cs_subset_sort(shared->sub, "sort");
1205 const enum EmailSortType old_sort_aux = cs_subset_sort(shared->sub, "sort_aux");
1206 const unsigned char old_use_threads = cs_subset_enum(shared->sub, "use_threads");
1207
1208 mutt_message(_("Tag the messages you want to attach"));
1209 struct MuttWindow *dlg = index_pager_init();
1210 struct IndexSharedData *index_shared = dlg->wdata;
1211 index_shared->attach_msg = true;
1212 dialog_push(dlg);
1213 struct Mailbox *m_attach_new = dlg_index(dlg, m_attach);
1214 dialog_pop();
1215 mutt_window_free(&dlg);
1216
1217 if (!shared->mailbox)
1218 {
1219 /* Restore old $sort variables */
1220 cs_subset_str_native_set(shared->sub, "sort", old_sort, NULL);
1221 cs_subset_str_native_set(shared->sub, "sort_aux", old_sort_aux, NULL);
1222 cs_subset_str_native_set(shared->sub, "use_threads", old_use_threads, NULL);
1225 return FR_SUCCESS;
1226 }
1227
1228 bool added_attachment = false;
1229 for (int i = 0; i < m_attach_new->msg_count; i++)
1230 {
1231 if (!m_attach_new->emails[i])
1232 break;
1233 if (!message_is_tagged(m_attach_new->emails[i]))
1234 continue;
1235
1236 struct AttachPtr *ap = mutt_aptr_new();
1237 ap->body = mutt_make_message_attach(m_attach_new, m_attach_new->emails[i],
1238 true, shared->sub);
1239 if (ap->body)
1240 {
1241 added_attachment = true;
1242 update_idx(shared->adata->menu, shared->adata->actx, ap);
1243 }
1244 else
1245 {
1246 mutt_error(_("Unable to attach"));
1247 mutt_aptr_free(&ap);
1248 }
1249 }
1251
1252 if (m_attach_new == m_attach)
1253 {
1254 m_attach->readonly = old_readonly;
1255 }
1256 mx_fastclose_mailbox(m_attach_new, false);
1257
1258 /* Restore old $sort variables */
1259 cs_subset_str_native_set(shared->sub, "sort", old_sort, NULL);
1260 cs_subset_str_native_set(shared->sub, "sort_aux", old_sort_aux, NULL);
1261 cs_subset_str_native_set(shared->sub, "use_threads", old_use_threads, NULL);
1263 if (added_attachment)
1264 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1265 return added_attachment ? FR_SUCCESS : FR_ERROR;
1266}
@ MUTT_SEL_NONE
No flags are set.
Definition lib.h:59
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:50
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:51
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:48
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition dialog.c:109
void dialog_pop(void)
Hide a Window from the user.
Definition dialog.c:148
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition dlg_index.c:1462
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
bool OptNews
(pseudo) used to change reader mode
Definition globals.c:53
struct Mailbox * dlg_index(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails -.
Definition dlg_index.c:1121
#define mutt_perror(...)
Definition logging2.h:95
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox?
Definition nntp.c:2797
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox?
Definition pop.c:1177
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2683
@ MENU_REDRAW_FULL
Redraw everything.
Definition lib.h:64
@ MODULE_ID_NNTP
ModuleNntp, Nntp
Definition module_api.h:83
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition mview.c:363
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition mx.c:411
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition mx.c:1326
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1650
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:595
@ MUTT_READONLY
Open in read-only mode.
Definition mxapi.h:45
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition newsrc.c:559
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition newsrc.c:957
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
Create a message attachment.
Definition sendlib.c:456
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition shared_data.h:37
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
Data shared between Index, Pager and Sidebar.
Definition shared_data.h:37
bool attach_msg
Are we in "attach message" mode?
Definition shared_data.h:46
A mailbox.
Definition mailbox.h:81
int msg_count
Total number of messages.
Definition mailbox.h:90
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
bool readonly
Don't allow changes to the mailbox.
Definition mailbox.h:118
void * wdata
Private data.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct Connection * conn
Connection to NNTP Server.
Definition adata.h:63
Nntp private Module data.
Definition module_data.h:30
struct NntpAccountData * current_news_srv
Current NNTP news server.
Definition module_data.h:32
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
+ Here is the call graph for this function:

◆ op_attach_detach()

static int op_attach_detach ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Delete the current entry - Implements compose_function_t -.

Definition at line 1271 of file functions.c.

1272{
1273 struct ComposeSharedData *shared = fdata->shared;
1274 struct AttachCtx *actx = shared->adata->actx;
1275 if (!check_count(actx))
1276 return FR_ERROR;
1277
1278 struct Menu *menu = shared->adata->menu;
1279 int rc = FR_NO_ACTION;
1280 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1281 aa_add_selection(&aa, actx, menu, menu->tag_prefix, event->count);
1282
1283 if (ARRAY_SIZE(&aa) > 1)
1284 {
1285 for (int i = ARRAY_SIZE(&aa) - 1; i >= 0; i--)
1286 {
1287 struct AttachPtr **app = ARRAY_GET(&aa, i);
1288 if (!app || !*app)
1289 continue;
1290 struct AttachPtr *ap = *app;
1291
1292 if (ap->unowned)
1293 ap->body->unlink = false;
1294
1295 const int index = body_index(actx, ap->body);
1296 if ((index >= 0) && (delete_attachment(actx, index, fdata->n->sub) == 0))
1297 rc = FR_SUCCESS;
1298 }
1299
1300 if (rc != FR_SUCCESS)
1301 {
1302 menu->num_tagged = 0;
1303 for (int i = 0; i < actx->idxlen; i++)
1304 {
1305 if (actx->idx[i]->body->tagged)
1306 menu->num_tagged++;
1307 }
1308 update_menu(actx, menu, false);
1309 ARRAY_FREE(&aa);
1310 return FR_ERROR;
1311 }
1312 }
1313 else
1314 {
1315 struct AttachPtr *cur_att = current_attachment(actx, menu);
1316 if (cur_att->unowned)
1317 cur_att->body->unlink = false;
1318
1319 const int index = menu_get_index(menu);
1320 if (delete_attachment(actx, index, fdata->n->sub) == -1)
1321 {
1322 menu->num_tagged = 0;
1323 for (int i = 0; i < actx->idxlen; i++)
1324 {
1325 if (actx->idx[i]->body->tagged)
1326 menu->num_tagged++;
1327 }
1328 update_menu(actx, menu, false);
1329 ARRAY_FREE(&aa);
1330 return FR_ERROR;
1331 }
1332
1333 rc = FR_SUCCESS;
1334 }
1335
1336 if (rc == FR_SUCCESS)
1338
1339 menu->num_tagged = 0;
1340 for (int i = 0; i < actx->idxlen; i++)
1341 {
1342 if (actx->idx[i]->body->tagged)
1343 menu->num_tagged++;
1344 }
1345
1346 update_menu(actx, menu, false);
1348
1349 const int index = menu_get_index(menu);
1350 if (index == 0)
1351 shared->email->body = actx->idx[0]->body;
1352
1353 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1354 ARRAY_FREE(&aa);
1355 return rc;
1356}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
static bool check_count(struct AttachCtx *actx)
Check if there are any attachments.
Definition functions.c:234
static int body_index(struct AttachCtx *actx, const struct Body *b)
Find the index of an attachment body.
Definition functions.c:557
static MenuRedrawFlags selection_redraw_flags(size_t count)
Choose redraw flags for a selection.
Definition functions.c:675
static int delete_attachment(struct AttachCtx *actx, int aidx, struct ConfigSubset *sub)
Delete an attachment.
Definition functions.c:377
void update_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Redraw the compose window.
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:153
struct AttachPtr * current_attachment(struct AttachCtx *actx, struct Menu *menu)
Get the current attachment.
Definition recvattach.c:71
int aa_add_selection(struct AttachPtrArray *aa, struct AttachCtx *actx, struct Menu *menu, bool use_tagged, int count)
Build a working set of Attachments for an action.
Definition selection.c:125
A set of attachments.
Definition attach.h:65
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:69
short idxlen
Number of attachmentes.
Definition attach.h:70
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition body.h:68
bool tagged
This attachment is tagged.
Definition body.h:90
struct NeoMutt * n
NeoMutt application data.
Definition functions.h:34
struct Body * body
List of MIME parts.
Definition email.h:69
int count
Optional count prefix, e.g. 3 for 3j
Definition get.h:78
Definition lib.h:86
int num_tagged
Number of tagged entries.
Definition lib.h:101
bool tag_prefix
User has pressed <tag-prefix>
Definition lib.h:92
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:

◆ op_attach_edit_content_id()

static int op_attach_edit_content_id ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit the 'Content-ID' of the attachment - Implements compose_function_t -.

Definition at line 1361 of file functions.c.

1363{
1364 struct ComposeSharedData *shared = fdata->shared;
1365 struct AttachCtx *actx = shared->adata->actx;
1366 if (!check_count(actx))
1367 return FR_ERROR;
1368
1369 int rc = FR_NO_ACTION;
1370 struct Menu *menu = shared->adata->menu;
1371 const int index = menu_get_index(menu);
1372 struct Buffer *buf = buf_pool_get();
1373 struct Buffer *cid = buf_pool_get();
1374 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1375 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1376 const int num = ARRAY_SIZE(&ba);
1377
1378 struct AttachPtr *cur_att = current_attachment(actx, menu);
1379
1380 char *id = cur_att->body->content_id;
1381 if (id)
1382 {
1383 buf_strcpy(buf, id);
1384 }
1385 else
1386 {
1387 id = gen_cid();
1388 buf_strcpy(buf, id);
1389 FREE(&id);
1390 }
1391
1392 if (mw_get_field("Content-ID: ", buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) == 0)
1393 {
1394 if (check_cid(buf_string(buf)))
1395 {
1396 bool changed = false;
1397 struct Body **bp = NULL;
1398 ARRAY_FOREACH(bp, &ba)
1399 {
1400 const bool multi = (ARRAY_SIZE(&ba) > 1);
1401 int suffix = multi ? (ARRAY_FOREACH_IDX_bp + 1) : 0;
1402
1403 do
1404 {
1405 if (suffix == 0)
1406 buf_strcpy(cid, buf_string(buf));
1407 else
1408 buf_printf(cid, "%s-%d", buf_string(buf), suffix);
1409
1410 suffix++;
1411 } while (content_id_exists(actx, *bp, buf_string(cid)));
1412
1413 if (!mutt_str_equal((*bp)->content_id, buf_string(cid)))
1414 {
1415 mutt_str_replace(&(*bp)->content_id, buf_string(cid));
1416 changed = true;
1417 }
1418 }
1419
1420 if (changed)
1421 {
1423 resolve_attachment(menu, shared->sub, index, num);
1425 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1426 rc = FR_SUCCESS;
1427 }
1428 }
1429 else
1430 {
1431 mutt_error(_("Content-ID can only contain the characters: -.0-9@A-Z_a-z"));
1432 rc = FR_ERROR;
1433 }
1434 }
1435
1436 ARRAY_FREE(&ba);
1437 buf_pool_release(&cid);
1438 buf_pool_release(&buf);
1439
1440 if (rc != FR_ERROR)
1442
1443 return rc;
1444}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
static char * gen_cid(void)
Generate a random Content ID.
Definition functions.c:251
static void resolve_attachment(struct Menu *menu, const struct ConfigSubset *sub, int index, int num)
Advance the Attachment List selection after an action.
Definition functions.c:692
static bool check_cid(const char *cid)
Check if a Content-ID is valid.
Definition functions.c:267
static bool content_id_exists(struct AttachCtx *actx, const struct Body *skip, const char *cid)
Check whether a Content-ID is already in use.
Definition functions.c:287
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
int ba_add_selection(struct BodyArray *ba, struct AttachCtx *actx, struct Menu *menu, bool use_tagged, int count)
Build a working set of attachment bodies for an action.
Definition selection.c:164
The body of an email.
Definition body.h:36
char * content_id
Content-Id (RFC2392)
Definition body.h:58
+ Here is the call graph for this function:

◆ op_attach_edit_description()

static int op_attach_edit_description ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit attachment description - Implements compose_function_t -.

Definition at line 1449 of file functions.c.

1451{
1452 struct ComposeSharedData *shared = fdata->shared;
1453 struct AttachCtx *actx = shared->adata->actx;
1454 if (!check_count(actx))
1455 return FR_ERROR;
1456
1457 int rc = FR_NO_ACTION;
1458 struct Menu *menu = shared->adata->menu;
1459 const int index = menu_get_index(menu);
1460 struct Buffer *buf = buf_pool_get();
1461 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1462
1463 struct AttachPtr *cur_att = current_attachment(actx, menu);
1464 buf_strcpy(buf, cur_att->body->description);
1465
1466 /* header names should not be translated */
1467 if (mw_get_field("Description: ", buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) == 0)
1468 {
1469 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1470 const int num = ARRAY_SIZE(&ba);
1471
1472 bool changed = false;
1473 struct Body **bp = NULL;
1474 ARRAY_FOREACH(bp, &ba)
1475 {
1476 if (!mutt_str_equal((*bp)->description, buf_string(buf)))
1477 {
1478 mutt_str_replace(&(*bp)->description, buf_string(buf));
1479 changed = true;
1480 }
1481 }
1482
1483 if (changed)
1484 {
1486 resolve_attachment(menu, shared->sub, index, num);
1487 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1488 rc = FR_SUCCESS;
1489 }
1490 }
1491
1492 ARRAY_FREE(&ba);
1493 buf_pool_release(&buf);
1494 return rc;
1495}
int num
Attachment index number.
Definition attach.h:42
char * description
content-description
Definition body.h:55
+ Here is the call graph for this function:

◆ op_attach_edit_encoding()

static int op_attach_edit_encoding ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit attachment transfer-encoding - Implements compose_function_t -.

Definition at line 1500 of file functions.c.

1502{
1503 struct ComposeSharedData *shared = fdata->shared;
1504 struct AttachCtx *actx = shared->adata->actx;
1505 if (!check_count(actx))
1506 return FR_ERROR;
1507
1508 int rc = FR_NO_ACTION;
1509 struct Menu *menu = shared->adata->menu;
1510 const int index = menu_get_index(menu);
1511 struct Buffer *buf = buf_pool_get();
1512 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1513
1514 struct AttachPtr *cur_att = current_attachment(actx, menu);
1515 buf_strcpy(buf, ENCODING(cur_att->body->encoding));
1516
1517 if ((mw_get_field("Content-Transfer-Encoding: ", buf, MUTT_COMP_NONE,
1518 HC_OTHER, NULL, NULL) == 0) &&
1519 !buf_is_empty(buf))
1520 {
1521 int enc = mutt_check_encoding(buf_string(buf));
1522 if ((enc != ENC_OTHER) && (enc != ENC_UUENCODED))
1523 {
1524 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1525 const int num = ARRAY_SIZE(&ba);
1526
1527 bool changed = false;
1528 struct Body **bp = NULL;
1529 ARRAY_FOREACH(bp, &ba)
1530 {
1531 if ((*bp)->encoding != enc)
1532 {
1533 (*bp)->encoding = enc;
1534 changed = true;
1535 }
1536 }
1537
1538 if (changed)
1539 {
1541 resolve_attachment(menu, shared->sub, index, num);
1544 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1545 rc = FR_SUCCESS;
1546 }
1547 }
1548 else
1549 {
1550 mutt_error(_("Invalid encoding"));
1551 rc = FR_ERROR;
1552 }
1553 }
1554
1555 ARRAY_FREE(&ba);
1556 buf_pool_release(&buf);
1557 return rc;
1558}
int mutt_check_encoding(const char *c)
Check the encoding type.
Definition parse.c:404
@ ENC_UUENCODED
UUEncoded text.
Definition mime.h:54
@ ENC_OTHER
Encoding unknown.
Definition mime.h:48
#define ENCODING(x)
Get the encoding name for an encoding type.
Definition mime.h:97
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
+ Here is the call graph for this function:

◆ op_attach_edit_language()

static int op_attach_edit_language ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit the 'Content-Language' of the attachment - Implements compose_function_t -.

Definition at line 1563 of file functions.c.

1565{
1566 struct ComposeSharedData *shared = fdata->shared;
1567 struct AttachCtx *actx = shared->adata->actx;
1568 if (!check_count(actx))
1569 return FR_ERROR;
1570
1571 int rc = FR_NO_ACTION;
1572 struct Menu *menu = shared->adata->menu;
1573 const int index = menu_get_index(menu);
1574 struct Buffer *buf = buf_pool_get();
1575 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1576 struct AttachPtr *cur_att = current_attachment(actx, menu);
1577
1578 buf_strcpy(buf, cur_att->body->language);
1579 if (mw_get_field("Content-Language: ", buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) == 0)
1580 {
1581 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1582 const int num = ARRAY_SIZE(&ba);
1583
1584 bool changed = false;
1585 struct Body **bp = NULL;
1586 ARRAY_FOREACH(bp, &ba)
1587 {
1588 if (!mutt_str_equal((*bp)->language, buf_string(buf)))
1589 {
1590 mutt_str_replace(&(*bp)->language, buf_string(buf));
1591 changed = true;
1592 }
1593 }
1594
1595 if (changed)
1596 {
1598 resolve_attachment(menu, shared->sub, index, num);
1600 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1601 rc = FR_SUCCESS;
1602 }
1604 }
1605 else
1606 {
1607 mutt_warning(_("Empty 'Content-Language'"));
1608 rc = FR_ERROR;
1609 }
1610
1611 ARRAY_FREE(&ba);
1612 buf_pool_release(&buf);
1613 return rc;
1614}
#define mutt_warning(...)
Definition logging2.h:92
char * language
content-language (RFC8255)
Definition body.h:78
+ Here is the call graph for this function:

◆ op_attach_edit_mime()

static int op_attach_edit_mime ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit attachment using mailcap entry - Implements compose_function_t -.

Definition at line 1619 of file functions.c.

1620{
1621 struct ComposeSharedData *shared = fdata->shared;
1622 struct AttachCtx *actx = shared->adata->actx;
1623 if (!check_count(actx))
1624 return FR_ERROR;
1625
1626 int rc = FR_NO_ACTION;
1627 struct Menu *menu = shared->adata->menu;
1628 const int index = menu_get_index(menu);
1629 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1630 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1631 const int num = ARRAY_SIZE(&ba);
1632 if (ARRAY_EMPTY(&ba))
1633 goto done;
1634
1635 struct Body **bp = NULL;
1636 ARRAY_FOREACH(bp, &ba)
1637 {
1638 if (!mutt_edit_attachment(*bp))
1639 continue;
1640
1641 mutt_update_encoding(*bp, shared->sub);
1642 rc = FR_SUCCESS;
1643 }
1644
1645 if (rc != FR_SUCCESS)
1646 goto done;
1647
1649 resolve_attachment(menu, shared->sub, index, num);
1650 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1651
1652done:
1653 ARRAY_FREE(&ba);
1654 return rc;
1655}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
bool mutt_edit_attachment(struct Body *b)
Edit an attachment.
void mutt_update_encoding(struct Body *b, struct ConfigSubset *sub)
Update the encoding type.
Definition sendlib.c:424
+ Here is the call graph for this function:

◆ op_attach_edit_type()

static int op_attach_edit_type ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit attachment content type - Implements compose_function_t -.

Definition at line 1660 of file functions.c.

1661{
1662 struct ComposeSharedData *shared = fdata->shared;
1663 if (!check_count(shared->adata->actx))
1664 return FR_ERROR;
1665
1666 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
1667 shared->adata->menu);
1668 if (!mutt_edit_content_type(NULL, cur_att->body, NULL))
1669 return FR_NO_ACTION;
1670
1671 /* this may have been a change to text/something */
1672 mutt_update_encoding(cur_att->body, shared->sub);
1674 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1675 return FR_SUCCESS;
1676}
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition external.c:1073
@ MENU_REDRAW_CURRENT
Redraw the current line of the menu.
Definition lib.h:63
+ Here is the call graph for this function:

◆ op_attach_filter()

static int op_attach_filter ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Filter attachment through a shell command - Implements compose_function_t -.

This function handles:

  • OP_ATTACH_FILTER
  • OP_PIPE

Definition at line 1685 of file functions.c.

1686{
1687 struct ComposeSharedData *shared = fdata->shared;
1688 struct AttachCtx *actx = shared->adata->actx;
1689 if (!check_count(actx))
1690 return FR_ERROR;
1691
1692 struct Menu *menu = shared->adata->menu;
1693 const int index = menu_get_index(menu);
1694 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1695 aa_add_selection(&aa, actx, menu, menu->tag_prefix, event->count);
1696 const int num = ARRAY_SIZE(&aa);
1697 struct AttachPtr **app = NULL;
1698 ARRAY_FOREACH(app, &aa)
1699 {
1700 if ((*app)->body->type == TYPE_MULTIPART)
1701 {
1702 ARRAY_FREE(&aa);
1703 mutt_error(_("Can't filter multipart attachments"));
1704 return FR_ERROR;
1705 }
1706 }
1707
1708 const int op = event->op;
1709 mutt_pipe_attachment_list(&aa, (op == OP_ATTACH_FILTER));
1710 if (op == OP_ATTACH_FILTER) /* cte might have changed */
1711 {
1713 }
1714 resolve_attachment(menu, shared->sub, index, num);
1715 ARRAY_FREE(&aa);
1717 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
1718 return FR_SUCCESS;
1719}
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
void mutt_pipe_attachment_list(struct AttachPtrArray *aa, bool filter)
Pipe selected attachments to a command.
Definition recvattach.c:699
+ Here is the call graph for this function:

◆ op_attach_get_attachment()

static int op_attach_get_attachment ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Get a temporary copy of an attachment - Implements compose_function_t -.

Definition at line 1724 of file functions.c.

1726{
1727 struct ComposeSharedData *shared = fdata->shared;
1728 struct AttachCtx *actx = shared->adata->actx;
1729 if (!check_count(actx))
1730 return FR_ERROR;
1731
1732 int rc = FR_ERROR;
1733 struct Menu *menu = shared->adata->menu;
1734 const int index = menu_get_index(menu);
1735 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1736 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
1737 const int num = ARRAY_SIZE(&ba);
1738 if (ARRAY_EMPTY(&ba))
1739 goto done;
1740
1741 struct Body **bp = NULL;
1742 bool got_attachment = false;
1743 ARRAY_FOREACH(bp, &ba)
1744 {
1745 if ((*bp)->type == TYPE_MULTIPART)
1746 {
1747 mutt_warning(_("Can't get multipart attachments"));
1748 continue;
1749 }
1751 got_attachment = true;
1752 }
1753
1754 if (got_attachment)
1755 {
1757 resolve_attachment(menu, shared->sub, index, num);
1758 rc = FR_SUCCESS;
1759 }
1760
1761done:
1762 ARRAY_FREE(&ba);
1763 /* No send2hook since this doesn't change the message. */
1764 return rc;
1765}
int mutt_get_tmp_attachment(struct Body *b)
Get a temporary copy of an attachment.
Definition mutt_attach.c:68
+ Here is the call graph for this function:

◆ op_attach_group_alts()

static int op_attach_group_alts ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Group selected attachments as 'multipart/alternative' - Implements compose_function_t -.

Definition at line 1770 of file functions.c.

1771{
1772 struct ComposeSharedData *shared = fdata->shared;
1773 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1774 ba_add_selection(&ba, shared->adata->actx, shared->adata->menu,
1775 shared->adata->menu->tag_prefix, event->count);
1776 if (ARRAY_SIZE(&ba) < 2)
1777 {
1778 ARRAY_FREE(&ba);
1779 mutt_error(_("Grouping 'alternatives' requires at least 2 selected attachments"));
1780 return FR_ERROR;
1781 }
1782
1783 const int rc = group_attachments(shared, "alternative", &ba);
1784 ARRAY_FREE(&ba);
1785 return rc;
1786}
static int group_attachments(struct ComposeSharedData *shared, char *subtype, struct BodyArray *ba)
Group selected attachments into a multipart group.
Definition functions.c:802
+ Here is the call graph for this function:

◆ op_attach_group_lingual()

static int op_attach_group_lingual ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Group selected attachments as 'multipart/multilingual' - Implements compose_function_t -.

Definition at line 1791 of file functions.c.

1793{
1794 struct ComposeSharedData *shared = fdata->shared;
1795 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1796 ba_add_selection(&ba, shared->adata->actx, shared->adata->menu,
1797 shared->adata->menu->tag_prefix, event->count);
1798 if (ARRAY_SIZE(&ba) < 2)
1799 {
1800 ARRAY_FREE(&ba);
1801 mutt_error(_("Grouping 'multilingual' requires at least 2 selected attachments"));
1802 return FR_ERROR;
1803 }
1804
1805 int tagged_with_lang_num = 0;
1806 struct Body **bp = NULL;
1807 ARRAY_FOREACH(bp, &ba)
1808 {
1809 if ((*bp)->language && *(*bp)->language)
1810 tagged_with_lang_num++;
1811 }
1812
1813 if (ARRAY_SIZE(&ba) != tagged_with_lang_num)
1814 {
1815 if (query_yesorno(_("Not all parts have 'Content-Language' set, continue?"),
1816 MUTT_YES) != MUTT_YES)
1817 {
1818 ARRAY_FREE(&ba);
1819 mutt_message(_("Not sending this message"));
1820 return FR_ERROR;
1821 }
1822 }
1823
1824 const int rc = group_attachments(shared, "multilingual", &ba);
1825 ARRAY_FREE(&ba);
1826 return rc;
1827}
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
+ Here is the call graph for this function:

◆ op_attach_group_related()

static int op_attach_group_related ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Group selected attachments as 'multipart/related' - Implements compose_function_t -.

Definition at line 1832 of file functions.c.

1834{
1835 struct ComposeSharedData *shared = fdata->shared;
1836 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
1837 ba_add_selection(&ba, shared->adata->actx, shared->adata->menu,
1838 shared->adata->menu->tag_prefix, event->count);
1839 if (ARRAY_SIZE(&ba) < 2)
1840 {
1841 ARRAY_FREE(&ba);
1842 mutt_error(_("Grouping 'related' requires at least 2 selected attachments"));
1843 return FR_ERROR;
1844 }
1845
1846 // ensure Content-ID is set for selected attachments
1847 struct Body **bp = NULL;
1848 ARRAY_FOREACH(bp, &ba)
1849 {
1850 if ((*bp)->type == TYPE_MULTIPART)
1851 continue;
1852
1853 if (!(*bp)->content_id)
1854 {
1855 (*bp)->content_id = gen_cid();
1856 }
1857 }
1858
1859 const int rc = group_attachments(shared, "related", &ba);
1860 ARRAY_FREE(&ba);
1861 return rc;
1862}
+ Here is the call graph for this function:

◆ op_attach_move_down()

static int op_attach_move_down ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Move an attachment down in the attachment list - Implements compose_function_t -.

Definition at line 1867 of file functions.c.

1868{
1869 struct ComposeSharedData *shared = fdata->shared;
1870 if (shared->adata->menu->tag_prefix || (event->count > 1))
1871 return move_attachment(shared, false, event->count);
1872
1873 int index = menu_get_index(shared->adata->menu);
1874
1875 struct AttachCtx *actx = shared->adata->actx;
1876
1877 if (index < 0)
1878 return FR_ERROR;
1879
1880 if (index == (actx->idxlen - 1))
1881 {
1882 mutt_error(_("Attachment is already at bottom"));
1883 return FR_ERROR;
1884 }
1885 if ((actx->idx[index]->parent_type == TYPE_MULTIPART) &&
1886 !actx->idx[index]->body->next)
1887 {
1888 mutt_error(_("Attachment can't be moved out of group"));
1889 return FR_ERROR;
1890 }
1891
1892 // find next attachment at current level
1893 int nextidx = index + 1;
1894 while ((nextidx < actx->idxlen) &&
1895 (actx->idx[nextidx]->level > actx->idx[index]->level))
1896 {
1897 nextidx++;
1898 }
1899 if (nextidx == actx->idxlen)
1900 {
1901 mutt_error(_("Attachment is already at bottom"));
1902 return FR_ERROR;
1903 }
1904
1905 // find final position
1906 int finalidx = index + 1;
1907 if (nextidx < actx->idxlen - 1)
1908 {
1909 if ((actx->idx[nextidx]->body->type == TYPE_MULTIPART) &&
1910 (actx->idx[nextidx + 1]->level > actx->idx[nextidx]->level))
1911 {
1912 finalidx += attach_body_count(actx->idx[nextidx]->body->parts, true);
1913 }
1914 }
1915
1916 compose_attach_swap(shared->email, shared->adata->actx, index, nextidx);
1917 mutt_update_tree(shared->adata->actx);
1920 menu_set_index(shared->adata->menu, finalidx);
1921 return FR_SUCCESS;
1922}
int attach_body_count(struct Body *body, bool recurse)
Count bodies.
Definition lib.c:42
static void compose_attach_swap(struct Email *e, struct AttachCtx *actx, int first, int second)
Swap two adjacent entries in the attachment list.
Definition functions.c:491
static int move_attachment(struct ComposeSharedData *shared, bool up, int count)
Move attachments in the attachment list.
Definition functions.c:714
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:167
void mutt_update_tree(struct AttachCtx *actx)
Refresh the list of attachments.
Definition recvattach.c:118
int level
Nesting depth of attachment.
Definition attach.h:41
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition attach.h:39
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
struct Body * next
next attachment in the list
Definition body.h:72
unsigned int type
content-type primary type, ContentType
Definition body.h:40
+ Here is the call graph for this function:

◆ op_attach_move_up()

static int op_attach_move_up ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Move an attachment up in the attachment list - Implements compose_function_t -.

Definition at line 1927 of file functions.c.

1928{
1929 struct ComposeSharedData *shared = fdata->shared;
1930 if (shared->adata->menu->tag_prefix || (event->count > 1))
1931 return move_attachment(shared, true, event->count);
1932
1933 int index = menu_get_index(shared->adata->menu);
1934 if (index < 0)
1935 return FR_ERROR;
1936
1937 struct AttachCtx *actx = shared->adata->actx;
1938
1939 if (index == 0)
1940 {
1941 mutt_error(_("Attachment is already at top"));
1942 return FR_ERROR;
1943 }
1944 if (actx->idx[index - 1]->level < actx->idx[index]->level)
1945 {
1946 mutt_error(_("Attachment can't be moved out of group"));
1947 return FR_ERROR;
1948 }
1949
1950 // find previous attachment at current level
1951 int previdx = index - 1;
1952 while ((previdx > 0) && (actx->idx[previdx]->level > actx->idx[index]->level))
1953 previdx--;
1954
1955 compose_attach_swap(shared->email, actx, previdx, index);
1956 mutt_update_tree(actx);
1959 menu_set_index(shared->adata->menu, previdx);
1960 return FR_SUCCESS;
1961}
+ Here is the call graph for this function:

◆ op_attach_new_mime()

static int op_attach_new_mime ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Compose new attachment using mailcap entry - Implements compose_function_t -.

Definition at line 1966 of file functions.c.

1967{
1968 struct ComposeSharedData *shared = fdata->shared;
1969 int rc = FR_NO_ACTION;
1970 struct Buffer *fname = buf_pool_get();
1971 struct Buffer *type = NULL;
1972 struct AttachPtr *ap = NULL;
1973
1974 struct FileCompletionData cdata = { false, shared->mailbox, NULL, NULL, NULL };
1975 if ((mw_get_field(_("New file: "), fname, MUTT_COMP_NONE, HC_FILE,
1976 &CompleteFileOps, &cdata) != 0) ||
1977 buf_is_empty(fname))
1978 {
1979 goto done;
1980 }
1981 expand_path(fname, false);
1982
1983 /* Call to lookup_mime_type () ? maybe later */
1984 type = buf_pool_get();
1985 if ((mw_get_field("Content-Type: ", type, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0) ||
1986 buf_is_empty(type))
1987 {
1988 goto done;
1989 }
1990
1991 rc = FR_ERROR;
1992 char *p = strchr(buf_string(type), '/');
1993 if (!p)
1994 {
1995 mutt_error(_("Content-Type is of the form base/sub"));
1996 goto done;
1997 }
1998 *p++ = 0;
1999 enum ContentType itype = mutt_check_mime_type(buf_string(type));
2000 if (itype == TYPE_OTHER)
2001 {
2002 mutt_error(_("Unknown Content-Type %s"), buf_string(type));
2003 goto done;
2004 }
2005
2006 ap = mutt_aptr_new();
2007 /* Touch the file */
2008 if (!mutt_file_touch(buf_string(fname)))
2009 {
2010 mutt_error(_("Can't create file %s"), buf_string(fname));
2011 goto done;
2012 }
2013
2014 ap->body = mutt_make_file_attach(buf_string(fname), shared->sub);
2015 if (!ap->body)
2016 {
2017 mutt_error(_("Error attaching file"));
2018 goto done;
2019 }
2020 update_idx(shared->adata->menu, shared->adata->actx, ap);
2021 ap = NULL; // shared->adata->actx has taken ownership
2022
2023 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
2024 shared->adata->menu);
2025 cur_att->body->type = itype;
2026 mutt_str_replace(&cur_att->body->subtype, p);
2027 cur_att->body->unlink = true;
2030
2031 if (mutt_compose_attachment(cur_att->body))
2032 {
2033 mutt_update_encoding(cur_att->body, shared->sub);
2035 }
2036 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2037 rc = FR_SUCCESS;
2038
2039done:
2040 mutt_aptr_free(&ap);
2041 buf_pool_release(&type);
2042 buf_pool_release(&fname);
2043 return rc;
2044}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition parse.c:333
bool mutt_file_touch(const char *path)
Make sure a file exists.
Definition file.c:974
@ HC_FILE
Files.
Definition lib.h:59
ContentType
Content-Type.
Definition mime.h:30
@ TYPE_OTHER
Unknown Content-Type.
Definition mime.h:31
int mutt_compose_attachment(struct Body *b)
Create an attachment.
char * subtype
content-type subtype
Definition body.h:61
int rc
Return code to leave compose.
Definition shared_data.h:47
Input for the file completion function.
Definition curs_lib.h:39
+ Here is the call graph for this function:

◆ op_attach_print()

static int op_attach_print ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Print the current entry - Implements compose_function_t -.

Definition at line 2049 of file functions.c.

2050{
2051 struct ComposeSharedData *shared = fdata->shared;
2052 struct AttachCtx *actx = shared->adata->actx;
2053 if (!check_count(actx))
2054 return FR_ERROR;
2055
2056 struct Menu *menu = shared->adata->menu;
2057 const int index = menu_get_index(menu);
2058 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
2059 aa_add_selection(&aa, actx, menu, menu->tag_prefix, event->count);
2060 const int num = ARRAY_SIZE(&aa);
2061 struct AttachPtr **app = NULL;
2062 ARRAY_FOREACH(app, &aa)
2063 {
2064 if ((*app)->body->type == TYPE_MULTIPART)
2065 {
2066 ARRAY_FREE(&aa);
2067 mutt_error(_("Can't print multipart attachments"));
2068 return FR_ERROR;
2069 }
2070 }
2071
2073 ARRAY_FREE(&aa);
2074 resolve_attachment(menu, shared->sub, index, num);
2075 /* no send2hook, since this doesn't modify the message */
2076 return FR_SUCCESS;
2077}
void mutt_print_attachment_list(struct AttachPtrArray *aa)
Print selected attachments.
Definition recvattach.c:848
+ Here is the call graph for this function:

◆ op_attach_rename_attachment()

static int op_attach_rename_attachment ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Send attachment with a different name - Implements compose_function_t -.

Definition at line 2082 of file functions.c.

2084{
2085 struct ComposeSharedData *shared = fdata->shared;
2086 if (!check_count(shared->adata->actx))
2087 return FR_ERROR;
2088 char *src = NULL;
2089 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
2090 shared->adata->menu);
2091 if (cur_att->body->d_filename)
2092 src = cur_att->body->d_filename;
2093 else
2094 src = cur_att->body->filename;
2095 struct Buffer *fname = buf_pool_get();
2096 buf_strcpy(fname, mutt_path_basename(NONULL(src)));
2097 struct FileCompletionData cdata = { false, shared->mailbox, NULL, NULL, NULL };
2098 int rc = mw_get_field(_("Send attachment with name: "), fname, MUTT_COMP_NONE,
2099 HC_FILE, &CompleteFileOps, &cdata);
2100 if (rc == 0)
2101 {
2102 // It's valid to set an empty string here, to erase what was set
2103 mutt_str_replace(&cur_att->body->d_filename, buf_string(fname));
2105 }
2106 buf_pool_release(&fname);
2107 return FR_SUCCESS;
2108}
const char * mutt_path_basename(const char *path)
Find the last component for a pathname.
Definition path.c:282
#define NONULL(x)
Definition string2.h:44
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition body.h:56
char * filename
When sending a message, this is the file to which this structure refers.
Definition body.h:59
+ Here is the call graph for this function:

◆ op_attach_save()

static int op_attach_save ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Save message/attachment to a mailbox/file - Implements compose_function_t -.

Definition at line 2113 of file functions.c.

2114{
2115 struct ComposeSharedData *shared = fdata->shared;
2116 struct AttachCtx *actx = shared->adata->actx;
2117 if (!check_count(actx))
2118 return FR_ERROR;
2119
2120 struct Menu *menu = shared->adata->menu;
2121 const int index = menu_get_index(menu);
2122 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
2123 aa_add_selection(&aa, actx, menu, menu->tag_prefix, event->count);
2124 const int num = ARRAY_SIZE(&aa);
2125 struct AttachPtr **app = NULL;
2126 ARRAY_FOREACH(app, &aa)
2127 {
2128 if ((*app)->body->type == TYPE_MULTIPART)
2129 {
2130 ARRAY_FREE(&aa);
2131 mutt_error(_("Can't save multipart attachments"));
2132 return FR_ERROR;
2133 }
2134 }
2135
2136 mutt_save_attachment_list(&aa, NULL, menu);
2137 ARRAY_FREE(&aa);
2138 resolve_attachment(menu, shared->sub, index, num);
2139 /* no send2hook, since this doesn't modify the message */
2140 return FR_SUCCESS;
2141}
void mutt_save_attachment_list(struct AttachPtrArray *aa, struct Email *e, struct Menu *menu)
Save a list of selected attachments.
Definition recvattach.c:425
+ Here is the call graph for this function:

◆ op_attach_toggle_disposition()

static int op_attach_toggle_disposition ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Toggle disposition between inline/attachment - Implements compose_function_t -.

Definition at line 2146 of file functions.c.

2148{
2149 struct ComposeSharedData *shared = fdata->shared;
2150 /* toggle the content-disposition between inline/attachment */
2151 struct AttachCtx *actx = shared->adata->actx;
2152 if (!check_count(actx))
2153 return FR_ERROR;
2154
2155 int rc = FR_NO_ACTION;
2156 struct Menu *menu = shared->adata->menu;
2157 const int index = menu_get_index(menu);
2158 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
2159 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
2160 const int num = ARRAY_SIZE(&ba);
2161
2162 struct Body **bp = NULL;
2163 ARRAY_FOREACH(bp, &ba)
2164 {
2165 (*bp)->disposition = ((*bp)->disposition == DISP_INLINE) ? DISP_ATTACH : DISP_INLINE;
2166 rc = FR_SUCCESS;
2167 }
2168
2169 if (rc == FR_SUCCESS)
2170 {
2172 resolve_attachment(menu, shared->sub, index, num);
2173 }
2174
2175 ARRAY_FREE(&ba);
2177 return rc;
2178}
@ DISP_ATTACH
Content is attached.
Definition mime.h:63
@ DISP_INLINE
Content is inline.
Definition mime.h:62
unsigned int disposition
content-disposition, ContentDisposition
Definition body.h:42
+ Here is the call graph for this function:

◆ op_attach_toggle_recode()

static int op_attach_toggle_recode ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Toggle recoding of this attachment - Implements compose_function_t -.

Definition at line 2183 of file functions.c.

2185{
2186 struct ComposeSharedData *shared = fdata->shared;
2187 struct AttachCtx *actx = shared->adata->actx;
2188 if (!check_count(actx))
2189 return FR_ERROR;
2190
2191 int rc = FR_NO_ACTION;
2192 struct Menu *menu = shared->adata->menu;
2193 const int index = menu_get_index(menu);
2194 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
2195 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
2196 const int num = ARRAY_SIZE(&ba);
2197
2198 struct Body **bp = NULL;
2199 ARRAY_FOREACH(bp, &ba)
2200 {
2201 if (!mutt_is_text_part(*bp))
2202 continue;
2203
2204 (*bp)->noconv = !(*bp)->noconv;
2205 rc = FR_SUCCESS;
2206 }
2207
2208 if (rc == FR_NO_ACTION)
2209 {
2210 mutt_error(_("Recoding only affects text attachments"));
2211 ARRAY_FREE(&ba);
2212 return FR_ERROR;
2213 }
2214
2215 if (ARRAY_SIZE(&ba) == 1)
2216 {
2217 struct AttachPtr *cur_att = current_attachment(actx, menu);
2218 if (cur_att->body->noconv)
2219 mutt_message(_("The current attachment won't be converted"));
2220 else
2221 mutt_message(_("The current attachment will be converted"));
2222 }
2223 else
2224 {
2226 }
2227
2229 resolve_attachment(menu, shared->sub, index, num);
2230 ARRAY_FREE(&ba);
2231 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2232 return FR_SUCCESS;
2233}
bool mutt_is_text_part(const struct Body *b)
Is this part of an email in plain text?
Definition muttlib.c:396
bool noconv
Don't do character set conversion.
Definition body.h:46
+ Here is the call graph for this function:

◆ op_attach_toggle_unlink()

static int op_attach_toggle_unlink ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Toggle whether to delete file after sending it - Implements compose_function_t -.

Definition at line 2238 of file functions.c.

2240{
2241 struct ComposeSharedData *shared = fdata->shared;
2242 struct AttachCtx *actx = shared->adata->actx;
2243 if (!check_count(actx))
2244 return FR_ERROR;
2245
2246 int rc = FR_NO_ACTION;
2247 struct Menu *menu = shared->adata->menu;
2248 const int index = menu_get_index(menu);
2249 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
2250 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
2251 const int num = ARRAY_SIZE(&ba);
2252
2253 struct Body **bp = NULL;
2254 ARRAY_FOREACH(bp, &ba)
2255 {
2256 (*bp)->unlink = !(*bp)->unlink;
2257 rc = FR_SUCCESS;
2258 }
2259
2260 if (rc == FR_SUCCESS)
2261 {
2263 resolve_attachment(menu, shared->sub, index, num);
2264 }
2265
2266 ARRAY_FREE(&ba);
2267 /* No send2hook since this doesn't change the message. */
2268 return rc;
2269}
+ Here is the call graph for this function:

◆ op_attach_ungroup()

static int op_attach_ungroup ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Ungroup a 'multipart' attachment - Implements compose_function_t -.

Definition at line 2274 of file functions.c.

2275{
2276 struct ComposeSharedData *shared = fdata->shared;
2277 if (shared->adata->actx->idx[shared->adata->menu->current]->body->type != TYPE_MULTIPART)
2278 {
2279 mutt_error(_("Attachment is not 'multipart'"));
2280 return FR_ERROR;
2281 }
2282
2283 int aidx = shared->adata->menu->current;
2284 struct AttachCtx *actx = shared->adata->actx;
2285 struct Body *b = actx->idx[aidx]->body;
2286 struct Body *b_next = b->next;
2287 struct Body *b_previous = NULL;
2288 struct Body *b_parent = NULL;
2289 int parent_type = actx->idx[aidx]->parent_type;
2290 int level = actx->idx[aidx]->level;
2291
2292 // reorder body pointers
2293 if (attach_body_previous(shared->email->body, b, &b_previous))
2294 b_previous->next = b->parts;
2295 else if (attach_body_parent(shared->email->body, NULL, b, &b_parent))
2296 b_parent->parts = b->parts;
2297 else
2298 shared->email->body = b->parts;
2299
2300 // update attachment list
2301 int i = aidx + 1;
2302 while ((i < actx->idxlen) && (actx->idx[i]->level > level))
2303 {
2304 actx->idx[i]->level--;
2305 if (actx->idx[i]->level == level)
2306 {
2307 actx->idx[i]->parent_type = parent_type;
2308 // set body->next for final attachment in group
2309 if (!actx->idx[i]->body->next)
2310 actx->idx[i]->body->next = b_next;
2311 }
2312 i++;
2313 }
2314
2315 // free memory
2316 actx->idx[aidx]->body->parts = NULL;
2317 actx->idx[aidx]->body->next = NULL;
2318 actx->idx[aidx]->body->email = NULL;
2319 mutt_body_free(&actx->idx[aidx]->body);
2320 FREE(&actx->idx[aidx]->tree);
2321 FREE(&actx->idx[aidx]);
2322
2323 // reorder attachment list
2324 for (int j = aidx; j < (actx->idxlen - 1); j++)
2325 actx->idx[j] = actx->idx[j + 1];
2326 actx->idx[actx->idxlen - 1] = NULL;
2327 actx->idxlen--;
2328 update_menu(actx, shared->adata->menu, false);
2329
2330 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2331 return FR_SUCCESS;
2332}
bool attach_body_parent(struct Body *start, struct Body *start_parent, struct Body *body, struct Body **body_parent)
Find the parent of a body.
Definition lib.c:71
bool attach_body_previous(struct Body *start, struct Body *body, struct Body **previous)
Find the previous body of a body.
Definition lib.c:142
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
char * tree
Tree characters to display.
Definition attach.h:40
struct Email * email
header information for message/rfc822
Definition body.h:74
int current
Current entry.
Definition lib.h:87
+ Here is the call graph for this function:

◆ op_attach_update_encoding()

static int op_attach_update_encoding ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Update an attachment's encoding info - Implements compose_function_t -.

Definition at line 2337 of file functions.c.

2339{
2340 struct ComposeSharedData *shared = fdata->shared;
2341 struct AttachCtx *actx = shared->adata->actx;
2342 if (!check_count(actx))
2343 return FR_ERROR;
2344
2345 int rc = FR_NO_ACTION;
2346 struct Menu *menu = shared->adata->menu;
2347 const int index = menu_get_index(menu);
2348 struct BodyArray ba = ARRAY_HEAD_INITIALIZER;
2349 ba_add_selection(&ba, actx, menu, menu->tag_prefix, event->count);
2350 const int num = ARRAY_SIZE(&ba);
2351 if (ARRAY_EMPTY(&ba))
2352 goto done;
2353
2354 struct Body **bp = NULL;
2355 ARRAY_FOREACH(bp, &ba)
2356 {
2357 mutt_update_encoding(*bp, shared->sub);
2358 }
2359
2361 resolve_attachment(menu, shared->sub, index, num);
2363 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2364 rc = FR_SUCCESS;
2365
2366done:
2367 ARRAY_FREE(&ba);
2368 return rc;
2369}
+ Here is the call graph for this function:

◆ op_envelope_edit_headers()

static int op_envelope_edit_headers ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit the message with headers - Implements compose_function_t -.

Definition at line 2376 of file functions.c.

2378{
2379 struct ComposeSharedData *shared = fdata->shared;
2381 const char *tag = NULL;
2382 char *err = NULL;
2383 mutt_env_to_local(shared->email->env);
2384 const char *const c_editor = cs_subset_string(shared->sub, "editor");
2385 if (shared->email->body->type == TYPE_MULTIPART)
2386 {
2387 struct Body *b = shared->email->body->parts;
2388 while (b && b->parts)
2389 b = b->parts;
2390 if (b)
2391 mutt_edit_headers(NONULL(c_editor), b->filename, shared->email, shared->fcc);
2392 }
2393 else
2394 {
2395 mutt_edit_headers(NONULL(c_editor), shared->email->body->filename,
2396 shared->email, shared->fcc);
2397 }
2398
2399 if (mutt_env_to_intl(shared->email->env, &tag, &err))
2400 {
2401 mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
2402 FREE(&err);
2403 }
2405
2407 mutt_update_encoding(shared->email->body, shared->sub);
2408
2409 /* attachments may have been added */
2410 if (shared->adata->actx->idxlen &&
2411 shared->adata->actx->idx[shared->adata->actx->idxlen - 1]->body->next)
2412 {
2414 update_menu(shared->adata->actx, shared->adata->menu, true);
2415 }
2416
2418 /* Unconditional hook since editor was invoked */
2419 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2420 return FR_SUCCESS;
2421}
void mutt_actx_entries_free(struct AttachCtx *actx)
Free entries in an Attachment Context.
Definition attach.c:162
void mutt_edit_headers(const char *editor, const char *body, struct Email *e, struct Buffer *fcc)
Let the user edit the message header and body.
Definition header.c:181
@ NT_EMAIL_CHANGE_ENVELOPE
Email's Envelope has changed.
Definition email.h:187
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope's Address fields to Punycode format.
Definition envelope.c:350
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope's Address fields to local format.
Definition envelope.c:316
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition rfc3676.c:505
void mutt_rfc3676_space_stuff(struct Email *e)
Perform RFC3676 space stuffing on an Email.
Definition rfc3676.c:492
struct Buffer * fcc
Buffer to save FCC.
Definition shared_data.h:44
struct Envelope * env
Envelope information.
Definition email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ op_compose_edit_file()

static int op_compose_edit_file ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit the file to be attached - Implements compose_function_t -.

Definition at line 2426 of file functions.c.

2427{
2428 struct ComposeSharedData *shared = fdata->shared;
2429 if (!check_count(shared->adata->actx))
2430 return FR_ERROR;
2431 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
2432 shared->adata->menu);
2433 if (cur_att->body->type == TYPE_MULTIPART)
2434 {
2435 mutt_error(_("Can't edit multipart attachments"));
2436 return FR_ERROR;
2437 }
2438 const char *const c_editor = cs_subset_string(shared->sub, "editor");
2439 mutt_edit_file(NONULL(c_editor), cur_att->body->filename);
2440 mutt_update_encoding(cur_att->body, shared->sub);
2443 /* Unconditional hook since editor was invoked */
2444 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2445 return FR_SUCCESS;
2446}
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition curs_lib.c:117
+ Here is the call graph for this function:

◆ op_compose_edit_message()

static int op_compose_edit_message ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Edit the message - Implements compose_function_t -.

Definition at line 2451 of file functions.c.

2453{
2454 struct ComposeSharedData *shared = fdata->shared;
2455 const bool c_edit_headers = cs_subset_bool(shared->sub, "edit_headers");
2456 if (!c_edit_headers)
2457 {
2459 const char *const c_editor = cs_subset_string(shared->sub, "editor");
2460 mutt_edit_file(c_editor, shared->email->body->filename);
2462 mutt_update_encoding(shared->email->body, shared->sub);
2464 /* Unconditional hook since editor was invoked */
2465 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2466 return FR_SUCCESS;
2467 }
2468
2469 return op_envelope_edit_headers(fdata, event);
2470}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
static int op_envelope_edit_headers(struct ComposeFunctionData *fdata, const struct KeyEvent *event)
Edit the message with headers - Implements compose_function_t -.
Definition functions.c:2376
+ Here is the call graph for this function:

◆ op_compose_ispell()

static int op_compose_ispell ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Run ispell on the message - Implements compose_function_t -.

Definition at line 2475 of file functions.c.

2476{
2477 struct ComposeSharedData *shared = fdata->shared;
2478 endwin();
2479 const char *const c_ispell = cs_subset_string(shared->sub, "ispell");
2480 struct Buffer *cmd = buf_pool_get();
2481 struct Buffer *quoted = buf_pool_get();
2482 buf_quote_filename(quoted, shared->email->body->filename, true);
2483 buf_printf(cmd, "%s -x %s", NONULL(c_ispell), buf_string(quoted));
2484 buf_pool_release(&quoted);
2485 if (mutt_system(buf_string(cmd)) == -1)
2486 {
2487 mutt_error(_("Error running \"%s\""), buf_string(cmd));
2488 buf_pool_release(&cmd);
2489 return FR_ERROR;
2490 }
2491 buf_pool_release(&cmd);
2492
2493 mutt_update_encoding(shared->email->body, shared->sub);
2495 return FR_SUCCESS;
2496}
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition file.c:803
int mutt_system(const char *cmd)
Run an external command.
Definition system.c:51
int endwin(void)
+ Here is the call graph for this function:

◆ op_compose_postpone_message()

static int op_compose_postpone_message ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Save this message to send later - Implements compose_function_t -.

Definition at line 2501 of file functions.c.

2503{
2504 struct ComposeSharedData *shared = fdata->shared;
2505 if (check_attachments(shared->adata->actx, shared->sub) != 0)
2506 {
2508 return FR_ERROR;
2509 }
2510
2511 shared->rc = 1;
2512 return FR_DONE;
2513}
static int check_attachments(struct AttachCtx *actx, struct ConfigSubset *sub)
Check if any attachments have changed or been deleted.
Definition functions.c:312
@ FR_DONE
Exit the Dialog.
Definition dispatcher.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ op_compose_rename_file()

static int op_compose_rename_file ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Rename/move an attached file - Implements compose_function_t -.

Definition at line 2518 of file functions.c.

2520{
2521 struct ComposeSharedData *shared = fdata->shared;
2522 if (!check_count(shared->adata->actx))
2523 return FR_ERROR;
2524 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
2525 shared->adata->menu);
2526 if (cur_att->body->type == TYPE_MULTIPART)
2527 {
2528 mutt_error(_("Can't rename multipart attachments"));
2529 return FR_ERROR;
2530 }
2531 struct Buffer *fname = buf_pool_get();
2532 buf_strcpy(fname, cur_att->body->filename);
2533 pretty_mailbox(fname);
2534 struct FileCompletionData cdata = { false, shared->mailbox, NULL, NULL, NULL };
2535 if ((mw_get_field(_("Rename to: "), fname, MUTT_COMP_NONE, HC_FILE,
2536 &CompleteFileOps, &cdata) == 0) &&
2537 !buf_is_empty(fname))
2538 {
2539 struct stat st = { 0 };
2540 if (stat(cur_att->body->filename, &st) == -1)
2541 {
2542 /* L10N: "stat" is a system call. Do "man 2 stat" for more information. */
2543 mutt_error(_("Can't stat %s: %s"), buf_string(fname), strerror(errno));
2544 buf_pool_release(&fname);
2545 return FR_ERROR;
2546 }
2547
2548 expand_path(fname, false);
2549 if (mutt_file_rename(cur_att->body->filename, buf_string(fname)))
2550 {
2551 buf_pool_release(&fname);
2552 return FR_ERROR;
2553 }
2554
2555 mutt_str_replace(&cur_att->body->filename, buf_string(fname));
2557
2558 if (cur_att->body->stamp >= st.st_mtime)
2559 mutt_stamp_attachment(cur_att->body);
2560 exec_message_hook(NULL, shared->email, CMD_SEND2_HOOK);
2561 }
2562 buf_pool_release(&fname);
2563 return FR_SUCCESS;
2564}
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition file.c:1258
void mutt_stamp_attachment(struct Body *b)
Timestamp an Attachment.
Definition sendlib.c:412
time_t stamp
Time stamp of last encoding update.
Definition body.h:77
+ Here is the call graph for this function:

◆ op_compose_send_message()

static int op_compose_send_message ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Send the message - Implements compose_function_t -.

Definition at line 2569 of file functions.c.

2571{
2572 struct ComposeSharedData *shared = fdata->shared;
2573 /* Note: We don't invoke send2-hook here, since we want to leave
2574 * users an opportunity to change settings from the ":" prompt. */
2575 if (check_attachments(shared->adata->actx, shared->sub) != 0)
2576 {
2578 return FR_NO_ACTION;
2579 }
2580
2581 if (!shared->fcc_set && !buf_is_empty(shared->fcc))
2582 {
2583 enum QuadOption ans = query_quadoption(_("Save a copy of this message?"),
2584 shared->sub, "copy");
2585 if (ans == MUTT_ABORT)
2586 return FR_NO_ACTION;
2587 else if (ans == MUTT_NO)
2588 buf_reset(shared->fcc);
2589 }
2590
2591 shared->rc = 0;
2592 return FR_DONE;
2593}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
QuadOption
Possible values for a quad-option.
Definition quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:384
bool fcc_set
User has edited the Fcc: field.
Definition shared_data.h:46
+ Here is the call graph for this function:

◆ op_compose_write_message()

static int op_compose_write_message ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Write the message to a folder - Implements compose_function_t -.

Definition at line 2598 of file functions.c.

2600{
2601 struct ComposeSharedData *shared = fdata->shared;
2602 int rc = FR_NO_ACTION;
2603 struct Buffer *fname = buf_pool_get();
2604 if (shared->mailbox)
2605 {
2606 buf_strcpy(fname, mailbox_path(shared->mailbox));
2607 pretty_mailbox(fname);
2608 }
2609 if (shared->adata->actx->idxlen)
2610 shared->email->body = shared->adata->actx->idx[0]->body;
2611 if ((mw_enter_fname(_("Write message to mailbox"), fname, true,
2612 shared->mailbox, false, NULL, NULL, MUTT_SEL_NONE) != -1) &&
2613 !buf_is_empty(fname))
2614 {
2615 mutt_message(_("Writing message to %s ..."), buf_string(fname));
2616 expand_path(fname, false);
2617
2618 if (shared->email->body->next)
2619 shared->email->body = mutt_make_multipart(shared->email->body);
2620
2621 if (mutt_write_fcc(buf_string(fname), shared->email, NULL, false, NULL,
2622 NULL, shared->sub) == 0)
2623 mutt_message(_("Message written"));
2624
2625 shared->email->body = mutt_remove_multipart(shared->email->body);
2626 rc = FR_SUCCESS;
2627 }
2628 buf_pool_release(&fname);
2629 return rc;
2630}
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition multipart.c:133
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition multipart.c:107
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath, struct ConfigSubset *sub)
Write email to FCC mailbox.
Definition sendlib.c:1028
+ Here is the call graph for this function:

◆ op_display_headers()

static int op_display_headers ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Display message and toggle header weeding - Implements compose_function_t -.

This function handles:

  • OP_ATTACH_VIEW
  • OP_ATTACH_VIEW_MAILCAP
  • OP_ATTACH_VIEW_PAGER
  • OP_ATTACH_VIEW_TEXT
  • OP_DISPLAY_HEADERS

Definition at line 2642 of file functions.c.

2643{
2644 struct ComposeSharedData *shared = fdata->shared;
2645 if (!check_count(shared->adata->actx))
2646 return FR_ERROR;
2647
2648 enum ViewAttachMode mode = MUTT_VA_REGULAR;
2649
2650 const int op = event->op;
2651 switch (op)
2652 {
2653 case OP_ATTACH_VIEW:
2654 case OP_DISPLAY_HEADERS:
2655 break;
2656
2657 case OP_ATTACH_VIEW_MAILCAP:
2658 mode = MUTT_VA_MAILCAP;
2659 break;
2660
2661 case OP_ATTACH_VIEW_PAGER:
2662 mode = MUTT_VA_PAGER;
2663 break;
2664
2665 case OP_ATTACH_VIEW_TEXT:
2666 mode = MUTT_VA_AS_TEXT;
2667 break;
2668 }
2669
2670 if (mode == MUTT_VA_REGULAR)
2671 {
2672 mutt_attach_display_loop(shared->sub, shared->adata->menu, op,
2673 shared->email, shared->adata->actx, false);
2674 }
2675 else
2676 {
2677 struct AttachPtr *cur_att = current_attachment(shared->adata->actx,
2678 shared->adata->menu);
2679 mutt_view_attachment(NULL, cur_att->body, mode, shared->email,
2680 shared->adata->actx, shared->adata->menu->win);
2681 }
2682
2684 /* no send2hook, since this doesn't modify the message */
2685 return FR_SUCCESS;
2686}
int mutt_view_attachment(FILE *fp, struct Body *b, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
ViewAttachMode
Options for mutt_view_attachment()
Definition mutt_attach.h:44
@ MUTT_VA_MAILCAP
Force viewing using mailcap entry.
Definition mutt_attach.h:46
@ MUTT_VA_REGULAR
View using default method.
Definition mutt_attach.h:45
@ MUTT_VA_PAGER
View attachment in pager using copiousoutput mailcap.
Definition mutt_attach.h:48
@ MUTT_VA_AS_TEXT
Force viewing as text.
Definition mutt_attach.h:47
int mutt_attach_display_loop(struct ConfigSubset *sub, struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
Event loop for the Attachment menu.
Definition recvattach.c:919
struct MuttWindow * win
Window holding the Menu.
Definition lib.h:94
+ Here is the call graph for this function:

◆ op_quit()

static int op_quit ( struct ComposeFunctionData * fdata,
const struct KeyEvent * event )
static

Save changes and exit this dialog - Implements compose_function_t -.

Definition at line 2691 of file functions.c.

2692{
2693 struct ComposeSharedData *shared = fdata->shared;
2694 enum QuadOption ans = query_quadoption(_("Save (postpone) draft message?"),
2695 shared->sub, "postpone");
2696 if (ans == MUTT_NO)
2697 {
2698 for (int i = 0; i < shared->adata->actx->idxlen; i++)
2699 if (shared->adata->actx->idx[i]->unowned)
2700 shared->adata->actx->idx[i]->body->unlink = false;
2701
2702 if (!(shared->flags & MUTT_COMPOSE_NOFREEHEADER))
2703 {
2704 for (int i = 0; i < shared->adata->actx->idxlen; i++)
2705 {
2706 /* avoid freeing other attachments */
2707 shared->adata->actx->idx[i]->body->next = NULL;
2708 if (!shared->adata->actx->idx[i]->body->email)
2709 shared->adata->actx->idx[i]->body->parts = NULL;
2710 mutt_body_free(&shared->adata->actx->idx[i]->body);
2711 }
2712 }
2713 shared->rc = -1;
2714 return FR_DONE;
2715 }
2716 else if (ans == MUTT_ABORT)
2717 {
2718 return FR_NO_ACTION;
2719 }
2720
2721 return op_compose_postpone_message(fdata, event);
2722}
#define MUTT_COMPOSE_NOFREEHEADER
Don't free the header when closing compose dialog.
Definition lib.h:55
static int op_compose_postpone_message(struct ComposeFunctionData *fdata, const struct KeyEvent *event)
Save this message to send later - Implements compose_function_t -.
Definition functions.c:2501
int flags
Flags, e.g. MUTT_COMPOSE_NOFREEHEADER.
Definition shared_data.h:45
+ Here is the call graph for this function: