static char rcsid[] = "@(#)$Id: pattern.c,v 1.52 2006/04/09 07:37:19 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.52 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
****************************************************************************/
/** General pattern matching for the ELM mailer.
**/
#include "def_elm.h"
#include "s_elm.h"
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
static char *tag_word = NULL;
static char *tagged_word = NULL;
static char *Tagged_word = NULL;
static char *delete_word = NULL;
static char *mark_delete_word = NULL;
static char *Mark_delete_word = NULL;
static char *undelete_word = NULL;
static char *undeleted_word = NULL;
static char *Undeleted_word = NULL;
static int DoAll P_((int func,struct menu_common *menu,
struct screen_parts *LOC));
static int DoFlagged P_((int func, struct menu_common *menu,
struct screen_parts *LOC));
DEBUG_VAR(Debug,__FILE__,"mbox");
int meta_match(function, menu, page, LOC)
int function;
struct menu_common *menu;
struct menu_context *page;
struct screen_parts *LOC;
{
/** Perform specific function based on whether an entered string
matches either the From or Subject lines..
Return TRUE if the current message was matched, else FALSE.
**/
int i, tagged=0, count=0, curtag = 0;
char msg[SLEN];
struct string * meta_pattern = NULL;
int status, line;
if (delete_word == NULL) {
tag_word = catgets(elm_msg_cat, ElmSet, ElmTag, "Tag");
tagged_word = catgets(elm_msg_cat, ElmSet, ElmTagged, "tagged");
Tagged_word = catgets(elm_msg_cat, ElmSet, ElmCapTagged, "Tagged");
delete_word = catgets(elm_msg_cat, ElmSet, ElmDelete, "Delete");
mark_delete_word = catgets(elm_msg_cat, ElmSet, ElmMarkDelete, "marked for deletion");
Mark_delete_word = catgets(elm_msg_cat, ElmSet, ElmCapMarkDelete, "Marked for deletion");
undelete_word = catgets(elm_msg_cat, ElmSet, ElmUndelete, "Undelete");
undeleted_word = catgets(elm_msg_cat, ElmSet, ElmUndeleted, "undeleted");
Undeleted_word = catgets(elm_msg_cat, ElmSet, ElmCapUndeleted, "Undeleted");
}
menu_Write_to_screen(LOC->prompt_page,
CATGETS(elm_msg_cat, ElmSet,
ElmMessagesMatchPattern,
"%s %S that match pattern..."),
function==TAGGED?tag_word: function==DELETED?delete_word:undelete_word,
mcommon_give_item(menu, m_items));
if (function == TAGGED) { /* are messages already tagged??? */
int mc = mcommon_get_count(menu);
for (i=0; i < mc; i++) {
if (mcommon_ison_status(menu,i,status_basic,TAGGED))
tagged++;
}
if (tagged) {
char tagmsg[SLEN];
int ch;
int delay_redraw = 0;
again:
if (tagged > 1) {
elm_sfprintf(tagmsg, sizeof tagmsg,
CATGETS(elm_msg_cat, ElmSet,
ElmSomeMessagesATagged,
"Some %S are already tagged."),
mcommon_give_item(menu,m_items));
ch = prompt_letter(1,"",*def_ans_yes,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel,
LOC->prompt_page,
CATGETS(elm_msg_cat, ElmSet, ElmRemoveTags,
"%s Remove Tags? (%c/%c) "),
tagmsg, *def_ans_yes, *def_ans_no);
} else {
elm_sfprintf(tagmsg, sizeof tagmsg,
CATGETS(elm_msg_cat, ElmSet,
ElmAMessageATagged,
"One %S is already tagged."),
mcommon_give_item(menu,m_item));
ch = prompt_letter(1,"",*def_ans_yes,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel,
LOC->prompt_page,
CATGETS(elm_msg_cat, ElmSet, ElmRemoveTag,
"%s Remove Tag? (%c/%c) "),
tagmsg, *def_ans_yes, *def_ans_no);
}
if (('L'&31) == ch ||
REDRAW_MARK == ch) {
menu_ClearScreen(page); /* Reset possible redraw flag */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(LOC->prompt_page))
menu_ClearScreen(LOC->prompt_page); /* Clear redraw mark from prompt_area*/
/* NOTICE: using menu_trigger_redraw(page) on here
may cause redraw loop!
*/
delay_redraw++;
goto again;
}
if (delay_redraw)
menu_trigger_redraw(page);
if (TERMCH_interrupt_char == ch)
goto clean;
if (ch != *def_ans_no) { /* remove tags... */
for (i=0; i < mc; i++) {
int vis;
mcommon_clearf_status(menu,i,status_basic,TAGGED);
vis = compute_visible(i+1, menu);
menu_header_status_update(LOC->header_page,vis-1);
}
}
}
}
/* FIXME --optionally_enter* should use prompt_area */
line = menu_GetAbsLine(LOC->prompt_page,1);
status = optionally_enter2(page,
&meta_pattern, line, 0,
OE_REDRAW_MARK|
OE_SIG_CHAR /* Ctrl-C */,
CATGETS(elm_msg_cat, ElmSet, ElmEnterPattern,
"Enter pattern: "));
{
int delay_redraw = 0;
while (status == REDRAW_MARK) {
menu_ClearScreen(page); /* Reset possible redraw flag */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(LOC->prompt_page))
menu_ClearScreen(LOC->prompt_page); /* Clear redraw mark from prompt_area*/
delay_redraw++; /* Can't trigger redraw yet... */
status = optionally_enter2(page,
&meta_pattern, line, 0,
OE_REDRAW_MARK|OE_APPEND_CURRENT|
OE_SIG_CHAR /* Ctrl-C */,
CATGETS(elm_msg_cat, ElmSet,
ElmEnterPattern,
"Enter pattern: "));
}
if (delay_redraw)
menu_trigger_redraw(page);
}
if (status != 0 || !meta_pattern ||
string_len(meta_pattern) == 0) {
if (meta_pattern)
free_string( & (meta_pattern));
menu_ClearLine(LOC->prompt_page,1);
return(curtag);
}
if (function == DELETED &&
string_matches_ascii(meta_pattern, s2us("tagged"))) {
if (meta_pattern)
free_string( & (meta_pattern));
return(DeleteTagged(menu, page, LOC->header_page));
} else if (string_matches_ascii(meta_pattern, s2us("flagged")))
count = DoFlagged(function, menu, LOC);
else if (string_matches_ascii(meta_pattern, s2us("all")))
count = DoAll(function, menu, LOC);
else {
int mc = mcommon_get_count(menu);
int current = mcommon_get_current(menu);
int selected = mcommon_get_selected(menu);
for (i = 0; i < mc; i++) {
if (mcommon_matches(menu,i,meta_pattern) &&
(!selected ||
(selected && mcommon_ison_status(menu,i,
status_basic,VISIBLE))
)) {
int vis;
if (function == UNDELETE)
mcommon_clearf_status(menu,i,status_basic,DELETED);
else if ((function == DELETED) &&
(mcommon_get_type(menu,i) & SYSTEM)) {
if(i == current - 1) curtag--;
count--;
} else
mcommon_setf_status(menu,i, status_basic,function);
vis = compute_visible(i+1, menu);
menu_header_status_update(LOC->header_page,vis-1);
if(i == current - 1) curtag++;
count++;
}
}
}
menu_ClearLine(LOC->prompt_page,1); /* remove "pattern: " prompt */
if (count > 1) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTaggedMessages,
"%s %d %S."),
function==TAGGED? Tagged_word :
function==DELETED? Mark_delete_word : Undeleted_word,
count,
mcommon_give_item(menu,m_items));
} else if (count == 1) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTaggedMessage,
"%s 1 %S."),
function==TAGGED? Tagged_word :
function==DELETED? Mark_delete_word : Undeleted_word,
mcommon_give_item(menu,m_item));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNoMatchesNoTags,
"No matches. No %S %s."),
mcommon_give_item(menu,m_items),
function==TAGGED? tagged_word :
function==DELETED? mark_delete_word: undeleted_word);
}
clean:
if (meta_pattern)
free_string( & (meta_pattern));
return(curtag);
}
int pattern_match(menu, page, LOC)
struct menu_common *menu;
struct menu_context *page;
struct screen_parts *LOC;
{
/** Get a pattern from the user and try to match it with the
from/subject lines being displayed. If matched (ignoring
case), move current message pointer to that message, if
not, error and return ZERO **/
/* If redraw is needed use
menu_trigger_redraw(page)
*/
int i;
/* Elm 2.4 remembers old entered patterns, so we need to keep
that static. This leaks these malloced areas on end of program */
static struct string * pattern = NULL;
static struct string * alt_pattern = NULL;
int ret = 0 ;
int delay_redraw = 0;
int anywhere = FALSE;
int matched;
struct string * SEARCH = NULL; /* SHARED: point either to
pattern or alt_pattern */
int val;
int line;
int append = 0;
/* Redraw loop */
append = OE_ALT_SOLIDUS;
do {
menu_PutLineX(LOC->prompt_page,0,40,
CATGETS(elm_msg_cat, ElmSet, ElmMatchAnywhere,
"/ = Match anywhere in %S."),
mcommon_give_item(menu, m_items));
/* FIXME --optionally_enter* should use prompt_area */
line = menu_GetAbsLine(LOC->prompt_page,1);
val = optionally_enter2(page,
&pattern, line, 0,
OE_REDRAW_MARK|append|
OE_SIG_CHAR /* Ctrl-C */,
CATGETS(elm_msg_cat, ElmSet, ElmMatchPattern,
"Match pattern:"));
if (REDRAW_MARK == val) {
menu_ClearScreen(page); /* Clear possible redraw mark */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(LOC->prompt_page))
menu_ClearScreen(LOC->prompt_page); /* Clear redraw mark from prompt_area*/
/* NOTICE: using menu_trigger_redraw(page) on here
may cause redraw loop!
*/
delay_redraw++;
if (pattern &&
string_len(pattern) > 0)
append = OE_APPEND_CURRENT;
}
} while (val == REDRAW_MARK);
anywhere = FALSE;
SEARCH = pattern;
if (val == OE_ALT_SOLIDUS) {
append = 0;
menu_MoveCursor(LOC->prompt_page,0,40);
menu_CleartoEOLN(LOC->prompt_page);
do {
/* FIXME --optionally_enter* should use prompt_area */
line = menu_GetAbsLine(LOC->prompt_page,1);
val = optionally_enter2(page,
&alt_pattern, line, 0,
OE_REDRAW_MARK|append|
OE_SIG_CHAR /* Ctrl-C */,
CATGETS(elm_msg_cat, ElmSet,
ElmMatchPatternInEntire,
"Match pattern (in entire %S):"),
mcommon_give_item(menu,m_item));
if (REDRAW_MARK == val) {
menu_ClearScreen(page); /* Clear possible redraw mark */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(LOC->prompt_page))
menu_ClearScreen(LOC->prompt_page); /* Clear redraw mark from prompt_area*/
/* NOTICE: using menu_trigger_redraw(page) on here
may cause redraw loop!
*/
delay_redraw++;
append = OE_APPEND_CURRENT;
}
} while (val == REDRAW_MARK);
anywhere = TRUE;
SEARCH = alt_pattern;
}
if (0 != val) {
if (-1 == val) /* Ctrl-C */
goto out;
ret = EOF;
goto out;
}
if (SEARCH) {
if (string_len(SEARCH) == 0) {
ret = 0;
goto out;
}
if (anywhere)
ret = mcommon_match_in_text(menu,SEARCH,page, LOC);
else {
int current = mcommon_get_current(menu);
int mc = mcommon_get_count(menu);
int selected = mcommon_get_selected(menu);
for (i = current; i < mc; i++) {
if (mcommon_matches(menu,i,SEARCH) &&
(!selected ||
(selected && mcommon_ison_status(menu,i,
status_basic,VISIBLE))
)) {
current = ++i;
mcommon_set_current(menu,current);
copy_current(menu,LOC->header_page);
get_page(menu, LOC->header_page);
ret = 1;
goto out;
}
}
}
}
out:
/* NOTE:
We do not free pattern and alt_pattern -- they are static
and should have remembered, so that behauviour matches
to Elm 2.4
*/
if (delay_redraw)
menu_trigger_redraw(page);
else
menu_trigger_redraw(LOC->prompt_page);
return(ret);
}
/* This will tag, delete, or undelete all or the currently visible messages */
static int DoAll(func, menu, LOC)
int func;
struct menu_common *menu;
struct screen_parts *LOC;
{
int i, count = 0;
int mc = mcommon_get_count(menu);
int selected = mcommon_get_selected(menu);
for (i=0; i < mc; i++) {
if (!selected ||
(selected && mcommon_ison_status(menu,i,status_basic,VISIBLE))) {
int vis;
if (func == UNDELETE)
mcommon_clearf_status(menu,i,status_basic,DELETED);
else
mcommon_setf_status(menu,i,status_basic,func);
vis = compute_visible(i+1, menu);
menu_header_status_update(LOC->header_page,vis-1); /* ! ! ! */
++count;
}
}
DPRINT(Debug,7,(&Debug, "DoAll=%d\n",count));
return(count);
}
static int DoFlagged(func, menu, LOC)
int func;
struct menu_common *menu;
struct screen_parts *LOC;
{
int i, count = 0;
int mc = mcommon_get_count(menu);
int selected = mcommon_get_selected(menu);
for (i=0; i < mc; i++) {
if (!selected ||
(selected && mcommon_ison_status(menu,i,status_basic,VISIBLE))) {
if (mcommon_ison_status(menu,i,status_1,S1_FLAGGED)) {
int vis;
if (func == UNDELETE)
mcommon_clearf_status(menu,i,status_basic,DELETED);
else
mcommon_setf_status(menu,i,status_basic,func);
vis = compute_visible(i+1, menu);
menu_header_status_update(LOC->header_page,vis-1); /* ! ! ! */
++count;
}
}
}
DPRINT(Debug,7,(&Debug, "DoFlagged=%d\n",count));
return(count);
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1