Improved subject simplification by regexp.
authorMelvin Hadasht <melvin.hadasht@free.fr>
Sat, 29 Dec 2001 05:29:09 +0000 (05:29 +0000)
committerMelvin Hadasht <melvin.hadasht@free.fr>
Sat, 29 Dec 2001 05:29:09 +0000 (05:29 +0000)
ChangeLog.claws
configure.in
src/prefs_folder_item.h
src/string_match.c
src/string_match.h
src/summaryview.c

index 5165891..0216d27 100644 (file)
@@ -1,3 +1,19 @@
+2001-12-29 [melvin]    0.6.6claws30
+
+       * src/string_match.[ch]
+               Optimized a bit: regexp pattern buffer compiled only once, and
+                 one subroutine call removed. Fixed ^ regexp search: Now, 
+                 "(^Re: )|(^Hello)" removes only "Re: " from "Re: Hello".
+       
+       * src/summaryview.c
+               Subject filtering changed to filter summary columns and
+                 not directly the messages subject cache. The loss in 
+                 performance is balanced by the improvement of string_match.
+               Added an alert panel if there is an error in the regexp.
+
+       * src/src/prefs_folder_item.h
+               Added a regexp pattern buffer.
+
 2001-12-28 [alfons]    0.6.6claws29
 
        * src/string_match.[ch]
index 909692a..2a42e29 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=6
 MICRO_VERSION=6
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws29
+EXTRA_VERSION=claws30
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl
index 0892293..a39fc48 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "folder.h"
 #include <glib.h>
+#include <sys/types.h>
+#include <regex.h>
 
 struct _PrefsFolderItem {
        gchar * directory;
@@ -49,6 +51,7 @@ struct _PrefsFolderItem {
        gchar *default_to;
        gboolean enable_simplify_subject;
        gchar *simplify_subject_regexp;
+       regex_t *simplify_subject_preg;
        gboolean enable_folder_chmod;
        gint folder_chmod;
        gboolean enable_default_account;
index a703666..0517e4f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Sylpheed -- regexp pattern matching utilities
  * Copyright (C) 2001 Thomas Link, Hiroyuki Yamamoto
+ *                    Modified by Melvin Hadasht.
  *
  * 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
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <glib.h>
-#include <sys/types.h>
-#include <regex.h>
+#include "intl.h"
 #include "string_match.h"
 
-/* the size used for regexec in string_remove_match */
-#define STRING_MATCH_MR_SIZE 30
-
-
-static int string_match_regexp (char * txt, char * rexp,
-                                int size, regmatch_t matches[],
-                                int cflags, int eflags);
-
-int string_remove_match(char *txt, char *rexp, int cflags, int eflags)
+int string_match_precompile (gchar *rexp, regex_t *preg, int cflags)
 {
-       regmatch_t matches[STRING_MATCH_MR_SIZE];
-       int foundp;
+       int problem = 0;
 
-       g_return_val_if_fail(txt, -1);
        g_return_val_if_fail(rexp, -1);
+       g_return_val_if_fail(*rexp, -1);
 
-       if (strlen(txt) > 0 && strlen(rexp) > 0) {
-               foundp = string_match_regexp(txt, rexp, STRING_MATCH_MR_SIZE, 
-                                            matches, cflags, eflags);
-       } else {
-               return -1;
-       }
-
-       if (foundp && matches[0].rm_so != -1 && matches[0].rm_eo != -1) {
-               if (matches[0].rm_so == matches[0].rm_eo) {
-                       /* in case the match is an empty string */
-                       return matches[0].rm_so + 1;
-               } else {
-                       strcpy(txt + matches[0].rm_so, txt + matches[0].rm_eo);
-                       return matches[0].rm_so;
-               }
-       } else {
-               return -1;
-       }
+       problem = regcomp(preg, rexp, cflags);  
+       
+       return problem;
 }
 
-int string_remove_all_matches(char *txt, char *rexp, int cflags, int eflags)
-{
-       int pos = 0;
-       int pos0 = pos;
-
-       g_return_val_if_fail(txt, 0);
-       g_return_val_if_fail(rexp, 0);
-
-       while (pos0 >= 0 && pos < strlen(txt) && strlen(txt) > 0) {
-               /* printf("%s %d:%d\n", txt, pos0, pos); */
-               pos0 = string_remove_match(txt + pos, rexp, cflags, eflags);
-               if (pos0 >= 0) {
-                       pos = pos + pos0;
-               }
-       }
-       return pos;
-}
 
-static int string_match_regexp(char * txt, char * rexp,
-                              int size, regmatch_t matches[],
-                              int cflags, int eflags)
+gchar *string_remove_match(gchar *buf, gint buflen, gchar * txt, regex_t *preg)
 {
-       regex_t re;
-       int problem;
-
-       g_return_val_if_fail(txt, 0);
-       g_return_val_if_fail(rexp, 0);
+       regmatch_t match;
+       int notfound;
+       gint i, j ,k;
 
-       problem = regcomp(&re, rexp, cflags);  
-       if (problem == 0) {
-               problem = regexec(&re, txt, size, matches, eflags);
+       if (!preg)
+               return txt;
+       if (*txt != 0x00) {
+               i = 0;
+               j = 0;
+               do {
+                       notfound = regexec(preg, txt+j, 1, &match, (j ? REG_NOTBOL : 0));
+                       if (notfound) {
+                               while (txt[j] && i < buflen -1)
+                                       buf[i++] = txt[j++];
+                       } else {
+                               if ( match.rm_so == match.rm_eo)
+                                       buf[i++] = txt[j++];
+                               else {
+                                       k = j;
+                                       while (txt[j] &&  j != k + match.rm_so) 
+                                               buf[i++] = txt[j++];
+                                       if (txt[j])
+                                               j = k + match.rm_eo;
+                               }
+                       }
+               } while (txt[j] && i < buflen - 1);
+               buf[i] = 0x00;
+               if (buf[0] == 0x00)
+                       strcpy(buf, _("(Subject cleared by regexp)"));
+               return buf;             
        }
-       regfree(&re);
-       return problem == 0;
+       return txt;
 }
 
index 0bd5f78..86793bd 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Sylpheed -- regexp pattern matching utilities
  * Copyright (C) 2001 Thomas Link, Hiroyuki Yamamoto
+ *                    Modified by Melvin Hadasht.
  *
  * 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
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+
 #ifndef STRING_MATCH_H__
 #define STRING_MATCH_H__
 
-/* remove substring matching REXP from TXT. Destructive! */
-/* for documentation of CFLAGS and EFLAGS see "man regex" */
-/* returns -1 = not found; N = next find pos */
-/* if the match is an empty string (e.g. "x\?"), the find position will
-   be increased by 1 */
-int string_remove_match        (char *txt, char *rexp, int cflags, int eflags);
+#include <sys/types.h>
+#include <regex.h>
+#include <glib.h>
 
-/* remove all substrings matching REXP from TXT. Destructive! */
-/* for documentation of CFLAGS and EFLAGS see "man regex" */
-/* returns position of last replacement (i.e. TXT has been modified up
-   to this position, use this as the starting point for further mangling) */
-int string_remove_all_matches  (char *txt, char *rexp, int cflags, int eflags);
+/* Precompile the preg buffer for the rexp regexp string. See regex man for the
+ * meaning of cflags.  
+ */
 
+int string_match_precompile (gchar *rexp, regex_t *preg, int cflags);
 
-#endif /* STRING_MATCH_H__ */
+/* remove from txt the substrings matching the regexp in the precompiled preg buffer.  
+ * The result is stored in the preallocated buf buffer which maximal length
+ * is buflen.
+ */
+gchar *string_remove_match(gchar *buf, gint buflen, gchar * txt, regex_t *preg);
 
+#endif /* STRING_MATCH_H__ */
index 367b002..bfdb897 100644 (file)
@@ -16,7 +16,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
-
 #include "defs.h"
 
 #include <glib.h>
@@ -199,6 +198,7 @@ static void summary_display_msg             (SummaryView            *summaryview,
 static void summary_toggle_view                (SummaryView            *summaryview);
 static void summary_set_row_marks      (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
+static void summaryview_subject_filter_init (PrefsFolderItem    *prefs);
 
 /* message handling */
 static void summary_mark_row           (SummaryView            *summaryview,
@@ -819,14 +819,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
                mlist = not_killed;
        }
 
-       if (item->prefs->enable_simplify_subject
-           && item->prefs->simplify_subject_regexp != NULL
-           && strlen(item->prefs->simplify_subject_regexp) != 0) {
-               summary_simplify_subject(summaryview, 
-                                        item->prefs->simplify_subject_regexp,
-                                        mlist);
-       }
-
        STATUSBAR_POP(summaryview->mainwin);
 
        /* set ctree and hash table from the msginfo list
@@ -2012,6 +2004,8 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                        summaryview->important_score =
                                summaryview->folder_item->prefs->important_score;
        }
+
+       summaryview_subject_filter_init(summaryview->folder_item->prefs);
        
        if (summaryview->folder_item->threaded) {
                GNode *root, *gnode;
@@ -2194,6 +2188,8 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        static gchar *from_name = NULL;
        static gchar col_number[11];
        static gchar col_score[11];
+       static gchar buf[BUFFSIZE];
+       PrefsFolderItem *prefs = summaryview->folder_item->prefs;
        gint *col_pos = summaryview->col_pos;
 
        text[col_pos[S_COL_MARK]]   = NULL;
@@ -2253,8 +2249,16 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
                }
        }
 
-       text[col_pos[S_COL_SUBJECT]] = msginfo->subject ? msginfo->subject :
-               _("(No Subject)");
+       if (prefs->enable_simplify_subject 
+           && prefs->simplify_subject_preg != NULL )
+               text[col_pos[S_COL_SUBJECT]] = msginfo->subject ? 
+                       string_remove_match(buf, BUFFSIZE, msginfo->subject, 
+                                       prefs->simplify_subject_preg) : 
+                       
+                       _("(No Subject)");
+       else 
+               text[col_pos[S_COL_SUBJECT]] = msginfo->subject ? msginfo->subject :
+                       _("(No Subject)");
 }
 
 #define CHANGE_FLAGS(msginfo) \
@@ -3650,17 +3654,6 @@ static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
        }
 }
 
-void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
-                             GSList * mlist)
-{
-       GSList * cur;
-       for(cur = mlist ; cur != NULL ; cur = cur->next) {
-               MsgInfo * msginfo = (MsgInfo *) cur->data;
-               string_remove_all_matches(msginfo->subject, rexp, 
-                                         REG_EXTENDED, 0);
-       }
-}
-
 void summary_processing(SummaryView *summaryview, GSList * mlist)
 {
        GSList * processing_list;
@@ -4956,6 +4949,38 @@ static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
        gtk_object_set_data(GTK_OBJECT(widget), "dont_toggle",
                            GINT_TO_POINTER(0));
 }
+static void summaryview_subject_filter_init(PrefsFolderItem *prefs)
+{
+       int err;
+       gchar buf[BUFFSIZE];
+       if (prefs->enable_simplify_subject) {
+               if (prefs->simplify_subject_regexp && 
+                               *prefs->simplify_subject_regexp != 0x00) {
+
+                       if (!prefs->simplify_subject_preg) 
+                               prefs->simplify_subject_preg = g_new(regex_t, 1);
+                       else
+                               regfree(prefs->simplify_subject_preg);
+
+                       err = string_match_precompile(prefs->simplify_subject_regexp, 
+                                       prefs->simplify_subject_preg, REG_EXTENDED);
+                       if (err) {
+                               regerror(err, prefs->simplify_subject_preg, buf, BUFFSIZE);
+                               alertpanel_error(_("Regular expression (regexp) error:\n%s"), buf);
+                               g_free(prefs->simplify_subject_preg);
+                               prefs->simplify_subject_preg = NULL;
+                       }
+               } else {
+                       if (prefs->simplify_subject_preg) {
+                               regfree(prefs->simplify_subject_preg);
+                               g_free(prefs->simplify_subject_preg);
+                               prefs->simplify_subject_preg = NULL;
+                       }
+               }
+       }
+}
+
+
 /*
  * End of Source.
  */