aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-search.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/mail-search.c')
-rw-r--r--mail/mail-search.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/mail/mail-search.c b/mail/mail-search.c
new file mode 100644
index 0000000000..424ccee991
--- /dev/null
+++ b/mail/mail-search.c
@@ -0,0 +1,403 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jon Trowbridge <trow@ximian.com>
+ *
+ * Copyright 2001-2003 Ximian, Inc. (www.ximian.com)
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "mail-search.h"
+#include "e-searching-tokenizer.h"
+#include <gtkhtml/gtkhtml-search.h>
+#include <gtkhtml/htmlengine.h>
+#include <libgnomeui/gnome-window-icon.h>
+#include <gdk/gdkkeysyms.h>
+
+
+static ESearchingTokenizer *mail_search_tokenizer (MailSearch *ms);
+static void mail_search_redisplay_message (MailSearch *ms);
+
+
+static GtkObjectClass *parent_class = NULL;
+
+
+static void
+mail_search_finalise (GObject *obj)
+{
+ MailSearch *ms = MAIL_SEARCH (obj);
+
+ g_free (ms->last_search);
+ g_object_weak_unref ((GObject *) ms->mail, (GWeakNotify) gtk_widget_destroy, ms);
+ g_object_unref (ms->mail);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+mail_search_destroy (GtkObject *obj)
+{
+ MailSearch *ms = (MailSearch *) obj;
+ ESearchingTokenizer *st = mail_search_tokenizer (ms);
+
+ if (ms->begin_handler) {
+ g_signal_handler_disconnect (ms->mail->html->engine->ht, ms->begin_handler);
+ ms->begin_handler = 0;
+ g_signal_handler_disconnect (ms->mail->html->engine->ht, ms->match_handler);
+ ms->match_handler = 0;
+
+ e_searching_tokenizer_set_primary_search_string (st, NULL);
+ mail_search_redisplay_message (ms);
+ }
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (obj);
+}
+
+static void
+mail_search_class_init (MailSearchClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GtkObjectClass *gtk_object_class = (GtkObjectClass *) klass;
+
+ parent_class = (GtkObjectClass *) g_type_class_ref (GTK_TYPE_DIALOG);
+
+ object_class->finalize = mail_search_finalise;
+
+ gtk_object_class->destroy = mail_search_destroy;
+}
+
+static void
+mail_search_init (MailSearch *ms)
+{
+
+}
+
+GtkType
+mail_search_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (MailSearchClass),
+ NULL, NULL,
+ (GClassInitFunc) mail_search_class_init,
+ NULL, NULL,
+ sizeof (MailSearch),
+ 0,
+ (GInstanceInitFunc) mail_search_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_DIALOG, "MailSearch", &info, 0);
+ }
+
+ return type;
+}
+
+/*
+ * Convenience
+ */
+
+static ESearchingTokenizer *
+mail_search_tokenizer (MailSearch *ms)
+{
+ return E_SEARCHING_TOKENIZER (ms->mail->html->engine->ht);
+}
+
+static void
+mail_search_redisplay_message (MailSearch *ms)
+{
+ mail_display_redisplay (ms->mail, FALSE);
+}
+
+static void
+mail_search_set_subject (MailSearch *ms, const char *subject)
+{
+ char *utf8_subject = NULL;
+
+ if (subject && *subject) {
+ utf8_subject = g_strdup (subject);
+
+ if (g_utf8_validate (utf8_subject, -1, NULL)) {
+#define ARBITRARY_CUTOFF 40
+ if (g_utf8_strlen (utf8_subject, -1) > ARBITRARY_CUTOFF + 3) {
+ char *p = g_utf8_offset_to_pointer (utf8_subject, ARBITRARY_CUTOFF);
+
+ strcpy (p, "...");
+ }
+ } else {
+ /* If the subject contains bad utf8, don't show anything in the frame label. */
+ g_free (utf8_subject);
+ utf8_subject = NULL;
+ }
+ } else {
+ utf8_subject = g_strdup (_("(Untitled Message)"));
+ }
+
+ gtk_frame_set_label (GTK_FRAME (ms->msg_frame), utf8_subject);
+
+ g_free (utf8_subject);
+}
+
+/*
+ * Construct Objects
+ */
+
+static void
+toggled_case_cb (GtkToggleButton *b, MailSearch *ms)
+{
+ ms->case_sensitive = gtk_toggle_button_get_active (b);
+
+ e_searching_tokenizer_set_primary_case_sensitivity (mail_search_tokenizer (ms),
+ ms->case_sensitive);
+ mail_search_redisplay_message (ms);
+
+}
+
+#if 0
+static void
+toggled_fwd_cb (GtkToggleButton *b, MailSearch *ms)
+{
+ ms->search_forward = gtk_toggle_button_get_active (b);
+ gtk_html_engine_search_set_forward (ms->mail->html, ms->search_forward);
+}
+#endif
+
+static void
+dialog_response_cb (GtkWidget *widget, int button, MailSearch *ms)
+{
+ ESearchingTokenizer *st = mail_search_tokenizer (ms);
+
+ if (button == GTK_RESPONSE_ACCEPT) {
+ char *search_text;
+
+ search_text = gtk_editable_get_chars (GTK_EDITABLE (ms->entry), 0, -1);
+ g_strstrip (search_text);
+
+ if (search_text && *search_text) {
+ if (ms->last_search && !strcmp (ms->last_search, search_text)) {
+
+ if (!gtk_html_engine_search_next (ms->mail->html)) {
+ g_free (ms->last_search);
+ ms->last_search = NULL;
+ }
+ } else {
+ g_free (ms->last_search);
+ ms->last_search = NULL;
+
+ e_searching_tokenizer_set_primary_search_string (st, search_text);
+ e_searching_tokenizer_set_primary_case_sensitivity (st, ms->case_sensitive);
+
+ mail_search_redisplay_message (ms);
+
+ if (gtk_html_engine_search (ms->mail->html, search_text,
+ ms->case_sensitive, ms->search_forward,
+ FALSE)) {
+ ms->last_search = g_strdup (search_text);
+ }
+ }
+ }
+
+ g_free (search_text);
+ } else if (button == GTK_RESPONSE_CLOSE) {
+ gtk_widget_destroy (widget);
+ }
+}
+
+static void
+begin_cb (ESearchingTokenizer *st, char *foo, MailSearch *ms)
+{
+ const char *subject;
+
+ if (ms && ms->mail && ms->mail->current_message) {
+ subject = ms->mail->current_message->subject;
+
+ if (subject == NULL)
+ subject = _("Untitled Message");
+ } else {
+ subject = _("Empty Message");
+ }
+
+ gtk_label_set_text (GTK_LABEL (ms->count_label), "0");
+ mail_search_set_subject (ms, subject);
+}
+
+static void
+match_cb (ESearchingTokenizer *st, MailSearch *ms)
+{
+ char buf[16];
+
+ g_snprintf (buf, 16, "%d", e_searching_tokenizer_match_count (st));
+ gtk_label_set_text (GTK_LABEL (ms->count_label), buf);
+}
+
+static void
+entry_run_search (GtkWidget *w, MailSearch *ms)
+{
+ /* run search when enter pressed on widget */
+ gtk_dialog_response ((GtkDialog *) ms, GTK_RESPONSE_ACCEPT);
+}
+
+void
+mail_search_construct (MailSearch *ms, MailDisplay *mail)
+{
+ GtkWidget *find_hbox;
+ GtkWidget *matches_hbox;
+ GtkWidget *toggles_hbox;
+ GtkWidget *frame_vbox;
+ GtkWidget *entry;
+ GtkWidget *count_label;
+ GtkWidget *case_check;
+#if 0
+ GtkWidget *fwd_check;
+#endif
+ GtkWidget *button;
+ GtkWidget *msg_hbox;
+ GtkWidget *msg_frame;
+ GtkAccelGroup *accel_group;
+
+ g_return_if_fail (ms != NULL && IS_MAIL_SEARCH (ms));
+ g_return_if_fail (mail != NULL && IS_MAIL_DISPLAY (mail));
+
+ /* Basic set-up */
+
+ ms->mail = mail;
+ g_object_ref (mail);
+
+ gtk_window_set_title ((GtkWindow *) ms, _("Find in Message"));
+
+ button = gtk_dialog_add_button ((GtkDialog *) ms, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+ gtk_dialog_set_default_response ((GtkDialog *) ms, GTK_RESPONSE_ACCEPT);
+ accel_group = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW (ms), accel_group);
+ gtk_widget_add_accelerator (button, "activate", accel_group, GDK_Escape, 0, GTK_ACCEL_LOCKED);
+
+ gtk_dialog_add_button ((GtkDialog *) ms, GTK_STOCK_FIND, GTK_RESPONSE_ACCEPT);
+
+ ms->search_forward = TRUE;
+ ms->case_sensitive = FALSE;
+
+ ms->begin_handler = g_signal_connect (ms->mail->html->engine->ht, "begin",
+ G_CALLBACK (begin_cb), ms);
+ ms->match_handler = g_signal_connect (ms->mail->html->engine->ht, "match",
+ G_CALLBACK (match_cb), ms);
+
+ /* Construct the dialog contents. */
+
+ msg_hbox = gtk_hbox_new (FALSE, 3);
+ find_hbox = gtk_hbox_new (FALSE, 3);
+ matches_hbox = gtk_hbox_new (FALSE, 3);
+ toggles_hbox = gtk_hbox_new (FALSE, 3);
+ frame_vbox = gtk_vbox_new (FALSE, 3);
+ gtk_container_set_border_width ((GtkContainer *) frame_vbox, 3);
+
+ entry = gtk_entry_new ();
+ count_label = gtk_label_new ("0");
+
+ msg_frame = gtk_frame_new (NULL);
+ gtk_container_set_border_width ((GtkContainer *) msg_frame, 6);
+
+ case_check = gtk_check_button_new_with_label (_("Case Sensitive"));
+#if 0
+ fwd_check = gtk_check_button_new_with_label (_("Search Forward"));
+#endif
+
+ ms->entry = entry;
+ ms->count_label = count_label;
+
+ ms->msg_frame = msg_frame;
+
+ if (mail->current_message->subject && *mail->current_message->subject)
+ mail_search_set_subject (ms, mail->current_message->subject);
+ else
+ mail_search_set_subject (ms, NULL);
+
+#if 0
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fwd_check), ms->search_forward);
+#endif
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (case_check), ms->case_sensitive);
+
+ gtk_box_pack_start (GTK_BOX (msg_hbox), GTK_WIDGET (msg_frame), TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (find_hbox), gtk_label_new (_("Find:")), FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (find_hbox), entry, TRUE, TRUE, 3);
+
+ gtk_box_pack_start (GTK_BOX (matches_hbox), gtk_hbox_new (FALSE, 0), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (matches_hbox), gtk_label_new (_("Matches:")), FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (matches_hbox), count_label, FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (matches_hbox), gtk_hbox_new (FALSE, 0), TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (toggles_hbox), case_check, FALSE, FALSE, 3);
+
+ /*
+ * Disabling the forward/backward search button because there are problems with it
+ * (related to how gtkhtml handles searches), the GUI freeze is upon us, and I
+ * don't know if they'll get resolved for 1.0. Hopefully getting this fixed can
+ * be a 1.1 item.
+ */
+
+#if 0
+ gtk_box_pack_start (GTK_BOX (toggles_hbox), fwd_check, FALSE, FALSE, 3);
+#endif
+
+ gtk_box_pack_start (GTK_BOX (frame_vbox), find_hbox, FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (frame_vbox), matches_hbox, FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (frame_vbox), toggles_hbox, FALSE, FALSE, 3);
+
+ gtk_container_add (GTK_CONTAINER (msg_frame), GTK_WIDGET (frame_vbox));
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ms)->vbox), msg_hbox, TRUE, TRUE, 0);
+
+ gtk_widget_grab_focus (entry); /* Give focus to entry by default */
+ g_signal_connect (entry, "activate", G_CALLBACK (entry_run_search), ms);
+ gnome_window_icon_set_from_file (GTK_WINDOW (ms), EVOLUTION_ICONSDIR "/find-message.xpm");
+
+ gtk_widget_show_all (msg_hbox);
+ gtk_widget_show_all (find_hbox);
+ gtk_widget_show_all (matches_hbox);
+ gtk_widget_show_all (toggles_hbox);
+
+ /* Hook up signals */
+
+ g_signal_connect (case_check, "toggled", G_CALLBACK (toggled_case_cb), ms);
+#if 0
+ g_signal_connect (fwd_check, "toggled", G_CALLBACK (toggled_fwd_cb), ms);
+#endif
+ g_signal_connect (ms, "response", G_CALLBACK (dialog_response_cb), ms);
+
+ g_object_weak_ref ((GObject *) ms->mail, (GWeakNotify) gtk_widget_destroy, ms);
+}
+
+GtkWidget *
+mail_search_new (MailDisplay *mail)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (IS_MAIL_DISPLAY (mail), NULL);
+
+ widget = g_object_new (mail_search_get_type (), NULL);
+ mail_search_construct (MAIL_SEARCH (widget), mail);
+
+ return widget;
+}
+