Mercurial > hg > Applications > mh
view sbr/m_convert.c @ 3:f89a9a79e124
utf-8
author | kono |
---|---|
date | Wed, 20 Apr 2005 00:25:01 +0900 |
parents | bce86c4163a3 |
children | 441a2190cfae |
line wrap: on
line source
/* m_convert.c - parse a message sequence and set SELECTED */ #ifndef lint static char ident[] = "@(#)$Id$"; #endif /* lint */ #include "../h/mh.h" #include <stdio.h> #include <ctype.h> #define BADMSG (-2) #define BADRNG (-3) #define BADNEW (-4) #define BADNUM (-5) #define BADLST (-6) #define FIRST 1 #define LAST 2 #define getnew(mp) (mp -> hghmsg + 1) static int convdir; static char *delimp; static m_conv(), attr(); /* */ m_convert (mp, name) register struct msgs *mp; register char *name; { register int first, last; register char *bp, *cp; int found, range, err, flags; switch (err = attr (mp, cp = name)) { case NOTOK: return 0; case OK: break; default: if (err < 0) goto badmsg; return 1; } found = 0; flags = mp -> msgflags & MHPATH ? EXISTS | SELECT_EMPTY : EXISTS; if ((mp -> msgflags & MHPATH) && strcmp (cp, "new") == 0) if ((err = first = getnew (mp)) <= 0) goto badmsg; else goto single; if (strcmp (cp, "all") == 0) cp = "first-last"; if ((err = first = m_conv (mp, cp, FIRST)) <= 0) goto badmsg; if (*(cp = delimp) && *cp != '-' && *cp != ':') { badelim: ; advise (NULLCP, "illegal argument delimiter: `%c'(0%o)", *delimp, *delimp); return 0; } if (*cp == '-') { cp++; if ((err = last = m_conv (mp, cp, LAST)) <= 0) { badmsg: ; switch (err) { case BADMSG: advise (NULLCP, "no %s message", cp); break; case BADNUM: advise (NULLCP, "message %s doesn't exist", cp); break; case BADRNG: advise (NULLCP, "message %s out of range 1-%d", cp, mp -> hghmsg); break; case BADLST: badlist: ; advise (NULLCP, "bad message list %s", name); break; case BADNEW: advise (NULLCP, "folder full, no %s message", name); break; default: advise (NULLCP, "no messages match specification"); } return 0; } if (last < first) goto badlist; if (*delimp) goto badelim; if (first > mp -> hghmsg || last < mp -> lowmsg) { rangerr: ; advise (NULLCP, "no messages in range %s", name); return 0; } if (last > mp -> hghmsg) last = mp -> hghmsg; if (first < mp -> lowmsg) first = mp -> lowmsg; } else if (*cp == ':') { cp++; if (*cp == '-') { convdir = -1; cp++; } else if (*cp == '+') { convdir = 1; cp++; } if ((range = atoi (bp = cp)) == 0) goto badlist; while (isdigit (*bp)) bp++; if (*bp) goto badelim; if ((convdir > 0 && first > mp -> hghmsg) || (convdir < 0 && first < mp -> lowmsg)) goto rangerr; if (first < mp -> lowmsg) first = mp -> lowmsg; if (first > mp -> hghmsg) first = mp -> hghmsg; for (last = first; last >= mp -> lowmsg && last <= mp -> hghmsg; last += convdir) if (mp -> msgstats[last] & EXISTS) if (--range <= 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; } } else { if (!(mp -> msgflags & MHPATH)) if (first > mp -> hghmsg || first < mp -> lowmsg || !(mp -> msgstats[first] & EXISTS)) { if (strcmp (name, "cur") == 0 || strcmp (name, ".") == 0) advise (NULLCP, "no %s message", name); else advise (NULLCP, "message %d doesn't exist", first); return 0; } single: ; last = first; if (mp -> msgflags & MHPATH) mp -> msgstats[first] |= SELECT_EMPTY; } for (; first <= last; first++) if (mp -> msgstats[first] & flags) { if (!(mp -> msgstats[first] & SELECTED)) { mp -> numsel++; mp -> msgstats[first] |= SELECTED; if (mp -> lowsel == 0 || first < mp -> lowsel) mp -> lowsel = first; if (first > mp -> hghsel) mp -> hghsel = first; } found++; } if (!found) goto rangerr; return 1; } /* */ static m_conv (mp, str, call) register struct msgs *mp; register char *str; register int call; { register int i; register char *cp, *bp; char buf[16]; convdir = 1; cp = bp = str; if (isdigit (*cp)) { while (isdigit (*bp)) bp++; delimp = bp; return ((i = atoi (cp)) <= mp -> hghmsg ? i : *delimp || call == LAST ? mp -> hghmsg + 1 : mp -> msgflags & MHPATH ? BADRNG : BADNUM); } bp = buf; #ifndef LOCALE while ((*cp >= 'a' && *cp <= 'z') || *cp == '.') #else while (isalpha(*cp) || *cp == '.') /* doesn't enforce lower case */ #endif /* LOCALE */ *bp++ = *cp++; *bp++ = 0; delimp = cp; if (strcmp (buf, "first") == 0) return (mp -> hghmsg || !(mp -> msgflags & MHPATH) ? mp -> lowmsg : BADMSG); if (strcmp (buf, "last") == 0) { convdir = -1; return (mp -> hghmsg || !(mp -> msgflags & MHPATH) ? mp -> hghmsg : BADMSG); } if (strcmp (buf, "cur") == 0 || strcmp (buf, ".") == 0) return (mp -> curmsg > 0 ? mp -> curmsg : BADMSG); if (strcmp (buf, "prev") == 0) { convdir = -1; for (i = (mp -> curmsg <= mp -> hghmsg) ? mp -> curmsg - 1 : mp -> hghmsg; i >= mp -> lowmsg; i--) { if (mp -> msgstats[i] & EXISTS) return i; } return BADMSG; } if (strcmp (buf, "next") == 0) { for (i = (mp -> curmsg >= mp -> lowmsg) ? mp -> curmsg + 1 : mp -> lowmsg; i <= mp -> hghmsg; i++) { if (mp -> msgstats[i] & EXISTS) return i; } return BADMSG; } return BADLST; } /* */ static attr (mp, cp) register struct msgs *mp; register char *cp; { char *bp = (char *)NULL; int bits, found, inverted, range = 0, /* no range */ first = 0; register int i, j; register char *dp; if (strcmp (cp, "cur") == 0)/* hack for "cur-xyz", etc. */ return OK; if (ssequal ("cur:", cp)) /* this code need to be rewritten... */ return OK; if (inverted = (dp = m_find (nsequence)) && *dp && ssequal (dp, cp)) cp += strlen (dp); convdir = 1; for (dp = cp; *dp && isalnum(*dp); dp++) continue; if (*dp == ':') { bp = dp++; range = 1; if (isalpha (*dp)) { /* optimize? */ if (strcmp (dp, "prev") == 0) { convdir = -1; first = (mp -> curmsg > 0) && (mp -> curmsg <= mp -> hghmsg) ? mp -> curmsg - 1 : mp -> hghmsg; } else if (strcmp (dp, "next") == 0) { convdir = 1; first = (mp -> curmsg >= mp -> lowmsg) ? mp -> curmsg + 1 : mp -> lowmsg; } else if (strcmp (dp, "first") == 0) { convdir = 1; } else if (strcmp (dp, "last") == 0) { convdir = -1; } else return BADLST; } else { /* a numeric range */ if (*dp == '+') dp++; else if (*dp == '-') { dp++; convdir = -1; } if ((range = atoi(dp)) == 0) return BADLST; while (isdigit (*dp)) dp++; if (*dp) return BADLST; } *bp = '\0'; /* terminate sequence name */ } bits = FFATTRSLOT; for (i = 0; mp -> msgattrs[i]; i++) if (strcmp (mp -> msgattrs[i], cp) == 0) break; if (bp) *bp = ':'; /* restore sequence name */ if (mp -> msgattrs[i] == NULL) return OK; found = 0; for (j = first ? first : (convdir > 0) ? mp -> lowmsg : mp -> hghmsg; j >= mp -> lowmsg && j <= mp -> hghmsg; j += convdir) if ((mp -> msgstats[j] & EXISTS) && inverted ? !(mp -> msgstats[j] & (1 << (bits + i))) : mp -> msgstats[j] & (1 << (bits + i))) { if (!(mp -> msgstats[j] & SELECTED)) { mp -> numsel++; mp -> msgstats[j] |= SELECTED; if (mp -> lowsel == 0 || j < mp -> lowsel) mp -> lowsel = j; if (j > mp -> hghsel) mp -> hghsel = j; } found++; if (range && found >= range) break; /* we've done enough */ } if (found > 0) return found; if (first) return BADMSG; advise (NULLCP, "sequence %s %s", cp, inverted ? "full" : "empty"); return NOTOK; }