* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* simple, editor-based message editing */
+/**
+ * @page editmsg Prepare an email to be edited
+ *
+ * Prepare an email to be edited
+ */
#include "config.h"
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
+#include "email/lib.h"
+#include "core/lib.h"
#include "mutt.h"
#include "context.h"
#include "copy.h"
+#include "curs_lib.h"
#include "globals.h"
-#include "header.h"
-#include "mailbox.h"
+#include "muttlib.h"
#include "mx.h"
-#include "options.h"
#include "protos.h"
/**
- * edit_or_view_one_message - Edit an email or view it in an external editor
- * @param edit true if the message should be editable. If false, changes
- * to the massage (in the editor) will be ignored.
- * @param ctx Context
- * @param cur Header of email
- * @retval 1 Message not modified
- * @retval 0 Message edited successfully
+ * ev_message - Edit an email or view it in an external editor
+ * @param action Action to perform, e.g. #EVM_EDIT
+ * @param m Mailbox
+ * @param e Email
+ * @retval 1 Message not modified
+ * @retval 0 Message edited successfully
* @retval -1 Error
*/
-static int edit_or_view_one_message(bool edit, struct Context *ctx, struct Header *cur)
+static int ev_message(enum EvMessage action, struct Mailbox *m, struct Email *e)
{
- char tmp[_POSIX_PATH_MAX];
- char buf[STRING];
- int omagic;
- int oerrno;
+ char buf[256];
int rc;
-
- bool o_read;
- bool o_old;
-
- int of, cf;
-
- struct Context tmpctx;
- struct Message *msg = NULL;
-
FILE *fp = NULL;
-
struct stat sb;
- time_t mtime = 0;
+ bool old_append = m->append;
- mutt_mktemp(tmp, sizeof(tmp));
+ struct Buffer *fname = mutt_buffer_pool_get();
+ mutt_buffer_mktemp(fname);
- omagic = MboxType;
- MboxType = MUTT_MBOX;
+ enum MailboxType omagic = C_MboxType;
+ C_MboxType = MUTT_MBOX;
- rc = (mx_open_mailbox(tmp, MUTT_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
+ struct Mailbox *m_fname = mx_path_resolve(mutt_b2s(fname));
+ struct Context *ctx_tmp = mx_mbox_open(m_fname, MUTT_NEWFOLDER);
- MboxType = omagic;
+ C_MboxType = omagic;
- if (rc == -1)
+ if (!ctx_tmp)
{
mutt_error(_("could not create temporary folder: %s"), strerror(errno));
+ mutt_buffer_pool_release(&fname);
+ mailbox_free(&m_fname);
return -1;
}
- rc = mutt_append_message(
- &tmpctx, ctx, cur, 0,
- CH_NOLEN | ((ctx->magic == MUTT_MBOX || ctx->magic == MUTT_MMDF) ? 0 : CH_NOSTATUS));
- oerrno = errno;
+ const CopyHeaderFlags chflags =
+ CH_NOLEN |
+ (((m->magic == MUTT_MBOX) || (m->magic == MUTT_MMDF)) ? CH_NO_FLAGS : CH_NOSTATUS);
+ rc = mutt_append_message(ctx_tmp->mailbox, m, e, MUTT_CM_NO_FLAGS, chflags);
+ int oerrno = errno;
- mx_close_mailbox(&tmpctx, NULL);
+ mx_mbox_close(&ctx_tmp);
if (rc == -1)
{
goto bail;
}
- rc = stat(tmp, &sb);
+ rc = stat(mutt_b2s(fname), &sb);
if (rc == -1)
{
- mutt_error(_("Can't stat %s: %s"), tmp, strerror(errno));
+ mutt_error(_("Can't stat %s: %s"), mutt_b2s(fname), strerror(errno));
goto bail;
}
* truncate the last newline in the temp file, which is logically part of
* the message separator, and not the body of the message. If we fail to
* remove it, the message will grow by one line each time the user edits
- * the message.
- */
- if (sb.st_size != 0 && truncate(tmp, sb.st_size - 1) == -1)
+ * the message. */
+ if ((sb.st_size != 0) && (truncate(mutt_b2s(fname), sb.st_size - 1) == -1))
{
mutt_error(_("could not truncate temporary mail folder: %s"), strerror(errno));
goto bail;
}
- if (!edit)
+ if (action == EVM_VIEW)
{
/* remove write permissions */
- rc = mutt_file_chmod_rm_stat(tmp, S_IWUSR | S_IWGRP | S_IWOTH, &sb);
+ rc = mutt_file_chmod_rm_stat(mutt_b2s(fname), S_IWUSR | S_IWGRP | S_IWOTH, &sb);
if (rc == -1)
{
- mutt_debug(1, "Could not remove write permissions of %s: %s", tmp, strerror(errno));
+ mutt_debug(LL_DEBUG1, "Could not remove write permissions of %s: %s",
+ mutt_b2s(fname), strerror(errno));
/* Do not bail out here as we are checking afterwards if we should adopt
* changes of the temporary file. */
}
}
/* Do not reuse the stat sb here as it is outdated. */
- mtime = mutt_file_decrease_mtime(tmp, NULL);
+ time_t mtime = mutt_file_decrease_mtime(mutt_b2s(fname), NULL);
- mutt_edit_file(NONULL(Editor), tmp);
+ mutt_edit_file(NONULL(C_Editor), mutt_b2s(fname));
- rc = stat(tmp, &sb);
+ rc = stat(mutt_b2s(fname), &sb);
if (rc == -1)
{
- mutt_error(_("Can't stat %s: %s"), tmp, strerror(errno));
+ mutt_error(_("Can't stat %s: %s"), mutt_b2s(fname), strerror(errno));
goto bail;
}
if (sb.st_size == 0)
{
- mutt_message(_("Message file is empty!"));
+ mutt_message(_("Message file is empty"));
rc = 1;
goto bail;
}
- if (edit && sb.st_mtime == mtime)
+ if ((action == EVM_EDIT) && (sb.st_mtime == mtime))
{
- mutt_message(_("Message not modified!"));
+ mutt_message(_("Message not modified"));
rc = 1;
goto bail;
}
- if (!edit && sb.st_mtime != mtime)
+ if ((action == EVM_VIEW) && (sb.st_mtime != mtime))
{
mutt_message(_("Message of read-only mailbox modified! Ignoring changes."));
rc = 1;
goto bail;
}
- if (!edit)
+ if (action == EVM_VIEW)
{
/* stop processing here and skip right to the end */
rc = 1;
goto bail;
}
- fp = fopen(tmp, "r");
+ fp = fopen(mutt_b2s(fname), "r");
if (!fp)
{
rc = -1;
goto bail;
}
- if (mx_open_mailbox(ctx->path, MUTT_APPEND, &tmpctx) == NULL)
+ struct Context *ctx_app = mx_mbox_open(m, MUTT_APPEND | MUTT_QUIET);
+ if (!ctx_app)
{
rc = -1;
/* L10N: %s is from strerror(errno) */
goto bail;
}
- of = 0;
- cf = ((tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF) ? 0 : CH_NOSTATUS);
+ MsgOpenFlags of = MUTT_MSG_NO_FLAGS;
+ CopyHeaderFlags cf =
+ (((ctx_app->mailbox->magic == MUTT_MBOX) || (ctx_app->mailbox->magic == MUTT_MMDF)) ?
+ CH_NO_FLAGS :
+ CH_NOSTATUS);
if (fgets(buf, sizeof(buf), fp) && is_from(buf, NULL, 0, NULL))
{
- if (tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF)
+ if ((ctx_app->mailbox->magic == MUTT_MBOX) || (ctx_app->mailbox->magic == MUTT_MMDF))
cf = CH_FROM | CH_FORCE_FROM;
}
else
/* XXX - we have to play games with the message flags to avoid
* problematic behavior with maildir folders. */
- o_read = cur->read;
- o_old = cur->old;
- cur->read = cur->old = false;
- msg = mx_open_new_message(&tmpctx, cur, of);
- cur->read = o_read;
- cur->old = o_old;
+ bool o_read = e->read;
+ bool o_old = e->old;
+ e->read = false;
+ e->old = false;
+ struct Message *msg = mx_msg_open_new(ctx_app->mailbox, e, of);
+ e->read = o_read;
+ e->old = o_old;
if (!msg)
{
mutt_error(_("Can't append to folder: %s"), strerror(errno));
- mx_close_mailbox(&tmpctx, NULL);
+ mx_mbox_close(&ctx_app);
goto bail;
}
- rc = mutt_copy_hdr(fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL);
+ rc = mutt_copy_hdr(fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL, 0);
if (rc == 0)
{
fputc('\n', msg->fp);
mutt_file_copy_stream(fp, msg->fp);
}
- rc = mx_commit_message(msg, &tmpctx);
- mx_close_message(&tmpctx, &msg);
+ rc = mx_msg_commit(ctx_app->mailbox, msg);
+ mx_msg_close(ctx_app->mailbox, &msg);
- mx_close_mailbox(&tmpctx, NULL);
+ mx_mbox_close(&ctx_app);
bail:
- if (fp)
- mutt_file_fclose(&fp);
+ mutt_file_fclose(&fp);
if (rc >= 0)
- unlink(tmp);
+ unlink(mutt_b2s(fname));
if (rc == 0)
{
- mutt_set_flag(Context, cur, MUTT_DELETE, 1);
- mutt_set_flag(Context, cur, MUTT_PURGE, 1);
- mutt_set_flag(Context, cur, MUTT_READ, 1);
+ mutt_set_flag(m, e, MUTT_DELETE, true);
+ mutt_set_flag(m, e, MUTT_PURGE, true);
+ mutt_set_flag(m, e, MUTT_READ, true);
- if (OPT_DELETE_UNTAG)
- mutt_set_flag(Context, cur, MUTT_TAG, 0);
+ if (C_DeleteUntag)
+ mutt_set_flag(m, e, MUTT_TAG, false);
}
else if (rc == -1)
- mutt_message(_("Error. Preserving temporary file: %s"), tmp);
+ mutt_message(_("Error. Preserving temporary file: %s"), mutt_b2s(fname));
+
+ m->append = old_append;
+ mutt_buffer_pool_release(&fname);
return rc;
}
-int edit_or_view_message(bool edit, struct Context *ctx, struct Header *hdr)
+/**
+ * mutt_ev_message - Edit or view a message
+ * @param m Mailbox
+ * @param el List of Emails
+ * @param action Action to perform, e.g. #EVM_EDIT
+ * @retval 1 Message not modified
+ * @retval 0 Message edited successfully
+ * @retval -1 Error
+ */
+int mutt_ev_message(struct Mailbox *m, struct EmailList *el, enum EvMessage action)
{
- if (hdr)
- return edit_or_view_one_message(edit, ctx, hdr);
-
- for (int i = 0; i < ctx->msgcount; i++)
+ struct EmailNode *en = NULL;
+ STAILQ_FOREACH(en, el, entries)
{
- if (!message_is_tagged(ctx, i))
- continue;
-
- if (edit_or_view_one_message(edit, ctx, ctx->hdrs[i]) == -1)
+ if (ev_message(action, m, en->email) == -1)
return -1;
}
return 0;
}
-
-int mutt_edit_message(struct Context *ctx, struct Header *hdr)
-{
- return edit_or_view_message(true, ctx, hdr); /* true means edit */
-}
-
-int mutt_view_message(struct Context *ctx, struct Header *hdr)
-{
- return edit_or_view_message(false, ctx, hdr); /* false means only view */
-}