summaryrefslogtreecommitdiff
path: root/mh
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2002-09-27 13:26:27 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2002-09-27 13:26:27 +0000
commita14aceea0b23e88b3e661c0e46be15abb6a47a70 (patch)
tree3a96d6e083050bfc84b842bd391c720b849e1847 /mh
parent6da00798774c622fa265407b84e18fb9d2d2f2f9 (diff)
downloadmailutils-a14aceea0b23e88b3e661c0e46be15abb6a47a70.tar.gz
mailutils-a14aceea0b23e88b3e661c0e46be15abb6a47a70.tar.bz2
(mh_msgset_reverse,mh_msgset_negate,
mh_msgset_current, mh_msgset_free): new functions. Added comments.
Diffstat (limited to 'mh')
-rw-r--r--mh/mh_msgset.c378
1 files changed, 296 insertions, 82 deletions
diff --git a/mh/mh_msgset.c b/mh/mh_msgset.c
index 96690045e..ec4acf5f4 100644
--- a/mh/mh_msgset.c
+++ b/mh/mh_msgset.c
@@ -18,7 +18,10 @@
/* MH message sets. */
#include <mh.h>
+#include <mailutils/argcv.h>
+/* Expand a message set (msgcnt;msglist) to accomodate `inc' more
+ elements */
static void
_expand (size_t *msgcnt, size_t **msglist, size_t inc)
{
@@ -34,6 +37,7 @@ _expand (size_t *msgcnt, size_t **msglist, size_t inc)
}
}
+/* Fatal error handler */
static void
msgset_abort (const char *arg)
{
@@ -41,6 +45,8 @@ msgset_abort (const char *arg)
exit (1);
}
+/* Handlers for expansion of the reserved message names */
+
static int
msgset_first (mailbox_t mbox, size_t *pnum)
{
@@ -135,11 +141,16 @@ static struct msgset_keyword {
{ NULL },
};
+/* Preprocess a part of a complex message designation. Returns
+ a pointer to the allocated memory containing expanded part of
+ the designation. Pointer to the beginning of the not expanded
+ part (in arg) is placed into *rest */
static char *
msgset_preproc_part (mailbox_t mbox, char *arg, char **rest)
{
struct msgset_keyword *p;
-
+ char *cp;
+
for (p = keywords; p->name; p++)
if (strncmp (arg, p->name, strlen (p->name)) == 0)
{
@@ -161,16 +172,29 @@ msgset_preproc_part (mailbox_t mbox, char *arg, char **rest)
*rest = arg + strlen (p->name);
return ret;
}
+ cp = strchr (arg, '-');
+ if (cp)
+ {
+ char *ret;
+
+ *rest = cp;
+ ret = xmalloc (cp - arg + 1);
+ memcpy (ret, arg, cp - arg);
+ ret[cp - arg] = 0;
+ return ret;
+ }
+
*rest = arg + strlen (arg);
return strdup (arg);
}
+/* Preprocess (expand) a single message designation */
static char *
msgset_preproc (mailbox_t mbox, char *arg)
{
char *buf, *tail;
- if (strcmp (arg, "all") == 0)
+ if (strcmp (arg, "all") == 0 || strcmp (arg, ".") == 0)
{
/* Special case */
arg = "first-last";
@@ -207,21 +231,91 @@ comp_mesg (const void *a, const void *b)
return 0;
}
+static int _mh_msgset_parse __P((mailbox_t mbox, mh_msgset_t *msgset,
+ int argc, char **argv));
+
+/* Treat arg as a name of user-defined sequence and attempt to
+ expand it. Return 0 if succeeded, non-zero otherwise. */
int
-mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv)
+expand_user_seq (mailbox_t mbox, mh_msgset_t *msgset, char *arg)
+{
+ int argc;
+ char **argv;
+ char *p, *listp;
+ int rc = 1;
+ int negate = 0;
+
+ p = strchr (arg, ':');
+ if (p)
+ *p++ = 0;
+ listp = mh_global_sequences_get (arg, NULL);
+ if (!listp)
+ {
+ int len;
+ char *neg = mh_global_profile_get ("Sequence-Negation", NULL);
+ if (!neg)
+ return 1;
+ len = strlen (neg);
+ if (strncmp (arg, neg, len))
+ return 1;
+ negate = 1;
+ listp = mh_global_sequences_get (arg + len, NULL);
+ if (!listp)
+ return 1;
+ }
+
+ if (argcv_get (listp, "", NULL, &argc, &argv) == 0)
+ rc = _mh_msgset_parse (mbox, msgset, argc, argv);
+ argcv_free (argc, argv);
+ if (rc)
+ return rc;
+
+ if (negate)
+ mh_msgset_negate (mbox, msgset);
+
+ if (p)
+ {
+ int first, num;
+
+ num = strtoul (p, &p, 0);
+ if (*p)
+ {
+ mh_msgset_free (msgset);
+ return 1;
+ }
+ if (num < 0)
+ {
+ first = num + msgset->count;
+ num = - num;
+ }
+ else
+ first = 0;
+ if (num > msgset->count)
+ {
+ mh_msgset_free (msgset);
+ return 1;
+ }
+
+ if (first > 0)
+ memmove (msgset->list, &msgset->list[first],
+ sizeof (msgset->list[0]) * num);
+ msgset->count = num;
+ }
+
+ return rc;
+}
+
+/* Parse a message specification from (argc;argv). Returned msgset is
+ not sorted nor optimised */
+int
+_mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv)
{
size_t msgcnt;
size_t *msglist;
- char *xargv[2];
size_t i, msgno;
if (argc == 0)
- {
- argc = 1;
- argv = xargv;
- argv[0] = "cur";
- argv[1] = NULL;
- }
+ return 1;
msgcnt = argc;
msglist = calloc (msgcnt, sizeof(*msglist));
@@ -232,94 +326,142 @@ mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv)
size_t msg_first, n;
long num;
char *arg = msgset_preproc (mbox, argv[i]);
- start = strtoul (arg, &p, 0);
- switch (*p)
+
+ if (!isdigit (arg[0]))
{
- case 0:
- n = mh_get_message (mbox, start, NULL);
- if (!n)
- {
- mh_error ("message %d does not exist", start);
- exit (1);
- }
- msglist[msgno++] = n;
- break;
+ int j;
+ mh_msgset_t m;
- case '-':
- end = strtoul (p+1, &p, 0);
- if (*p || end == start)
- msgset_abort (argv[i]);
- if (end < start)
+ if (expand_user_seq (mbox, &m, arg))
{
- size_t t = start;
- start = end;
- end = t;
- }
- _expand (&msgcnt, &msglist, end - start);
- msg_first = msgno;
- for (; start <= end; start++)
- {
- n = mh_get_message (mbox, start, NULL);
- if (n)
- msglist[msgno++] = n;
- }
- if (msgno == msg_first)
- {
- mh_error ("no messages in range %s", argv[i]);
+ mh_error ("message set %s does not exist", arg);
exit (1);
}
- break;
-
- case ':':
- num = strtoul (p+1, &p, 0);
- if (*p)
- msgset_abort (argv[i]);
- end = start + num;
- if (end < start)
- {
- size_t t = start;
- start = end + 1;
- end = t;
- }
- else
- end--;
- _expand (&msgcnt, &msglist, end - start);
- msg_first = msgno;
- for (; start <= end; start++)
+ _expand (&msgcnt, &msglist, m.count);
+ for (j = 0; j < m.count; j++)
+ msglist[msgno++] = m.list[j];
+ mh_msgset_free (&m);
+ }
+ else
+ {
+ start = strtoul (arg, &p, 0);
+ switch (*p)
{
+ case 0:
n = mh_get_message (mbox, start, NULL);
- if (n)
- msglist[msgno++] = n;
- }
- if (msgno == msg_first)
- {
- mh_error ("no messages in range %s", argv[i]);
- exit (1);
+ if (!n)
+ {
+ mh_error ("message %d does not exist", start);
+ exit (1);
+ }
+ msglist[msgno++] = n;
+ break;
+
+ case '-':
+ end = strtoul (p+1, &p, 0);
+ if (*p || end == start)
+ msgset_abort (argv[i]);
+ if (end < start)
+ {
+ size_t t = start;
+ start = end;
+ end = t;
+ }
+ _expand (&msgcnt, &msglist, end - start);
+ msg_first = msgno;
+ for (; start <= end; start++)
+ {
+ n = mh_get_message (mbox, start, NULL);
+ if (n)
+ msglist[msgno++] = n;
+ }
+ if (msgno == msg_first)
+ {
+ mh_error ("no messages in range %s", argv[i]);
+ exit (1);
+ }
+ break;
+
+ case ':':
+ num = strtoul (p+1, &p, 0);
+ if (*p)
+ msgset_abort (argv[i]);
+ end = start + num;
+ if (end < start)
+ {
+ size_t t = start;
+ start = end + 1;
+ end = t;
+ }
+ else
+ end--;
+ _expand (&msgcnt, &msglist, end - start);
+ msg_first = msgno;
+ for (; start <= end; start++)
+ {
+ n = mh_get_message (mbox, start, NULL);
+ if (n)
+ msglist[msgno++] = n;
+ }
+ if (msgno == msg_first)
+ {
+ mh_error ("no messages in range %s", argv[i]);
+ exit (1);
+ }
+ break;
+
+ default:
+ msgset_abort (argv[i]);
}
- break;
-
- default:
- msgset_abort (argv[i]);
}
free (arg);
}
- msgcnt = msgno;
-
- /* Sort the resulting message set */
- qsort (msglist, msgcnt, sizeof (*msglist), comp_mesg);
-
- /* Remove duplicates. */
- for (i = 0, msgno = 1; i < msgcnt; i++)
- if (msglist[msgno-1] != msglist[i])
- msglist[msgno++] = msglist[i];
- msgcnt = msgno;
-
- msgset->count = msgcnt;
+ msgset->count = msgno;
msgset->list = msglist;
return 0;
}
+/* Parse a message specification from (argc;argv). Returned msgset is
+ sorted and optimised (i.e. it does not contain duplicate message
+ numbers) */
+int
+mh_msgset_parse (mailbox_t mbox, mh_msgset_t *msgset,
+ int argc, char **argv, char *def)
+{
+ char *xargv[2];
+ int rc;
+
+ if (argc == 0)
+ {
+ argc = 1;
+ argv = xargv;
+ argv[0] = def ? def : "cur";
+ argv[1] = NULL;
+ }
+
+ rc = _mh_msgset_parse (mbox, msgset, argc, argv);
+
+ if (rc == 0)
+ {
+ size_t i, msgno;
+ size_t msgcnt = msgset->count;
+ size_t *msglist = msgset->list;
+
+ /* Sort the resulting message set */
+ qsort (msglist, msgcnt, sizeof (*msgset->list), comp_mesg);
+
+ /* Remove duplicates. */
+ for (i = 0, msgno = 1; i < msgset->count; i++)
+ if (msglist[msgno-1] != msglist[i])
+ msglist[msgno++] = msglist[i];
+ msgset->count = msgno;
+ }
+ return rc;
+}
+
+/* Check if message with ordinal number `num' is contained in the
+ message set. */
int
mh_msgset_member (mh_msgset_t *msgset, size_t num)
{
@@ -400,3 +542,75 @@ mh_get_message (mailbox_t mbox, size_t seqno, message_t *mesg)
return mh_search_message (mbox, 1, count, seqno, mesg);
}
+/* Reverse the order of messages in the message set */
+void
+mh_msgset_reverse (mh_msgset_t *msgset)
+{
+ int head, tail;
+
+ for (head = 0, tail = msgset->count-1; head < tail; head++, tail--)
+ {
+ size_t val = msgset->list[head];
+ msgset->list[head] = msgset->list[tail];
+ msgset->list[tail] = val;
+ }
+}
+
+/* Set the current message to that contained at position `index'
+ in the given message set */
+int
+mh_msgset_current (mailbox_t mbox, mh_msgset_t *msgset, int index)
+{
+ message_t msg = NULL;
+ if (mailbox_get_message (mbox, msgset->list[index], &msg))
+ return 1;
+ return mh_message_number (msg, &current_message);
+}
+
+/* Free memory allocated for the message set. Note, that the msgset
+ itself is supposed to reside in the statically allocated memory and
+ therefore is not freed */
+void
+mh_msgset_free (mh_msgset_t *msgset)
+{
+ if (msgset->count)
+ free (msgset->list);
+}
+
+/* Negate the message set: on return `msgset' consists of the messages
+ _not contained_ in the input message set. Any memory associated with
+ the input message set is freed */
+void
+mh_msgset_negate (mailbox_t mbox, mh_msgset_t *msgset)
+{
+ size_t i, total = 0, msgno;
+ size_t *list;
+
+ mailbox_messages_count (mbox, &total);
+ list = calloc (total, sizeof (list[0]));
+ if (!list)
+ {
+ mh_error ("not enough memory");
+ abort ();
+ }
+
+ for (i = 1, msgno = 0; i <= total; i++)
+ {
+ if (!mh_msgset_member (msgset, i))
+ list[msgno++] = i;
+ }
+
+ list = realloc (list, sizeof (list[0]) * msgno);
+ if (!list)
+ {
+ mh_error ("not enough memory");
+ abort ();
+ }
+ mh_msgset_free (msgset);
+ msgset->count = msgno;
+ msgset->list = list;
+}
+
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.