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