]>
diplodocus.org Git - nmh/blob - sbr/m_convert.c
3 * m_convert.c -- parse a message range or sequence and set SELECTED
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
13 * error codes for sequence
14 * and message range processing
25 #define getnew(mp) (mp->hghmsg + 1)
27 static int convdir
; /* convert direction */
33 static int m_conv (struct msgs
*, char *, int);
34 static int attr (struct msgs
*, char *);
38 m_convert (struct msgs
*mp
, char *name
)
40 int first
, last
, found
, range
, err
;
43 /* check if user defined sequence */
44 err
= attr (mp
, cp
= name
);
53 * else err == 0, so continue
59 * Check for special "new" sequence, which
60 * is valid only if ALLOW_NEW is set.
62 if ((mp
->msgflags
& ALLOW_NEW
) && !strcmp (cp
, "new")) {
63 if ((err
= first
= getnew (mp
)) <= 0)
69 if (!strcmp (cp
, "all"))
72 if ((err
= first
= m_conv (mp
, cp
, FIRST
)) <= 0)
76 if (*cp
!= '\0' && *cp
!= '-' && *cp
!= ':') {
78 advise (NULL
, "illegal argument delimiter: `%c'(0%o)", *delimp
, *delimp
);
84 if ((err
= last
= m_conv (mp
, cp
, LAST
)) <= 0) {
88 advise (NULL
, "no %s message", cp
);
92 advise (NULL
, "message %s doesn't exist", cp
);
96 advise (NULL
, "message %s out of range 1-%d", cp
, mp
->hghmsg
);
101 advise (NULL
, "bad message list %s", name
);
105 advise (NULL
, "folder full, no %s message", name
);
109 advise (NULL
, "no messages match specification");
118 if (first
> mp
->hghmsg
|| last
< mp
->lowmsg
) {
120 advise (NULL
, "no messages in range %s", name
);
124 /* tighten the range to search */
125 if (last
> mp
->hghmsg
)
127 if (first
< mp
->lowmsg
)
130 } else if (*cp
== ':') {
141 if ((range
= atoi (bp
= cp
)) == 0)
143 while (isdigit ((unsigned char) *bp
))
147 if ((convdir
> 0 && first
> mp
->hghmsg
)
148 || (convdir
< 0 && first
< mp
->lowmsg
))
151 /* tighten the range to search */
152 if (first
< mp
->lowmsg
)
154 if (first
> mp
->hghmsg
)
158 last
>= mp
->lowmsg
&& last
<= mp
->hghmsg
;
160 if (does_exist (mp
, last
))
163 if (last
< mp
->lowmsg
)
165 if (last
> mp
->hghmsg
)
178 * If ALLOW_NEW is set, then allow selecting of an
179 * empty slot. If ALLOW_NEW is not set, then we
180 * check if message is in-range and exists.
182 if (mp
->msgflags
& ALLOW_NEW
) {
184 * We can get into a case where the "cur" sequence is way out
185 * of range, and because it's allowed to not exist (think
186 * of "rmm; next") it doesn't get checked to make sure it's
187 * within the range of messages in seq_init(). So if our
188 * desired sequence is out of range of the allocated folder
189 * limits simply reallocate the folder so it's within range.
191 if (first
< mp
->lowoff
|| first
> mp
->hghoff
)
192 mp
= folder_realloc(mp
, first
< mp
->lowoff
? first
: mp
->lowoff
,
193 first
> mp
->hghoff
? first
: mp
->hghoff
);
195 set_select_empty (mp
, first
);
197 if (first
> mp
->hghmsg
198 || first
< mp
->lowmsg
199 || !(does_exist (mp
, first
))) {
200 if (!strcmp (name
, "cur") || !strcmp (name
, "."))
201 advise (NULL
, "no %s message", name
);
203 advise (NULL
, "message %d doesn't exist", first
);
207 last
= first
; /* range of 1 */
211 * Cycle through the range and select the messages
212 * that exist. If ALLOW_NEW is set, then we also check
213 * if we are selecting an empty slot.
215 for (; first
<= last
; first
++) {
216 if (does_exist (mp
, first
) ||
217 ((mp
->msgflags
& ALLOW_NEW
) && is_select_empty (mp
, first
))) {
218 if (!is_selected (mp
, first
)) {
219 set_selected (mp
, first
);
221 if (mp
->lowsel
== 0 || first
< mp
->lowsel
)
223 if (first
> mp
->hghsel
)
237 * Convert the various message names to
238 * their numeric values.
250 m_conv (struct msgs
*mp
, char *str
, int call
)
258 if (isdigit ((unsigned char) *cp
)) {
259 while (isdigit ((unsigned char) *bp
))
266 else if (*delimp
|| call
== LAST
)
267 return mp
->hghmsg
+ 1;
268 else if (mp
->msgflags
& ALLOW_NEW
)
275 /* doesn't enforce lower case */
276 for (bp
= buf
; (isalpha((unsigned char) *cp
) || *cp
== '.')
277 && (bp
- buf
< (int) sizeof(buf
) - 1); )
279 for (bp
= buf
; ((*cp
>= 'a' && *cp
<= 'z') || *cp
== '.')
280 && (bp
- buf
< (int) sizeof(buf
) - 1); )
288 if (!strcmp (buf
, "first"))
289 return (mp
->hghmsg
|| !(mp
->msgflags
& ALLOW_NEW
)
290 ? mp
->lowmsg
: BADMSG
);
292 if (!strcmp (buf
, "last")) {
294 return (mp
->hghmsg
|| !(mp
->msgflags
& ALLOW_NEW
) ? mp
->hghmsg
: BADMSG
);
297 if (!strcmp (buf
, "cur") || !strcmp (buf
, "."))
298 return (mp
->curmsg
> 0 ? mp
->curmsg
: BADMSG
);
300 if (!strcmp (buf
, "prev")) {
302 for (i
= (mp
->curmsg
<= mp
->hghmsg
) ? mp
->curmsg
- 1 : mp
->hghmsg
;
303 i
>= mp
->lowmsg
; i
--) {
304 if (does_exist (mp
, i
))
310 if (!strcmp (buf
, "next")) {
311 for (i
= (mp
->curmsg
>= mp
->lowmsg
) ? mp
->curmsg
+ 1 : mp
->lowmsg
;
312 i
<= mp
->hghmsg
; i
++) {
313 if (does_exist (mp
, i
))
323 * Handle user defined sequences.
324 * They can take the following forms:
337 attr (struct msgs
*mp
, char *cp
)
344 range
= 0, /* no range */
347 /* hack for "cur-name", "cur-n", etc. */
348 if (!strcmp (cp
, "cur"))
350 if (ssequal ("cur:", cp
)) /* this code need to be rewritten... */
353 /* Check for sequence negation */
354 if ((dp
= context_find (nsequence
)) && *dp
!= '\0' && ssequal (dp
, cp
)) {
359 convdir
= 1; /* convert direction */
361 for (dp
= cp
; *dp
&& isalnum((unsigned char) *dp
); dp
++)
374 if (isalpha ((unsigned char) *dp
)) {
375 if (!strcmp (dp
, "prev")) {
377 first
= (mp
->curmsg
> 0) && (mp
->curmsg
<= mp
->hghmsg
)
381 else if (!strcmp (dp
, "next")) {
383 first
= (mp
->curmsg
>= mp
->lowmsg
)
387 else if (!strcmp (dp
, "first")) {
390 else if (!strcmp (dp
, "last")) {
403 else if (*dp
== '-') {
407 if ((range
= atoi(dp
)) == 0)
409 while (isdigit ((unsigned char) *dp
))
415 *bp
= '\0'; /* temporarily terminate sequence name */
418 i
= seq_getnum (mp
, cp
); /* get index of sequence */
421 *bp
= ':'; /* restore sequence name */
425 found
= 0; /* count the number we select for this argument */
427 for (j
= first
? first
: (convdir
> 0) ? mp
->lowmsg
: mp
->hghmsg
;
428 j
>= mp
->lowmsg
&& j
<= mp
->hghmsg
; j
+= convdir
) {
429 if (does_exist (mp
, j
)
430 && inverted
? !in_sequence (mp
, i
, j
) : in_sequence (mp
, i
, j
)) {
431 if (!is_selected (mp
, j
)) {
432 set_selected (mp
, j
);
434 if (mp
->lowsel
== 0 || j
< mp
->lowsel
)
442 * If we have a range, then break out
443 * once we've found enough.
445 if (range
&& found
>= range
)
455 advise (NULL
, "sequence %s %s", cp
, inverted
? "full" : "empty");