2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 Hiroyuki Yamamoto
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.
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.
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.
27 #include <gdk/gdkkeysyms.h>
28 #include <gtk/gtkwidget.h>
29 #include <gtk/gtkwindow.h>
30 #include <gtk/gtkvbox.h>
31 #include <gtk/gtktable.h>
32 #include <gtk/gtklabel.h>
33 #include <gtk/gtkentry.h>
34 #include <gtk/gtkhbox.h>
35 #include <gtk/gtkcheckbutton.h>
36 #include <gtk/gtkhbbox.h>
37 #include <gtk/gtkbutton.h>
38 #include <gtk/gtkctree.h>
45 #include "summary_search.h"
46 #include "summaryview.h"
49 #include "manage_window.h"
50 #include "alertpanel.h"
52 static GtkWidget
*window
;
53 static GtkWidget
*from_entry
;
54 static GtkWidget
*to_entry
;
55 static GtkWidget
*subject_entry
;
56 static GtkWidget
*case_checkbtn
;
57 static GtkWidget
*backward_checkbtn
;
58 static GtkWidget
*all_checkbtn
;
59 static GtkWidget
*search_btn
;
60 static GtkWidget
*clear_btn
;
61 static GtkWidget
*close_btn
;
63 static void summary_search_create(SummaryView
*summaryview
);
64 static void summary_search_execute(GtkButton
*button
, gpointer data
);
65 static void summary_search_clear(GtkButton
*button
, gpointer data
);
66 static void from_activated(void);
67 static void to_activated(void);
68 static void subject_activated(void);
69 static void key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
);
71 void summary_search(SummaryView
*summaryview
)
74 summary_search_create(summaryview
);
76 gtk_widget_grab_focus(search_btn
);
77 gtk_widget_grab_focus(subject_entry
);
78 gtk_widget_show(window
);
81 void summary_search_cb(gpointer data
, guint action
, GtkWidget
*widget
)
83 MainWindow
*mainwin
= data
;
85 summary_search(mainwin
->summaryview
);
88 static void summary_search_create(SummaryView
*summaryview
)
92 GtkWidget
*from_label
;
94 GtkWidget
*subject_label
;
95 GtkWidget
*checkbtn_hbox
;
96 GtkWidget
*confirm_area
;
98 window
= gtk_window_new (GTK_WINDOW_DIALOG
);
99 gtk_window_set_title (GTK_WINDOW (window
), _("Search"));
100 gtk_widget_set_usize (window
, 450, -1);
101 /*gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);*/
102 gtk_window_set_policy(GTK_WINDOW(window
), FALSE
, TRUE
, TRUE
);
103 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
104 gtk_signal_connect(GTK_OBJECT(window
), "delete_event",
105 GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete
), NULL
);
106 gtk_signal_connect(GTK_OBJECT(window
), "key_press_event",
107 GTK_SIGNAL_FUNC(key_pressed
), NULL
);
108 gtk_signal_connect(GTK_OBJECT(window
), "focus_in_event",
109 GTK_SIGNAL_FUNC(manage_window_focus_in
), NULL
);
110 gtk_signal_connect(GTK_OBJECT(window
), "focus_out_event",
111 GTK_SIGNAL_FUNC(manage_window_focus_out
), NULL
);
113 vbox1
= gtk_vbox_new (FALSE
, 0);
114 gtk_widget_show (vbox1
);
115 gtk_container_add (GTK_CONTAINER (window
), vbox1
);
117 table1
= gtk_table_new (3, 3, FALSE
);
118 gtk_widget_show (table1
);
119 gtk_box_pack_start (GTK_BOX (vbox1
), table1
, TRUE
, TRUE
, 0);
120 gtk_container_set_border_width (GTK_CONTAINER (table1
), 4);
121 gtk_table_set_row_spacings (GTK_TABLE (table1
), 8);
122 gtk_table_set_col_spacings (GTK_TABLE (table1
), 8);
124 from_entry
= gtk_entry_new ();
125 gtk_widget_show (from_entry
);
126 gtk_table_attach (GTK_TABLE (table1
), from_entry
, 1, 3, 0, 1,
127 GTK_EXPAND
|GTK_FILL
, 0, 0, 0);
128 gtk_signal_connect(GTK_OBJECT(from_entry
), "activate",
129 GTK_SIGNAL_FUNC(from_activated
), summaryview
);
131 to_entry
= gtk_entry_new ();
132 gtk_widget_show (to_entry
);
133 gtk_table_attach (GTK_TABLE (table1
), to_entry
, 1, 3, 1, 2,
134 GTK_EXPAND
|GTK_FILL
, 0, 0, 0);
135 gtk_signal_connect(GTK_OBJECT(to_entry
), "activate",
136 GTK_SIGNAL_FUNC(to_activated
), summaryview
);
138 subject_entry
= gtk_entry_new ();
139 gtk_widget_show (subject_entry
);
140 gtk_table_attach (GTK_TABLE (table1
), subject_entry
, 1, 3, 2, 3,
141 GTK_EXPAND
|GTK_FILL
, 0, 0, 0);
142 gtk_signal_connect(GTK_OBJECT(subject_entry
), "activate",
143 GTK_SIGNAL_FUNC(subject_activated
), summaryview
);
145 from_label
= gtk_label_new (_("From:"));
146 gtk_widget_show (from_label
);
147 gtk_table_attach (GTK_TABLE (table1
), from_label
, 0, 1, 0, 1,
149 gtk_label_set_justify (GTK_LABEL (from_label
), GTK_JUSTIFY_RIGHT
);
150 gtk_misc_set_alignment (GTK_MISC (from_label
), 1, 0.5);
152 to_label
= gtk_label_new (_("To:"));
153 gtk_widget_show (to_label
);
154 gtk_table_attach (GTK_TABLE (table1
), to_label
, 0, 1, 1, 2,
156 gtk_label_set_justify (GTK_LABEL (to_label
), GTK_JUSTIFY_RIGHT
);
157 gtk_misc_set_alignment (GTK_MISC (to_label
), 1, 0.5);
159 subject_label
= gtk_label_new (_("Subject:"));
160 gtk_widget_show (subject_label
);
162 gtk_table_attach (GTK_TABLE (table1
), subject_label
, 0, 1, 2, 3,
164 gtk_label_set_justify (GTK_LABEL (subject_label
), GTK_JUSTIFY_RIGHT
);
165 gtk_misc_set_alignment (GTK_MISC (subject_label
), 1, 0.5);
167 checkbtn_hbox
= gtk_hbox_new (FALSE
, 8);
168 gtk_widget_show (checkbtn_hbox
);
169 gtk_box_pack_start (GTK_BOX (vbox1
), checkbtn_hbox
, TRUE
, TRUE
, 0);
170 gtk_container_set_border_width (GTK_CONTAINER (checkbtn_hbox
), 8);
172 case_checkbtn
= gtk_check_button_new_with_label (_("Case sensitive"));
173 gtk_widget_show (case_checkbtn
);
174 gtk_box_pack_start (GTK_BOX (checkbtn_hbox
), case_checkbtn
,
178 gtk_check_button_new_with_label (_("Backward search"));
179 gtk_widget_show (backward_checkbtn
);
180 gtk_box_pack_start (GTK_BOX (checkbtn_hbox
), backward_checkbtn
,
184 gtk_check_button_new_with_label (_("Select all matched"));
185 gtk_widget_show (all_checkbtn
);
186 gtk_box_pack_start (GTK_BOX (checkbtn_hbox
), all_checkbtn
,
189 gtkut_button_set_create(&confirm_area
,
190 &search_btn
, _("Search"),
191 &clear_btn
, _("Clear"),
192 &close_btn
, _("Close"));
193 gtk_widget_show (confirm_area
);
194 gtk_box_pack_start (GTK_BOX (vbox1
), confirm_area
, FALSE
, FALSE
, 0);
195 gtk_widget_grab_default(search_btn
);
197 gtk_signal_connect(GTK_OBJECT(search_btn
), "clicked",
198 GTK_SIGNAL_FUNC(summary_search_execute
),
200 gtk_signal_connect(GTK_OBJECT(clear_btn
), "clicked",
201 GTK_SIGNAL_FUNC(summary_search_clear
),
203 gtk_signal_connect_object(GTK_OBJECT(close_btn
), "clicked",
204 GTK_SIGNAL_FUNC(gtk_widget_hide
),
209 #define STRDUP_MBSTOWCS(wcs, s) \
211 wcs = g_malloc((strlen(s) + 1) * sizeof(wchar_t)); \
212 mbstowcs(wcs, s, strlen(s) + 1); \
215 static void summary_search_execute(GtkButton
*button
, gpointer data
)
217 SummaryView
*summaryview
= data
;
218 GtkCTree
*ctree
= GTK_CTREE(summaryview
->ctree
);
224 gboolean all_searched
= FALSE
;
225 gboolean from_matched
;
227 gboolean subj_matched
;
228 wchar_t *wcs_hs
, *fromwcs
, *towcs
, *subjwcs
;
229 wchar_t *(* WCSFindFunc
) (const wchar_t *haystack
,
230 const wchar_t *needle
);
232 case_sens
= gtk_toggle_button_get_active
233 (GTK_TOGGLE_BUTTON(case_checkbtn
));
234 backward
= gtk_toggle_button_get_active
235 (GTK_TOGGLE_BUTTON(backward_checkbtn
));
236 search_all
= gtk_toggle_button_get_active
237 (GTK_TOGGLE_BUTTON(all_checkbtn
));
241 WCSFindFunc
= wcsstr
;
244 WCSFindFunc
= wcswcs
;
246 WCSFindFunc
= wcscasestr
;
248 #endif /* HAVE_WCSSTR */
250 WCSFindFunc
= wcscasestr
;
252 fromwcs
= (wchar_t *)GTK_ENTRY(from_entry
)->text
;
253 towcs
= (wchar_t *)GTK_ENTRY(to_entry
)->text
;
254 subjwcs
= (wchar_t *)GTK_ENTRY(subject_entry
)->text
;
257 gtk_clist_freeze(GTK_CLIST(ctree
));
258 gtk_clist_unselect_all(GTK_CLIST(ctree
));
259 node
= GTK_CTREE_NODE(GTK_CLIST(ctree
)->row_list
);
260 } else if (!summaryview
->selected
) {
262 node
= GTK_CTREE_NODE(GTK_CLIST(ctree
)->row_list_end
);
264 node
= GTK_CTREE_NODE(GTK_CLIST(ctree
)->row_list
);
269 node
= GTK_CTREE_NODE_PREV(summaryview
->selected
);
271 node
= GTK_CTREE_NODE_NEXT(summaryview
->selected
);
280 gtk_clist_thaw(GTK_CLIST(ctree
));
287 _("Search string not found."));
292 str
= _("Beginning of list reached; continue from end?");
294 str
= _("End of list reached; continue from beginning?");
296 val
= alertpanel(_("Search finished"), str
,
297 _("Yes"), _("No"), NULL
);
298 if (G_ALERTDEFAULT
== val
) {
300 node
= GTK_CTREE_NODE
301 (GTK_CLIST(ctree
)->row_list_end
);
303 node
= GTK_CTREE_NODE
304 (GTK_CLIST(ctree
)->row_list
);
308 manage_window_focus_in(window
, NULL
, NULL
);
313 from_matched
= to_matched
= subj_matched
= FALSE
;
315 msginfo
= gtk_ctree_node_get_row_data(ctree
, node
);
317 if (*fromwcs
&& msginfo
->from
) {
318 STRDUP_MBSTOWCS(wcs_hs
, msginfo
->from
);
319 if (WCSFindFunc(wcs_hs
, fromwcs
) != NULL
)
323 if (*towcs
&& msginfo
->to
) {
324 STRDUP_MBSTOWCS(wcs_hs
, msginfo
->to
);
325 if (WCSFindFunc(wcs_hs
, towcs
) != NULL
)
329 if (*subjwcs
&& msginfo
->subject
) {
330 STRDUP_MBSTOWCS(wcs_hs
, msginfo
->subject
);
331 if (WCSFindFunc(wcs_hs
, subjwcs
) != NULL
)
336 if (from_matched
|| to_matched
|| subj_matched
) {
338 gtk_ctree_select(ctree
, node
);
340 gtk_clist_freeze(GTK_CLIST(ctree
));
341 gtk_clist_unselect_all(GTK_CLIST(ctree
));
342 gtk_ctree_select(ctree
, node
);
343 gtk_ctree_node_moveto(ctree
, node
, 0, 0.5, 0);
344 gtkut_ctree_set_focus_row(ctree
, node
);
345 gtk_clist_thaw(GTK_CLIST(ctree
));
350 node
= backward
? GTK_CTREE_NODE_PREV(node
)
351 : GTK_CTREE_NODE_NEXT(node
);
355 static void summary_search_clear(GtkButton
*button
, gpointer data
)
357 gtk_editable_delete_text(GTK_EDITABLE(from_entry
), 0, -1);
358 gtk_editable_delete_text(GTK_EDITABLE(to_entry
), 0, -1);
359 gtk_editable_delete_text(GTK_EDITABLE(subject_entry
), 0, -1);
362 static void from_activated(void)
364 gtk_widget_grab_focus(to_entry
);
367 static void to_activated(void)
369 gtk_widget_grab_focus(subject_entry
);
372 static void subject_activated(void)
374 gtk_button_clicked(GTK_BUTTON(search_btn
));
377 static void key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
379 if (event
&& event
->keyval
== GDK_Escape
)
380 gtk_widget_hide(window
);