diff options
| author | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
| commit | 0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch) | |
| tree | af916a30553c78ce9d4f2d8658656a175c5b6921 /src/message_search.c | |
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/message_search.c')
| -rw-r--r-- | src/message_search.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/src/message_search.c b/src/message_search.c new file mode 100644 index 0000000..29d4737 --- /dev/null +++ b/src/message_search.c | |||
| @@ -0,0 +1,283 @@ | |||
| 1 | /* | ||
| 2 | * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client | ||
| 3 | * Copyright (C) 1999-2014 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 * gtkut_get_dpi_multiplier(), -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 | } | ||
