aboutsummaryrefslogblamecommitdiffstats
path: root/mail/mail-search.c
blob: 9955b34e3a3ce94d4da2414affb43945edeb7889 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                           

                                                                   















                                                                      

                   
                        
                                  
                                   
                               
                                         
 


                                    
                                   


                                           

                                                                                   
 
                                 


                                                      




                                               


                                                                                   
        
                                                      










                                 
                                          

                                 
                                              
                                                 





                                                                

                  
                                                                                                                





                                














                                                                  
           
                                                             
 

                                  
                                  
                                                  
                
                                                               



                                                                                                    

                                                  




                                                                                                       
                
                                                                  
         


                                                                      


                              
  






                                                              
        

                                                                                       

                                           

 
     



                                                              
                                                                                
 
      

           
                                                

                                                             
        




                                                                   
                                                                         
 

                                                             
                                                       
                                  
                



                                                                                       





                                                                                        
                                

                                                         
                                

                                                                                                            
                                
                                                                   
                                






                                                                                                   
                
                                     
                                                       
                                            


         
           
                                                             
 

                            
                                                          
                                                             
                

                                                        
                
                                             
         
        
                                                              
                                              




                                                  

                     


                                                                           
 



                                                     
                                                                    

 


                                                         


                                
                              
                         
                               
                              
     
                             
      
                          
                            
                             
        

                                                                  
        
                          
        
                        









                                                                                        

                                   





                                                                                  

                                            
                                               


                                               
                                               
        

                                          
        
                                                
        
                                                                            
     
                                                                            
      
        

                                      
        
                                    
        



                                                                              
        
     
                                                                                          
      
                                                                                          
        
                                                                                         
        

                                                                                              
                                                                                            

                                                                                                    
                                                                                            
        
                                                                                 
        







                                                                                          
                                                                                 
      
        



                                                                                
                                                                               
        
                                                                                        
        
                                                                            
                                                                                
                                                                                                  
        



                                           
        
                             

                                                                                   
     
                                                                                 
      

                                                                             

                                                                                       




                                   

                          
                                                                    




                                                              

 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 * mail-search.c
 *
 * Copyright (C) 2001 Ximian, Inc.
 *
 * Developed by Jon Trowbridge <trow@ximian.com>
 */

/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 * 
 * 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 Place, Suite 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>

static GtkObjectClass *parent_class;

static void
mail_search_finalise (GObject *obj)
{
    MailSearch *ms = MAIL_SEARCH (obj);

    g_signal_handler_disconnect(ms->mail->html->engine->ht, ms->match_handler);
    g_signal_handler_disconnect(ms->mail->html->engine->ht, ms->begin_handler);

    g_free (ms->last_search);
    g_object_unref((ms->mail));

    ((GObjectClass *)parent_class)->finalize(obj);
}

static void
mail_search_class_init (MailSearchClass *klass)
{
    GObjectClass *object_class = (GObjectClass *) klass;

    parent_class = GTK_OBJECT_CLASS (g_type_class_ref(gtk_dialog_get_type ()));
    
    object_class->finalize = mail_search_finalise;
}

static void
mail_search_init (MailSearch *ms)
{

}

GtkType
mail_search_get_type (void)
{
    static GType mail_search_type = 0;

    if (! mail_search_type) {
        GTypeInfo mail_search_info = {
            sizeof (MailSearchClass),
            NULL, NULL,
            (GClassInitFunc) mail_search_class_init,
            NULL, NULL,
            sizeof (MailSearch),
            0,
            (GInstanceInitFunc) mail_search_init,
        };

        mail_search_type = g_type_register_static (GTK_TYPE_DIALOG, "MailSearch", &mail_search_info, 0);
    }

    return mail_search_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_destroy_cb (GtkWidget *w, MailSearch *ms)
{
    ESearchingTokenizer *st = mail_search_tokenizer (ms);
    
    e_searching_tokenizer_set_primary_search_string (st, NULL);
    mail_search_redisplay_message (ms);
}

static void
dialog_clicked_cb (GtkWidget *widget, gint button_number, MailSearch *ms)
{
    ESearchingTokenizer *st = mail_search_tokenizer (ms);
    
    if (button_number == 0) {        /* "Search" */
        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_number == 1) { /* "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;
    
    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_button_new_from_stock (GTK_STOCK_FIND);
    gtk_button_set_label ((GtkButton *) button, _("Search"));
    gtk_dialog_add_action_widget ((GtkDialog*) ms, button, GTK_RESPONSE_ACCEPT);
    gtk_dialog_add_button ((GtkDialog *) ms, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
    gtk_dialog_set_default_response ((GtkDialog *) ms, 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, 0);
    find_hbox    = gtk_hbox_new (FALSE, 0);
    matches_hbox = gtk_hbox_new (FALSE, 0);
    toggles_hbox = gtk_hbox_new (FALSE, 0);
    frame_vbox   = gtk_vbox_new (FALSE, 0);
    
    entry       = gtk_entry_new ();
    count_label = gtk_label_new ("0");
    
    msg_frame   = gtk_frame_new (NULL); 
    
    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), FALSE, FALSE, 3);
    
    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, 0);
    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, 4);
    
    /*
     * 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, 4);
#endif
    
    gtk_box_pack_start (GTK_BOX (frame_vbox), find_hbox, TRUE, TRUE, 8);
    gtk_box_pack_start (GTK_BOX (frame_vbox), matches_hbox, TRUE, TRUE, 0); 
    gtk_box_pack_start (GTK_BOX (frame_vbox), toggles_hbox, TRUE, TRUE, 0);
    
    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, "clicked", G_CALLBACK (dialog_clicked_cb), ms);
    
    g_object_weak_ref ((GObject *) ms, (GWeakNotify) dialog_destroy_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 (mail && IS_MAIL_DISPLAY (mail), NULL);
    
    widget = g_object_new (mail_search_get_type (), NULL);
    mail_search_construct (MAIL_SEARCH (widget), mail);
    
    return widget;
}