static char rcsid[] = "@(#)$Id: message_limit.c,v 1.9 2006/04/09 07:37:42 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.9 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
******************************************************************************
* Inludes code from limit.c which have following copyright:
*
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
#include "def_mcommon.h"
#include "s_elm.h"
DEBUG_VAR(Debug,__FILE__,"menu");
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
static char *us2s P_((unsigned char *str));
static char *us2s(str)
unsigned char *str;
{
return (char *)str;
}
static int limit_selection P_((int based_on, struct string *pattern,
int *vector,
struct MailboxView *mailbox));
static int limit_by_string_subject P_((const struct string *pattern,
int *vector,
struct MailboxView *mailbox));
static int limit_by_header P_((struct string *header,
struct string*value,
int *vector,
struct MailboxView *mailbox,
struct menu_context *page));
static int limit_by_string_subject(pattern,vector,mailbox)
CONST struct string *pattern;
int *vector;
struct MailboxView *mailbox;
{
int iindex;
int ret = 0;
int mc = get_message_count(mailbox);
DPRINT(Debug,9,(&Debug,
"limit_by_string_subject: pattern=%S\n",
pattern));
for (iindex = 0 ; iindex < mc ; iindex++) {
struct header_rec * hdr = give_header(mailbox,iindex);
int match = 0;
if (hdr && hdr->subject)
match = find_pattern_from_string(hdr->subject,
pattern,1);
if (match)
vector[ret++] = iindex;
}
DPRINT(Debug,9,(&Debug,
"limit_by_string_subject=%d\n",
ret));
return ret;
}
static int limit_by_header(header,value, vector, mailbox,page)
struct string *header;
struct string *value;
int *vector;
struct MailboxView *mailbox;
struct menu_context *page;
{
int ret = 0;
int message_number;
int mc = get_message_count(mailbox);
struct string * Z = ascify_string(header);
char * header1 = us2s(stream_from_string(Z,0,NULL));
int LINES, COLUMNS;
menu_get_sizes(page,&LINES,&COLUMNS);
DPRINT(Debug,9,(&Debug,
"limit_by_string_subject: header=%S value=%S\n",
header,value));
DPRINT(Debug,9,(&Debug,
"limit_by_string_subject: header1=%s\n",
header1));
for (message_number = 0 ; message_number < mc ; message_number++) {
struct header_rec *hdr;
FILE *ZZ;
int val = (message_number+1) / (float) mc * 100;
if ((message_number+1) % readmsginc == 0 ||
val % readdatapercentinc == 0) {
PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet,
ElmSearchingInMessage,
"Searching %d (%02d%%) "),
(message_number+1), val);
CleartoEOLN();
}
if (give_message_data(mailbox,message_number,
&hdr,&ZZ,NULL,NO_mime_parse)) {
int match = 0;
header_list_ptr all_headers;
if (skip_envelope(hdr, ZZ) == -1)
continue;
all_headers = file_read_headers(ZZ,
RHL_CHECK_HEADER);
if (all_headers) {
header_list_ptr walk;
for (walk = locate_header_by_name(all_headers,header1);
walk;
walk = walk->next_this_header) {
if (!value)
match++;
else {
struct string * A =
give_decoded_header(walk,
!(hdr->status &
NOHDRENCODING),
hdr -> header_charset);
if (find_pattern_from_string(A,value,1))
match++;
free_string(&A);
}
}
delete_headers(&all_headers);
}
if (match)
vector[ret++] = message_number;
}
}
PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet,
ElmSearchingInMessageDone,
"Searching %d. Done "),
(message_number+1));
free(header1);
free_string(&Z);
DPRINT(Debug,9,(&Debug,
"limit_by_string_subject=%d\n",
ret));
return ret;
}
#define TO 1
#define FROM 2
#define CC 3
static int limit_selection(based_on, pattern, vector,mailbox)
int based_on;
struct string *pattern;
int *vector;
struct MailboxView *mailbox;
{
int ret = 0;
int iindex;
int mc = get_message_count(mailbox);
DPRINT(Debug,9,(&Debug,
"limit_selection: based_on=%d pattern=%S\n",
based_on,pattern));
for (iindex = 0 ; iindex < mc ; iindex++) {
struct header_rec * hdr = give_header(mailbox,iindex);
int match;
switch (based_on) {
case FROM:
match = from_matches(hdr,pattern);
break;
case TO:
match = to_matches(hdr,pattern);
break;
case CC:
match = cc_matches(hdr,pattern);
break;
case SUBJECT:
default:
match = subject_matches(hdr,pattern);
break;
}
if (match)
vector[ret++] = iindex;
}
DPRINT(Debug,9,(&Debug,
"limit_selection=%d\n",ret));
return ret;
}
int mc_limit_helper_mbx(u,str,retarr, page)
union mcommon_union *u;
struct string *str;
int **retarr;
struct menu_context *page;
{
int ret = -1;
int *vector = NULL;
struct MailboxView *mbxview = u->mbx.mw;
int n = get_message_count(mbxview);
if (n < 1)
goto fail;
vector = safe_malloc(n * sizeof(vector[0]));
if (string_matches_ascii(str, s2us("thread"))) {
int current = get_current(mbxview);
struct header_rec * hdr = give_header(mbxview,current-1);
struct string * temp;
if (!hdr)
goto fail;
if (!hdr->subject)
goto fail;
temp = skip_ascii_head_from_string(hdr-> subject, s2us("Re: "),1);
ret = limit_by_string_subject(temp,vector,mbxview);
free_string(&temp);
} else {
struct string *first = NULL;
struct string *rest = NULL;
int L = string_len(str);
uint16 delim;
int pos = 0;
if (!get_word_from_string(str,&first,&pos,GWF_lowercase,
/* ASCII assumed */
s2us(" \t:"),&delim))
goto fail2;
if (pos < L)
pos++;
if (pos < L &&
0x0020 /* space */ == give_unicode_from_string(str,pos))
pos++;
if (0x003A /* : */ == delim) {
rest = clip_from_string(str,&pos,L);
ret = limit_by_header(first, rest, vector, mbxview, page);
} else if (string_matches_ascii(first,s2us("subject"))) {
rest = clip_from_string(str,&pos,L);
ret = limit_selection(SUBJECT, rest, vector, mbxview);
} else if (string_matches_ascii(first, s2us("to"))) {
rest = clip_from_string(str,&pos,L);
ret = limit_selection(TO, rest, vector, mbxview);
} else if (string_matches_ascii(first, s2us("cc"))) {
rest = clip_from_string(str,&pos,L);
ret = limit_selection(CC, rest, vector, mbxview);
} else if (string_matches_ascii(first, s2us("from"))) {
rest = clip_from_string(str,&pos,L);
ret = limit_selection(FROM, rest, vector, mbxview);
} else if (string_matches_ascii(first, s2us("header"))) {
struct string *header = NULL;
uint16 delim;
/* Continue seach from pos where previous ended */
if (!get_word_from_string(str,&header,&pos,
GWF_lowercase|GWF_trim_space,
/* ASCII assumed */
s2us(":"),&delim))
goto fail3;
if (pos < L)
pos++;
if (pos < L &&
0x0020 /* space */ == give_unicode_from_string(str,pos))
pos++;
rest = clip_from_string(str,&pos,L);
ret = limit_by_header(header,rest,vector, mbxview, page);
fail3:
if (header)
free_string(&header);
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmLimitNotValidCriterion,
"\"%S\" not a valid criterion."),
first);
}
fail2:
if (first)
free_string(&first);
if (rest)
free_string(&rest);
}
fail:
if (ret <= 0) {
if (vector)
free(vector);
*retarr = NULL;
} else
*retarr = vector;
return ret;
}
void mc_limit_print_help_mbx(last_selected)
int last_selected;
{
if (last_selected)
lib_transient(CATGETS(elm_msg_cat, ElmSet, ElmEnterLastSelected,
"Enter: {\"subject\",\"to\",\"from\",\"cc\",\"header\"} [pattern] OR {\"tagged\",\"all\",...}"));
else
lib_transient(CATGETS(elm_msg_cat, ElmSet, ElmEnterSelected,
"Enter: {\"subject\",\"to\",\"from\",\"header\"} [pattern] OR \"thread\",\"tagged\",...}"));
}
void mc_limit_print_result_mbx(u)
union mcommon_union *u;
{
struct MailboxView *mbxview = u->mbx.mw;
if (get_selected(mbxview) > 1)
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmLimitMessagesSelected,
"%d messages selected."),
get_selected(mbxview));
else if (get_selected(mbxview) == 1)
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmLimitMessageSelected,
"1 message selected."));
else
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmLimitNoMessagesSelected,
"No messages selected."));
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1