2012-11-18 [colin] 3.9.0cvs5-stable
[claws.git] / src / advsearch.c
index 306afa74c009305837c1785e476c58c60409f75a..ed806e2cc5a5f28ed6370e6e24bc20f19011d140 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2012 the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 # include "claws-features.h"
@@ -11,6 +30,7 @@
 #include "matcher.h"
 #include "matcher_parser.h"
 #include "utils.h"
+#include "prefs_common.h"
 
 struct _AdvancedSearch {
        struct {
@@ -294,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);
@@ -330,19 +324,52 @@ 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;
+               search->is_fast = TRUE;
+       }
 
        matcher = matcherprop_new(match_header, NULL, MATCHTYPE_MATCHCASE,
                        search->request.matchstring, 0);
@@ -353,11 +380,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)
@@ -379,26 +413,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:
@@ -425,6 +465,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,
@@ -440,7 +481,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;
@@ -463,13 +504,14 @@ static gboolean search_impl(MsgInfoList **messages, AdvancedSearch* search,
                                        return FALSE;
                        }
                }
-       } else {
+       } else if (!folderItem->no_select) {
                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;
                }