X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/0bfb53a23531bea3aaeadcd1a6f6c372eef96612..4a56a28ac439137ba2b71fcb5952b4e4abd1e2fc:/sbr/m_convert.c diff --git a/sbr/m_convert.c b/sbr/m_convert.c index 496978ee..566b02a5 100644 --- a/sbr/m_convert.c +++ b/sbr/m_convert.c @@ -1,6 +1,4 @@ - -/* - * m_convert.c -- parse a message range or sequence and set SELECTED +/* m_convert.c -- parse a message range or sequence and set SELECTED * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for @@ -8,6 +6,7 @@ */ #include +#include /* * error codes for sequence @@ -22,6 +21,7 @@ #define FIRST 1 #define LAST 2 + #define getnew(mp) (mp->hghmsg + 1) static int convdir; /* convert direction */ @@ -37,24 +37,24 @@ static int attr (struct msgs *, char *); int m_convert (struct msgs *mp, char *name) { - int first, last, found, range, err; - unsigned char *bp; - char *cp; + int first, last, found, count, is_range, err; + char *bp, *cp; /* check if user defined sequence */ err = attr (mp, cp = name); if (err == -1) return 0; - else if (err < 0) + if (err < 0) goto badmsg; - else if (err > 0) + if (err > 0) return 1; /* * else err == 0, so continue */ found = 0; + is_range = 1; /* * Check for special "new" sequence, which @@ -63,8 +63,7 @@ m_convert (struct msgs *mp, char *name) if ((mp->msgflags & ALLOW_NEW) && !strcmp (cp, "new")) { if ((err = first = getnew (mp)) <= 0) goto badmsg; - else - goto single; + goto single; } if (!strcmp (cp, "all")) @@ -74,9 +73,9 @@ m_convert (struct msgs *mp, char *name) goto badmsg; cp = delimp; - if (*cp != '\0' && *cp != '-' && *cp != ':') { + if (*cp != '\0' && *cp != '-' && *cp != ':' && *cp != '=') { badelim: - advise (NULL, "illegal argument delimiter: `%c'(0%o)", *delimp, *delimp); + inform("illegal argument delimiter: `%c'(0%o)", *delimp, *delimp); return 0; } @@ -86,28 +85,28 @@ badelim: badmsg: switch (err) { case BADMSG: - advise (NULL, "no %s message", cp); + inform("no %s message", cp); break; case BADNUM: - advise (NULL, "message %s doesn't exist", cp); + inform("message %s doesn't exist", cp); break; case BADRNG: - advise (NULL, "message %s out of range 1-%d", cp, mp->hghmsg); + inform("message %s out of range 1-%d", cp, mp->hghmsg); break; case BADLST: badlist: - advise (NULL, "bad message list %s", name); + inform("bad message list %s", name); break; case BADNEW: - advise (NULL, "folder full, no %s message", name); + inform("folder full, no %s message", name); break; default: - advise (NULL, "no messages match specification"); + inform("no messages match specification"); } return 0; } @@ -118,7 +117,7 @@ badlist: goto badelim; if (first > mp->hghmsg || last < mp->lowmsg) { rangerr: - advise (NULL, "no messages in range %s", name); + inform("no messages in range %s", name); return 0; } @@ -128,20 +127,25 @@ rangerr: if (first < mp->lowmsg) first = mp->lowmsg; - } else if (*cp == ':') { + } else if (*cp == ':' || *cp == '=') { + + if (*cp == '=') + is_range = 0; + cp++; + if (*cp == '-') { + /* foo:-3 or foo=-3 */ convdir = -1; cp++; - } else { - if (*cp == '+') { - convdir = 1; - cp++; - } + } else if (*cp == '+') { + /* foo:+3 or foo=+3 is same as foo:3 or foo=3 */ + convdir = 1; + cp++; } - if ((range = atoi (bp = cp)) == 0) + if ((count = atoi (bp = cp)) == 0) goto badlist; - while (isdigit (*bp)) + while (isdigit ((unsigned char) *bp)) bp++; if (*bp) goto badelim; @@ -159,16 +163,24 @@ rangerr: last >= mp->lowmsg && last <= mp->hghmsg; last += convdir) if (does_exist (mp, last)) - if (--range <= 0) + if (--count <= 0) break; - if (last < mp->lowmsg) - last = mp->lowmsg; - if (last > mp->hghmsg) - last = mp->hghmsg; - if (last < first) { - range = last; - last = first; - first = range; + if (is_range) { /* a range includes any messages that exist */ + if (last < mp->lowmsg) + last = mp->lowmsg; + if (last > mp->hghmsg) + last = mp->hghmsg; + if (last < first) { + count = last; + last = first; + first = count; + } + } else { /* looking for the nth message. if not enough, fail. */ + if (last < mp->lowmsg || last > mp->hghmsg) { + inform("no such message"); + return 0; + } + first = last; } } else { @@ -190,8 +202,8 @@ single: * limits simply reallocate the folder so it's within range. */ if (first < mp->lowoff || first > mp->hghoff) - mp = folder_realloc(mp, first < mp->lowoff ? first : mp->lowoff, - first > mp->hghoff ? first : mp->hghoff); + mp = folder_realloc(mp, min(first, mp->lowoff), + max(first, mp->hghoff)); set_select_empty (mp, first); } else { @@ -199,9 +211,9 @@ single: || first < mp->lowmsg || !(does_exist (mp, first))) { if (!strcmp (name, "cur") || !strcmp (name, ".")) - advise (NULL, "no %s message", name); + inform("no %s message", name); else - advise (NULL, "message %d doesn't exist", first); + inform("message %d doesn't exist", first); return 0; } } @@ -250,36 +262,30 @@ single: static int m_conv (struct msgs *mp, char *str, int call) { - register int i; - register unsigned char *cp, *bp; - unsigned char buf[16]; + int i; + char *cp, *bp; + char buf[16]; convdir = 1; cp = bp = str; - if (isdigit (*cp)) { - while (isdigit (*bp)) + if (isdigit ((unsigned char) *cp)) { + while (isdigit ((unsigned char) *bp)) bp++; delimp = bp; i = atoi (cp); if (i <= mp->hghmsg) return i; - else if (*delimp || call == LAST) + if (*delimp || call == LAST) return mp->hghmsg + 1; - else if (mp->msgflags & ALLOW_NEW) + if (mp->msgflags & ALLOW_NEW) return BADRNG; - else - return BADNUM; + return BADNUM; } -#ifdef LOCALE /* doesn't enforce lower case */ - for (bp = buf; (isalpha(*cp) || *cp == '.') + for (bp = buf; (isalpha((unsigned char) *cp) || *cp == '.') && (bp - buf < (int) sizeof(buf) - 1); ) -#else - for (bp = buf; ((*cp >= 'a' && *cp <= 'z') || *cp == '.') - && (bp - buf < (int) sizeof(buf) - 1); ) -#endif /* LOCALE */ { *bp++ = *cp++; } @@ -337,19 +343,25 @@ m_conv (struct msgs *mp, char *str, int call) static int attr (struct msgs *mp, char *cp) { - register unsigned char *dp; + char *dp; char *bp = NULL; - register int i, j; + char *ep; + char op; + int i, j; int found, inverted = 0, - range = 0, /* no range */ - first = 0; + count = 0, /* range given? else use entire sequence */ + just_one = 0, /* want entire sequence or range */ + first = 0, + start = 0; /* hack for "cur-name", "cur-n", etc. */ if (!strcmp (cp, "cur")) return 0; - if (ssequal ("cur:", cp)) /* this code need to be rewritten... */ - return 0; + if (has_prefix(cp, "cur")) { + if (cp[3] == ':' || cp[3] == '=') + return 0; + } /* Check for sequence negation */ if ((dp = context_find (nsequence)) && *dp != '\0' && ssequal (dp, cp)) { @@ -359,12 +371,12 @@ attr (struct msgs *mp, char *cp) convdir = 1; /* convert direction */ - for (dp = cp; *dp && isalnum(*dp); dp++) + for (dp = cp; *dp && isalnum((unsigned char) *dp); dp++) continue; if (*dp == ':') { bp = dp++; - range = 1; + count = 1; /* * seq:prev (or) @@ -372,87 +384,125 @@ attr (struct msgs *mp, char *cp) * seq:first (or) * seq:last */ - if (isalpha (*dp)) { + if (isalpha ((unsigned char) *dp)) { if (!strcmp (dp, "prev")) { convdir = -1; first = (mp->curmsg > 0) && (mp->curmsg <= mp->hghmsg) ? mp->curmsg - 1 : mp->hghmsg; + start = first; } else if (!strcmp (dp, "next")) { convdir = 1; first = (mp->curmsg >= mp->lowmsg) ? mp->curmsg + 1 : mp->lowmsg; + start = first; } else if (!strcmp (dp, "first")) { convdir = 1; + start = mp->lowmsg; } else if (!strcmp (dp, "last")) { convdir = -1; + start = mp->hghmsg; } - else + else { return BADLST; + } } else { /* * seq:n (or) * seq:+n (or) * seq:-n */ - if (*dp == '+') + if (*dp == '+') { + /* foo:+3 is same as foo:3 */ dp++; - else if (*dp == '-') { + convdir = 1; + start = mp->lowmsg; + } else if (*dp == '-' || *dp == ':') { + /* foo:-3 or foo::3 */ dp++; convdir = -1; + start = mp->hghmsg; } - if ((range = atoi(dp)) == 0) - return BADLST; - while (isdigit (*dp)) - dp++; - if (*dp) + count = strtol(dp,&ep,10); + if (count == 0 || *ep) /* 0 illegal */ return BADLST; } + op = *bp; + *bp = '\0'; /* temporarily terminate sequence name */ + } else if (*dp == '=') { + + bp = dp++; + + if (*dp == '+') { + /* foo=+3 is same as foo=3 */ + dp++; + convdir = 1; + start = mp->lowmsg; + } else if (*dp == '-') { + /* foo=-3 */ + dp++; + convdir = -1; + start = mp->hghmsg; + } + + count = strtol(dp,&ep,10); /* 0 illegal */ + if (count == 0 || *ep) + return BADLST; + + just_one = 1; + + op = *bp; *bp = '\0'; /* temporarily terminate sequence name */ } i = seq_getnum (mp, cp); /* get index of sequence */ if (bp) - *bp = ':'; /* restore sequence name */ + *bp = op; /* restore sequence name */ if (i == -1) return 0; found = 0; /* count the number we select for this argument */ - for (j = first ? first : (convdir > 0) ? mp->lowmsg : mp->hghmsg; - j >= mp->lowmsg && j <= mp->hghmsg; j += convdir) { + if (!start) + start = mp->lowmsg; + + for (j = start; j >= mp->lowmsg && j <= mp->hghmsg; j += convdir) { + if (does_exist (mp, j) && inverted ? !in_sequence (mp, i, j) : in_sequence (mp, i, j)) { - if (!is_selected (mp, j)) { - set_selected (mp, j); - mp->numsel++; - if (mp->lowsel == 0 || j < mp->lowsel) - mp->lowsel = j; - if (j > mp->hghsel) - mp->hghsel = j; - } found++; - + /* we want all that we find, or just the last in the +/_ case */ + if (!just_one || found >= count) { + if (!is_selected (mp, j)) { + set_selected (mp, j); + mp->numsel++; + if (mp->lowsel == 0 || j < mp->lowsel) + mp->lowsel = j; + if (j > mp->hghsel) + mp->hghsel = j; + } + } /* - * If we have a range, then break out + * If we have any sort of limit, then break out * once we've found enough. */ - if (range && found >= range) + if (count && found >= count) break; + } } - if (found > 0) - return found; + if (mp->numsel > 0) + return mp->numsel; - if (first) + if (first || just_one) return BADMSG; - advise (NULL, "sequence %s %s", cp, inverted ? "full" : "empty"); + inform("sequence %s %s", cp, inverted ? "full" : "empty"); return -1; }