1: /* m_convert.c - parse a message sequence and set SELECTED */ 2: 3: #include "../h/mh.h" 4: #include <stdio.h> 5: #include <ctype.h> 6: 7: #define BADLST (-1) 8: #define BADMSG (-2) 9: #define BADRNG (-3) 10: #define BADNEW (-4) 11: #define BADNUM (-5) 12: 13: #define FIRST 1 14: #define LAST 2 15: 16: #define getnew(mp) (mp -> hghmsg + 1) 17: 18: static int convdir; 19: static char *delimp; 20: 21: /* */ 22: 23: m_convert (mp, name) 24: register struct msgs *mp; 25: register char *name; 26: { 27: register int first, 28: last; 29: register char *bp, 30: *cp; 31: int found, 32: range, 33: err, 34: flags; 35: 36: switch (err = attr (mp, cp = name)) { 37: case NOTOK: 38: return 0; 39: 40: case OK: 41: break; 42: 43: default: 44: return 1; 45: } 46: 47: found = 0; 48: flags = mp -> msgflags & MHPATH ? EXISTS | SELECT_EMPTY : EXISTS; 49: 50: if ((mp -> msgflags & MHPATH) && strcmp (cp, "new") == 0) 51: if ((err = first = getnew (mp)) <= 0) 52: goto badmsg; 53: else 54: goto single; 55: if (strcmp (cp, "all") == 0) 56: cp = "first-last"; 57: if ((err = first = m_conv (mp, cp, FIRST)) <= 0) 58: goto badmsg; 59: if (*(cp = delimp) && *cp != '-' && *cp != ':') { 60: badelim: ; 61: advise (NULLCP, "illegal argument delimiter: `%c'(0%o)", 62: *delimp, *delimp); 63: return 0; 64: } 65: if (*cp == '-') { 66: cp++; 67: if ((err = last = m_conv (mp, cp, LAST)) <= 0) { 68: badmsg: ; 69: switch (err) { 70: case BADMSG: 71: advise (NULLCP, "no %s message", cp); 72: break; 73: 74: case BADNUM: 75: advise (NULLCP, "message %s doesn't exist", cp); 76: break; 77: 78: case BADRNG: 79: advise (NULLCP, "message %s out of range 1-%d", 80: cp, mp -> hghmsg); 81: break; 82: 83: case BADLST: 84: badlist: ; 85: advise (NULLCP, "bad message list %s", name); 86: break; 87: 88: case BADNEW: 89: advise (NULLCP, "folder full, no %s message", name); 90: break; 91: 92: default: 93: advise (NULLCP, "no messages match specification"); 94: } 95: return 0; 96: } 97: if (last < first) 98: goto badlist; 99: if (*delimp) 100: goto badelim; 101: if (first > mp -> hghmsg || last < mp -> lowmsg) { 102: rangerr: ; 103: advise (NULLCP, "no messages in range %s", name); 104: return 0; 105: } 106: if (last > mp -> hghmsg) 107: last = mp -> hghmsg; 108: if (first < mp -> lowmsg) 109: first = mp -> lowmsg; 110: } 111: else 112: if (*cp == ':') { 113: cp++; 114: if (*cp == '-') { 115: convdir = -1; 116: cp++; 117: } 118: else 119: if (*cp == '+') { 120: convdir = 1; 121: cp++; 122: } 123: if ((range = atoi (bp = cp)) == 0) 124: goto badlist; 125: while (isdigit (*bp)) 126: bp++; 127: if (*bp) 128: goto badelim; 129: if ((convdir > 0 && first > mp -> hghmsg) 130: || (convdir < 0 && first < mp -> lowmsg)) 131: goto rangerr; 132: if (first < mp -> lowmsg) 133: first = mp -> lowmsg; 134: if (first > mp -> hghmsg) 135: first = mp -> hghmsg; 136: for (last = first; 137: last >= mp -> lowmsg && last <= mp -> hghmsg; 138: last += convdir) 139: if (mp -> msgstats[last] & EXISTS) 140: if (--range <= 0) 141: break; 142: if (last < mp -> lowmsg) 143: last = mp -> lowmsg; 144: if (last > mp -> hghmsg) 145: last = mp -> hghmsg; 146: if (last < first) { 147: range = last; 148: last = first; 149: first = range; 150: } 151: } 152: else { 153: if (!(mp -> msgflags & MHPATH)) 154: if (first > mp -> hghmsg 155: || first < mp -> lowmsg 156: || !(mp -> msgstats[first] & EXISTS)) { 157: if (strcmp (name, "cur") == 0 || strcmp (name, ".") == 0) 158: advise (NULLCP, "no %s message", name); 159: else 160: advise (NULLCP, "message %d doesn't exist", first); 161: return 0; 162: } 163: single: ; 164: last = first; 165: if (mp -> msgflags & MHPATH) 166: mp -> msgstats[first] |= SELECT_EMPTY; 167: } 168: for (; first <= last; first++) 169: if (mp -> msgstats[first] & flags) { 170: if (!(mp -> msgstats[first] & SELECTED)) { 171: mp -> numsel++; 172: mp -> msgstats[first] |= SELECTED; 173: if (mp -> lowsel == 0 || first < mp -> lowsel) 174: mp -> lowsel = first; 175: if (first > mp -> hghsel) 176: mp -> hghsel = first; 177: } 178: found++; 179: } 180: if (!found) 181: goto rangerr; 182: 183: return 1; 184: } 185: 186: /* */ 187: 188: static m_conv (mp, str, call) 189: register struct msgs *mp; 190: register char *str; 191: register int call; 192: { 193: register int i; 194: register char *cp, 195: *bp; 196: char buf[16]; 197: 198: convdir = 1; 199: cp = bp = str; 200: if (isdigit (*cp)) { 201: while (isdigit (*bp)) 202: bp++; 203: delimp = bp; 204: return ((i = atoi (cp)) <= mp -> hghmsg ? i 205: : *delimp || call == LAST ? mp -> hghmsg + 1 206: : mp -> msgflags & MHPATH ? BADRNG : BADNUM); 207: } 208: 209: bp = buf; 210: while ((*cp >= 'a' && *cp <= 'z') || *cp == '.') 211: *bp++ = *cp++; 212: *bp++ = NULL; 213: delimp = cp; 214: 215: if (strcmp (buf, "first") == 0) 216: return (mp -> hghmsg || !(mp -> msgflags & MHPATH) 217: ? mp -> lowmsg : BADMSG); 218: 219: if (strcmp (buf, "last") == 0) { 220: convdir = -1; 221: return (mp -> hghmsg || !(mp -> msgflags & MHPATH) 222: ? mp -> hghmsg : BADMSG); 223: } 224: 225: if (strcmp (buf, "cur") == 0 || strcmp (buf, ".") == 0) 226: return (mp -> curmsg > 0 ? mp -> curmsg : BADMSG); 227: 228: if (strcmp (buf, "prev") == 0) { 229: convdir = -1; 230: for (i = (mp -> curmsg <= mp -> hghmsg) ? mp -> curmsg - 1 : mp -> hghmsg; 231: i >= mp -> lowmsg; i--) { 232: if (mp -> msgstats[i] & EXISTS) 233: return i; 234: } 235: return BADMSG; 236: } 237: 238: if (strcmp (buf, "next") == 0) { 239: for (i = (mp -> curmsg >= mp -> lowmsg) ? mp -> curmsg + 1 : mp -> lowmsg; 240: i <= mp -> hghmsg; i++) { 241: if (mp -> msgstats[i] & EXISTS) 242: return i; 243: } 244: return BADMSG; 245: } 246: 247: return BADLST; 248: } 249: 250: /* */ 251: 252: static attr (mp, cp) 253: register struct msgs *mp; 254: register char *cp; 255: { 256: int bits, 257: found, 258: inverted; 259: register int i, 260: j; 261: register char *dp; 262: 263: if (strcmp (cp, "cur") == 0)/* hack for "cur-xyz", etc. */ 264: return OK; 265: 266: if (inverted = (dp = m_find (nsequence)) && *dp && ssequal (dp, cp)) 267: cp += strlen (dp); 268: 269: bits = FFATTRSLOT; 270: for (i = 0; mp -> msgattrs[i]; i++) 271: if (strcmp (mp -> msgattrs[i], cp) == 0) 272: break; 273: if (mp -> msgattrs[i] == NULL) 274: return OK; 275: 276: found = 0; 277: for (j = mp -> lowmsg; j <= mp -> hghmsg; j++) 278: if ((mp -> msgstats[j] & EXISTS) 279: && inverted ? !(mp -> msgstats[j] & (1 << (bits + i))) 280: : mp -> msgstats[j] & (1 << (bits + i))) { 281: if (!(mp -> msgstats[j] & SELECTED)) { 282: mp -> numsel++; 283: mp -> msgstats[j] |= SELECTED; 284: if (mp -> lowsel == 0 || j < mp -> lowsel) 285: mp -> lowsel = j; 286: if (j > mp -> hghsel) 287: mp -> hghsel = j; 288: } 289: found++; 290: } 291: if (found > 0) 292: return found; 293: 294: advise (NULLCP, "sequence %s %s", cp, inverted ? "full" : "empty"); 295: return NOTOK; 296: }