move ascii.* into the lib-lib.
[apps/madmutt.git] / editmsg.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 /* simple, editor-based message editing */
11
12 #if HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15
16 #include <lib-lib/macros.h>
17 #include <lib-lib/str.h>
18
19 #include "mutt.h"
20 #include "copy.h"
21 #include "mx.h"
22
23
24 #include <sys/stat.h>
25 #include <errno.h>
26
27 #include <time.h>
28
29 /*
30  * return value:
31  * 
32  * 1    message not modified
33  * 0    message edited successfully
34  * -1   error
35  */
36
37 static int edit_one_message (CONTEXT * ctx, HEADER * cur)
38 {
39   char tmp[_POSIX_PATH_MAX];
40   char buff[STRING];
41   int omagic;
42   int oerrno;
43   int rc;
44
45   unsigned short o_read;
46   unsigned short o_old;
47
48   int of, cf;
49
50   CONTEXT tmpctx;
51   MESSAGE *msg;
52
53   FILE *fp = NULL;
54
55   struct stat sb;
56   time_t mtime = 0;
57   size_t size = 0;
58
59   mutt_mktemp (tmp);
60
61   omagic = DefaultMagic;
62   DefaultMagic = M_MBOX;
63
64   rc = (mx_open_mailbox (tmp, M_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
65
66   DefaultMagic = omagic;
67
68   if (rc == -1) {
69     mutt_error (_("could not create temporary folder: %s"), strerror (errno));
70     return -1;
71   }
72
73   rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN |
74                             ((ctx->magic == M_MBOX
75                               || ctx->magic == M_MMDF) ? 0 : CH_NOSTATUS));
76   oerrno = errno;
77
78   mx_close_mailbox (&tmpctx, NULL);
79
80   if (rc == -1) {
81     mutt_error (_("could not write temporary mail folder: %s"),
82                 strerror (oerrno));
83     goto bail;
84   }
85
86   if (stat (tmp, &sb) == 0) {
87     mtime = sb.st_mtime;
88     size = sb.st_size;
89   }
90
91   /*
92    * 2002-09-05 me@sigpipe.org
93    * The file the user is going to edit is not a real mbox, so we need to
94    * truncate the last newline in the temp file, which is logically part of
95    * the message separator, and not the body of the message.  If we fail to
96    * remove it, the message will grow by one line each time the user edits
97    * the message.
98    */
99   if (size != 0 && truncate (tmp, --size) == -1) {
100     mutt_error (_("could not truncate temporary mail folder: %s"),
101                 strerror (errno));
102     goto bail;
103   }
104
105   mutt_edit_file (NONULL (Editor), tmp);
106
107   if ((rc = stat (tmp, &sb)) == -1) {
108     mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
109     goto bail;
110   }
111
112   if (sb.st_size == 0) {
113     mutt_message (_("Message file is empty!"));
114     rc = 1;
115     goto bail;
116   }
117
118   if (sb.st_mtime == mtime && sb.st_size == size) {
119     mutt_message (_("Message not modified!"));
120     rc = 1;
121     goto bail;
122   }
123
124   if ((fp = fopen (tmp, "r")) == NULL) {
125     rc = -1;
126     mutt_error (_("Can't open message file: %s"), strerror (errno));
127     goto bail;
128   }
129
130   if (mx_open_mailbox (ctx->path, M_APPEND, &tmpctx) == NULL) {
131     rc = -1;
132     mutt_error (_("Can't append to folder: %s"), strerror (errno));
133     goto bail;
134   }
135
136   of = 0;
137   cf = ((tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF) ? 0 : CH_NOSTATUS);
138
139   if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL)) {
140     if (tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF)
141       cf = CH_FROM | CH_FORCE_FROM;
142   }
143   else
144     of = M_ADD_FROM;
145
146   /* 
147    * XXX - we have to play games with the message flags to avoid
148    * problematic behaviour with maildir folders.
149    *
150    */
151
152   o_read = cur->read;
153   o_old = cur->old;
154   cur->read = cur->old = 0;
155   msg = mx_open_new_message (&tmpctx, cur, of);
156   cur->read = o_read;
157   cur->old = o_old;
158
159   if (msg == NULL) {
160     mutt_error (_("Can't append to folder: %s"), strerror (errno));
161     mx_close_mailbox (&tmpctx, NULL);
162     goto bail;
163   }
164
165   if ((rc =
166        mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf,
167                       NULL)) == 0) {
168     fputc ('\n', msg->fp);
169     rc = mutt_copy_stream (fp, msg->fp);
170   }
171
172   rc = mx_commit_message (msg, &tmpctx);
173   mx_close_message (&msg);
174
175   mx_close_mailbox (&tmpctx, NULL);
176
177 bail:
178   if (fp)
179     fclose (fp);
180
181   if (rc >= 0)
182     unlink (tmp);
183
184   if (rc == 0) {
185     mutt_set_flag (Context, cur, M_DELETE, 1);
186     mutt_set_flag (Context, cur, M_READ, 1);
187
188     if (option (OPTDELETEUNTAG))
189       mutt_set_flag (Context, cur, M_TAG, 0);
190   }
191   else if (rc == -1)
192     mutt_message (_("Error. Preserving temporary file: %s"), tmp);
193
194
195   return rc;
196 }
197
198 int mutt_edit_message (CONTEXT * ctx, HEADER * hdr)
199 {
200   int i, j;
201
202   if (hdr)
203     return edit_one_message (ctx, hdr);
204
205
206   for (i = 0; i < ctx->vcount; i++) {
207     j = ctx->v2r[i];
208     if (ctx->hdrs[j]->tagged) {
209       if (edit_one_message (ctx, ctx->hdrs[j]) == -1)
210         return -1;
211     }
212   }
213
214   return 0;
215 }