* uip/mhlistsbr.c, uip/mhlsbr.c, uip/picksbr.c: cast
[mmh] / uip / comp.c
1
2 /*
3  * comp.c -- compose a message
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <h/utils.h>
14 #include <fcntl.h>
15
16 static struct swit switches[] = {
17 #define DFOLDSW                0
18     { "draftfolder +folder", 0 },
19 #define DMSGSW                 1
20     { "draftmessage msg", 0 },
21 #define NDFLDSW                2
22     { "nodraftfolder", 0 },
23 #define EDITRSW                3
24     { "editor editor", 0 },
25 #define NEDITSW                4
26     { "noedit", 0 },
27 #define FILESW                 5
28     { "file file", 0 },
29 #define FORMSW                 6
30     { "form formfile", 0 },
31 #define USESW                  7
32     { "use", 0 },
33 #define NUSESW                 8
34     { "nouse", 0 },
35 #define WHATSW                 9
36     { "whatnowproc program", 0 },
37 #define NWHATSW               10
38     { "nowhatnowproc", 0 },
39 #define VERSIONSW             11
40     { "version", 0 },
41 #define HELPSW                12
42     { "help", 0 },
43     { NULL, 0 }
44 };
45
46 static struct swit aqrunl[] = {
47 #define NOSW          0
48     { "quit", 0 },
49 #define YESW          1
50     { "replace", 0 },
51 #define USELSW        2
52     { "use", 0 },
53 #define LISTDSW       3
54     { "list", 0 },
55 #define REFILSW       4
56     { "refile +folder", 0 },
57 #define NEWSW         5
58     { "new", 0 },
59     { NULL, 0 }
60 };
61
62 static struct swit aqrul[] = {
63     { "quit", 0 },
64     { "replace", 0 },
65     { "use", 0 },
66     { "list", 0 },
67     { "refile", 0 },
68     { NULL, 0 }
69 };
70
71
72 int
73 main (int argc, char **argv)
74 {
75     int use = NOUSE, nedit = 0, nwhat = 0;
76     int i, in, isdf = 0, out;
77     char *cp, *cwd, *maildir, *dfolder = NULL;
78     char *ed = NULL, *file = NULL, *form = NULL;
79     char *folder = NULL, *msg = NULL, buf[BUFSIZ];
80     char drft[BUFSIZ], **argp, **arguments;
81     struct msgs *mp = NULL;
82     struct stat st;
83
84 #ifdef LOCALE
85     setlocale(LC_ALL, "");
86 #endif
87     invo_name = r1bindex (argv[0], '/');
88
89     /* read user profile/context */
90     context_read();
91
92     arguments = getarguments (invo_name, argc, argv, 1);
93     argp = arguments;
94
95     while ((cp = *argp++)) {
96         if (*cp == '-') {
97             switch (smatch (++cp, switches)) {
98                 case AMBIGSW: 
99                     ambigsw (cp, switches);
100                     done (1);
101                 case UNKWNSW: 
102                     adios (NULL, "-%s unknown", cp);
103
104                 case HELPSW: 
105                     snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]",
106                         invo_name);
107                     print_help (buf, switches, 1);
108                     done (1);
109                 case VERSIONSW:
110                     print_version(invo_name);
111                     done (1);
112
113                 case EDITRSW: 
114                     if (!(ed = *argp++) || *ed == '-')
115                         adios (NULL, "missing argument to %s", argp[-2]);
116                     nedit = 0;
117                     continue;
118                 case NEDITSW: 
119                     nedit++;
120                     continue;
121
122                 case WHATSW: 
123                     if (!(whatnowproc = *argp++) || *whatnowproc == '-')
124                         adios (NULL, "missing argument to %s", argp[-2]);
125                     nwhat = 0;
126                     continue;
127                 case NWHATSW: 
128                     nwhat++;
129                     continue;
130
131                 case FORMSW: 
132                     if (!(form = *argp++) || *form == '-')
133                         adios (NULL, "missing argument to %s", argp[-2]);
134                     continue;
135
136                 case USESW: 
137                     use++;
138                     continue;
139                 case NUSESW: 
140                     use = NOUSE;
141                     continue;
142
143                 case FILESW:    /* compatibility */
144                     if (file)
145                         adios (NULL, "only one file at a time!");
146                     if (!(file = *argp++) || *file == '-')
147                         adios (NULL, "missing argument to %s", argp[-2]);
148                     isdf = NOTOK;
149                     continue;
150
151                 case DFOLDSW: 
152                     if (dfolder)
153                         adios (NULL, "only one draft folder at a time!");
154                     if (!(cp = *argp++) || *cp == '-')
155                         adios (NULL, "missing argument to %s", argp[-2]);
156                     dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
157                             *cp != '@' ? TFOLDER : TSUBCWF);
158                     continue;
159                 case DMSGSW: 
160                     if (file)
161                         adios (NULL, "only one draft message at a time!");
162                     if (!(file = *argp++) || *file == '-')
163                         adios (NULL, "missing argument to %s", argp[-2]);
164                     continue;
165                 case NDFLDSW: 
166                     dfolder = NULL;
167                     isdf = NOTOK;
168                     continue;
169             }
170         }
171         if (*cp == '+' || *cp == '@') {
172             if (folder)
173                 adios (NULL, "only one folder at a time!");
174             else
175                 folder = pluspath (cp);
176         } else {
177             if (msg)
178                 adios (NULL, "only one message at a time!");
179             else
180                 msg = cp;
181         }
182     }
183
184     cwd = getcpy (pwd ());
185
186     if (!context_find ("path"))
187         free (path ("./", TFOLDER));
188
189     /*
190      * Check if we are using a draft folder
191      * and have specified a message in it.
192      */
193     if ((dfolder || context_find ("Draft-Folder")) && !folder && msg && !file) {
194         file = msg;
195         msg = NULL;
196     }
197     if (form && (folder || msg))
198             adios (NULL, "can't mix forms and folders/msgs");
199
200     if (folder || msg) {
201         /*
202          * Use a message as the "form" for the new message.
203          */
204         if (!msg)
205             msg = "cur";
206         if (!folder)
207             folder = getfolder (1);
208         maildir = m_maildir (folder);
209
210         if (chdir (maildir) == NOTOK)
211             adios (maildir, "unable to change directory to");
212
213         /* read folder and create message structure */
214         if (!(mp = folder_read (folder)))
215             adios (NULL, "unable to read folder %s", folder);
216
217         /* check for empty folder */
218         if (mp->nummsg == 0)
219             adios (NULL, "no messages in %s", folder);
220
221         /* parse the message range/sequence/name and set SELECTED */
222         if (!m_convert (mp, msg))
223             done (1);
224         seq_setprev (mp);       /* set the previous-sequence */
225
226         if (mp->numsel > 1)
227             adios (NULL, "only one message at a time!");
228
229         if ((in = open (form = getcpy (m_name (mp->lowsel)), O_RDONLY)) == NOTOK)
230             adios (form, "unable to open message");
231     } else
232         in = open_form(&form, components);
233
234 try_it_again:
235     strncpy (drft, m_draft (dfolder, file, use, &isdf), sizeof(drft));
236
237     /*
238      * Check if we have an existing draft
239      */
240     if ((out = open (drft, O_RDONLY)) != NOTOK) {
241         i = fdcompare (in, out);
242         close (out);
243
244         /*
245          * If we have given -use flag, or if the
246          * draft is just the same as the components
247          * file, then no need to ask any questions.
248          */
249         if (use || i)
250             goto edit_it;
251
252         if (stat (drft, &st) == NOTOK)
253             adios (drft, "unable to stat");
254         printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
255         for (i = LISTDSW; i != YESW;) {
256             if (!(argp = getans ("\nDisposition? ", isdf ? aqrunl : aqrul)))
257                 done (1);
258             switch (i = smatch (*argp, isdf ? aqrunl : aqrul)) {
259                 case NOSW: 
260                     done (0);
261                 case NEWSW: 
262                     file = NULL;
263                     use = NOUSE;
264                     goto try_it_again;
265                 case YESW: 
266                     break;
267                 case USELSW:
268                     use++;
269                     goto edit_it;
270                 case LISTDSW: 
271                     showfile (++argp, drft);
272                     break;
273                 case REFILSW: 
274                     if (refile (++argp, drft) == 0)
275                         i = YESW;
276                     break;
277                 default: 
278                     advise (NULL, "say what?");
279                     break;
280             }
281         }
282     } else {
283         if (use)
284             adios (drft, "unable to open");
285     }
286
287     if ((out = creat (drft, m_gmprot ())) == NOTOK)
288         adios (drft, "unable to create");
289     cpydata (in, out, form, drft);
290     close (in);
291     close (out);
292
293 edit_it:
294     context_save ();    /* save the context file */
295
296     if (nwhat)
297         done (0);
298     what_now (ed, nedit, use, drft, NULL, 0, NULLMP, NULL, 0, cwd);
299     done (1);
300     return 1;
301 }