2012-11-16 [colin] 3.9.0cvs8
[claws.git] / src / advsearch.c
index 0e5ca69ffd24afe1fb47732e87b14ec39577bdeb..c83c90e2ea0c8cec2add8717797d3371fc5ce8d4 100644 (file)
@@ -30,6 +30,7 @@
 #include "matcher.h"
 #include "matcher_parser.h"
 #include "utils.h"
+#include "prefs_common.h"
 
 struct _AdvancedSearch {
        struct {
@@ -313,32 +314,6 @@ gchar *advsearch_expand_search_string(const gchar *search_string)
        return returnstr;
 }
 
-// --------------------------
-
-static gchar *expand_tag_search_string(const gchar *search_string)
-{
-       gchar *newstr = NULL;
-       gchar **words = search_string ? g_strsplit(search_string, " ", -1):NULL;
-       gint i = 0;
-       while (words && words[i] && *words[i]) {
-               g_strstrip(words[i]);
-               if (!newstr) {
-                       newstr = g_strdup_printf("tag matchcase \"%s\"", words[i]);
-               } else {
-                       gint o_len = strlen(newstr);
-                       gint s_len = 17; /* strlen("|tag matchcase \"\"") */
-                       gint n_len = s_len + strlen(words[i]);
-                       newstr = g_realloc(newstr, o_len + n_len + 1);
-                       strcpy(newstr + o_len, "|tag matchcase \"");
-                       strcpy(newstr + o_len + (s_len - 1), words[i]);
-                       strcpy(newstr + o_len + (n_len - 1), "\"");
-               }
-               i++;
-       }
-       g_strfreev(words);
-       return newstr;
-}
-
 static void prepare_matcher_extended(AdvancedSearch *search)
 {
        gchar *newstr = advsearch_expand_search_string(search->request.matchstring);
@@ -349,19 +324,51 @@ static void prepare_matcher_extended(AdvancedSearch *search)
        }
 }
 
+#define debug_matcher_list(prefix, list)                                       \
+do {                                                                           \
+       gchar *str = list ? matcherlist_to_string(list) : g_strdup("(NULL)");   \
+                                                                               \
+       debug_print("%s: %s\n", prefix, str);                                   \
+                                                                               \
+       g_free(str);                                                            \
+} while(0)
+
 static void prepare_matcher_tag(AdvancedSearch *search)
 {
-       char *newstr = expand_tag_search_string(search->request.matchstring);
-       search->predicate = matcher_parser_get_cond(newstr, &search->is_fast);
-       g_free(newstr);
+       gchar **words = search->request.matchstring 
+                       ? g_strsplit(search->request.matchstring, " ", -1)
+                       : NULL;
+       gint i = 0;
+
+       if (search->predicate == NULL) {
+               search->predicate = g_new0(MatcherList, 1);
+               search->predicate->bool_and = FALSE;
+               search->is_fast = TRUE;
+       }
+
+       while (words && words[i] && *words[i]) {
+               MatcherProp *matcher;
+
+               g_strstrip(words[i]);
+
+               matcher = matcherprop_new(MATCHCRITERIA_TAG, NULL,
+                                         MATCHTYPE_MATCHCASE, words[i], 0);
+
+               search->predicate->matchers = g_slist_prepend(search->predicate->matchers, matcher);
+
+               i++;
+       }
+       g_strfreev(words);
 }
 
 static void prepare_matcher_header(AdvancedSearch *search, gint match_header)
 {
        MatcherProp *matcher;
 
-       if (search->predicate == NULL)
+       if (search->predicate == NULL) {
                search->predicate = g_new0(MatcherList, 1);
+               search->predicate->bool_and = FALSE;
+       }
 
        matcher = matcherprop_new(match_header, NULL, MATCHTYPE_MATCHCASE,
                        search->request.matchstring, 0);
@@ -372,11 +379,18 @@ static void prepare_matcher_header(AdvancedSearch *search, gint match_header)
 static void prepare_matcher_mixed(AdvancedSearch *search)
 {
        prepare_matcher_tag(search);
+       debug_matcher_list("tag matcher list", search->predicate);
+
+       /* we want an OR search */
+       if (search->predicate)
+               search->predicate->bool_and = FALSE;
 
        prepare_matcher_header(search, MATCHCRITERIA_SUBJECT);
+       debug_matcher_list("tag + subject matcher list", search->predicate);
        prepare_matcher_header(search, MATCHCRITERIA_FROM);
+       debug_matcher_list("tag + subject + from matcher list", search->predicate);
        prepare_matcher_header(search, MATCHCRITERIA_TO);
-       prepare_matcher_header(search, MATCHCRITERIA_TAG);
+       debug_matcher_list("tag + subject + from + to matcher list", search->predicate);
 }
 
 static void prepare_matcher(AdvancedSearch *search)
@@ -398,26 +412,32 @@ static void prepare_matcher(AdvancedSearch *search)
        switch (search->request.type) {
                case ADVANCED_SEARCH_SUBJECT:
                        prepare_matcher_header(search, MATCHCRITERIA_SUBJECT);
+                       debug_matcher_list("subject search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_FROM:
                        prepare_matcher_header(search, MATCHCRITERIA_FROM);
+                       debug_matcher_list("from search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_TO:
                        prepare_matcher_header(search, MATCHCRITERIA_TO);
+                       debug_matcher_list("to search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_TAG:
-                       prepare_matcher_header(search, MATCHCRITERIA_TAG);
+                       prepare_matcher_tag(search);
+                       debug_matcher_list("tag search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_MIXED:
                        prepare_matcher_mixed(search);
+                       debug_matcher_list("mixed search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_EXTENDED:
                        prepare_matcher_extended(search);
+                       debug_matcher_list("extended search", search->predicate);
                        break;
 
                default:
@@ -444,6 +464,7 @@ static gboolean search_filter_folder(MsgNumberList **msgnums, AdvancedSearch *se
                                          FolderItem *folderItem, gboolean onServer)
 {
        gint matched;
+       gboolean tried_server = onServer;
 
        matched = folder_item_search_msgs(folderItem->folder,
                folderItem,
@@ -459,7 +480,7 @@ static gboolean search_filter_folder(MsgNumberList **msgnums, AdvancedSearch *se
                return FALSE;
        }
 
-       if (folderItem->folder->klass->supports_server_search && !onServer) {
+       if (folderItem->folder->klass->supports_server_search && tried_server && !onServer) {
                return search_filter_folder(msgnums, search, folderItem, onServer);
        } else {
                return TRUE;
@@ -486,9 +507,10 @@ static gboolean search_impl(MsgInfoList **messages, AdvancedSearch* search,
                MsgNumberList *msgnums = NULL;
                MsgNumberList *cur;
                MsgInfoList *msgs = NULL;
+               gboolean can_search_on_server = folderItem->folder->klass->supports_server_search;
 
                if (!search_filter_folder(&msgnums, search, folderItem,
-                                       folderItem->folder->klass->supports_server_search)) {
+                                         can_search_on_server)) {
                        g_slist_free(msgnums);
                        return FALSE;
                }