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