Statistics
| Revision:

root / src / message_search.c @ 528

History | View | Annotate | Download (6.9 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 31 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
#ifdef HAVE_CONFIG_H
21 1 hiro
#  include "config.h"
22 1 hiro
#endif
23 1 hiro
24 1 hiro
#include "defs.h"
25 1 hiro
26 1 hiro
#include <glib.h>
27 92 hiro
#include <glib/gi18n.h>
28 1 hiro
#include <gdk/gdkkeysyms.h>
29 1 hiro
#include <gtk/gtkwidget.h>
30 1 hiro
#include <gtk/gtkwindow.h>
31 1 hiro
#include <gtk/gtkvbox.h>
32 1 hiro
#include <gtk/gtktable.h>
33 1 hiro
#include <gtk/gtklabel.h>
34 1 hiro
#include <gtk/gtkentry.h>
35 1 hiro
#include <gtk/gtkhbox.h>
36 1 hiro
#include <gtk/gtkcheckbutton.h>
37 1 hiro
#include <gtk/gtkhbbox.h>
38 1 hiro
#include <gtk/gtkbutton.h>
39 237 hiro
#include <gtk/gtkstock.h>
40 1 hiro
#include <stdio.h>
41 1 hiro
#include <stdlib.h>
42 1 hiro
#include <string.h>
43 1 hiro
44 1 hiro
#include "main.h"
45 1 hiro
#include "message_search.h"
46 1 hiro
#include "messageview.h"
47 1 hiro
#include "utils.h"
48 1 hiro
#include "gtkutils.h"
49 1 hiro
#include "manage_window.h"
50 1 hiro
#include "alertpanel.h"
51 1 hiro
52 272 hiro
static struct MessageSearchWindow {
53 272 hiro
        GtkWidget *window;
54 272 hiro
        GtkWidget *body_entry;
55 272 hiro
        GtkWidget *case_checkbtn;
56 406 hiro
        GtkWidget *next_btn;
57 272 hiro
        GtkWidget *prev_btn;
58 272 hiro
        GtkWidget *close_btn;
59 1 hiro
60 272 hiro
        MessageView *messageview;
61 272 hiro
} search_window;
62 272 hiro
63 287 hiro
static void message_search_create        (void);
64 287 hiro
static void message_search_execute        (gboolean         backward);
65 272 hiro
66 287 hiro
static void message_search_prev_clicked        (GtkButton        *button,
67 287 hiro
                                         gpointer         data);
68 287 hiro
static void message_search_next_clicked        (GtkButton        *button,
69 287 hiro
                                         gpointer         data);
70 287 hiro
static void body_activated                (void);
71 287 hiro
static gboolean key_pressed                (GtkWidget        *widget,
72 287 hiro
                                         GdkEventKey        *event,
73 287 hiro
                                         gpointer         data);
74 1 hiro
75 1 hiro
void message_search(MessageView *messageview)
76 1 hiro
{
77 272 hiro
        if (!search_window.window)
78 272 hiro
                message_search_create();
79 1 hiro
        else
80 272 hiro
                gtk_widget_hide(search_window.window);
81 1 hiro
82 272 hiro
        search_window.messageview = messageview;
83 272 hiro
84 272 hiro
        gtk_widget_grab_focus(search_window.next_btn);
85 272 hiro
        gtk_widget_grab_focus(search_window.body_entry);
86 272 hiro
        gtk_widget_show(search_window.window);
87 1 hiro
}
88 1 hiro
89 272 hiro
static void message_search_create(void)
90 1 hiro
{
91 272 hiro
        GtkWidget *window;
92 272 hiro
93 1 hiro
        GtkWidget *vbox1;
94 1 hiro
        GtkWidget *hbox1;
95 1 hiro
        GtkWidget *body_label;
96 272 hiro
        GtkWidget *body_entry;
97 272 hiro
98 1 hiro
        GtkWidget *checkbtn_hbox;
99 272 hiro
        GtkWidget *case_checkbtn;
100 272 hiro
101 1 hiro
        GtkWidget *confirm_area;
102 406 hiro
        GtkWidget *next_btn;
103 272 hiro
        GtkWidget *prev_btn;
104 272 hiro
        GtkWidget *close_btn;
105 1 hiro
106 1 hiro
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
107 1 hiro
        gtk_window_set_title (GTK_WINDOW (window),
108 1 hiro
                              _("Find in current message"));
109 1 hiro
        gtk_widget_set_size_request (window, 450, -1);
110 1 hiro
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE);
111 1 hiro
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
112 1 hiro
        g_signal_connect(G_OBJECT(window), "delete_event",
113 1 hiro
                         G_CALLBACK(gtk_widget_hide_on_delete), NULL);
114 1 hiro
        g_signal_connect(G_OBJECT(window), "key_press_event",
115 1 hiro
                         G_CALLBACK(key_pressed), NULL);
116 1 hiro
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
117 1 hiro
118 1 hiro
        vbox1 = gtk_vbox_new (FALSE, 0);
119 1 hiro
        gtk_widget_show (vbox1);
120 1 hiro
        gtk_container_add (GTK_CONTAINER (window), vbox1);
121 1 hiro
122 1 hiro
        hbox1 = gtk_hbox_new (FALSE, 8);
123 1 hiro
        gtk_widget_show (hbox1);
124 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
125 1 hiro
126 1 hiro
        body_label = gtk_label_new (_("Find text:"));
127 1 hiro
        gtk_widget_show (body_label);
128 1 hiro
        gtk_box_pack_start (GTK_BOX (hbox1), body_label, FALSE, FALSE, 0);
129 1 hiro
130 1 hiro
        body_entry = gtk_entry_new ();
131 1 hiro
        gtk_widget_show (body_entry);
132 1 hiro
        gtk_box_pack_start (GTK_BOX (hbox1), body_entry, TRUE, TRUE, 0);
133 1 hiro
        g_signal_connect(G_OBJECT(body_entry), "activate",
134 272 hiro
                         G_CALLBACK(body_activated), NULL);
135 1 hiro
136 1 hiro
        checkbtn_hbox = gtk_hbox_new (FALSE, 8);
137 1 hiro
        gtk_widget_show (checkbtn_hbox);
138 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), checkbtn_hbox, TRUE, TRUE, 0);
139 1 hiro
        gtk_container_set_border_width (GTK_CONTAINER (checkbtn_hbox), 8);
140 1 hiro
141 1 hiro
        case_checkbtn = gtk_check_button_new_with_label (_("Case sensitive"));
142 1 hiro
        gtk_widget_show (case_checkbtn);
143 1 hiro
        gtk_box_pack_start (GTK_BOX (checkbtn_hbox), case_checkbtn,
144 1 hiro
                            FALSE, FALSE, 0);
145 1 hiro
146 31 hiro
        gtkut_stock_button_set_create(&confirm_area,
147 406 hiro
                                      &next_btn, GTK_STOCK_GO_FORWARD,
148 272 hiro
                                      &prev_btn, GTK_STOCK_GO_BACK,
149 31 hiro
                                      &close_btn, GTK_STOCK_CLOSE);
150 406 hiro
        gtkut_box_set_reverse_order(GTK_BOX(confirm_area), FALSE);
151 1 hiro
        gtk_widget_show (confirm_area);
152 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), confirm_area, FALSE, FALSE, 0);
153 272 hiro
        gtk_widget_grab_default(next_btn);
154 1 hiro
155 272 hiro
        g_signal_connect(G_OBJECT(prev_btn), "clicked",
156 272 hiro
                         G_CALLBACK(message_search_prev_clicked), NULL);
157 272 hiro
        g_signal_connect(G_OBJECT(next_btn), "clicked",
158 272 hiro
                         G_CALLBACK(message_search_next_clicked), NULL);
159 1 hiro
        g_signal_connect_closure
160 1 hiro
                (G_OBJECT(close_btn), "clicked",
161 1 hiro
                 g_cclosure_new_swap(G_CALLBACK(gtk_widget_hide),
162 1 hiro
                                     window, NULL),
163 1 hiro
                 FALSE);
164 272 hiro
165 272 hiro
        search_window.window = window;
166 272 hiro
        search_window.body_entry = body_entry;
167 272 hiro
        search_window.case_checkbtn = case_checkbtn;
168 406 hiro
        search_window.next_btn = next_btn;
169 272 hiro
        search_window.prev_btn = prev_btn;
170 272 hiro
        search_window.close_btn = close_btn;
171 1 hiro
}
172 1 hiro
173 272 hiro
static void message_search_execute(gboolean backward)
174 1 hiro
{
175 272 hiro
        MessageView *messageview = search_window.messageview;
176 1 hiro
        gboolean case_sens;
177 1 hiro
        gboolean all_searched = FALSE;
178 1 hiro
        const gchar *body_str;
179 1 hiro
180 272 hiro
        body_str = gtk_entry_get_text(GTK_ENTRY(search_window.body_entry));
181 1 hiro
        if (*body_str == '\0') return;
182 1 hiro
183 1 hiro
        case_sens = gtk_toggle_button_get_active
184 272 hiro
                (GTK_TOGGLE_BUTTON(search_window.case_checkbtn));
185 1 hiro
186 1 hiro
        for (;;) {
187 1 hiro
                gchar *str;
188 1 hiro
                AlertValue val;
189 1 hiro
190 1 hiro
                if (backward) {
191 1 hiro
                        if (messageview_search_string_backward
192 1 hiro
                                (messageview, body_str, case_sens) == TRUE)
193 1 hiro
                                break;
194 1 hiro
                } else {
195 1 hiro
                        if (messageview_search_string
196 1 hiro
                                (messageview, body_str, case_sens) == TRUE)
197 1 hiro
                                break;
198 1 hiro
                }
199 1 hiro
200 1 hiro
                if (all_searched) {
201 1 hiro
                        alertpanel_message
202 1 hiro
                                (_("Search failed"),
203 1 hiro
                                 _("Search string not found."),
204 1 hiro
                                 ALERT_WARNING);
205 1 hiro
                        break;
206 1 hiro
                }
207 1 hiro
208 1 hiro
                all_searched = TRUE;
209 1 hiro
210 1 hiro
                if (backward)
211 1 hiro
                        str = _("Beginning of message reached; "
212 1 hiro
                                "continue from end?");
213 1 hiro
                else
214 1 hiro
                        str = _("End of message reached; "
215 1 hiro
                                "continue from beginning?");
216 1 hiro
217 1 hiro
                val = alertpanel(_("Search finished"), str,
218 47 hiro
                                 GTK_STOCK_YES, GTK_STOCK_NO, NULL);
219 1 hiro
                if (G_ALERTDEFAULT == val) {
220 272 hiro
                        manage_window_focus_in(search_window.window,
221 272 hiro
                                               NULL, NULL);
222 1 hiro
                        messageview_set_position(messageview,
223 1 hiro
                                                 backward ? -1 : 0);
224 1 hiro
                } else
225 1 hiro
                        break;
226 1 hiro
        }
227 1 hiro
}
228 1 hiro
229 272 hiro
static void message_search_prev_clicked(GtkButton *button, gpointer data)
230 272 hiro
{
231 272 hiro
        message_search_execute(TRUE);
232 272 hiro
}
233 272 hiro
234 272 hiro
static void message_search_next_clicked(GtkButton *button, gpointer data)
235 272 hiro
{
236 272 hiro
        message_search_execute(FALSE);
237 272 hiro
}
238 272 hiro
239 1 hiro
static void body_activated(void)
240 1 hiro
{
241 272 hiro
        gtk_button_clicked(GTK_BUTTON(search_window.next_btn));
242 1 hiro
}
243 1 hiro
244 1 hiro
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
245 1 hiro
                            gpointer data)
246 1 hiro
{
247 1 hiro
        if (event && event->keyval == GDK_Escape)
248 272 hiro
                gtk_widget_hide(search_window.window);
249 1 hiro
        return FALSE;
250 1 hiro
}