Removed `-format string' switches but made -form accept `=formatstring'.
[mmh] / uip / scan.c
1 /*
2 ** scan.c -- display a one-line "scan" listing of folder or messages
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/fmt_scan.h>
11 #include <h/scansbr.h>
12 #include <h/tws.h>
13 #include <h/utils.h>
14 #include <errno.h>
15
16 static struct swit switches[] = {
17 #define CLRSW  0
18         { "clear", 0 },
19 #define NCLRSW  1
20         { "noclear", 0 },
21 #define FORMSW  2
22         { "form formatfile", 0 },
23 #define WIDTHSW  3
24         { "width columns", 0 },
25 #define FILESW  4
26         { "file file", 4 },
27 #define VERSIONSW 5
28         { "version", 0 },
29 #define HELPSW  6
30         { "help", 0 },
31         { NULL, 0 }
32 };
33
34
35 /*
36 ** prototypes
37 */
38 void clear_screen(void);  /* from termsbr.c */
39
40
41 int
42 main(int argc, char **argv)
43 {
44         int clearflag = 0, ontty;
45         int width = 0;
46         int i, state, msgnum;
47         int seqnum[NUMATTRS], unseen, num_unseen_seq = 0;
48         char *cp, *maildir, *file = NULL, *folder = NULL;
49         char *form = NULL, buf[BUFSIZ];
50         char **argp, *nfs, **arguments;
51         struct msgs_array msgs = { 0, 0, NULL };
52         struct msgs *mp;
53         FILE *in;
54
55 #ifdef LOCALE
56         setlocale(LC_ALL, "");
57 #endif
58         invo_name = mhbasename(argv[0]);
59
60         /* read user profile/context */
61         context_read();
62
63         arguments = getarguments(invo_name, argc, argv, 1);
64         argp = arguments;
65
66         /*
67         ** Parse arguments
68         */
69         while ((cp = *argp++)) {
70                 if (*cp == '-') {
71                         switch (smatch(++cp, switches)) {
72                         case AMBIGSW:
73                                 ambigsw(cp, switches);
74                                 done(1);
75                         case UNKWNSW:
76                                 adios(NULL, "-%s unknown", cp);
77
78                         case HELPSW:
79                                 snprintf(buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name);
80                                 print_help(buf, switches, 1);
81                                 done(1);
82                         case VERSIONSW:
83                                 print_version(invo_name);
84                                 done(1);
85
86                         case CLRSW:
87                                 clearflag++;
88                                 continue;
89                         case NCLRSW:
90                                 clearflag = 0;
91                                 continue;
92
93                         case FORMSW:
94                                 if (!(form = *argp++) || *form == '-')
95                                         adios(NULL, "missing argument to %s",
96                                                         argp[-2]);
97                                 continue;
98
99                         case WIDTHSW:
100                                 if (!(cp = *argp++) || *cp == '-')
101                                         adios(NULL, "missing argument to %s",
102                                                         argp[-2]);
103                                 width = atoi(cp);
104                                 continue;
105
106                         case FILESW:
107                                 if (!(cp = *argp++) || (cp[0] == '-' && cp[1]))
108                                         adios(NULL, "missing argument to %s",
109                                                         argp[-2]);
110                                 if (strcmp(file = cp, "-")!=0)
111                                         file = getcpy(expanddir(cp));
112                                 continue;
113                         }
114                 }
115                 if (*cp == '+' || *cp == '@') {
116                         if (folder)
117                                 adios(NULL, "only one folder at a time!");
118                         else
119                                 folder = getcpy(expandfol(cp));
120                 } else
121                         app_msgarg(&msgs, cp);
122         }
123
124         /*
125         ** Get new format string.  Must be before chdir().
126         */
127         nfs = new_fs(form, FORMAT);
128
129         /*
130         ** We are scanning a maildrop file
131         */
132         if (file) {
133                 if (msgs.size)
134                         adios(NULL, "\"msgs\" not allowed with -file");
135                 if (folder)
136                         adios(NULL, "\"+folder\" not allowed with -file");
137
138                 /* check if "file" is really stdin */
139                 if (strcmp(file, "-") == 0) {
140                         in = stdin;
141                         file = "stdin";
142                 } else if (!(in = fopen(file, "r"))) {
143                         adios(file, "unable to open");
144                 }
145
146                 m_unknown(in);
147                 for (msgnum = 1; ; ++msgnum) {
148                         state = scan(in, msgnum, -1, nfs, width, 0, 0,
149                                         NULL, 0L, 1);
150                         if (state != SCNMSG && state != SCNENC)
151                                 break;
152                 }
153                 fclose(in);
154                 done(0);
155         }
156
157         /*
158         ** We are scanning a folder
159         */
160
161         if (!msgs.size)
162                 app_msgarg(&msgs, seq_all);
163         if (!folder)
164                 folder = getcurfol();
165         maildir = toabsdir(folder);
166
167         if (chdir(maildir) == NOTOK)
168                 adios(maildir, "unable to change directory to");
169
170         /* read folder and create message structure */
171         if (!(mp = folder_read(folder)))
172                 adios(NULL, "unable to read folder %s", folder);
173
174         /* check for empty folder */
175         if (mp->nummsg == 0)
176                 adios(NULL, "no messages in %s", folder);
177
178         /* parse all the message ranges/sequences and set SELECTED */
179         for (msgnum = 0; msgnum < msgs.size; msgnum++)
180                 if (!m_convert(mp, msgs.msgs[msgnum]))
181                         done(1);
182         seq_setprev(mp);  /* set the Previous-Sequence */
183
184         context_replace(curfolder, folder);  /* update current folder */
185         seq_save(mp);  /* synchronize message sequences */
186         context_save();  /* save the context file */
187
188         /*
189         ** Get the sequence number for each `unseen' sequence
190         */
191         if (!(cp = context_find(usequence))) {
192                 cp = seq_unseen;  /* use default, if not set */
193         }
194         if (*cp) {
195                 char **ap, *dp;
196
197                 dp = getcpy(cp);
198                 ap = brkstring(dp, " ", "\n");
199                 for (i = 0; ap && *ap; i++, ap++) {
200                         seqnum[i] = seq_getnum(mp, *ap);
201                 }
202                 num_unseen_seq = i;
203                 if (dp) {
204                         free(dp);
205                 }
206         }
207
208         ontty = isatty(fileno(stdout));
209
210         for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
211                 if (is_selected(mp, msgnum)) {
212                         if ((in = fopen(cp = m_name(msgnum), "r")) == NULL) {
213                                 admonish(cp, "unable to open message");
214                                 continue;
215                         }
216
217                         /*
218                         ** Check if message is in any sequence given
219                         ** by Unseen-Sequence profile entry.
220                         */
221                         unseen = 0;
222                         for (i = 0; i < num_unseen_seq; i++) {
223                                 if (in_sequence(mp, seqnum[i], msgnum)) {
224                                         unseen = 1;
225                                         break;
226                                 }
227                         }
228
229                         switch (state = scan(in, msgnum, 0, nfs, width,
230                                                 msgnum == mp->curmsg, unseen,
231                                                 folder, 0L, 1)) {
232                         case SCNMSG:
233                         case SCNENC:
234                         case SCNERR:
235                                 break;
236
237                         default:
238                                 adios(NULL, "scan() botch(%d)", state);
239
240                         case SCNEOF:
241                                 advise(NULL, "message %d: empty", msgnum);
242                                 break;
243                         }
244                         fclose(in);
245                         if (ontty)
246                                 fflush(stdout);
247                 }
248         }
249
250         folder_free(mp);  /* free folder/message structure */
251         if (clearflag)
252                 clear_screen();
253
254         done(0);
255         return 1;
256 }