]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/sbr/m_convert.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / sbr / m_convert.c
1 /* m_convert.c - parse a message sequence and set SELECTED */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: m_convert.c,v 1.10 1992/12/15 00:20:22 jromine Exp $";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include <stdio.h>
8 #include <ctype.h>
9
10 #define BADMSG (-2)
11 #define BADRNG (-3)
12 #define BADNEW (-4)
13 #define BADNUM (-5)
14 #define BADLST (-6)
15
16 #define FIRST 1
17 #define LAST 2
18
19 #define getnew(mp) (mp -> hghmsg + 1)
20
21 static int convdir;
22 static char *delimp;
23
24 static m_conv(), attr();
25 /* \f */
26
27 m_convert (mp, name)
28 register struct msgs *mp;
29 register char *name;
30 {
31 register int first,
32 last;
33 register char *bp,
34 *cp;
35 int found,
36 range,
37 err,
38 flags;
39
40 switch (err = attr (mp, cp = name)) {
41 case NOTOK:
42 return 0;
43
44 case OK:
45 break;
46
47 default:
48 if (err < 0)
49 goto badmsg;
50 return 1;
51 }
52
53 found = 0;
54 flags = mp -> msgflags & MHPATH ? EXISTS | SELECT_EMPTY : EXISTS;
55
56 if ((mp -> msgflags & MHPATH) && strcmp (cp, "new") == 0)
57 if ((err = first = getnew (mp)) <= 0)
58 goto badmsg;
59 else
60 goto single;
61 if (strcmp (cp, "all") == 0)
62 cp = "first-last";
63 if ((err = first = m_conv (mp, cp, FIRST)) <= 0)
64 goto badmsg;
65 if (*(cp = delimp) && *cp != '-' && *cp != ':') {
66 badelim: ;
67 advise (NULLCP, "illegal argument delimiter: `%c'(0%o)",
68 *delimp, *delimp);
69 return 0;
70 }
71 if (*cp == '-') {
72 cp++;
73 if ((err = last = m_conv (mp, cp, LAST)) <= 0) {
74 badmsg: ;
75 switch (err) {
76 case BADMSG:
77 advise (NULLCP, "no %s message", cp);
78 break;
79
80 case BADNUM:
81 advise (NULLCP, "message %s doesn't exist", cp);
82 break;
83
84 case BADRNG:
85 advise (NULLCP, "message %s out of range 1-%d",
86 cp, mp -> hghmsg);
87 break;
88
89 case BADLST:
90 badlist: ;
91 advise (NULLCP, "bad message list %s", name);
92 break;
93
94 case BADNEW:
95 advise (NULLCP, "folder full, no %s message", name);
96 break;
97
98 default:
99 advise (NULLCP, "no messages match specification");
100 }
101 return 0;
102 }
103 if (last < first)
104 goto badlist;
105 if (*delimp)
106 goto badelim;
107 if (first > mp -> hghmsg || last < mp -> lowmsg) {
108 rangerr: ;
109 advise (NULLCP, "no messages in range %s", name);
110 return 0;
111 }
112 if (last > mp -> hghmsg)
113 last = mp -> hghmsg;
114 if (first < mp -> lowmsg)
115 first = mp -> lowmsg;
116 }
117 else
118 if (*cp == ':') {
119 cp++;
120 if (*cp == '-') {
121 convdir = -1;
122 cp++;
123 }
124 else
125 if (*cp == '+') {
126 convdir = 1;
127 cp++;
128 }
129 if ((range = atoi (bp = cp)) == 0)
130 goto badlist;
131 while (isdigit (*bp))
132 bp++;
133 if (*bp)
134 goto badelim;
135 if ((convdir > 0 && first > mp -> hghmsg)
136 || (convdir < 0 && first < mp -> lowmsg))
137 goto rangerr;
138 if (first < mp -> lowmsg)
139 first = mp -> lowmsg;
140 if (first > mp -> hghmsg)
141 first = mp -> hghmsg;
142 for (last = first;
143 last >= mp -> lowmsg && last <= mp -> hghmsg;
144 last += convdir)
145 if (mp -> msgstats[last] & EXISTS)
146 if (--range <= 0)
147 break;
148 if (last < mp -> lowmsg)
149 last = mp -> lowmsg;
150 if (last > mp -> hghmsg)
151 last = mp -> hghmsg;
152 if (last < first) {
153 range = last;
154 last = first;
155 first = range;
156 }
157 }
158 else {
159 if (!(mp -> msgflags & MHPATH))
160 if (first > mp -> hghmsg
161 || first < mp -> lowmsg
162 || !(mp -> msgstats[first] & EXISTS)) {
163 if (strcmp (name, "cur") == 0 || strcmp (name, ".") == 0)
164 advise (NULLCP, "no %s message", name);
165 else
166 advise (NULLCP, "message %d doesn't exist", first);
167 return 0;
168 }
169 single: ;
170 last = first;
171 if (mp -> msgflags & MHPATH)
172 mp -> msgstats[first] |= SELECT_EMPTY;
173 }
174 for (; first <= last; first++)
175 if (mp -> msgstats[first] & flags) {
176 if (!(mp -> msgstats[first] & SELECTED)) {
177 mp -> numsel++;
178 mp -> msgstats[first] |= SELECTED;
179 if (mp -> lowsel == 0 || first < mp -> lowsel)
180 mp -> lowsel = first;
181 if (first > mp -> hghsel)
182 mp -> hghsel = first;
183 }
184 found++;
185 }
186 if (!found)
187 goto rangerr;
188
189 return 1;
190 }
191
192 /* \f */
193
194 static m_conv (mp, str, call)
195 register struct msgs *mp;
196 register char *str;
197 register int call;
198 {
199 register int i;
200 register char *cp,
201 *bp;
202 char buf[16];
203
204 convdir = 1;
205 cp = bp = str;
206 if (isdigit (*cp)) {
207 while (isdigit (*bp))
208 bp++;
209 delimp = bp;
210 return ((i = atoi (cp)) <= mp -> hghmsg ? i
211 : *delimp || call == LAST ? mp -> hghmsg + 1
212 : mp -> msgflags & MHPATH ? BADRNG : BADNUM);
213 }
214
215 bp = buf;
216 #ifndef LOCALE
217 while ((*cp >= 'a' && *cp <= 'z') || *cp == '.')
218 #else
219 while (isalpha(*cp) || *cp == '.') /* doesn't enforce lower case */
220 #endif /* LOCALE */
221 *bp++ = *cp++;
222 *bp++ = 0;
223 delimp = cp;
224
225 if (strcmp (buf, "first") == 0)
226 return (mp -> hghmsg || !(mp -> msgflags & MHPATH)
227 ? mp -> lowmsg : BADMSG);
228
229 if (strcmp (buf, "last") == 0) {
230 convdir = -1;
231 return (mp -> hghmsg || !(mp -> msgflags & MHPATH)
232 ? mp -> hghmsg : BADMSG);
233 }
234
235 if (strcmp (buf, "cur") == 0 || strcmp (buf, ".") == 0)
236 return (mp -> curmsg > 0 ? mp -> curmsg : BADMSG);
237
238 if (strcmp (buf, "prev") == 0) {
239 convdir = -1;
240 for (i = (mp -> curmsg <= mp -> hghmsg) ? mp -> curmsg - 1 : mp -> hghmsg;
241 i >= mp -> lowmsg; i--) {
242 if (mp -> msgstats[i] & EXISTS)
243 return i;
244 }
245 return BADMSG;
246 }
247
248 if (strcmp (buf, "next") == 0) {
249 for (i = (mp -> curmsg >= mp -> lowmsg) ? mp -> curmsg + 1 : mp -> lowmsg;
250 i <= mp -> hghmsg; i++) {
251 if (mp -> msgstats[i] & EXISTS)
252 return i;
253 }
254 return BADMSG;
255 }
256
257 return BADLST;
258 }
259
260 /* \f */
261
262 static attr (mp, cp)
263 register struct msgs *mp;
264 register char *cp;
265 {
266 char *bp = (char *)NULL;
267 int bits,
268 found,
269 inverted,
270 range = 0, /* no range */
271 first = 0;
272 register int i,
273 j;
274 register char *dp;
275
276 if (strcmp (cp, "cur") == 0)/* hack for "cur-xyz", etc. */
277 return OK;
278 if (ssequal ("cur:", cp)) /* this code need to be rewritten... */
279 return OK;
280
281 if (inverted = (dp = m_find (nsequence)) && *dp && ssequal (dp, cp))
282 cp += strlen (dp);
283
284 convdir = 1;
285 for (dp = cp; *dp && isalnum(*dp); dp++)
286 continue;
287 if (*dp == ':') {
288 bp = dp++;
289
290 range = 1;
291 if (isalpha (*dp)) { /* optimize? */
292 if (strcmp (dp, "prev") == 0) {
293 convdir = -1;
294 first = (mp -> curmsg > 0) && (mp -> curmsg <= mp -> hghmsg)
295 ? mp -> curmsg - 1
296 : mp -> hghmsg;
297 }
298 else if (strcmp (dp, "next") == 0) {
299 convdir = 1;
300 first = (mp -> curmsg >= mp -> lowmsg)
301 ? mp -> curmsg + 1
302 : mp -> lowmsg;
303 }
304 else if (strcmp (dp, "first") == 0) {
305 convdir = 1;
306 }
307 else if (strcmp (dp, "last") == 0) {
308 convdir = -1;
309 }
310 else
311 return BADLST;
312 }
313 else { /* a numeric range */
314 if (*dp == '+')
315 dp++;
316 else if (*dp == '-') {
317 dp++;
318 convdir = -1;
319 }
320 if ((range = atoi(dp)) == 0)
321 return BADLST;
322 while (isdigit (*dp))
323 dp++;
324 if (*dp)
325 return BADLST;
326 }
327
328 *bp = '\0'; /* terminate sequence name */
329 }
330
331
332 bits = FFATTRSLOT;
333 for (i = 0; mp -> msgattrs[i]; i++)
334 if (strcmp (mp -> msgattrs[i], cp) == 0)
335 break;
336 if (bp)
337 *bp = ':'; /* restore sequence name */
338 if (mp -> msgattrs[i] == NULL)
339 return OK;
340
341 found = 0;
342 for (j = first ? first : (convdir > 0) ? mp -> lowmsg : mp -> hghmsg;
343 j >= mp -> lowmsg && j <= mp -> hghmsg; j += convdir)
344 if ((mp -> msgstats[j] & EXISTS)
345 && inverted ? !(mp -> msgstats[j] & (1 << (bits + i)))
346 : mp -> msgstats[j] & (1 << (bits + i))) {
347 if (!(mp -> msgstats[j] & SELECTED)) {
348 mp -> numsel++;
349 mp -> msgstats[j] |= SELECTED;
350 if (mp -> lowsel == 0 || j < mp -> lowsel)
351 mp -> lowsel = j;
352 if (j > mp -> hghsel)
353 mp -> hghsel = j;
354 }
355 found++;
356 if (range && found >= range)
357 break; /* we've done enough */
358 }
359 if (found > 0)
360 return found;
361
362 if (first)
363 return BADMSG;
364 advise (NULLCP, "sequence %s %s", cp, inverted ? "full" : "empty");
365 return NOTOK;
366 }