Commit 0f0b9dd4 0f0b9dd4e9b7b27b8248a440089c45d76109e327 by Sergey Poznyakoff

Mh-specific message sets.

1 parent bb31d731
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* MH message sets. */
#include <mh.h>
static void
_expand (size_t *msgcnt, size_t **msglist, size_t inc)
{
if (!inc)
return;
*msgcnt += inc;
*msglist = realloc (*msglist, (*msgcnt)*sizeof(**msglist));
if (!*msglist)
{
mh_error ("not enough memory");
abort ();
}
}
static void
msgset_abort (const char *arg)
{
mh_error ("bad message list `%s'", arg);
exit (1);
}
static int
msgset_first (mailbox_t mbox, size_t *pnum)
{
*pnum = 1;
return 0;
}
static int
msgset_last (mailbox_t mbox, size_t *pnum)
{
int rc;
size_t count = 0;
rc = mailbox_messages_count (mbox, &count);
if (rc)
{
mh_error ("can't get last message: %s", mu_errstring (rc));
exit (1);
}
*pnum = count;
return 0;
}
static int
msgset_cur (mailbox_t mbox, size_t *pnum)
{
size_t i, count = 0;
static int cached_n = 0;
if (cached_n)
{
*pnum = cached_n;
return 0;
}
mailbox_messages_count (mbox, &count);
for (i = 1; i <= count; i++)
{
message_t msg = NULL;
size_t uid = 0;
mailbox_get_message (mbox, i, &msg);
mh_message_number (msg, &uid);
if (uid == current_message)
{
*pnum = cached_n = i;
return 0;
}
}
mh_error ("no cur message");
exit (1);
}
static int
msgset_prev (mailbox_t mbox, size_t *pnum)
{
size_t cur_n = 0;
msgset_cur (mbox, &cur_n);
if (cur_n < 1)
{
mh_error ("mo prev message");
exit (1);
}
*pnum = cur_n - 1;
return 0;
}
static int
msgset_next (mailbox_t mbox, size_t *pnum)
{
size_t cur_n = 0, total = 0;
msgset_cur (mbox, &cur_n);
mailbox_messages_count (mbox, &total);
if (cur_n + 1 > total)
{
mh_error ("mo next message");
exit (1);
}
*pnum = cur_n + 1;
return 0;
}
static struct msgset_keyword {
char *name;
int (*handler) __P((mailbox_t mbox, size_t *pnum));
} keywords[] = {
{ "first", msgset_first },
{ "last", msgset_last },
{ "prev", msgset_prev },
{ "next", msgset_next },
{ "cur", msgset_cur },
{ NULL },
};
static char *
msgset_preproc (mailbox_t mbox, char *arg)
{
struct msgset_keyword *p;
for (p = keywords; p->name; p++)
if (strncmp (arg, p->name, strlen (p->name)) == 0)
{
int rc;
size_t uid, num;
char *ret = NULL;
message_t msg;
if (p->handler (mbox, &num))
msgset_abort (arg);
rc = mailbox_get_message (mbox, num, &msg);
if (rc)
{
mh_error ("can't get message %d: %s", num, mu_errstring (rc));
exit (1);
}
message_get_uid (msg, &uid);
asprintf (&ret, "%lu%s", (unsigned long) uid, arg + strlen (p->name));
return ret;
}
return strdup (arg);
}
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;
}
msgcnt = argc;
msglist = calloc (msgcnt, sizeof(*msglist));
for (i = 0, msgno = 0; i < argc; i++)
{
char *p = NULL;
size_t start, end;
long num;
char *arg = msgset_preproc (mbox, argv[i]);
start = strtoul (arg, &p, 0);
switch (*p)
{
case 0:
msglist[msgno++] = start;
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);
for (; start <= end; start++)
msglist[msgno++] = start;
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;
end = t;
}
_expand (&msgcnt, &msglist, end - start);
for (; start <= end; start++)
msglist[msgno++] = start;
break;
default:
msgset_abort (argv[i]);
}
free (arg);
}
msgset->count = msgcnt;
msgset->list = msglist;
return 0;
}
int
mh_msgset_member (mh_msgset_t *msgset, size_t num)
{
size_t i;
for (i = 0; i < msgset->count; i++)
if (msgset->list[i] == num)
return i + 1;
return 0;
}