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 ****************************************************************************** * 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: */