Rearranged whitespace (and comments) in all the code!
[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 HEADSW  4
27         { "header", 0 },
28 #define NHEADSW  5
29         { "noheader", 0 },
30 #define WIDTHSW  6
31         { "width columns", 0 },
32 #define REVSW  7
33         { "reverse", 0 },
34 #define NREVSW  8
35         { "noreverse", 0 },
36 #define FILESW  9
37         { "file file", 4 },
38 #define VERSIONSW 10
39         { "version", 0 },
40 #define HELPSW  11
41         { "help", 0 },
42         { NULL, 0 }
43 };
44
45
46 /*
47  * global for sbr/formatsbr.c - yech!
48  */
49 #ifdef LBL
50 extern struct msgs *fmt_current_folder;
51 #endif
52
53 /*
54  * prototypes
55  */
56 void clear_screen(void);  /* from termsbr.c */
57
58
59 int
60 main (int argc, char **argv)
61 {
62         int clearflag = 0, hdrflag = 0, ontty;
63         int width = 0, revflag = 0;
64         int i, state, msgnum;
65         int seqnum[NUMATTRS], unseen, num_unseen_seq = 0;
66         char *cp, *maildir, *file = NULL, *folder = NULL;
67         char *form = NULL, *format = NULL, buf[BUFSIZ];
68         char **argp, *nfs, **arguments;
69         struct msgs_array msgs = { 0, 0, NULL };
70         struct msgs *mp;
71         FILE *in;
72
73 #ifdef LOCALE
74         setlocale(LC_ALL, "");
75 #endif
76         invo_name = r1bindex (argv[0], '/');
77
78         /* read user profile/context */
79         context_read();
80
81         mts_init (invo_name);
82         arguments = getarguments (invo_name, argc, argv, 1);
83         argp = arguments;
84
85         /*
86          * Parse arguments
87          */
88         while ((cp = *argp++)) {
89                 if (*cp == '-') {
90                         switch (smatch (++cp, switches)) {
91                                 case AMBIGSW:
92                                         ambigsw (cp, switches);
93                                         done (1);
94                                 case UNKWNSW:
95                                         adios (NULL, "-%s unknown", cp);
96
97                                 case HELPSW:
98                                         snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]",
99                                                 invo_name);
100                                         print_help (buf, switches, 1);
101                                         done (1);
102                                 case VERSIONSW:
103                                         print_version(invo_name);
104                                         done (1);
105
106                                 case CLRSW:
107                                         clearflag++;
108                                         continue;
109                                 case NCLRSW:
110                                         clearflag = 0;
111                                         continue;
112
113                                 case FORMSW:
114                                         if (!(form = *argp++) || *form == '-')
115                                                 adios (NULL, "missing argument to %s", argp[-2]);
116                                         format = NULL;
117                                         continue;
118                                 case FMTSW:
119                                         if (!(format = *argp++) || *format == '-')
120                                                 adios (NULL, "missing argument to %s", argp[-2]);
121                                         form = NULL;
122                                         continue;
123
124                                 case HEADSW:
125                                         hdrflag++;
126                                         continue;
127                                 case NHEADSW:
128                                         hdrflag = 0;
129                                         continue;
130
131                                 case WIDTHSW:
132                                         if (!(cp = *argp++) || *cp == '-')
133                                                 adios (NULL, "missing argument to %s", argp[-2]);
134                                         width = atoi (cp);
135                                         continue;
136                                 case REVSW:
137                                         revflag++;
138                                         continue;
139                                 case NREVSW:
140                                         revflag = 0;
141                                         continue;
142
143                                 case FILESW:
144                                         if (!(cp = *argp++) || (cp[0] == '-' && cp[1]))
145                                                 adios (NULL, "missing argument to %s", argp[-2]);
146                                         if (strcmp (file = cp, "-"))
147                                                 file = path (cp, TFILE);
148                                         continue;
149                         }
150                 }
151                 if (*cp == '+' || *cp == '@') {
152                         if (folder)
153                                 adios (NULL, "only one folder at a time!");
154                         else
155                                 folder = pluspath (cp);
156                 } else
157                                 app_msgarg(&msgs, cp);
158         }
159
160         if (!context_find ("path"))
161                 free (path ("./", TFOLDER));
162
163         /*
164          * Get new format string.  Must be before chdir().
165          */
166         nfs = new_fs (form, format, FORMAT);
167
168         /*
169          * We are scanning a maildrop file
170          */
171         if (file) {
172                 if (msgs.size)
173                         adios (NULL, "\"msgs\" not allowed with -file");
174                 if (folder)
175                         adios (NULL, "\"+folder\" not allowed with -file");
176
177                 /* check if "file" is really stdin */
178                 if (strcmp (file, "-") == 0) {
179                         in = stdin;
180                         file = "stdin";
181                 } else {
182                         if ((in = fopen (file, "r")) == NULL)
183                                 adios (file, "unable to open");
184                 }
185
186 #ifndef JLR
187                 if (hdrflag) {
188                         printf ("FOLDER %s\t%s\n", file, dtimenow (1));
189                 }
190 #endif /* JLR */
191
192                 m_unknown (in);
193                 for (msgnum = 1; ; ++msgnum) {
194                         state = scan (in, msgnum, -1, nfs, width, 0, 0,
195                                         hdrflag ? file : NULL, 0L, 1);
196                         if (state != SCNMSG && state != SCNENC)
197                                 break;
198                 }
199                 fclose (in);
200                 done (0);
201         }
202
203         /*
204          * We are scanning a folder
205          */
206
207         if (!msgs.size)
208                 app_msgarg(&msgs, "all");
209         if (!folder)
210                 folder = getfolder (1);
211         maildir = m_maildir (folder);
212
213         if (chdir (maildir) == NOTOK)
214                 adios (maildir, "unable to change directory to");
215
216         /* read folder and create message structure */
217         if (!(mp = folder_read (folder)))
218                 adios (NULL, "unable to read folder %s", folder);
219
220         /* check for empty folder */
221         if (mp->nummsg == 0)
222                 adios (NULL, "no messages in %s", folder);
223
224         /* parse all the message ranges/sequences and set SELECTED */
225         for (msgnum = 0; msgnum < msgs.size; msgnum++)
226                 if (!m_convert (mp, msgs.msgs[msgnum]))
227                         done(1);
228         seq_setprev (mp);  /* set the Previous-Sequence */
229
230         context_replace (pfolder, folder);  /* update current folder */
231         seq_save (mp);  /* synchronize message sequences */
232         context_save ();  /* save the context file */
233
234         /*
235          * Get the sequence number for each sequence
236          * specified by Unseen-Sequence
237          */
238         if ((cp = context_find (usequence)) && *cp) {
239                 char **ap, *dp;
240
241                 dp = getcpy(cp);
242                 ap = brkstring (dp, " ", "\n");
243                 for (i = 0; ap && *ap; i++, ap++)
244                         seqnum[i] = seq_getnum (mp, *ap);
245
246                 num_unseen_seq = i;
247                 if (dp)
248                         free(dp);
249         }
250
251         ontty = isatty (fileno (stdout));
252
253 #ifdef LBL
254         else
255                 fmt_current_folder = mp;
256 #endif
257
258         for (msgnum = revflag ? mp->hghsel : mp->lowsel;
259                  (revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel);
260                  msgnum += (revflag ? -1 : 1)) {
261                 if (is_selected(mp, msgnum)) {
262                         if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) {
263 #if 0
264                                 if (errno != EACCES)
265 #endif
266                                         admonish (cp, "unable to open message");
267 #if 0
268                                 else
269                                         printf ("%*d  unreadable\n", DMAXFOLDER, msgnum);
270 #endif
271                                 continue;
272                         }
273
274 #ifndef JLR
275                         if (hdrflag) {
276                                 printf ("FOLDER %s\t%s\n", folder, dtimenow(1));
277                         }
278 #endif /* JLR */
279
280                         /*
281                          * Check if message is in any sequence given
282                          * by Unseen-Sequence profile entry.
283                          */
284                         unseen = 0;
285                         for (i = 0; i < num_unseen_seq; i++) {
286                                 if (in_sequence(mp, seqnum[i], msgnum)) {
287                                         unseen = 1;
288                                         break;
289                                 }
290                         }
291
292                         switch (state = scan (in, msgnum, 0, nfs, width,
293                                                 msgnum == mp->curmsg, unseen,
294                                                 folder, 0L, 1)) {
295                                 case SCNMSG:
296                                 case SCNENC:
297                                 case SCNERR:
298                                         break;
299
300                                 default:
301                                         adios (NULL, "scan() botch (%d)", state);
302
303                                 case SCNEOF:
304 #if 0
305                                         printf ("%*d  empty\n", DMAXFOLDER, msgnum);
306 #else
307                                         advise (NULL, "message %d: empty", msgnum);
308 #endif
309                                         break;
310                         }
311                         hdrflag = 0;
312                         fclose (in);
313                         if (ontty)
314                                 fflush (stdout);
315                 }
316         }
317
318 #ifdef LBL
319         seq_save (mp);  /* because formatsbr might have made changes */
320 #endif
321
322         folder_free (mp);  /* free folder/message structure */
323         if (clearflag)
324                 clear_screen ();
325
326         done (0);
327         return 1;
328 }