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