Statistics
| Revision:

root / src / message_search.c @ 3039

History | View | Annotate | Download (7.8 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 1022 hiro
 * Copyright (C) 1999-2006 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 1022 hiro
static void message_search_close        (void);
66 272 hiro
67 287 hiro
static void message_search_prev_clicked        (GtkButton        *button,
68 287 hiro
                                         gpointer         data);
69 287 hiro
static void message_search_next_clicked        (GtkButton        *button,
70 287 hiro
                                         gpointer         data);
71 1022 hiro
static void close_clicked                (GtkButton        *button,
72 1022 hiro
                                         gpointer         data);
73 287 hiro
static void body_activated                (void);
74 1022 hiro
static gboolean window_deleted                (GtkWidget        *widget,
75 1022 hiro
                                         GdkEventAny        *event,
76 1022 hiro
                                         gpointer         data);
77 287 hiro
static gboolean key_pressed                (GtkWidget        *widget,
78 287 hiro
                                         GdkEventKey        *event,
79 287 hiro
                                         gpointer         data);
80 1 hiro
81 1022 hiro
static void view_destroyed                (GtkWidget        *widget,
82 1022 hiro
                                         gpointer         data);
83 1022 hiro
84 1 hiro
void message_search(MessageView *messageview)
85 1 hiro
{
86 272 hiro
        if (!search_window.window)
87 272 hiro
                message_search_create();
88 1 hiro
89 272 hiro
        search_window.messageview = messageview;
90 1022 hiro
        g_signal_handlers_disconnect_by_func(GTK_WIDGET_PTR(messageview),
91 1022 hiro
                                             view_destroyed, messageview);
92 1022 hiro
        g_signal_connect(G_OBJECT(GTK_WIDGET_PTR(messageview)), "destroy",
93 1022 hiro
                         G_CALLBACK(view_destroyed), messageview);
94 272 hiro
95 272 hiro
        gtk_widget_grab_focus(search_window.next_btn);
96 272 hiro
        gtk_widget_grab_focus(search_window.body_entry);
97 272 hiro
        gtk_widget_show(search_window.window);
98 1022 hiro
        gtk_window_present(GTK_WINDOW(search_window.window));
99 1 hiro
}
100 1 hiro
101 272 hiro
static void message_search_create(void)
102 1 hiro
{
103 272 hiro
        GtkWidget *window;
104 272 hiro
105 1 hiro
        GtkWidget *vbox1;
106 1 hiro
        GtkWidget *hbox1;
107 1 hiro
        GtkWidget *body_label;
108 272 hiro
        GtkWidget *body_entry;
109 272 hiro
110 1 hiro
        GtkWidget *checkbtn_hbox;
111 272 hiro
        GtkWidget *case_checkbtn;
112 272 hiro
113 1 hiro
        GtkWidget *confirm_area;
114 406 hiro
        GtkWidget *next_btn;
115 272 hiro
        GtkWidget *prev_btn;
116 272 hiro
        GtkWidget *close_btn;
117 1 hiro
118 1 hiro
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
119 1 hiro
        gtk_window_set_title (GTK_WINDOW (window),
120 1 hiro
                              _("Find in current message"));
121 1 hiro
        gtk_widget_set_size_request (window, 450, -1);
122 1 hiro
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE);
123 1 hiro
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
124 1 hiro
        g_signal_connect(G_OBJECT(window), "delete_event",
125 1022 hiro
                         G_CALLBACK(window_deleted), NULL);
126 1 hiro
        g_signal_connect(G_OBJECT(window), "key_press_event",
127 1 hiro
                         G_CALLBACK(key_pressed), NULL);
128 1 hiro
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
129 1 hiro
130 1 hiro
        vbox1 = gtk_vbox_new (FALSE, 0);
131 1 hiro
        gtk_widget_show (vbox1);
132 1 hiro
        gtk_container_add (GTK_CONTAINER (window), vbox1);
133 1 hiro
134 1 hiro
        hbox1 = gtk_hbox_new (FALSE, 8);
135 1 hiro
        gtk_widget_show (hbox1);
136 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
137 1 hiro
138 1 hiro
        body_label = gtk_label_new (_("Find text:"));
139 1 hiro
        gtk_widget_show (body_label);
140 1 hiro
        gtk_box_pack_start (GTK_BOX (hbox1), body_label, FALSE, FALSE, 0);
141 1 hiro
142 1 hiro
        body_entry = gtk_entry_new ();
143 1 hiro
        gtk_widget_show (body_entry);
144 1 hiro
        gtk_box_pack_start (GTK_BOX (hbox1), body_entry, TRUE, TRUE, 0);
145 1 hiro
        g_signal_connect(G_OBJECT(body_entry), "activate",
146 272 hiro
                         G_CALLBACK(body_activated), NULL);
147 1 hiro
148 1 hiro
        checkbtn_hbox = gtk_hbox_new (FALSE, 8);
149 1 hiro
        gtk_widget_show (checkbtn_hbox);
150 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), checkbtn_hbox, TRUE, TRUE, 0);
151 1 hiro
        gtk_container_set_border_width (GTK_CONTAINER (checkbtn_hbox), 8);
152 1 hiro
153 1 hiro
        case_checkbtn = gtk_check_button_new_with_label (_("Case sensitive"));
154 1 hiro
        gtk_widget_show (case_checkbtn);
155 1 hiro
        gtk_box_pack_start (GTK_BOX (checkbtn_hbox), case_checkbtn,
156 1 hiro
                            FALSE, FALSE, 0);
157 1 hiro
158 31 hiro
        gtkut_stock_button_set_create(&confirm_area,
159 406 hiro
                                      &next_btn, GTK_STOCK_GO_FORWARD,
160 272 hiro
                                      &prev_btn, GTK_STOCK_GO_BACK,
161 31 hiro
                                      &close_btn, GTK_STOCK_CLOSE);
162 406 hiro
        gtkut_box_set_reverse_order(GTK_BOX(confirm_area), FALSE);
163 1 hiro
        gtk_widget_show (confirm_area);
164 1 hiro
        gtk_box_pack_start (GTK_BOX (vbox1), confirm_area, FALSE, FALSE, 0);
165 272 hiro
        gtk_widget_grab_default(next_btn);
166 1 hiro
167 272 hiro
        g_signal_connect(G_OBJECT(prev_btn), "clicked",
168 272 hiro
                         G_CALLBACK(message_search_prev_clicked), NULL);
169 272 hiro
        g_signal_connect(G_OBJECT(next_btn), "clicked",
170 272 hiro
                         G_CALLBACK(message_search_next_clicked), NULL);
171 1022 hiro
        g_signal_connect(G_OBJECT(close_btn), "clicked",
172 1022 hiro
                         G_CALLBACK(close_clicked), NULL);
173 272 hiro
174 272 hiro
        search_window.window = window;
175 272 hiro
        search_window.body_entry = body_entry;
176 272 hiro
        search_window.case_checkbtn = case_checkbtn;
177 406 hiro
        search_window.next_btn = next_btn;
178 272 hiro
        search_window.prev_btn = prev_btn;
179 272 hiro
        search_window.close_btn = close_btn;
180 1 hiro
}
181 1 hiro
182 272 hiro
static void message_search_execute(gboolean backward)
183 1 hiro
{
184 272 hiro
        MessageView *messageview = search_window.messageview;
185 1 hiro
        gboolean case_sens;
186 1 hiro
        gboolean all_searched = FALSE;
187 1 hiro
        const gchar *body_str;
188 1 hiro
189 272 hiro
        body_str = gtk_entry_get_text(GTK_ENTRY(search_window.body_entry));
190 1 hiro
        if (*body_str == '\0') return;
191 1 hiro
192 1 hiro
        case_sens = gtk_toggle_button_get_active
193 272 hiro
                (GTK_TOGGLE_BUTTON(search_window.case_checkbtn));
194 1 hiro
195 1 hiro
        for (;;) {
196 1 hiro
                gchar *str;
197 1 hiro
                AlertValue val;
198 1 hiro
199 1 hiro
                if (backward) {
200 1 hiro
                        if (messageview_search_string_backward
201 1 hiro
                                (messageview, body_str, case_sens) == TRUE)
202 1 hiro
                                break;
203 1 hiro
                } else {
204 1 hiro
                        if (messageview_search_string
205 1 hiro
                                (messageview, body_str, case_sens) == TRUE)
206 1 hiro
                                break;
207 1 hiro
                }
208 1 hiro
209 1 hiro
                if (all_searched) {
210 1 hiro
                        alertpanel_message
211 1 hiro
                                (_("Search failed"),
212 1 hiro
                                 _("Search string not found."),
213 1 hiro
                                 ALERT_WARNING);
214 1 hiro
                        break;
215 1 hiro
                }
216 1 hiro
217 1 hiro
                all_searched = TRUE;
218 1 hiro
219 1 hiro
                if (backward)
220 1 hiro
                        str = _("Beginning of message reached; "
221 1 hiro
                                "continue from end?");
222 1 hiro
                else
223 1 hiro
                        str = _("End of message reached; "
224 1 hiro
                                "continue from beginning?");
225 1 hiro
226 1 hiro
                val = alertpanel(_("Search finished"), str,
227 47 hiro
                                 GTK_STOCK_YES, GTK_STOCK_NO, NULL);
228 1 hiro
                if (G_ALERTDEFAULT == val) {
229 272 hiro
                        manage_window_focus_in(search_window.window,
230 272 hiro
                                               NULL, NULL);
231 1 hiro
                        messageview_set_position(messageview,
232 1 hiro
                                                 backward ? -1 : 0);
233 1 hiro
                } else
234 1 hiro
                        break;
235 1 hiro
        }
236 1 hiro
}
237 1 hiro
238 1022 hiro
static void message_search_close(void)
239 1022 hiro
{
240 1022 hiro
        search_window.messageview = NULL;
241 1022 hiro
        gtk_widget_hide(search_window.window);
242 1022 hiro
}
243 1022 hiro
244 272 hiro
static void message_search_prev_clicked(GtkButton *button, gpointer data)
245 272 hiro
{
246 272 hiro
        message_search_execute(TRUE);
247 272 hiro
}
248 272 hiro
249 272 hiro
static void message_search_next_clicked(GtkButton *button, gpointer data)
250 272 hiro
{
251 272 hiro
        message_search_execute(FALSE);
252 272 hiro
}
253 272 hiro
254 1022 hiro
static void close_clicked(GtkButton *button, gpointer data)
255 1022 hiro
{
256 1022 hiro
        message_search_close();
257 1022 hiro
}
258 1022 hiro
259 1 hiro
static void body_activated(void)
260 1 hiro
{
261 272 hiro
        gtk_button_clicked(GTK_BUTTON(search_window.next_btn));
262 1 hiro
}
263 1 hiro
264 1022 hiro
static gboolean window_deleted(GtkWidget *widget, GdkEventAny *event,
265 1022 hiro
                               gpointer data)
266 1022 hiro
{
267 1022 hiro
        message_search_close();
268 1022 hiro
        return TRUE;
269 1022 hiro
}
270 1022 hiro
271 1 hiro
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
272 1 hiro
                            gpointer data)
273 1 hiro
{
274 1 hiro
        if (event && event->keyval == GDK_Escape)
275 1022 hiro
                message_search_close();
276 1 hiro
        return FALSE;
277 1 hiro
}
278 1022 hiro
279 1022 hiro
static void view_destroyed(GtkWidget *widget, gpointer data)
280 1022 hiro
{
281 1022 hiro
        if ((MessageView *)data == search_window.messageview)
282 1022 hiro
                message_search_close();
283 1022 hiro
}