--- mutt-1.5.8/PATCHES~ never +++ mutt-1.5.8/PATCHES Tue Feb 22 15:42:50 CST 2005 @@ -1,0 +1 @@ +patch-1.5.8.dgc.groupalts.2 diff -Pur mutt-1.5.8-base/OPS mutt-1.5.8/OPS --- mutt-1.5.8-base/OPS Fri Jul 4 12:07:11 2003 +++ mutt-1.5.8/OPS Tue Feb 22 15:42:50 2005 @@ -32,7 +32,10 @@ OP_CREATE_MAILBOX "create a new mailbox (IMAP only)" OP_EDIT_TYPE "edit attachment content type" OP_COMPOSE_GET_ATTACHMENT "get a temporary copy of an attachment" +OP_COMPOSE_GROUP_ALTS "group tagged attachments as multipart/alternative" OP_COMPOSE_ISPELL "run ispell on the message" +OP_COMPOSE_MOVE_UP "move an attachment up in the attachment list" +OP_COMPOSE_MOVE_DOWN "move an attachment down in the attachment list" OP_COMPOSE_NEW_MIME "compose new attachment using mailcap entry" OP_COMPOSE_TOGGLE_RECODE "toggle recoding of this attachment" OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later" diff -Pur mutt-1.5.8-base/compose.c mutt-1.5.8/compose.c --- mutt-1.5.8-base/compose.c Thu Feb 3 12:47:52 2005 +++ mutt-1.5.8/compose.c Tue Feb 22 15:42:50 2005 @@ -214,6 +214,8 @@ for (i = 0; i < idxlen; i++) { + if (idx[i]->content->type == TYPEMULTIPART) + continue; strfcpy(pretty, idx[i]->content->filename, sizeof(pretty)); if(stat(idx[i]->content->filename, &st) != 0) { @@ -361,6 +363,43 @@ } +/* + * compose_attach_swap: swap two adjacent entries in the attachment list. + */ +static void compose_attach_swap (BODY *msg, ATTACHPTR **idx, short first) +{ + int i; + void *saved; + BODY *part; + + /* Reorder BODY pointers. + * Must traverse msg from top since BODY * has no previous ptr. + */ + for (part = msg; part; part = part->next) + { + if (part->next == idx[first]->content) + { + idx[first]->content->next = idx[first+1]->content->next; + idx[first+1]->content->next = idx[first]->content; + part->next = idx[first+1]->content; + break; + } + } + + /* Reorder index */ + saved = idx[first]; + idx[first] = idx[first+1]; + idx[first+1] = saved; + + /* Swap ptr->num */ + i = idx[first]->num; + idx[first]->num = idx[first+1]->num; + idx[first+1]->num = i; + + return; +} + + /* * cum_attachs_size: Cumulative Attachments Size * @@ -658,6 +697,132 @@ mutt_message_hook (NULL, msg, M_SEND2HOOK); break; + + case OP_COMPOSE_MOVE_UP: + if (menu->current == 0) + { + mutt_error(_("Attachment is already at top.")); + break; + } + if (menu->current == 1) + { + mutt_error(_("The fundamental part cannot be moved.")); + break; + } + compose_attach_swap(msg->content, idx, menu->current - 1); + menu->redraw = 1; + menu->current--; + break; + + + case OP_COMPOSE_MOVE_DOWN: + if (menu->current == idxlen-1) + { + mutt_error(_("Attachment is already at bottom.")); + break; + } + if (menu->current == 0) + { + mutt_error(_("The fundamental part cannot be moved.")); + break; + } + compose_attach_swap(msg->content, idx, menu->current); + menu->redraw = 1; + menu->current++; + break; + + case OP_COMPOSE_GROUP_ALTS: + { + BODY *group, *bptr, *alts; + ATTACHPTR *gptr; + int i, j; + char *p; + + if (menu->tagged < 2) + { + mutt_error(_("Grouping alternatives requires at least 2 tagged messages.")); + break; + } + +/* need to redo using mutt_gen_attach_list() */ + + group = safe_calloc(1, sizeof(BODY)); + group->type = TYPEMULTIPART; + group->subtype = "alternative"; + + alts = NULL; + for (i = 0, bptr = msg->content; bptr && bptr->next;) + { + /* always look at bptr->next, not bptr itself */ + if (bptr->next->tagged) + { + /* untag */ + bptr->next->tagged = 0; + + /* for first match, set group desc according to match */ +# define ALTS_TAG "Alternatives for \"%s\"" + if (!group->description) + { + p = bptr->next->description; + if (!p) + p = bptr->next->filename; + if (p) + { + group->description = safe_calloc(1, + strlen(p) + strlen(ALTS_TAG) + 1); + sprintf(group->description, ALTS_TAG, p); + } + } + + /* append bptr->next to the alts list, + * and remove from the msg->content list */ + if (alts == NULL) + { + group->parts = alts = bptr->next; + bptr->next = bptr->next->next; + alts->next = NULL; + } + else + { + alts->next = bptr->next; + bptr->next = bptr->next->next; + alts = alts->next; + alts->next = NULL; + } + + /* now delink the idx entry */ + for (j = i+1; j < idxlen-1; ++j) + { + idx[j] = idx[j+1]; + } + --idxlen; + } + else + { + bptr = bptr->next; + ++i; + } + } + + /* add group to attachment list */ + for (bptr = msg->content; bptr->next; bptr = bptr->next); + bptr->next = group; + group->next = NULL; + + gptr = safe_calloc(1, sizeof(ATTACHPTR)); + gptr->content = group; + idx[idxlen] = gptr; + update_idx(menu, idx, idxlen++); + + /* add a boundary */ + mutt_generate_boundary(&group->parameter); + + /* if no group desc yet, make one up */ + if (!group->description) + group->description = strdup("unknown alternative group"); + } + menu->redraw = 1; + break; case OP_COMPOSE_ATTACH_FILE: { diff -Pur mutt-1.5.8-base/doc/manual.sgml.head mutt-1.5.8/doc/manual.sgml.head --- mutt-1.5.8-base/doc/manual.sgml.head Sat Feb 12 13:41:36 2005 +++ mutt-1.5.8/doc/manual.sgml.head Tue Feb 22 15:42:50 2005 @@ -3029,6 +3029,21 @@ To remove a MIME type from the (-) and (+) +bindings.) Edit the descriptions, if you wish. Then tag the attachments +that are alternatives, and press the (&) binding +to group them together. The separate parts will be replaced by a single +new part with the multipart/alternative type. From this point on, the +alternatives must be manipulated or deleted as a group. + +Beware that such messages cannot be postponed. Once two attachments are +grouped as alternatives, they must be sent or lost. + + MIME Lookup