Updated to allow the user to select "sounds like" or "does not sound like"

2000-10-31  Jeffrey Stedfast  <fejj@helixcode.com>

	* filtertypes.xml: Updated to allow the user to select "sounds
	like" or "does not sound like" (uses header-soundex).

	* filter-message-search.c (header_matches): Oops. Should be using
	!g_strncasecmp. This should fix it so this filter match works
	right.
	(header_starts_with): Same.
	(header_ends_with): Same.
	(header_soundex): New filter callback for soundex matching (yes,
	it's probably a bloated feature but hey, it was fun to code)

svn path=/trunk/; revision=6302
This commit is contained in:
Jeffrey Stedfast
2000-10-31 23:38:22 +00:00
committed by Jeffrey Stedfast
parent 92fd4e32e4
commit 1d60c5cc02
4 changed files with 149 additions and 6 deletions

View File

@ -1,5 +1,18 @@
2000-10-31 Jeffrey Stedfast <fejj@helixcode.com>
* filtertypes.xml: Updated to allow the user to select "sounds
like" or "does not sound like" (uses header-soundex).
* filter-message-search.c (header_matches): Oops. Should be using
!g_strncasecmp. This should fix it so this filter match works
right.
(header_starts_with): Same.
(header_ends_with): Same.
(header_soundex): New filter callback for soundex matching (yes,
it's probably a bloated feature but hey, it was fun to code)
2000-10-31 Jeffrey Stedfast <fejj@helixcode.com>
* filter-folder.c (validate): Override the default validate
function to only return TRUE if a folder has been selected.

View File

@ -39,6 +39,7 @@ static ESExpResult *header_matches (struct _ESExp *f, int argc, struct _ESExpRes
static ESExpResult *header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
static ESExpResult *match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms);
static ESExpResult *body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
@ -66,6 +67,7 @@ static struct {
{ "header-starts-with", (ESExpFunc *) header_starts_with, 0 },
{ "header-ends-with", (ESExpFunc *) header_ends_with, 0 },
{ "header-exists", (ESExpFunc *) header_exists, 0 },
{ "header-soundex", (ESExpFunc *) header_soundex, 0 },
{ "header-regex", (ESExpFunc *) header_regex, 0 },
{ "user-tag", (ESExpFunc *) user_tag, 0 },
{ "user-flag", (ESExpFunc *) user_flag, 0 },
@ -130,10 +132,10 @@ header_matches (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMe
}
if (is_lowercase) {
if (g_strcasecmp (contents, match))
if (!g_strcasecmp (contents, match))
matched = TRUE;
} else {
if (strcmp (contents, match))
if (!strcmp (contents, match))
matched = TRUE;
}
}
@ -174,10 +176,10 @@ header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, Filt
}
if (is_lowercase) {
if (g_strncasecmp (contents, match, strlen (match)))
if (!g_strncasecmp (contents, match, strlen (match)))
matched = TRUE;
} else {
if (strncmp (contents, match, strlen (match)))
if (!strncmp (contents, match, strlen (match)))
matched = TRUE;
}
}
@ -220,10 +222,10 @@ header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, Filter
end = (char *) contents + strlen (contents) - strlen (match);
if (is_lowercase) {
if (g_strcasecmp (end, match))
if (!g_strcasecmp (end, match))
matched = TRUE;
} else {
if (strcmp (end, match))
if (!strcmp (end, match))
matched = TRUE;
}
}
@ -257,6 +259,81 @@ header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMes
return r;
}
static unsigned char soundex_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0,
49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 0, 0, 0, 0, 0,
0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0,
49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static void
soundexify (const gchar *sound, gchar code[5])
{
guchar *c, last = '\0';
gint n;
for (c = (guchar *) sound; *c && !isalpha (*c); c++);
code[0] = toupper (*c);
memset (code + 1, '0', 3);
for (n = 1; *c && n < 5; c++) {
guchar ch = soundex_table[*c];
if (ch && ch != last) {
code[n++] = ch;
last = ch;
}
}
code[4] = '\0';
}
static gint
soundexcmp (const gchar *sound1, const gchar *sound2)
{
gchar code1[5], code2[5];
soundexify (sound1, code1);
soundexify (sound2, code2);
return strcmp (code1, code2);
}
static ESExpResult *
header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
gboolean matched = FALSE;
ESExpResult *r;
if (argc == 2) {
char *header = (argv[0])->value.string;
char *match = (argv[1])->value.string;
const char *contents;
contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), header);
if (contents) {
if (!soundexcmp (contents, match))
matched = TRUE;
}
}
r = e_sexp_result_new (ESEXP_RES_BOOL);
r->value.bool = matched;
return r;
}
static ESExpResult *
header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{

View File

@ -52,6 +52,18 @@
(match-all (not (header-ends-with "From" ${sender})))
</code>
</option>
<option value="matches soundex">
<title>sounds like</title>
<code>
(match-all (header-soundex "From" ${sender}))
</code>
</option>
<option value="not match soundex">
<title>does not sound like</title>
<code>
(match-all (not (header-soundex "From" ${sender})))
</code>
</option>
<option value="matches regex">
<title>matches regex</title>
<code>
@ -131,6 +143,21 @@
(header-ends-with "Cc" ${recipient}))))
</code>
</option>
<option value="matches soundex">
<title>sounds like</title>
<code>
(match-all (or (header-soundex "To" ${recipient})
(header-soundex "Cc" ${recipient})))
</code>
</option>
<option value="not match soundex">
<title>does not sound like</title>
<code>
(match-all (not (or
(header-soundex "To" ${recipient})
(header-soundex "Cc" ${recipient}))))
</code>
</option>
<option value="matches regex">
<title>matches regex</title>
<code>
@ -201,6 +228,18 @@
(match-all (not (header-ends-with "Subject" ${subject}))
</code>
</option>
<option value="matches soundex">
<title>sounds like</title>
<code>
(match-all (header-soundex "Subject" ${subject}))
</code>
</option>
<option value="not match soundex">
<title>does not sound like</title>
<code>
(match-all (not (header-soundex "Subject" ${subject})))
</code>
</option>
<option value="matches regex">
<title>matches regex</title>
<code>
@ -281,6 +320,18 @@
(match-all (not (header-exists ${header-field}))
</code>
</option>
<option value="matches soundex">
<title>sounds like</title>
<code>
(match-all (header-soundex ${header-field} ${word}))
</code>
</option>
<option value="not match soundex">
<title>does not sound like</title>
<code>
(match-all (not (header-soundex ${header-field} ${word})))
</code>
</option>
<option value="matches regex">
<title>matches regex</title>
<code>

View File

@ -31,6 +31,7 @@ char *s = N_("does not contain");
char *s = N_("does not end with");
char *s = N_("does not exist");
char *s = N_("does not match regex");
char *s = N_("does not sound like");
char *s = N_("does not start with");
char *s = N_("ends with");
char *s = N_("exists");
@ -41,6 +42,7 @@ char *s = N_("is");
char *s = N_("matches regex");
char *s = N_("on or after");
char *s = N_("on or before");
char *s = N_("sounds like");
char *s = N_("starts with");
char *s = N_("was after");
char *s = N_("was before");