1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2005-2019 Colin Leroy and The Claws Mail Team
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 3 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, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #include "claws-features.h"
22 #endif
23 
24 #include "defs.h"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkkeysyms.h>
33 
34 #include "prefs_common.h"
35 #include "prefs_gtk.h"
36 
37 #include "gtk/gtkutils.h"
38 #include "gtk/prefswindow.h"
39 #include "combobox.h"
40 #ifndef PASSWORD_CRYPTO_OLD
41 #include "password.h"
42 #include "password_gtk.h"
43 #endif
44 
45 #include "manage_window.h"
46 #ifdef HAVE_LIBETPAN
47 #include "imap-thread.h"
48 #endif
49 
50 typedef struct _OtherPage
51 {
52 	PrefsPage page;
53 
54 	GtkWidget *window;
55 
56 	GtkWidget *checkbtn_addaddrbyclick;
57 	GtkWidget *checkbtn_confonexit;
58 	GtkWidget *checkbtn_cleanonexit;
59 	GtkWidget *checkbtn_askonclean;
60 	GtkWidget *checkbtn_warnqueued;
61 	GtkWidget *spinbtn_iotimeout;
62 	GtkWidget *checkbtn_gtk_enable_accels;
63 	GtkWidget *checkbtn_gtk_can_change_accels;
64 	GtkWidget *checkbtn_askonfilter;
65 	GtkWidget *checkbtn_use_shred;
66 	GtkWidget *checkbtn_real_time_sync;
67 	GtkWidget *flush_metadata_faster_radiobtn;
68 	GtkWidget *flush_metadata_safer_radiobtn;
69 	GtkWidget *checkbtn_transhdr;
70 #ifndef PASSWORD_CRYPTO_OLD
71 	GtkWidget *checkbtn_use_passphrase;
72 #endif
73 } OtherPage;
74 
75 static struct KeybindDialog {
76 	GtkWidget *window;
77 	GtkWidget *combo;
78 } keybind;
79 
80 static void prefs_keybind_select		(void);
81 static gint prefs_keybind_deleted		(GtkWidget	*widget,
82 						 GdkEventAny	*event,
83 						 gpointer	 data);
84 static gboolean prefs_keybind_key_pressed	(GtkWidget	*widget,
85 						 GdkEventKey	*event,
86 						 gpointer	 data);
87 static void prefs_keybind_cancel		(void);
88 static void prefs_keybind_apply_clicked		(GtkWidget	*widget);
89 #ifndef PASSWORD_CRYPTO_OLD
90 static void prefs_change_master_passphrase(GtkButton *button, gpointer data);
91 static void prefs_use_passphrase_toggled(GtkToggleButton *button, gpointer data);
92 #endif
93 
94 
prefs_keybind_select(void)95 static void prefs_keybind_select(void)
96 {
97 	GtkWidget *window;
98 	GtkWidget *vbox1;
99 	GtkWidget *hbox1;
100 	GtkWidget *label;
101 	GtkWidget *combo;
102 	GtkWidget *confirm_area;
103 	GtkWidget *ok_btn;
104 	GtkWidget *cancel_btn;
105 
106 	window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_other");
107 	gtk_container_set_border_width (GTK_CONTAINER (window), 8);
108 	gtk_window_set_title (GTK_WINDOW (window),
109 				_("Choose preset keyboard shortcuts"));
110 	gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
111 	gtk_window_set_modal (GTK_WINDOW (window), TRUE);
112 	gtk_window_set_resizable(GTK_WINDOW (window), FALSE);
113 	gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
114 	manage_window_set_transient (GTK_WINDOW (window));
115 
116 	vbox1 = gtk_vbox_new (FALSE, VSPACING);
117 	gtk_container_add (GTK_CONTAINER (window), vbox1);
118 	gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
119 
120 	hbox1 = gtk_hbox_new (FALSE, 8);
121 	gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
122 
123 	label = gtk_label_new
124 		(_("Select preset:"));
125 	gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
126 	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
127 
128 	combo = combobox_text_new(FALSE,
129 			       _("Default"),
130 			       "Mew / Wanderlust",
131 			       "Mutt",
132 			       NULL);
133 	gtk_box_pack_start (GTK_BOX (hbox1), combo, TRUE, TRUE, 0);
134 
135 	hbox1 = gtk_hbox_new (FALSE, 8);
136 	gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
137 
138 	label = gtk_label_new
139 		(_("You can also modify each menu shortcut by pressing\n"
140 		   "any key(s) when focusing the mouse pointer on the item."));
141 	gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
142 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
143 	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
144 	gtkut_widget_set_small_font_size (label);
145 
146 	hbox1 = gtk_hbox_new (FALSE, 8);
147 	gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
148 
149 	gtkut_stock_button_set_create (&confirm_area, &cancel_btn, GTK_STOCK_CANCEL,
150 				       &ok_btn, GTK_STOCK_OK,
151 				       NULL, NULL);
152 	gtk_box_pack_end (GTK_BOX (hbox1), confirm_area, FALSE, FALSE, 0);
153 	gtk_widget_grab_focus (ok_btn);
154 
155 	MANAGE_WINDOW_SIGNALS_CONNECT(window);
156 	g_signal_connect (G_OBJECT (window), "delete_event",
157 			  G_CALLBACK (prefs_keybind_deleted), NULL);
158 	g_signal_connect (G_OBJECT (window), "key_press_event",
159 			  G_CALLBACK (prefs_keybind_key_pressed), NULL);
160 	g_signal_connect (G_OBJECT (ok_btn), "clicked",
161 			  G_CALLBACK (prefs_keybind_apply_clicked),
162 			  NULL);
163 	g_signal_connect (G_OBJECT (cancel_btn), "clicked",
164 			  G_CALLBACK (prefs_keybind_cancel),
165 			  NULL);
166 
167 	gtk_widget_show_all(window);
168 
169 	keybind.window = window;
170 	keybind.combo = combo;
171 }
172 
prefs_keybind_key_pressed(GtkWidget * widget,GdkEventKey * event,gpointer data)173 static gboolean prefs_keybind_key_pressed(GtkWidget *widget, GdkEventKey *event,
174 					  gpointer data)
175 {
176 	if (event && event->keyval == GDK_KEY_Escape)
177 		prefs_keybind_cancel();
178 	return FALSE;
179 }
180 
prefs_keybind_deleted(GtkWidget * widget,GdkEventAny * event,gpointer data)181 static gint prefs_keybind_deleted(GtkWidget *widget, GdkEventAny *event,
182 				  gpointer data)
183 {
184 	prefs_keybind_cancel();
185 	return TRUE;
186 }
187 
prefs_keybind_cancel(void)188 static void prefs_keybind_cancel(void)
189 {
190 	gtk_widget_destroy(keybind.window);
191 	keybind.window = NULL;
192 	keybind.combo = NULL;
193 }
194 
195 struct KeyBind {
196 	const gchar *accel_path;
197 	const gchar *accel_key;
198 };
199 
prefs_keybind_apply(struct KeyBind keybind[],gint num)200 static void prefs_keybind_apply(struct KeyBind keybind[], gint num)
201 {
202 	gint i;
203 	guint key;
204 	GdkModifierType mods;
205 
206 	for (i = 0; i < num; i++) {
207 		const gchar *accel_key
208 			= keybind[i].accel_key ? keybind[i].accel_key : "";
209 		gtk_accelerator_parse(accel_key, &key, &mods);
210 		if (key == 0 && mods == 0) {
211 			g_message("Failed parsing accelerator '%s' for path '%s'\n",
212 				  accel_key, keybind[i].accel_path);
213 		}
214 		gtk_accel_map_change_entry(keybind[i].accel_path,
215 					   key, mods, TRUE);
216 	}
217 }
218 
prefs_keybind_apply_clicked(GtkWidget * widget)219 static void prefs_keybind_apply_clicked(GtkWidget *widget)
220 {
221 	gchar *text;
222 	struct KeyBind *menurc;
223 	gint n_menurc;
224 
225 	static struct KeyBind default_menurc[] = {
226 		/* main */
227 		{"<Actions>/Menu/File/EmptyTrashes",			"<shift>D"},
228 		{"<Actions>/Menu/File/SaveAs",				"<control>S"},
229 		{"<Actions>/Menu/File/Print",				"<control>P"},
230 		{"<Actions>/Menu/File/OfflineMode",			"<control>W"},
231 		{"<Actions>/Menu/File/SynchroniseFolders",		"<control><shift>S"},
232 		{"<Actions>/Menu/File/Exit",				"<control>Q"},
233 
234 		{"<Actions>/Menu/Edit/Copy",				"<control>C"},
235 		{"<Actions>/Menu/Edit/SelectAll",			"<control>A"},
236 		{"<Actions>/Menu/Edit/Find",				"<control>F"},
237 		{"<Actions>/Menu/Edit/SearchFolder",			"<shift><control>F"},
238 		{"<Actions>/Menu/Edit/QuickSearch",			"slash"},
239 
240 		{"<Actions>/Menu/View/ShowHide/MessageView",		"V"},
241 		{"<Actions>/Menu/View/ThreadView",			"<control>T"},
242 		{"<Actions>/Menu/View/Goto/Prev",			"P"},
243 		{"<Actions>/Menu/View/Goto/Next",			"N"},
244 		{"<Actions>/Menu/View/Goto/PrevUnread",			"<shift>P"},
245 		{"<Actions>/Menu/View/Goto/NextUnread",			"<shift>N"},
246 		{"<Actions>/Menu/View/Goto/Folder",			"G"},
247 		{"<Actions>/Menu/View/OpenNewWindow",			"<control><alt>N"},
248 		{"<Actions>/Menu/View/MessageSource",			"<control>U"},
249 		{"<Actions>/Menu/View/AllHeaders",			"<control>H"},
250 		{"<Actions>/Menu/View/UpdateSummary",			"<control><alt>U"},
251 
252 		{"<Actions>/Menu/Message/Receive/CurrentAccount",
253 									"<control>I"},
254 		{"<Actions>/Menu/Message/Receive/AllAccounts",		"<shift><control>I"},
255 		{"<Actions>/Menu/Message/ComposeEmail",			"<control>M"},
256 		{"<Actions>/Menu/Message/Reply",			"<control>R"},
257 		{"<Actions>/Menu/Message/ReplyTo/All",			"<shift><control>R"},
258 		{"<Actions>/Menu/Message/ReplyTo/Sender",		""},
259 		{"<Actions>/Menu/Message/ReplyTo/List",			"<control>L"},
260 		{"<Actions>/Menu/Message/Forward",			"<control><alt>F"},
261 		{"<Actions>/Menu/Message/Move",				"<control>O"},
262 		{"<Actions>/Menu/Message/Copy",				"<shift><control>O"},
263 		{"<Actions>/Menu/Message/Trash",			"<control>D"},
264 		{"<Actions>/Menu/Message/Mark/Mark",			"<shift>asterisk"},
265 		{"<Actions>/Menu/Message/Mark/Unmark",			"U"},
266 		{"<Actions>/Menu/Message/Mark/MarkUnread",		"<shift>exclam"},
267 		{"<Actions>/Menu/Message/Mark/MarkRead",		""},
268 
269 		{"<Actions>/Menu/Tools/AddressBook",			"<shift><control>A"},
270 		{"<Actions>/Menu/Tools/Execute",			"X"},
271 		{"<Actions>/Menu/Tools/NetworkLog",			"<shift><control>L"},
272 		/* compose */
273 		{"<Actions>/Menu/Message/Send",				"<control>Return"},
274 		{"<Actions>/Menu/Message/SendLater",			"<shift><control>S"},
275 		{"<Actions>/Menu/Message/AttachFile",			"<control>M"},
276 		{"<Actions>/Menu/Message/InsertFile",			"<control>I"},
277 		{"<Actions>/Menu/Message/InsertSig",			"<control>G"},
278 		{"<Actions>/Menu/Message/Save",				"<control>S"},
279 		{"<Actions>/Menu/Message/Close",			"<control>W"},
280 		{"<Actions>/Menu/Edit/Undo",				"<control>Z"},
281 		{"<Actions>/Menu/Edit/Redo",				"<control>Y"},
282 		{"<Actions>/Menu/Edit/Cut",				"<control>X"},
283 		{"<Actions>/Menu/Edit/Copy",				"<control>C"},
284 		{"<Actions>/Menu/Edit/Paste",				"<control>V"},
285 		{"<Actions>/Menu/Edit/SelectAll",			"<control>A"},
286 		{"<Actions>/Menu/Edit/Advanced/BackChar",		"<control>B"},
287 		{"<Actions>/Menu/Edit/Advanced/ForwChar",		"<control>F"},
288 		{"<Actions>/Menu/Edit/Advanced/BackWord",		""},
289 		{"<Actions>/Menu/Edit/Advanced/ForwWord",		""},
290 		{"<Actions>/Menu/Edit/Advanced/BegLine",		""},
291 		{"<Actions>/Menu/Edit/Advanced/EndLine",		"<control>E"},
292 		{"<Actions>/Menu/Edit/Advanced/PrevLine",		"<control>P"},
293 		{"<Actions>/Menu/Edit/Advanced/NextLine",		"<control>N"},
294 		{"<Actions>/Menu/Edit/Advanced/DelBackChar",		"<control>H"},
295 		{"<Actions>/Menu/Edit/Advanced/DelForwChar",		"<control>D"},
296 		{"<Actions>/Menu/Edit/Advanced/DelBackWord",		""},
297 		{"<Actions>/Menu/Edit/Advanced/DelForwWord",		""},
298 		{"<Actions>/Menu/Edit/Advanced/DelLine",		"<control>U"},
299 		{"<Actions>/Menu/Edit/Advanced/DelEndLine",		"<control>K"},
300 		{"<Actions>/Menu/Edit/WrapPara",			"<control>L"},
301 		{"<Actions>/Menu/Edit/WrapAllLines",			"<control><alt>L"},
302 		{"<Actions>/Menu/Edit/AutoWrap",			"<shift><control>L"},
303 		{"<Actions>/Menu/Edit/ExtEditor",			"<shift><control>X"},
304 		{"<Actions>/Menu/Tools/AddressBook",			"<shift><control>A"},
305 	};
306 
307 	static struct KeyBind mew_wl_menurc[] = {
308 		/* main */
309 		{"<Actions>/Menu/File/EmptyTrashes",			"<shift>D"},
310 		{"<Actions>/Menu/File/SaveAs",				"Y"},
311 		{"<Actions>/Menu/File/Print",				"<control>numbersign"},
312 		{"<Actions>/Menu/File/Exit",				"<shift>Q"},
313 
314 		{"<Actions>/Menu/Edit/Copy",				"<control>C"},
315 		{"<Actions>/Menu/Edit/SelectAll",			"<control>A"},
316 		{"<Actions>/Menu/Edit/Find",				"<control>F"},
317 		{"<Actions>/Menu/Edit/SearchFolder",			"<control>S"},
318 		{"<Actions>/Menu/Edit/QuickSearch",			"slash"},
319 
320 		{"<Actions>/Menu/View/ShowHide/MessageView",		""},
321 		{"<Actions>/Menu/View/ThreadView",			"<shift>T"},
322 		{"<Actions>/Menu/View/Goto/Prev",			"P"},
323 		{"<Actions>/Menu/View/Goto/Next",			"N"},
324 		{"<Actions>/Menu/View/Goto/PrevUnread",			"<shift>P"},
325 		{"<Actions>/Menu/View/Goto/NextUnread",			"<shift>N"},
326 		{"<Actions>/Menu/View/Goto/Folder",			"G"},
327 		{"<Actions>/Menu/View/OpenNewWindow",			"<control><alt>N"},
328 		{"<Actions>/Menu/View/MessageSource",			"<control>U"},
329 		{"<Actions>/Menu/View/AllHeaders",			"<shift>H"},
330 		{"<Actions>/Menu/View/UpdateSummary",			"<shift>S"},
331 
332 		{"<Actions>/Menu/Message/Receive/CurrentAccount",
333 									"<control>I"},
334 		{"<Actions>/Menu/Message/Receive/AllAccounts",		"<shift><control>I"},
335 		{"<Actions>/Menu/Message/ComposeEmail",			"W"},
336 		{"<Actions>/Menu/Message/Reply",			"<control>R"},
337 		{"<Actions>/Menu/Message/ReplyTo/All",			"<shift>A"},
338 		{"<Actions>/Menu/Message/ReplyTo/Sender",		""},
339 		{"<Actions>/Menu/Message/ReplyTo/List",			"<control>L"},
340 		{"<Actions>/Menu/Message/Forward",			"F"},
341 		{"<Actions>/Menu/Message/Move",				"O"},
342 		{"<Actions>/Menu/Message/Copy",				"<shift>O"},
343 		{"<Actions>/Menu/Message/Trash",			"D"},
344 		{"<Actions>/Menu/Message/Mark/Mark",			"<shift>asterisk"},
345 		{"<Actions>/Menu/Message/Mark/Unmark",			"U"},
346 		{"<Actions>/Menu/Message/Mark/MarkUnread",		"<shift>exclam"},
347 		{"<Actions>/Menu/Message/Mark/MarkRead",		"<shift>R"},
348 
349 		{"<Actions>/Menu/Tools/AddressBook",			"<shift><control>A"},
350 		{"<Actions>/Menu/Tools/Execute",			"X"},
351 		{"<Actions>/Menu/Tools/NetworkLog",			"<shift><control>L"},
352 		/* compose */
353 		{"<Actions>/Menu/Message/Close",			"<alt>W"},
354 		{"<Actions>/Menu/Edit/SelectAll",			""},
355 		{"<Actions>/Menu/Edit/Advanced/BackChar",		"<alt>B"},
356 		{"<Actions>/Menu/Edit/Advanced/ForwChar",		"<alt>F"},
357 		{"<Actions>/Menu/Edit/Advanced/BackWord",		""},
358 		{"<Actions>/Menu/Edit/Advanced/ForwWord",		""},
359 		{"<Actions>/Menu/Edit/Advanced/BegLine",		"<control>A"},
360 		{"<Actions>/Menu/Edit/Advanced/DelBackWord",		"<control>W"},
361 		{"<Actions>/Menu/Edit/Advanced/DelForwWord",		"<alt>D"},
362 	};
363 
364 	static struct KeyBind mutt_menurc[] = {
365 		/* main */
366 		{"<Actions>/Menu/File/SaveAs",				"S"}, /* save-message */
367 		{"<Actions>/Menu/File/Print",				"P"}, /* print-message */
368 		{"<Actions>/Menu/File/Exit",				"Q"}, /* quit */
369 
370 		{"<Actions>/Menu/Edit/Copy",				"<control>C"}, /* - */
371 		{"<Actions>/Menu/Edit/SelectAll",			"<control>A"}, /* - */
372 		{"<Actions>/Menu/Edit/Find",				"<alt>B"}, /* <esc>B: search in message bodies */
373 		{"<Actions>/Menu/Edit/SearchFolder",			"slash"}, /* search */
374 		{"<Actions>/Menu/Edit/QuickSearch",			"L"}, /* limit */
375 
376 		{"<Actions>/Menu/View/ShowHide/MessageView",		"V"}, /* - */
377 		{"<Actions>/Menu/View/ThreadView",			"<control>T"}, /* - */
378 		{"<Actions>/Menu/View/Goto/Prev",			"K"}, /* previous-entry */
379 		{"<Actions>/Menu/View/Goto/Next",			"J"}, /* next-entry */
380 		{"<Actions>/Menu/View/Goto/PrevUnread",			"<alt>U"}, /* <esc>Tab: previous-new-then-unread */
381 		{"<Actions>/Menu/View/Goto/NextUnread",			"U"}, /* Tab: next-new-then-unread */
382 		{"<Actions>/Menu/View/Goto/Folder",			"C"}, /* change-folder */
383 		{"<Actions>/Menu/View/OpenNewWindow",			"<control><alt>N"}, /* - */
384 		{"<Actions>/Menu/View/MessageSource",			"E"}, /* edit the raw message */
385 		{"<Actions>/Menu/View/AllHeaders",			"H"}, /* display-toggle-weed */
386 		{"<Actions>/Menu/View/UpdateSummary",			"<control><alt>U"}, /* - */
387 
388 		{"<Actions>/Menu/Message/Receive/CurrentAccount",	"<control>I"}, /* - */
389 		{"<Actions>/Menu/Message/Receive/AllAccounts",		"<shift>G"}, /* fetch-mail */
390 		{"<Actions>/Menu/Message/ComposeEmail",			"M"}, /* mail */
391 		{"<Actions>/Menu/Message/Reply",			"R"}, /* reply */
392 		{"<Actions>/Menu/Message/ReplyTo/All",			"G"}, /* group-reply */
393 		{"<Actions>/Menu/Message/ReplyTo/List",			"<shift>L"}, /* list-reply */
394 		{"<Actions>/Menu/Message/Forward",			"F"}, /* forward-message */
395 		{"<Actions>/Menu/Message/Move",				"<control>O"}, /* - */
396 		{"<Actions>/Menu/Message/Copy",				"<shift>C"}, /* copy-message */
397 		{"<Actions>/Menu/Message/Trash",			"D"}, /* delete-message */
398 		{"<Actions>/Menu/Message/Mark/Mark",			"<shift>F"}, /* flag-message */
399 		{"<Actions>/Menu/Message/Mark/Unmark",			"<control><shift>F"}, /* - */
400 		{"<Actions>/Menu/Message/Mark/MarkUnread",		"<shift>N"}, /* toggle-new */
401 		{"<Actions>/Menu/Message/Mark/MarkRead",		"<control>R"}, /* read-thread */
402 
403 		{"<Actions>/Menu/Tools/AddressBook",			"<shift><control>A"}, /* - */
404 		{"<Actions>/Menu/Tools/Execute",			"dollar"}, /* sync-mailbox */
405 		{"<Actions>/Menu/Tools/NetworkLog",			"<shift><control>L"}, /* - */
406 		/* compose */
407 		{"<Actions>/Menu/Message/Close",			"<alt>W"}, /* - */
408 		{"<Actions>/Menu/Edit/Advanced/BackWord",		"<alt>B"}, /* - */
409 		{"<Actions>/Menu/Edit/Advanced/ForwWord",		"<alt>F"}, /* - */
410 		{"<Actions>/Menu/Edit/Advanced/BegLine",		"<control>A"}, /* - */
411 		{"<Actions>/Menu/Edit/Advanced/DelBackWord",		"<control>W"}, /* - */
412 		{"<Actions>/Menu/Edit/Advanced/DelForwWord",		"<alt>D"}, /* - */
413 	};
414 
415 	text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keybind.combo));
416 
417 	if (!strcmp(text, _("Default"))) {
418 		menurc = default_menurc;
419 		n_menurc = G_N_ELEMENTS(default_menurc);
420 	} else if (!strcmp(text, "Mew / Wanderlust")) {
421 		menurc = mew_wl_menurc;
422 		n_menurc = G_N_ELEMENTS(mew_wl_menurc);
423 	} else if (!strcmp(text, "Mutt")) {
424 		menurc = mutt_menurc;
425 		n_menurc = G_N_ELEMENTS(mutt_menurc);
426 	} else {
427 		g_free(text);
428 		return;
429 	}
430 	g_free(text);
431 
432 	prefs_keybind_apply(menurc, n_menurc);
433 
434 	gtk_widget_destroy(keybind.window);
435 	keybind.window = NULL;
436 	keybind.combo = NULL;
437 }
438 
prefs_other_create_widget(PrefsPage * _page,GtkWindow * window,gpointer data)439 static void prefs_other_create_widget(PrefsPage *_page, GtkWindow *window,
440 			       	  gpointer data)
441 {
442 	OtherPage *prefs_other = (OtherPage *) _page;
443 
444 	GtkWidget *vbox1;
445 	GtkWidget *hbox1;
446 
447 	GtkWidget *frame_addr;
448 	GtkWidget *vbox_addr;
449 	GtkWidget *checkbtn_addaddrbyclick;
450 
451 	GtkWidget *frame_exit;
452 	GtkWidget *vbox_exit;
453 	GtkWidget *checkbtn_confonexit;
454 	GtkWidget *checkbtn_cleanonexit;
455 	GtkWidget *checkbtn_warnqueued;
456 
457 	GtkWidget *frame_keys;
458 	GtkWidget *vbox_keys;
459 	GtkWidget *checkbtn_gtk_enable_accels;
460 	GtkWidget *checkbtn_gtk_can_change_accels;
461 	GtkWidget *button_keybind;
462 
463 	GtkWidget *label_iotimeout;
464 	GtkWidget *spinbtn_iotimeout;
465 	GtkAdjustment *spinbtn_iotimeout_adj;
466 
467 	GtkWidget *vbox2;
468 	GtkWidget *checkbtn_transhdr;
469 	GtkWidget *checkbtn_askonclean;
470 	GtkWidget *checkbtn_askonfilter;
471 	GtkWidget *checkbtn_use_shred;
472 	GtkWidget *checkbtn_real_time_sync;
473 
474 	GtkWidget *frame_metadata;
475 	GtkWidget *vbox_metadata;
476 	GtkWidget *metadata_label;
477 	GtkWidget *flush_metadata_faster_radiobtn;
478 	GtkWidget *flush_metadata_safer_radiobtn;
479 
480 #ifndef PASSWORD_CRYPTO_OLD
481 	GtkWidget *vbox_passphrase;
482 	GtkWidget *frame_passphrase;
483 	GtkWidget *checkbtn_use_passphrase;
484 	GtkWidget *button_change_passphrase;
485 #endif
486 
487 	gchar *shred_binary = NULL;
488 
489 	vbox1 = gtk_vbox_new (FALSE, VSPACING);
490 	gtk_widget_show (vbox1);
491 	gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
492 
493 	vbox_addr = gtkut_get_options_frame(vbox1, &frame_addr, _("Address book"));
494 
495 	PACK_CHECK_BUTTON
496 		(vbox_addr, checkbtn_addaddrbyclick,
497 		 _("Add address to destination when double-clicked"));
498 
499 	/* On Exit */
500 	vbox_exit = gtkut_get_options_frame(vbox1, &frame_exit, _("On exit"));
501 
502 	PACK_CHECK_BUTTON (vbox_exit, checkbtn_confonexit,
503 			   _("Confirm on exit"));
504 
505 	hbox1 = gtk_hbox_new (FALSE, 32);
506 	gtk_widget_show (hbox1);
507 	gtk_box_pack_start (GTK_BOX (vbox_exit), hbox1, FALSE, FALSE, 0);
508 
509 	PACK_CHECK_BUTTON (hbox1, checkbtn_cleanonexit,
510 			   _("Empty trash on exit"));
511 
512 	PACK_CHECK_BUTTON (vbox_exit, checkbtn_warnqueued,
513 			   _("Warn if there are queued messages"));
514 
515 	vbox_keys = gtkut_get_options_frame(vbox1, &frame_keys, _("Keyboard shortcuts"));
516 
517 	PACK_CHECK_BUTTON(vbox_keys, checkbtn_gtk_enable_accels,
518 			_("Enable keyboard shortcuts"));
519 
520 	PACK_CHECK_BUTTON(vbox_keys, checkbtn_gtk_can_change_accels,
521 			_("Enable customisable keyboard shortcuts"));
522 
523 	CLAWS_SET_TIP(checkbtn_gtk_can_change_accels,
524 			_("If checked, you can change the keyboard shortcuts of "
525 				"most of the menu items by focusing on the menu "
526 				"item and pressing a key combination.\n"
527 				"Uncheck this option if you want to lock all "
528 				"existing keyboard shortcuts."));
529 
530 	button_keybind = gtk_button_new_with_label(
531 				_(" Choose preset keyboard shortcuts... "));
532 	gtk_widget_show (button_keybind);
533 	hbox1 = gtk_hbox_new (FALSE, 8);
534 	gtk_widget_show (hbox1);
535 	gtk_box_pack_start (GTK_BOX (vbox_keys), hbox1, FALSE, FALSE, 0);
536 	gtk_box_pack_start (GTK_BOX (hbox1), button_keybind, FALSE, FALSE, 0);
537 	g_signal_connect (G_OBJECT (button_keybind), "clicked",
538 			  G_CALLBACK (prefs_keybind_select), NULL);
539 
540 
541 	vbox_metadata = gtkut_get_options_frame(vbox1, &frame_metadata, _("Metadata handling"));
542 	metadata_label = gtk_label_new(_("Safer mode asks the OS to write metadata to disk directly;\n"
543 					 "it avoids data loss after crashes but can take some time."));
544 	gtk_misc_set_alignment(GTK_MISC(metadata_label), 0, 0);
545 	gtk_box_pack_start (GTK_BOX (vbox_metadata), metadata_label, FALSE, FALSE, 0);
546 	flush_metadata_safer_radiobtn = gtk_radio_button_new_with_label(NULL, _("Safer"));
547 	flush_metadata_faster_radiobtn = gtk_radio_button_new_with_label_from_widget(
548 					   GTK_RADIO_BUTTON(flush_metadata_safer_radiobtn), _("Faster"));
549 	hbox1 = gtk_hbox_new (FALSE, 8);
550 	gtk_widget_show (hbox1);
551 	gtk_box_pack_start (GTK_BOX (vbox_metadata), hbox1, FALSE, FALSE, 0);
552 	gtk_box_pack_start (GTK_BOX (hbox1), flush_metadata_safer_radiobtn, FALSE, FALSE, 0);
553 	gtk_box_pack_start (GTK_BOX (hbox1), flush_metadata_faster_radiobtn, FALSE, FALSE, 0);
554 
555 	if (prefs_common.flush_metadata)
556 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(flush_metadata_safer_radiobtn), TRUE);
557 	else
558 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(flush_metadata_faster_radiobtn), TRUE);
559 
560 	gtk_widget_show_all(frame_metadata);
561 
562 	hbox1 = gtk_hbox_new (FALSE, 8);
563 	gtk_widget_show (hbox1);
564 	gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
565 
566 	label_iotimeout = gtk_label_new (_("Socket I/O timeout"));
567 	gtk_widget_show (label_iotimeout);
568 	gtk_box_pack_start (GTK_BOX (hbox1), label_iotimeout, FALSE, FALSE, 0);
569 
570 	spinbtn_iotimeout_adj = GTK_ADJUSTMENT(gtk_adjustment_new (60, 0, 1000, 1, 10, 0));
571 	spinbtn_iotimeout = gtk_spin_button_new
572 		(GTK_ADJUSTMENT (spinbtn_iotimeout_adj), 1, 0);
573 	gtk_widget_show (spinbtn_iotimeout);
574 	gtk_box_pack_start (GTK_BOX (hbox1), spinbtn_iotimeout,
575 			    FALSE, FALSE, 0);
576 	gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbtn_iotimeout), TRUE);
577 
578 	label_iotimeout = gtk_label_new (_("seconds"));
579 	gtk_widget_show (label_iotimeout);
580 	gtk_box_pack_start (GTK_BOX (hbox1), label_iotimeout, FALSE, FALSE, 0);
581 
582 	vbox2 = gtk_vbox_new (FALSE, 8);
583 	gtk_widget_show (vbox2);
584 	gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, FALSE, 0);
585 
586 	PACK_CHECK_BUTTON(vbox2, checkbtn_transhdr,
587 			   _("Translate header names"));
588 	CLAWS_SET_TIP(checkbtn_transhdr,
589 			     _("The display of standard headers (such as 'From:', 'Subject:') "
590 			     "will be translated into your language."));
591 	PACK_CHECK_BUTTON (vbox2, checkbtn_askonclean,
592 			   _("Ask before emptying trash"));
593 	PACK_CHECK_BUTTON (vbox2, checkbtn_askonfilter,
594 			   _("Ask about account specific filtering rules when "
595 			     "filtering manually"));
596 	shred_binary = g_find_program_in_path("shred");
597 	if (shred_binary) {
598 		PACK_CHECK_BUTTON (vbox2, checkbtn_use_shred,
599 				   _("Use secure file deletion if possible"));
600 		g_free(shred_binary);
601 	} else {
602 		PACK_CHECK_BUTTON (vbox2, checkbtn_use_shred,
603 				   _("Use secure file deletion if possible\n"
604 				     "(the 'shred' program is not available)"));
605 		gtk_widget_set_sensitive(checkbtn_use_shred, FALSE);
606 	}
607 	CLAWS_SET_TIP(checkbtn_use_shred,
608 			_("Use the 'shred' program to overwrite files with random data before "
609 			  "deleting them. This slows down deletion. Be sure to "
610 			  "read shred's man page for caveats."));
611 	PACK_CHECK_BUTTON (vbox2, checkbtn_real_time_sync,
612 			   _("Synchronise offline folders as soon as possible"));
613 
614 #ifndef PASSWORD_CRYPTO_OLD
615 	vbox_passphrase = gtkut_get_options_frame(vbox1, &frame_passphrase, _("Master passphrase"));
616 
617 	PACK_CHECK_BUTTON(vbox_passphrase, checkbtn_use_passphrase,
618 			_("Use a master passphrase"));
619 
620 	CLAWS_SET_TIP(checkbtn_use_passphrase,
621 			_("If checked, your saved account passwords will be protected "
622 				"by a master passphrase. If no master passphrase is set, "
623 				"you will be prompted to set one."));
624 
625 	button_change_passphrase = gtk_button_new_with_label(
626 			_("Change master passphrase"));
627 	gtk_widget_show (button_change_passphrase);
628 	hbox1 = gtk_hbox_new (FALSE, 8);
629 	gtk_widget_show (hbox1);
630 	gtk_box_pack_start (GTK_BOX (vbox_passphrase), hbox1, FALSE, FALSE, 0);
631 	gtk_box_pack_start (GTK_BOX (hbox1), button_change_passphrase,
632 			FALSE, FALSE, 0);
633 	g_signal_connect (G_OBJECT (checkbtn_use_passphrase), "toggled",
634 				G_CALLBACK (prefs_use_passphrase_toggled), button_change_passphrase);
635 	g_signal_connect (G_OBJECT (button_change_passphrase), "clicked",
636 			  G_CALLBACK (prefs_change_master_passphrase), NULL);
637 #endif
638 	SET_TOGGLE_SENSITIVITY(checkbtn_gtk_enable_accels, checkbtn_gtk_can_change_accels);
639 	SET_TOGGLE_SENSITIVITY(checkbtn_gtk_enable_accels, button_keybind);
640 
641 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_addaddrbyclick),
642 		prefs_common.add_address_by_click);
643 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_confonexit),
644 		prefs_common.confirm_on_exit);
645 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_cleanonexit),
646 		prefs_common.clean_on_exit);
647 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_askonclean),
648 		prefs_common.ask_on_clean);
649 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_warnqueued),
650 		prefs_common.warn_queued_on_exit);
651 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_gtk_enable_accels),
652 		prefs_common.gtk_enable_accels);
653 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_gtk_can_change_accels),
654 		prefs_common.gtk_can_change_accels);
655 
656 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbtn_iotimeout),
657 		prefs_common.io_timeout_secs);
658 
659 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_transhdr),
660 		prefs_common.trans_hdr);
661 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_askonfilter),
662 		prefs_common.ask_apply_per_account_filtering_rules);
663 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_use_shred),
664 		prefs_common.use_shred);
665 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_real_time_sync),
666 		prefs_common.real_time_sync);
667 
668 #ifndef PASSWORD_CRYPTO_OLD
669 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_use_passphrase),
670 		prefs_common.use_master_passphrase);
671 	gtk_widget_set_sensitive(button_change_passphrase,
672 			prefs_common.use_master_passphrase);
673 #endif
674 
675 	prefs_other->checkbtn_addaddrbyclick = checkbtn_addaddrbyclick;
676 	prefs_other->checkbtn_confonexit = checkbtn_confonexit;
677 	prefs_other->checkbtn_cleanonexit = checkbtn_cleanonexit;
678 	prefs_other->checkbtn_askonclean = checkbtn_askonclean;
679 	prefs_other->checkbtn_warnqueued = checkbtn_warnqueued;
680 	prefs_other->spinbtn_iotimeout = spinbtn_iotimeout;
681 	prefs_other->checkbtn_transhdr = checkbtn_transhdr;
682 	prefs_other->checkbtn_gtk_enable_accels = checkbtn_gtk_enable_accels;
683 	prefs_other->checkbtn_gtk_can_change_accels = checkbtn_gtk_can_change_accels;
684 	prefs_other->checkbtn_askonfilter = checkbtn_askonfilter;
685 	prefs_other->checkbtn_use_shred = checkbtn_use_shred;
686 	prefs_other->checkbtn_real_time_sync = checkbtn_real_time_sync;
687 	prefs_other->flush_metadata_safer_radiobtn = flush_metadata_safer_radiobtn;
688 	prefs_other->flush_metadata_faster_radiobtn = flush_metadata_faster_radiobtn;
689 #ifndef PASSWORD_CRYPTO_OLD
690 	prefs_other->checkbtn_use_passphrase = checkbtn_use_passphrase;
691 #endif
692 	prefs_other->page.widget = vbox1;
693 }
694 
prefs_other_save(PrefsPage * _page)695 static void prefs_other_save(PrefsPage *_page)
696 {
697 	OtherPage *page = (OtherPage *) _page;
698 	gboolean gtk_enable_accels;
699 	gboolean gtk_can_change_accels;
700 
701 	prefs_common.add_address_by_click = gtk_toggle_button_get_active(
702 		GTK_TOGGLE_BUTTON(page->checkbtn_addaddrbyclick));
703 	prefs_common.confirm_on_exit = gtk_toggle_button_get_active(
704 		GTK_TOGGLE_BUTTON(page->checkbtn_confonexit));
705 	prefs_common.clean_on_exit = gtk_toggle_button_get_active(
706 		GTK_TOGGLE_BUTTON(page->checkbtn_cleanonexit));
707 	prefs_common.ask_on_clean = gtk_toggle_button_get_active(
708 		GTK_TOGGLE_BUTTON(page->checkbtn_askonclean));
709 	prefs_common.warn_queued_on_exit = gtk_toggle_button_get_active(
710 		GTK_TOGGLE_BUTTON(page->checkbtn_warnqueued));
711 	prefs_common.io_timeout_secs = gtk_spin_button_get_value_as_int(
712 		GTK_SPIN_BUTTON(page->spinbtn_iotimeout));
713 	prefs_common.flush_metadata = gtk_toggle_button_get_active(
714 		GTK_TOGGLE_BUTTON(page->flush_metadata_safer_radiobtn));
715 	sock_set_io_timeout(prefs_common.io_timeout_secs);
716 #ifdef HAVE_LIBETPAN
717 	imap_main_set_timeout(prefs_common.io_timeout_secs);
718 #endif
719 	prefs_common.trans_hdr = gtk_toggle_button_get_active(
720 			GTK_TOGGLE_BUTTON(page->checkbtn_transhdr));
721 	prefs_common.ask_apply_per_account_filtering_rules =
722 		gtk_toggle_button_get_active(
723 			GTK_TOGGLE_BUTTON(page->checkbtn_askonfilter));
724 	prefs_common.use_shred =
725 		gtk_toggle_button_get_active(
726 			GTK_TOGGLE_BUTTON(page->checkbtn_use_shred));
727 	prefs_common.real_time_sync =
728 		gtk_toggle_button_get_active(
729 			GTK_TOGGLE_BUTTON(page->checkbtn_real_time_sync));
730 
731 #ifndef PASSWORD_CRYPTO_OLD
732 	/* If we're disabling use of master passphrase, we need to reencrypt
733 	 * all account passwords with hardcoded key. */
734 	if (!gtk_toggle_button_get_active(
735 			GTK_TOGGLE_BUTTON(page->checkbtn_use_passphrase))
736 			&& master_passphrase_is_set()) {
737 		master_passphrase_change(NULL, NULL);
738 
739 		/* In case user did not finish the passphrase change process
740 		 * (e.g. did not enter a correct current master passphrase),
741 		 * we need to enable the "use master passphrase" checkbox again,
742 		 * since the old master passphrase is still valid. */
743 		if (master_passphrase_is_set()) {
744 			gtk_toggle_button_set_active(
745 				GTK_TOGGLE_BUTTON(page->checkbtn_use_passphrase), TRUE);
746 		}
747 	}
748 
749 	if (gtk_toggle_button_get_active(
750 			GTK_TOGGLE_BUTTON(page->checkbtn_use_passphrase))
751 			&& !master_passphrase_is_set()) {
752 		master_passphrase_change_dialog();
753 
754 		/* In case user cancelled the passphrase change dialog, we need
755 		 * to disable the "use master passphrase" checkbox. */
756 		if (!master_passphrase_is_set()) {
757 			gtk_toggle_button_set_active(
758 				GTK_TOGGLE_BUTTON(page->checkbtn_use_passphrase), FALSE);
759 		}
760 	}
761 
762 	prefs_common.use_master_passphrase =
763 		gtk_toggle_button_get_active(
764 			GTK_TOGGLE_BUTTON(page->checkbtn_use_passphrase));
765 #endif
766 
767 	gtk_can_change_accels = gtk_toggle_button_get_active(
768 		GTK_TOGGLE_BUTTON(page->checkbtn_gtk_can_change_accels));
769 
770 	if (prefs_common.gtk_can_change_accels != gtk_can_change_accels) {
771 
772 		prefs_common.gtk_can_change_accels = gtk_can_change_accels;
773 
774 		gtk_settings_set_long_property(gtk_settings_get_default(),
775 				"gtk-can-change-accels",
776 				(glong)prefs_common.gtk_can_change_accels,
777 				"XProperty");
778 	}
779 	gtk_enable_accels = gtk_toggle_button_get_active(
780 		GTK_TOGGLE_BUTTON(page->checkbtn_gtk_enable_accels));
781 
782 	if (prefs_common.gtk_enable_accels != gtk_enable_accels) {
783 		prefs_common.gtk_enable_accels = gtk_enable_accels;
784 
785 		gtk_settings_set_long_property(gtk_settings_get_default(),
786 				"gtk-enable-accels",
787 				(glong)prefs_common.gtk_enable_accels,
788 				"XProperty");
789 
790 		gtk_settings_set_long_property(gtk_settings_get_default(),
791 				"gtk-enable-mnemonics",
792 				(glong)prefs_common.gtk_enable_accels,
793 				"XProperty");
794 	}
795 
796 	if (prefs_common.gtk_enable_accels != gtk_enable_accels ||
797 	    prefs_common.gtk_can_change_accels != gtk_can_change_accels) {
798 		/* gtk_can_change_accels value changed : we have (only if changed)
799 		 * to apply the gtk property to all widgets : */
800 		gtk_rc_reparse_all_for_settings(gtk_settings_get_default(), TRUE);
801 	}
802 }
803 
prefs_other_destroy_widget(PrefsPage * _page)804 static void prefs_other_destroy_widget(PrefsPage *_page)
805 {
806 }
807 
808 OtherPage *prefs_other;
809 
prefs_other_init(void)810 void prefs_other_init(void)
811 {
812 	OtherPage *page;
813 	static gchar *path[3];
814 
815 	path[0] = _("Other");
816 	path[1] = _("Miscellaneous");
817 	path[2] = NULL;
818 
819 	page = g_new0(OtherPage, 1);
820 	page->page.path = path;
821 	page->page.create_widget = prefs_other_create_widget;
822 	page->page.destroy_widget = prefs_other_destroy_widget;
823 	page->page.save_page = prefs_other_save;
824 	page->page.weight = 5.0;
825 	prefs_gtk_register_page((PrefsPage *) page);
826 	prefs_other = page;
827 
828 	gtk_settings_set_long_property(gtk_settings_get_default(),
829 			"gtk-can-change-accels",
830 			(glong)prefs_common.gtk_can_change_accels,
831 			"XProperty");
832 	gtk_settings_set_long_property(gtk_settings_get_default(),
833 			"gtk-enable-accels",
834 			(glong)prefs_common.gtk_enable_accels,
835 			"XProperty");
836 	gtk_settings_set_long_property(gtk_settings_get_default(),
837 			"gtk-enable-mnemonics",
838 			(glong)prefs_common.gtk_enable_accels,
839 			"XProperty");
840 }
841 
prefs_other_done(void)842 void prefs_other_done(void)
843 {
844 	prefs_gtk_unregister_page((PrefsPage *) prefs_other);
845 	g_free(prefs_other);
846 }
847 
848 #ifndef PASSWORD_CRYPTO_OLD
prefs_change_master_passphrase(GtkButton * button,gpointer data)849 void prefs_change_master_passphrase(GtkButton *button, gpointer data)
850 {
851 	/* Call the passphrase change dialog */
852 	master_passphrase_change_dialog();
853 }
854 
prefs_use_passphrase_toggled(GtkToggleButton * chkbtn,gpointer data)855 void prefs_use_passphrase_toggled(GtkToggleButton *chkbtn, gpointer data)
856 {
857 	GtkWidget *button = GTK_WIDGET(data);
858 	gboolean active = gtk_toggle_button_get_active(chkbtn);
859 
860 	if (!active)
861 		gtk_widget_set_sensitive(button, active);
862 }
863 #endif
864