NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
functions.c File Reference

Compose functions. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "functions.h"
#include "lib.h"
#include "attach/lib.h"
#include "browser/lib.h"
#include "enter/lib.h"
#include "index/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "attach_data.h"
#include "commands.h"
#include "hook.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "mview.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include "protos.h"
#include "rfc3676.h"
#include "shared_data.h"
#include <libintl.h>
#include "mixmaster/lib.h"
#include "nntp/lib.h"
#include "nntp/adata.h"
#include "pop/lib.h"
#include "imap/lib.h"
+ Include dependency graph for functions.c:

Go to the source code of this file.

Functions

static bool check_count (struct AttachCtx *actx)
 Check if there are any attachments. More...
 
static char * gen_cid (void)
 Generate a random Content ID. More...
 
static bool check_cid (const char *cid)
 Check if a Content-ID is valid. More...
 
static int check_attachments (struct AttachCtx *actx, struct ConfigSubset *sub)
 Check if any attachments have changed or been deleted. More...
 
static int delete_attachment (struct AttachCtx *actx, int aidx)
 Delete an attachment. More...
 
static void update_idx (struct Menu *menu, struct AttachCtx *actx, struct AttachPtr *ap)
 Add a new attachment to the message. More...
 
static void compose_attach_swap (struct Email *e, struct AttachCtx *actx, int first, int second)
 Swap two adjacent entries in the attachment list. More...
 
static int group_attachments (struct ComposeSharedData *shared, char *subtype)
 Group tagged attachments into a multipart group. More...
 
static int op_attachment_attach_file (struct ComposeSharedData *shared, int op)
 Attach files to this message - Implements compose_function_t -. More...
 
static int op_attachment_attach_key (struct ComposeSharedData *shared, int op)
 Attach a PGP public key - Implements compose_function_t -. More...
 
static int op_attachment_attach_message (struct ComposeSharedData *shared, int op)
 Attach messages to this message - Implements compose_function_t -. More...
 
static int op_attachment_detach (struct ComposeSharedData *shared, int op)
 Delete the current entry - Implements compose_function_t -. More...
 
static int op_attachment_edit_content_id (struct ComposeSharedData *shared, int op)
 Edit the 'Content-ID' of the attachment - Implements compose_function_t -. More...
 
static int op_attachment_edit_description (struct ComposeSharedData *shared, int op)
 Edit attachment description - Implements compose_function_t -. More...
 
static int op_attachment_edit_encoding (struct ComposeSharedData *shared, int op)
 Edit attachment transfer-encoding - Implements compose_function_t -. More...
 
static int op_attachment_edit_language (struct ComposeSharedData *shared, int op)
 Edit the 'Content-Language' of the attachment - Implements compose_function_t -. More...
 
static int op_attachment_edit_mime (struct ComposeSharedData *shared, int op)
 Edit attachment using mailcap entry - Implements compose_function_t -. More...
 
static int op_attachment_edit_type (struct ComposeSharedData *shared, int op)
 Edit attachment content type - Implements compose_function_t -. More...
 
static int op_attachment_filter (struct ComposeSharedData *shared, int op)
 Filter attachment through a shell command - Implements compose_function_t -. More...
 
static int op_attachment_get_attachment (struct ComposeSharedData *shared, int op)
 Get a temporary copy of an attachment - Implements compose_function_t -. More...
 
static int op_attachment_group_alts (struct ComposeSharedData *shared, int op)
 Group tagged attachments as 'multipart/alternative' - Implements compose_function_t -. More...
 
static int op_attachment_group_lingual (struct ComposeSharedData *shared, int op)
 Group tagged attachments as 'multipart/multilingual' - Implements compose_function_t -. More...
 
static int op_attachment_group_related (struct ComposeSharedData *shared, int op)
 Group tagged attachments as 'multipart/related' - Implements compose_function_t -. More...
 
static int op_attachment_move_down (struct ComposeSharedData *shared, int op)
 Move an attachment down in the attachment list - Implements compose_function_t -. More...
 
static int op_attachment_move_up (struct ComposeSharedData *shared, int op)
 Move an attachment up in the attachment list - Implements compose_function_t -. More...
 
static int op_attachment_new_mime (struct ComposeSharedData *shared, int op)
 Compose new attachment using mailcap entry - Implements compose_function_t -. More...
 
static int op_attachment_print (struct ComposeSharedData *shared, int op)
 Print the current entry - Implements compose_function_t -. More...
 
static int op_attachment_rename_attachment (struct ComposeSharedData *shared, int op)
 Send attachment with a different name - Implements compose_function_t -. More...
 
static int op_attachment_save (struct ComposeSharedData *shared, int op)
 Save message/attachment to a mailbox/file - Implements compose_function_t -. More...
 
static int op_attachment_toggle_disposition (struct ComposeSharedData *shared, int op)
 Toggle disposition between inline/attachment - Implements compose_function_t -. More...
 
static int op_attachment_toggle_recode (struct ComposeSharedData *shared, int op)
 Toggle recoding of this attachment - Implements compose_function_t -. More...
 
static int op_attachment_toggle_unlink (struct ComposeSharedData *shared, int op)
 Toggle whether to delete file after sending it - Implements compose_function_t -. More...
 
static int op_attachment_ungroup (struct ComposeSharedData *shared, int op)
 Ungroup a 'multipart' attachment - Implements compose_function_t -. More...
 
static int op_attachment_update_encoding (struct ComposeSharedData *shared, int op)
 Update an attachment's encoding info - Implements compose_function_t -. More...
 
static int op_envelope_edit_headers (struct ComposeSharedData *shared, int op)
 Edit the message with headers - Implements compose_function_t -. More...
 
static int op_compose_edit_file (struct ComposeSharedData *shared, int op)
 Edit the file to be attached - Implements compose_function_t -. More...
 
static int op_compose_edit_message (struct ComposeSharedData *shared, int op)
 Edit the message - Implements compose_function_t -. More...
 
static int op_compose_ispell (struct ComposeSharedData *shared, int op)
 Run ispell on the message - Implements compose_function_t -. More...
 
static int op_compose_postpone_message (struct ComposeSharedData *shared, int op)
 Save this message to send later - Implements compose_function_t -. More...
 
static int op_compose_rename_file (struct ComposeSharedData *shared, int op)
 Rename/move an attached file - Implements compose_function_t -. More...
 
static int op_compose_send_message (struct ComposeSharedData *shared, int op)
 Send the message - Implements compose_function_t -. More...
 
static int op_compose_write_message (struct ComposeSharedData *shared, int op)
 Write the message to a folder - Implements compose_function_t -. More...
 
static int op_display_headers (struct ComposeSharedData *shared, int op)
 Display message and toggle header weeding - Implements compose_function_t -. More...
 
static int op_exit (struct ComposeSharedData *shared, int op)
 Exit this menu - Implements compose_function_t -. More...
 
static int op_forget_passphrase (struct ComposeSharedData *shared, int op)
 Wipe passphrases from memory - Implements compose_function_t -. More...
 
int compose_function_dispatcher (struct MuttWindow *win, int op)
 Perform a Compose function - Implements function_dispatcher_t -. More...
 

Variables

struct ComposeFunction ComposeFunctions []
 All the NeoMutt functions that the Compose supports. More...
 

Detailed Description

Compose functions.

Authors
  • Richard Russon

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, see http://www.gnu.org/licenses/.

Definition in file functions.c.

Function Documentation

◆ check_count()

static bool check_count ( struct AttachCtx actx)
static

Check if there are any attachments.

Parameters
actxAttachment context
Return values
trueThere are attachments

Definition at line 90 of file functions.c.

91{
92 if (actx->idxlen == 0)
93 {
94 mutt_error(_("There are no attachments"));
95 return false;
96 }
97
98 return true;
99}
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:56
+ Here is the caller graph for this function:

◆ gen_cid()

static char * gen_cid ( void  )
static

Generate a random Content ID.

Return values
ptrContent ID
Note
The caller should free the string

Definition at line 107 of file functions.c.

108{
109 char rndid[MUTT_RANDTAG_LEN + 1];
110
111 mutt_rand_base32(rndid, sizeof(rndid) - 1);
112 rndid[MUTT_RANDTAG_LEN] = 0;
113
114 return mutt_str_dup(rndid);
115}
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: random.c:102
#define MUTT_RANDTAG_LEN
Definition: sendlib.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_cid()

static bool check_cid ( const char *  cid)
static

Check if a Content-ID is valid.

Parameters
cidContent-ID to check
Return values
trueContent-ID is valid
falseContent-ID is not valid

Definition at line 123 of file functions.c.

124{
125 static const char *check = "^[-\\.0-9@A-Z_a-z]+$";
126
127 struct Regex *check_cid_regex = mutt_regex_new(check, 0, NULL);
128
129 const bool valid = mutt_regex_match(check_cid_regex, cid);
130
131 mutt_regex_free(&check_cid_regex);
132
133 return valid;
134}
struct Regex * mutt_regex_new(const char *str, uint32_t flags, struct Buffer *err)
Create an Regex from a string.
Definition: regex.c:76
void mutt_regex_free(struct Regex **r)
Free a Regex object.
Definition: regex.c:114
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:631
Cached regular expression.
Definition: regex3.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_attachments()

static int check_attachments ( struct AttachCtx actx,
struct ConfigSubset sub 
)
static

Check if any attachments have changed or been deleted.

Parameters
actxAttachment context
subConfigSubset
Return values
0Success
-1Error

Definition at line 143 of file functions.c.

144{
145 int rc = -1;
146 struct stat st = { 0 };
147 struct Buffer *pretty = NULL, *msg = NULL;
148
149 for (int i = 0; i < actx->idxlen; i++)
150 {
151 if (actx->idx[i]->body->type == TYPE_MULTIPART)
152 continue;
153 if (stat(actx->idx[i]->body->filename, &st) != 0)
154 {
155 if (!pretty)
156 pretty = mutt_buffer_pool_get();
157 mutt_buffer_strcpy(pretty, actx->idx[i]->body->filename);
159 /* L10N: This message is displayed in the compose menu when an attachment
160 doesn't stat. %d is the attachment number and %s is the attachment
161 filename. The filename is located last to avoid a long path hiding
162 the error message. */
163 mutt_error(_("Attachment #%d no longer exists: %s"), i + 1,
164 mutt_buffer_string(pretty));
165 goto cleanup;
166 }
167
168 if (actx->idx[i]->body->stamp < st.st_mtime)
169 {
170 if (!pretty)
171 pretty = mutt_buffer_pool_get();
172 mutt_buffer_strcpy(pretty, actx->idx[i]->body->filename);
174
175 if (!msg)
176 msg = mutt_buffer_pool_get();
177 /* L10N: This message is displayed in the compose menu when an attachment
178 is modified behind the scenes. %d is the attachment number and %s is
179 the attachment filename. The filename is located last to avoid a long
180 path hiding the prompt question. */
181 mutt_buffer_printf(msg, _("Attachment #%d modified. Update encoding for %s?"),
182 i + 1, mutt_buffer_string(pretty));
183
185 if (ans == MUTT_YES)
186 mutt_update_encoding(actx->idx[i]->body, sub);
187 else if (ans == MUTT_ABORT)
188 goto cleanup;
189 }
190 }
191
192 rc = 0;
193
194cleanup:
197 return rc;
198}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
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_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:413
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:55
struct Body * body
Attachment.
Definition: attach.h:36
time_t stamp
Time stamp of last encoding update.
Definition: body.h:76
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete_attachment()

static int delete_attachment ( struct AttachCtx actx,
int  aidx 
)
static

Delete an attachment.

Parameters
actxAttachment context
aidxIndex number of attachment to delete
Return values
0Success
-1Error

Definition at line 207 of file functions.c.

208{
209 if (!actx || (aidx < 0) || (aidx >= actx->idxlen))
210 return -1;
211
212 struct AttachPtr **idx = actx->idx;
213 struct Body *bptr_previous = NULL;
214 struct Body *bptr_parent = NULL;
215
216 if (aidx == 0)
217 {
218 struct Body *b = actx->idx[0]->body;
219 if (!b->next) // There's only one attachment left
220 {
221 mutt_error(_("You may not delete the only attachment"));
222 return -1;
223 }
224 }
225
226 if (idx[aidx]->level > 0)
227 {
228 if (attach_body_parent(idx[0]->body, NULL, idx[aidx]->body, &bptr_parent))
229 {
230 if (attach_body_count(bptr_parent->parts, false) < 3)
231 {
232 mutt_error(_("Can't leave group with only one attachment"));
233 return -1;
234 }
235 }
236 }
237
238 // reorder body pointers
239 if (aidx > 0)
240 {
241 if (attach_body_previous(idx[0]->body, idx[aidx]->body, &bptr_previous))
242 bptr_previous->next = idx[aidx]->body->next;
243 else if (attach_body_parent(idx[0]->body, NULL, idx[aidx]->body, &bptr_parent))
244 bptr_parent->parts = idx[aidx]->body->next;
245 }
246
247 // free memory
248 int part_count = 1;
249 if (aidx < (actx->idxlen - 1))
250 {
251 if ((idx[aidx]->body->type == TYPE_MULTIPART) &&
252 (idx[aidx + 1]->level > idx[aidx]->level))
253 {
254 part_count += attach_body_count(idx[aidx]->body->parts, true);
255 }
256 }
257 idx[aidx]->body->next = NULL;
258 mutt_body_free(&(idx[aidx]->body));
259 for (int i = 0; i < part_count; i++)
260 {
261 FREE(&idx[aidx + i]->tree);
262 FREE(&idx[aidx + i]);
263 }
264
265 // reorder attachment list
266 for (int i = aidx; i < (actx->idxlen - part_count); i++)
267 idx[i] = idx[i + part_count];
268 for (int i = 0; i < part_count; i++)
269 idx[actx->idxlen - i - 1] = NULL;
270 actx->idxlen -= part_count;
271
272 return 0;
273}
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
int attach_body_count(struct Body *body, bool recurse)
Count bodies.
Definition: lib.c:42
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:57
#define FREE(x)
Definition: memory.h:43
An email to which things will be attached.
Definition: attach.h:35
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
struct Body * next
next attachment in the list
Definition: body.h:71
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_idx()

static void update_idx ( struct Menu menu,
struct AttachCtx actx,
struct AttachPtr ap 
)
static

Add a new attachment to the message.

Parameters
menuCurrent menu
actxAttachment context
apAttachment to add

Definition at line 281 of file functions.c.

282{
283 ap->level = 0;
284 for (int i = actx->idxlen; i > 0; i--)
285 {
286 if (ap->level == actx->idx[i - 1]->level)
287 {
288 actx->idx[i - 1]->body->next = ap->body;
289 break;
290 }
291 }
292
293 ap->body->aptr = ap;
294 mutt_actx_add_attach(actx, ap);
295 update_menu(actx, menu, false);
296 menu_set_index(menu, actx->vcount - 1);
297}
void mutt_actx_add_attach(struct AttachCtx *actx, struct AttachPtr *attach)
Add an Attachment to an Attachment Context.
Definition: attach.c:65
void update_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Redraw the compose window.
Definition: compose.c:222
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:168
short vcount
The number of virtual attachments.
Definition: attach.h:60
int level
Nesting depth of attachment.
Definition: attach.h:40
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:74
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compose_attach_swap()

static void compose_attach_swap ( struct Email e,
struct AttachCtx actx,
int  first,
int  second 
)
static

Swap two adjacent entries in the attachment list.

Parameters
eEmail
actxAttachment information
firstIndex of first attachment to swap
secondIndex of second attachment to swap

Definition at line 306 of file functions.c.

307{
308 struct AttachPtr **idx = actx->idx;
309
310 // check that attachments really are adjacent
311 if (idx[first]->body->next != idx[second]->body)
312 return;
313
314 // reorder Body pointers
315 if (first == 0)
316 {
317 // first attachment is the fundamental part
318 idx[first]->body->next = idx[second]->body->next;
319 idx[second]->body->next = idx[first]->body;
320 e->body = idx[second]->body;
321 }
322 else
323 {
324 // find previous attachment
325 struct Body *bptr_previous = NULL;
326 struct Body *bptr_parent = NULL;
327 if (attach_body_previous(e->body, idx[first]->body, &bptr_previous))
328 {
329 idx[first]->body->next = idx[second]->body->next;
330 idx[second]->body->next = idx[first]->body;
331 bptr_previous->next = idx[second]->body;
332 }
333 else if (attach_body_parent(e->body, NULL, idx[first]->body, &bptr_parent))
334 {
335 idx[first]->body->next = idx[second]->body->next;
336 idx[second]->body->next = idx[first]->body;
337 bptr_parent->parts = idx[second]->body;
338 }
339 }
340
341 // reorder attachment list
342 struct AttachPtr *saved = idx[second];
343 for (int i = second; i > first; i--)
344 idx[i] = idx[i - 1];
345 idx[first] = saved;
346
347 // if moved attachment is a group then move subparts too
348 if ((idx[first]->body->type == TYPE_MULTIPART) && (second < actx->idxlen - 1))
349 {
350 int i = second + 1;
351 while (idx[i]->level > idx[first]->level)
352 {
353 saved = idx[i];
354 int destidx = i - second + first;
355 for (int j = i; j > destidx; j--)
356 idx[j] = idx[j - 1];
357 idx[destidx] = saved;
358 i++;
359 if (i >= actx->idxlen)
360 break;
361 }
362 }
363}
struct Body * body
List of MIME parts.
Definition: email.h:67
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ group_attachments()

static int group_attachments ( struct ComposeSharedData shared,
char *  subtype 
)
static

Group tagged attachments into a multipart group.

Parameters
sharedShared compose data
subtypeMIME subtype
Return values
FR_SUCCESSSuccess
FR_ERRORFailure

Definition at line 372 of file functions.c.

373{
374 struct AttachCtx *actx = shared->adata->actx;
375 int group_level = -1;
376 struct Body *bptr_parent = NULL;
377
378 // Attachments to be grouped must have the same parent
379 for (int i = 0; i < actx->idxlen; i++)
380 {
381 // check if all tagged attachments are at same level
382 if (actx->idx[i]->body->tagged)
383 {
384 if (group_level == -1)
385 {
386 group_level = actx->idx[i]->level;
387 }
388 else
389 {
390 if (group_level != actx->idx[i]->level)
391 {
392 mutt_error(_("Attachments to be grouped must have the same parent"));
393 return FR_ERROR;
394 }
395 }
396 // if not at top level check if all tagged attachments have same parent
397 if (group_level > 0)
398 {
399 if (bptr_parent)
400 {
401 struct Body *bptr_test = NULL;
402 if (!attach_body_parent(actx->idx[0]->body, NULL, actx->idx[i]->body, &bptr_test))
403 mutt_debug(LL_DEBUG5, "can't find parent\n");
404 if (bptr_test != bptr_parent)
405 {
406 mutt_error(_("Attachments to be grouped must have the same parent"));
407 return FR_ERROR;
408 }
409 }
410 else
411 {
412 if (!attach_body_parent(actx->idx[0]->body, NULL, actx->idx[i]->body, &bptr_parent))
413 mutt_debug(LL_DEBUG5, "can't find parent\n");
414 }
415 }
416 }
417 }
418
419 // Can't group all attachments unless at top level
420 if (bptr_parent)
421 {
422 if (shared->adata->menu->num_tagged == attach_body_count(bptr_parent->parts, false))
423 {
424 mutt_error(_("Can't leave group with only one attachment"));
425 return FR_ERROR;
426 }
427 }
428
429 struct Body *group = mutt_body_new();
430 group->type = TYPE_MULTIPART;
431 group->subtype = mutt_str_dup(subtype);
432 group->encoding = ENC_7BIT;
433
434 struct Body *bptr_first = NULL; // first tagged attachment
435 struct Body *bptr = NULL; // current tagged attachment
436 struct Body *group_parent = NULL; // parent of group
437 struct Body *group_previous = NULL; // previous body to group
438 struct Body *group_part = NULL; // current attachment in group
439 int group_idx = 0; // index in attachment list where group will be inserted
440 int group_last_idx = 0; // index of last part of previous found group
441 int group_parent_type = TYPE_OTHER;
442
443 for (int i = 0; i < actx->idxlen; i++)
444 {
445 bptr = actx->idx[i]->body;
446 if (bptr->tagged)
447 {
448 // set group properties based on first tagged attachment
449 if (!bptr_first)
450 {
451 group->disposition = bptr->disposition;
452 if (bptr->language && !mutt_str_equal(subtype, "multilingual"))
453 group->language = mutt_str_dup(bptr->language);
454 group_parent_type = bptr->aptr->parent_type;
455 bptr_first = bptr;
456 if (i > 0)
457 {
458 if (!attach_body_previous(shared->email->body, bptr, &group_previous))
459 {
460 mutt_debug(LL_DEBUG5, "couldn't find previous\n");
461 }
462 if (!attach_body_parent(shared->email->body, NULL, bptr, &group_parent))
463 {
464 mutt_debug(LL_DEBUG5, "couldn't find parent\n");
465 }
466 }
467 }
468
469 shared->adata->menu->num_tagged--;
470 bptr->tagged = false;
471 bptr->aptr->level++;
473
474 // append bptr to the group parts list and remove from email body list
475 struct Body *bptr_previous = NULL;
476 if (attach_body_previous(shared->email->body, bptr, &bptr_previous))
477 bptr_previous->next = bptr->next;
478 else if (attach_body_parent(shared->email->body, NULL, bptr, &bptr_parent))
479 bptr_parent->parts = bptr->next;
480 else
481 shared->email->body = bptr->next;
482
483 if (group_part)
484 {
485 // add bptr to group parts list
486 group_part->next = bptr;
487 group_part = group_part->next;
488 group_part->next = NULL;
489
490 // reorder attachments and set levels
491 int bptr_attachments = attach_body_count(bptr, true);
492 for (int j = i + 1; j < (i + bptr_attachments); j++)
493 actx->idx[j]->level++;
494 if (i > (group_last_idx + 1))
495 {
496 for (int j = 0; j < bptr_attachments; j++)
497 {
498 struct AttachPtr *saved = actx->idx[i + bptr_attachments - 1];
499 for (int k = i + bptr_attachments - 1; k > (group_last_idx + 1); k--)
500 actx->idx[k] = actx->idx[k - 1];
501 actx->idx[group_last_idx + 1] = saved;
502 }
503 }
504 i += bptr_attachments - 1;
505 group_last_idx += bptr_attachments;
506 }
507 else
508 {
509 group_idx = i;
510 group->parts = bptr;
511 group_part = bptr;
512 group_part->next = NULL;
513 int bptr_attachments = attach_body_count(bptr, true);
514 for (int j = i + 1; j < (i + bptr_attachments); j++)
515 actx->idx[j]->level++;
516 i += bptr_attachments - 1;
517 group_last_idx = i;
518 }
519 }
520 }
521
522 if (!bptr_first)
523 {
524 mutt_body_free(&group);
525 return FR_ERROR;
526 }
527
528 // set group->next
529 int next_aidx = group_idx + attach_body_count(group->parts, true);
530 if (group_parent)
531 {
532 // find next attachment with the same parent as the group
533 struct Body *b = NULL;
534 struct Body *b_parent = NULL;
535 while (next_aidx < actx->idxlen)
536 {
537 b = actx->idx[next_aidx]->body;
538 b_parent = NULL;
539 if (attach_body_parent(shared->email->body, NULL, b, &b_parent))
540 {
541 if (group_parent == b_parent)
542 {
543 group->next = b;
544 break;
545 }
546 }
547 next_aidx++;
548 }
549 }
550 else if (next_aidx < actx->idxlen)
551 {
552 // group is at top level
553 group->next = actx->idx[next_aidx]->body;
554 }
555
556 // set previous or parent for group
557 if (group_previous)
558 group_previous->next = group;
559 else if (group_parent)
560 group_parent->parts = group;
561
563
564 struct AttachPtr *group_ap = mutt_aptr_new();
565 group_ap->body = group;
566 group_ap->body->aptr = group_ap;
567 group_ap->level = group_level;
568 group_ap->parent_type = group_parent_type;
569
570 // insert group into attachment list
571 mutt_actx_ins_attach(actx, group_ap, group_idx);
572
573 // update email body and last attachment pointers
574 shared->email->body = actx->idx[0]->body;
575 actx->idx[actx->idxlen - 1]->body->next = NULL;
576
577 update_menu(actx, shared->adata->menu, false);
578 shared->adata->menu->current = group_idx;
580
582 return FR_SUCCESS;
583}
void mutt_actx_ins_attach(struct AttachCtx *actx, struct AttachPtr *attach, int aidx)
Insert an Attachment into an Attachment Context at Specified Index.
Definition: attach.c:91
struct AttachPtr * mutt_aptr_new(void)
Create a new Attachment Pointer.
Definition: attach.c:40
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_ERROR
Valid function - error occurred.
Definition: dispatcher.h:38
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:658
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:49
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
#define MENU_REDRAW_INDEX
Redraw the index.
Definition: lib.h:56
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:178
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ TYPE_OTHER
Unknown Content-Type.
Definition: mime.h:31
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
A set of attachments.
Definition: attach.h:51
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition: attach.h:38
char * language
content-language (RFC8255)
Definition: body.h:77
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
bool tagged
This attachment is tagged.
Definition: body.h:89
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
struct Menu * menu
Menu displaying the attachments.
Definition: attach_data.h:35
struct AttachCtx * actx
Set of attachments.
Definition: attach_data.h:34
struct ComposeAttachData * adata
Attachments.
Definition: shared_data.h:37
struct Email * email
Email being composed.
Definition: shared_data.h:36
int current
Current entry.
Definition: lib.h:70
int num_tagged
Number of tagged entries.
Definition: lib.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ ComposeFunctions

struct ComposeFunction ComposeFunctions[]

All the NeoMutt functions that the Compose supports.

Definition at line 1921 of file functions.c.