]> granicus.if.org Git - neomutt/commitdiff
mutt_save_message: factor out Context
authorRichard Russon <rich@flatcap.org>
Fri, 11 Jan 2019 10:51:12 +0000 (10:51 +0000)
committerRichard Russon <rich@flatcap.org>
Fri, 8 Feb 2019 14:34:07 +0000 (14:34 +0000)
commands.c
commands.h
imap/imap.h
imap/message.c
index.c
pager.c

index 696faa8052338bcb7bde861955ef903a9cac94d2..f16f9e6eab0fd37d307ff21e82837231f02988ed 100644 (file)
@@ -963,75 +963,54 @@ int mutt_save_message_ctx(struct Email *e, bool delete, bool decode,
 
 /**
  * mutt_save_message - Save an email
- * @param e       Email
+ * @param m       Mailbox
+ * @param el      List of Emails to save
  * @param delete  If true, delete the original (save)
  * @param decode  If true, decode the message
  * @param decrypt If true, decrypt the message
  * @retval  0 Copy/save was successful
  * @retval -1 Error/abort
  */
-int mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt)
+int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete, bool decode, bool decrypt)
 {
+  if (!el || STAILQ_EMPTY(el))
+    return -1;
+
   bool need_passphrase = false;
   int app = 0;
   char buf[PATH_MAX];
   const char *prompt = NULL;
   struct Context *savectx = NULL;
   struct stat st;
+  struct EmailNode *en = STAILQ_FIRST(el);
+  bool single = !STAILQ_NEXT(en, entries);
 
   if (delete)
   {
     if (decode)
-      prompt = e ? _("Decode-save to mailbox") : _("Decode-save tagged to mailbox");
+      prompt = single ? _("Decode-save to mailbox") : _("Decode-save tagged to mailbox");
     else if (decrypt)
-      prompt = e ? _("Decrypt-save to mailbox") : _("Decrypt-save tagged to mailbox");
+      prompt = single ? _("Decrypt-save to mailbox") : _("Decrypt-save tagged to mailbox");
     else
-      prompt = e ? _("Save to mailbox") : _("Save tagged to mailbox");
+      prompt = single ? _("Save to mailbox") : _("Save tagged to mailbox");
   }
   else
   {
     if (decode)
-      prompt = e ? _("Decode-copy to mailbox") : _("Decode-copy tagged to mailbox");
+      prompt = single ? _("Decode-copy to mailbox") : _("Decode-copy tagged to mailbox");
     else if (decrypt)
-      prompt = e ? _("Decrypt-copy to mailbox") : _("Decrypt-copy tagged to mailbox");
+      prompt = single ? _("Decrypt-copy to mailbox") : _("Decrypt-copy tagged to mailbox");
     else
-      prompt = e ? _("Copy to mailbox") : _("Copy tagged to mailbox");
+      prompt = single ? _("Copy to mailbox") : _("Copy tagged to mailbox");
   }
 
-  if (e)
-  {
-    if (WithCrypto)
-    {
-      need_passphrase = (e->security & ENCRYPT);
-      app = e->security;
-    }
-    mutt_message_hook(Context->mailbox, e, MUTT_MESSAGE_HOOK);
-    mutt_default_save(buf, sizeof(buf), e);
-  }
-  else
+  if (WithCrypto)
   {
-    /* look for the first tagged message */
-    for (int i = 0; i < Context->mailbox->msg_count; i++)
-    {
-      if (message_is_tagged(Context, i))
-      {
-        e = Context->mailbox->emails[i];
-        break;
-      }
-    }
-
-    if (e)
-    {
-      mutt_message_hook(Context->mailbox, e, MUTT_MESSAGE_HOOK);
-      mutt_default_save(buf, sizeof(buf), e);
-      if (WithCrypto)
-      {
-        need_passphrase = (e->security & ENCRYPT);
-        app = e->security;
-      }
-      e = NULL;
-    }
+    need_passphrase = (en->email->security & ENCRYPT);
+    app = en->email->security;
   }
+  mutt_message_hook(m, en->email, MUTT_MESSAGE_HOOK);
+  mutt_default_save(buf, sizeof(buf), en->email);
 
   mutt_pretty_mailbox(buf, sizeof(buf));
   if (mutt_enter_fname(prompt, buf, sizeof(buf), 0) == -1)
@@ -1068,10 +1047,10 @@ int mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt)
   mutt_message(_("Copying to %s..."), buf);
 
 #ifdef USE_IMAP
-  if ((Context->mailbox->magic == MUTT_IMAP) && !(decode || decrypt) &&
+  if ((m->magic == MUTT_IMAP) && !(decode || decrypt) &&
       (imap_path_probe(buf, NULL) == MUTT_IMAP))
   {
-    switch (imap_copy_messages(Context->mailbox, e, buf, delete))
+    switch (imap_copy_messages(m, el, buf, delete))
     {
       /* success */
       case 0:
@@ -1088,100 +1067,95 @@ int mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt)
 #endif
 
   savectx = mx_mbox_open(NULL, buf, MUTT_APPEND);
-  if (savectx)
-  {
+  if (!savectx)
+    return -1;
+
 #ifdef USE_COMPRESSED
-    /* If we're saving to a compressed mailbox, the stats won't be updated
-     * until the next open.  Until then, improvise. */
-    struct Mailbox *cm = NULL;
-    if (savectx->mailbox->compress_info)
+  /* If we're saving to a compressed mailbox, the stats won't be updated
+   * until the next open.  Until then, improvise. */
+  struct Mailbox *cm = NULL;
+  if (savectx->mailbox->compress_info)
+  {
+    cm = mutt_find_mailbox(savectx->mailbox->realpath);
+  }
+  /* We probably haven't been opened yet */
+  if (cm && (cm->msg_count == 0))
+    cm = NULL;
+#endif
+  if (single)
+  {
+    if (mutt_save_message_ctx(en->email, delete, decode, decrypt, savectx->mailbox) != 0)
     {
-      cm = mutt_find_mailbox(savectx->mailbox->realpath);
+      mx_mbox_close(&savectx);
+      return -1;
     }
-    /* We probably haven't been opened yet */
-    if (cm && (cm->msg_count == 0))
-      cm = NULL;
-#endif
-    if (e)
+#ifdef USE_COMPRESSED
+    if (cm)
     {
-      if (mutt_save_message_ctx(e, delete, decode, decrypt, savectx->mailbox) != 0)
+      cm->msg_count++;
+      if (!en->email->read)
       {
-        mx_mbox_close(&savectx);
-        return -1;
+        cm->msg_unread++;
+        if (!en->email->old)
+          cm->msg_new++;
       }
+      if (en->email->flagged)
+        cm->msg_flagged++;
+    }
+#endif
+  }
+  else
+  {
+    int rc = 0;
+
+#ifdef USE_NOTMUCH
+    if (m->magic == MUTT_NOTMUCH)
+      nm_db_longrun_init(m, true);
+#endif
+    STAILQ_FOREACH(en, el, entries)
+    {
+      mutt_message_hook(m, en->email, MUTT_MESSAGE_HOOK);
+      rc = mutt_save_message_ctx(en->email, delete, decode,
+                                 decrypt, savectx->mailbox);
+      if (rc != 0)
+        break;
 #ifdef USE_COMPRESSED
       if (cm)
       {
+        struct Email *e2 = en->email;
         cm->msg_count++;
-        if (!e->read)
+        if (!e2->read)
         {
           cm->msg_unread++;
-          if (!e->old)
+          if (!e2->old)
             cm->msg_new++;
         }
-        if (e->flagged)
+        if (e2->flagged)
           cm->msg_flagged++;
       }
 #endif
     }
-    else
-    {
-      int rc = 0;
-
-#ifdef USE_NOTMUCH
-      if (Context->mailbox->magic == MUTT_NOTMUCH)
-        nm_db_longrun_init(Context->mailbox, true);
-#endif
-      for (int i = 0; i < Context->mailbox->msg_count; i++)
-      {
-        if (!message_is_tagged(Context, i))
-          continue;
-
-        mutt_message_hook(Context->mailbox, Context->mailbox->emails[i], MUTT_MESSAGE_HOOK);
-        rc = mutt_save_message_ctx(Context->mailbox->emails[i], delete, decode,
-                                   decrypt, savectx->mailbox);
-        if (rc != 0)
-          break;
-#ifdef USE_COMPRESSED
-        if (cm)
-        {
-          struct Email *e2 = Context->mailbox->emails[i];
-          cm->msg_count++;
-          if (!e2->read)
-          {
-            cm->msg_unread++;
-            if (!e2->old)
-              cm->msg_new++;
-          }
-          if (e2->flagged)
-            cm->msg_flagged++;
-        }
-#endif
-      }
 #ifdef USE_NOTMUCH
-      if (Context->mailbox->magic == MUTT_NOTMUCH)
-        nm_db_longrun_done(Context->mailbox);
+    if (m->magic == MUTT_NOTMUCH)
+      nm_db_longrun_done(m);
 #endif
-      if (rc != 0)
-      {
-        mx_mbox_close(&savectx);
-        return -1;
-      }
+    if (rc != 0)
+    {
+      mx_mbox_close(&savectx);
+      return -1;
     }
+  }
 
-    const bool need_mailbox_cleanup = ((savectx->mailbox->magic == MUTT_MBOX) ||
-                                       (savectx->mailbox->magic == MUTT_MMDF));
-
-    mx_mbox_close(&savectx);
+  const bool need_mailbox_cleanup = ((savectx->mailbox->magic == MUTT_MBOX) ||
+                                     (savectx->mailbox->magic == MUTT_MMDF));
 
-    if (need_mailbox_cleanup)
-      mutt_mailbox_cleanup(buf, &st);
+  mx_mbox_close(&savectx);
 
-    mutt_clear_error();
-    return 0;
-  }
+  if (need_mailbox_cleanup)
+    mutt_mailbox_cleanup(buf, &st);
 
-  return -1;
+  mutt_clear_error();
+  return 0;
 }
 
 /**
index 193b806443317d2cfa75f6cd99dbf3847bee48cc..e51a53b948d314d6e2d3ad18838d4d615a60289e 100644 (file)
@@ -52,7 +52,7 @@ void mutt_enter_command(void);
 void mutt_pipe_message(struct Email *e);
 void mutt_print_message(struct Email *e);
 int  mutt_save_message_ctx(struct Email *e, bool delete, bool decode, bool decrypt, struct Mailbox *m);
-int  mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt);
+int  mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete, bool decode, bool decrypt);
 int  mutt_select_sort(int reverse);
 void mutt_shell_escape(void);
 
index 4446842285aaa18dfa6db184c1a18351fd01e2bf..3c6921a220dd99a18f9a711f0ff99e2aab693629 100644 (file)
@@ -56,6 +56,7 @@
 
 struct BrowserState;
 struct Email;
+struct EmailList;
 struct Pattern;
 
 /* These Config Variables are only used in imap/auth.c */
@@ -96,7 +97,7 @@ int imap_mailbox_create(const char *folder);
 int imap_mailbox_rename(const char *path);
 
 /* message.c */
-int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool delete);
+int imap_copy_messages(struct Mailbox *m, struct EmailList *el, char *dest, bool delete);
 
 /* socket.c */
 void imap_logout_all(void);
index f615e261bbd3669b7ab619ebaf213de0d78c0664..3acee8d1481da258a7d12d088ccc2650472c738c 100644 (file)
@@ -1531,16 +1531,16 @@ fail:
 /**
  * imap_copy_messages - Server COPY messages to another folder
  * @param m      Mailbox
- * @param e      Email
+ * @param el     List of Emails to copy
  * @param dest   Destination folder
  * @param delete Delete the original?
  * @retval -1 Error
  * @retval  0 Success
  * @retval  1 Non-fatal error - try fetch/append
  */
-int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool delete)
+int imap_copy_messages(struct Mailbox *m, struct EmailList *el, char *dest, bool delete)
 {
-  if (!m || !dest)
+  if (!m || !el || !dest)
     return -1;
 
   struct Buffer cmd, sync_cmd;
@@ -1552,15 +1552,16 @@ int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool dele
   struct ConnAccount conn_account;
   int err_continue = MUTT_NO;
   int triedcreate = 0;
+  struct EmailNode *en = STAILQ_FIRST(el);
+  bool single = !STAILQ_NEXT(en, entries);
+  struct ImapAccountData *adata = imap_adata_get(m);
 
-  if (e && e->attach_del)
+  if (single && en->email->attach_del)
   {
     mutt_debug(3, "#1 Message contains attachments to be deleted\n");
     return 1;
   }
 
-  struct ImapAccountData *adata = imap_adata_get(m);
-
   if (imap_parse_path(dest, &conn_account, buf, sizeof(buf)))
   {
     mutt_debug(1, "bad destination %s\n", dest);
@@ -1586,25 +1587,22 @@ int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool dele
     mutt_buffer_init(&cmd);
 
     /* Null Header* means copy tagged messages */
-    if (!e)
+    if (!single)
     {
       /* if any messages have attachments to delete, fall through to FETCH
        * and APPEND. TODO: Copy what we can with COPY, fall through for the
        * remainder. */
-      for (int i = 0; i < m->msg_count; i++)
+      STAILQ_FOREACH(en, el, entries)
       {
-        if (!m->emails[i]->tagged)
-          continue;
-
-        if (m->emails[i]->attach_del)
+        if (en->email->attach_del)
         {
           mutt_debug(3, "#2 Message contains attachments to be deleted\n");
           return 1;
         }
 
-        if (m->emails[i]->active && m->emails[i]->changed)
+        if (en->email->active && en->email->changed)
         {
-          rc = imap_sync_message_for_copy(m, m->emails[i], &sync_cmd, &err_continue);
+          rc = imap_sync_message_for_copy(m, en->email, &sync_cmd, &err_continue);
           if (rc < 0)
           {
             mutt_debug(1, "#1 could not sync\n");
@@ -1633,12 +1631,12 @@ int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool dele
     }
     else
     {
-      mutt_message(_("Copying message %d to %s..."), e->index + 1, mbox);
-      mutt_buffer_add_printf(&cmd, "UID COPY %u %s", imap_edata_get(e)->uid, mmbox);
+      mutt_message(_("Copying message %d to %s..."), en->email->index + 1, mbox);
+      mutt_buffer_add_printf(&cmd, "UID COPY %u %s", imap_edata_get(en->email)->uid, mmbox);
 
-      if (e->active && e->changed)
+      if (en->email->active && en->email->changed)
       {
-        rc = imap_sync_message_for_copy(m, e, &sync_cmd, &err_continue);
+        rc = imap_sync_message_for_copy(m, en->email, &sync_cmd, &err_continue);
         if (rc < 0)
         {
           mutt_debug(1, "#2 could not sync\n");
@@ -1687,25 +1685,12 @@ int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool dele
   /* cleanup */
   if (delete)
   {
-    if (!e)
-    {
-      for (int i = 0; i < m->msg_count; i++)
-      {
-        if (!m->emails[i]->tagged)
-          continue;
-
-        mutt_set_flag(m, m->emails[i], MUTT_DELETE, 1);
-        mutt_set_flag(m, m->emails[i], MUTT_PURGE, 1);
-        if (DeleteUntag)
-          mutt_set_flag(m, m->emails[i], MUTT_TAG, 0);
-      }
-    }
-    else
+    STAILQ_FOREACH(en, el, entries)
     {
-      mutt_set_flag(m, e, MUTT_DELETE, 1);
-      mutt_set_flag(m, e, MUTT_PURGE, 1);
+      mutt_set_flag(m, en->email, MUTT_DELETE, 1);
+      mutt_set_flag(m, en->email, MUTT_PURGE, 1);
       if (DeleteUntag)
-        mutt_set_flag(m, e, MUTT_TAG, 0);
+        mutt_set_flag(m, en->email, MUTT_TAG, 0);
     }
   }
 
diff --git a/index.c b/index.c
index 66dc8a775b5453dd49c6878eb95cc85795a1ce8b..f7bb36ac1345c6beb416bc3a82e7982c331d2775 100644 (file)
--- a/index.c
+++ b/index.c
@@ -2549,9 +2549,12 @@ int mutt_index_menu(void)
       case OP_SAVE:
       case OP_DECODE_COPY:
       case OP_DECODE_SAVE:
+      {
         CHECK_MSGCOUNT;
         CHECK_VISIBLE;
-        if ((mutt_save_message(tag ? NULL : CUR_EMAIL,
+        struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
+        el_add_tagged(&el, Context, CUR_EMAIL, tag);
+        if ((mutt_save_message(Context->mailbox, &el,
                                (op == OP_DECRYPT_SAVE) || (op == OP_SAVE) || (op == OP_DECODE_SAVE),
                                (op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
                                (op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) == 0) &&
@@ -2574,7 +2577,9 @@ int mutt_index_menu(void)
           else
             menu->redraw |= REDRAW_CURRENT;
         }
+        el_free(&el);
         break;
+      }
 
       case OP_MAIN_NEXT_NEW:
       case OP_MAIN_NEXT_UNREAD:
diff --git a/pager.c b/pager.c
index 52f5250ea32726b293a56f83105f0da619a8eede..ed3569b0c2e21ec4cee17cae62e9ea8385c241dc 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -3271,16 +3271,19 @@ int mutt_pager(const char *banner, const char *fname, int flags, struct Pager *e
       case OP_DECODE_SAVE:
       case OP_DECODE_COPY:
       case OP_DECRYPT_COPY:
+      {
         if (!(WithCrypto != 0) && ch == OP_DECRYPT_COPY)
         {
           ch = -1;
           break;
         }
         CHECK_MODE(IsEmail(extra));
-        if ((mutt_save_message(
-                 extra->email, (ch == OP_DECRYPT_SAVE) || (ch == OP_SAVE) || (ch == OP_DECODE_SAVE),
-                 (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY),
-                 (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY)) == 0) &&
+        struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
+        el_add_email(&el, extra->email);
+        if ((mutt_save_message(Context->mailbox, &el,
+                               (ch == OP_DECRYPT_SAVE) || (ch == OP_SAVE) || (ch == OP_DECODE_SAVE),
+                               (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY),
+                               (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY)) == 0) &&
             ((ch == OP_SAVE) || (ch == OP_DECODE_SAVE) || (ch == OP_DECRYPT_SAVE)))
         {
           if (Resolve)
@@ -3291,7 +3294,9 @@ int mutt_pager(const char *banner, const char *fname, int flags, struct Pager *e
           else
             pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
         }
+        el_free(&el);
         break;
+      }
 
       case OP_SHELL_ESCAPE:
         mutt_shell_escape();