Statistics
| Revision:

root / src / message_search.c @ 1115

History | View | Annotate | Download (7.8 kB)

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