1 /*
2  * Copyright 2011 kubtek <kubtek@mail.com>
3  *
4  * This file is part of StarDict.
5  *
6  * StarDict is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * StarDict is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <cstdlib>
27 
28 #include <glib/gi18n.h>
29 #include <glib/gstdio.h>
30 
31 #ifdef _WIN32
32 #  include <gdk/gdkwin32.h>
33 #endif
34 
35 #include "stardict.h"
36 #include "conf.h"
37 #include "desktop.h"
38 #include "lib/utils.h"
39 #include "iskeyspressed.h"
40 #include "lib/md5.h"
41 #include "lib/file-utils.h"
42 
43 #include "prefsdlg.h"
44 #include "hotkeyeditor.h"
45 #include "cmdlineopts.h"
46 
47 #ifndef CONFIG_GPE
48 enum {
49 	LOGO = 0,
50 	DICTIONARY_SCAN_SETTINGS,
51 	DICTIONARY_FONT_SETTINGS,
52 	DICTIONARY_CACHE_SETTINGS,
53 	DICTIONARY_EXPORT_SETTINGS,
54 	DICTIONARY_SOUND_SETTINGS,
55 	DICTIONARY_VIDEO_SETTINGS,
56 	DICIONARY_ARTICLE_RENDERING,
57 	DICIONARY_DICT_MANAGEMENT,
58 	NETWORK_NETDICT,
59 	NETWORK_WEB_BROWSER,
60 	MAINWIN_INPUT_SETTINGS,
61 	MAINWIN_OPTIONS_SETTINGS,
62 	MAINWIN_SEARCH_WEBSITE_SETTINGS,
63 	NOTIFICATION_AREA_ICON_OPITIONS_SETTINGS,
64 	FLOATWIN_OPTIONS_SETTINGS,
65 	FLOATWIN_SIZE_SETTINGS,
66 };
67 
68 enum
69 {
70 	CATEGORY_COLUMN = 0,
71 	PAGE_NUM_COLUMN,
72 	NUM_COLUMNS
73 };
74 
75 
76 struct CategoriesTreeItem {
77   const gchar			*category;
78 
79   CategoriesTreeItem 	*children;
80 
81   gint			notebook_page;
82 };
83 
84 static CategoriesTreeItem dictionary_behavior [] = {
85 	{N_("Scan Selection"), NULL, DICTIONARY_SCAN_SETTINGS},
86 	{N_("Font"), NULL, DICTIONARY_FONT_SETTINGS},
87 	{N_("Cache"), NULL, DICTIONARY_CACHE_SETTINGS},
88 	{N_("Export"), NULL, DICTIONARY_EXPORT_SETTINGS},
89 	{N_("Sound"), NULL, DICTIONARY_SOUND_SETTINGS},
90 	{N_("Video"), NULL, DICTIONARY_VIDEO_SETTINGS},
91 	{N_("Article rendering"), NULL, DICIONARY_ARTICLE_RENDERING},
92 	{N_("Dict management"), NULL, DICIONARY_DICT_MANAGEMENT},
93 	{ NULL }
94 };
95 
96 static CategoriesTreeItem network_behavior [] = {
97     {N_("Net Dict"), NULL, NETWORK_NETDICT},
98     {N_("Web browser"), NULL, NETWORK_WEB_BROWSER},
99     { NULL }
100 };
101 
102 static CategoriesTreeItem mainwin_behavior [] =
103 {
104 	{N_("Input"), NULL, MAINWIN_INPUT_SETTINGS},
105 	{N_("Options"), NULL, MAINWIN_OPTIONS_SETTINGS},
106 	{N_("Search website"), NULL, MAINWIN_SEARCH_WEBSITE_SETTINGS},
107 
108 	{ NULL }
109 };
110 
111 static CategoriesTreeItem NotificationAreaIcon_behavior [] =
112 {
113 	{N_("Options"), NULL, NOTIFICATION_AREA_ICON_OPITIONS_SETTINGS},
114 
115 	{ NULL }
116 };
117 
118 static CategoriesTreeItem floatwin_behavior [] =
119 {
120 	{N_("Options"), NULL, FLOATWIN_OPTIONS_SETTINGS},
121 	{N_("Settings"), NULL, FLOATWIN_SIZE_SETTINGS},
122 
123 	{ NULL }
124 };
125 
126 static CategoriesTreeItem toplevel [] =
127 {
128 	{N_("Dictionary"), dictionary_behavior, LOGO},
129 	{N_("Network"), network_behavior, LOGO},
130 	{N_("Main window"), mainwin_behavior, LOGO},
131 	{N_("Notification area icon"), NotificationAreaIcon_behavior, LOGO},
132 	{N_("Floating window"), floatwin_behavior, LOGO},
133 
134 	{ NULL }
135 };
136 
137 static gint last_selected_page_num = DICTIONARY_SCAN_SETTINGS;
138 #endif
139 
response_handler(GtkDialog * dialog,gint res_id,PrefsDlg * oPrefsDlg)140 void PrefsDlg::response_handler (GtkDialog *dialog, gint res_id, PrefsDlg *oPrefsDlg)
141 {
142   if (res_id==GTK_RESPONSE_HELP)
143     show_help("stardict-prefs");
144 }
145 
146 #ifndef CONFIG_GPE
create_categories_tree_model()147 GtkTreeModel* PrefsDlg::create_categories_tree_model ()
148 {
149 	GtkTreeStore *model;
150 	GtkTreeIter iter;
151 	CategoriesTreeItem *category = toplevel;
152 
153 	model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
154 
155 	while (category->category) {
156 		CategoriesTreeItem *sub_category = category->children;
157 		gtk_tree_store_append (model, &iter, NULL);
158 		gtk_tree_store_set (model, &iter,
159 			CATEGORY_COLUMN, gettext (category->category),
160 			PAGE_NUM_COLUMN, category->notebook_page,
161 			-1);
162 
163 		while (sub_category->category) {
164 			GtkTreeIter child_iter;
165 			gtk_tree_store_append (model, &child_iter, &iter);
166 			gtk_tree_store_set (model, &child_iter,
167 				CATEGORY_COLUMN, gettext (sub_category->category),
168 				PAGE_NUM_COLUMN, sub_category->notebook_page,
169 				-1);
170 			sub_category++;
171 		}
172 		category++;
173 	}
174 	return GTK_TREE_MODEL (model);
175 }
176 
categories_tree_selection_cb(GtkTreeSelection * selection,PrefsDlg * oPrefsDlg)177 void PrefsDlg::categories_tree_selection_cb (GtkTreeSelection *selection, PrefsDlg *oPrefsDlg)
178 {
179  	GtkTreeIter iter;
180 	GValue value = {0, };
181 
182 	if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
183 		return;
184 
185 	gtk_tree_model_get_value (oPrefsDlg->categories_tree_model, &iter,
186 			    PAGE_NUM_COLUMN,
187 			    &value);
188 
189 	last_selected_page_num = g_value_get_int (&value);
190 
191 	if (oPrefsDlg->notebook != NULL)
192 		gtk_notebook_set_current_page (GTK_NOTEBOOK (oPrefsDlg->notebook),
193 					       last_selected_page_num);
194 	g_value_unset (&value);
195 }
196 
selection_init(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,PrefsDlg * oPrefsDlg)197 gboolean PrefsDlg::selection_init (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, PrefsDlg *oPrefsDlg)
198 {
199 	GValue value = {0, };
200 	gint page_num;
201 
202 	gtk_tree_model_get_value (oPrefsDlg->categories_tree_model, iter,
203 			    PAGE_NUM_COLUMN,
204 			    &value);
205 
206 	page_num = g_value_get_int (&value);
207 
208 	g_value_unset (&value);
209 
210 	if (page_num == last_selected_page_num)
211 	{
212 		GtkTreeSelection *selection;
213 
214 		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (oPrefsDlg->categories_tree));
215 
216 		gtk_tree_selection_select_iter (selection, iter);
217 
218 		gtk_notebook_set_current_page (GTK_NOTEBOOK (oPrefsDlg->notebook), page_num);
219 
220 		return TRUE;
221 	}
222 	return FALSE;
223 }
224 
categories_tree_realize(GtkWidget * widget,PrefsDlg * oPrefsDlg)225 void PrefsDlg::categories_tree_realize (GtkWidget *widget, PrefsDlg *oPrefsDlg)
226 {
227 	gtk_tree_view_expand_all(GTK_TREE_VIEW(widget));
228 
229 	gtk_tree_model_foreach(oPrefsDlg->categories_tree_model,
230 			       GtkTreeModelForeachFunc(selection_init),
231 			       oPrefsDlg);
232 }
233 
create_categories_tree(void)234 void PrefsDlg::create_categories_tree(void)
235 {
236   GtkWidget *sw;
237   GtkTreeModel *model;
238   GtkWidget *treeview;
239   GtkCellRenderer *renderer;
240   GtkTreeSelection *selection;
241   GtkTreeViewColumn *column;
242   gint col_offset;
243 
244   sw = gtk_scrolled_window_new (NULL, NULL);
245   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
246 				       GTK_SHADOW_ETCHED_IN);
247   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
248 				  GTK_POLICY_AUTOMATIC,
249 				  GTK_POLICY_AUTOMATIC);
250 
251   gtk_widget_set_size_request (sw, 140, 240);
252 
253   model = create_categories_tree_model ();
254 
255   treeview = gtk_tree_view_new_with_model (model);
256   g_object_unref (G_OBJECT (model));
257   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
258 
259   categories_tree = treeview;
260   categories_tree_model = model;
261 
262   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
263 
264   gtk_tree_selection_set_mode (selection,
265 			       GTK_SELECTION_SINGLE);
266 
267   /* add column for category */
268   renderer = gtk_cell_renderer_text_new ();
269   g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
270 
271   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
272 							    -1, _("Categories"),
273 							    renderer, "text",
274 							    CATEGORY_COLUMN,
275 							    NULL);
276 
277   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
278   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
279 
280   g_signal_connect (selection, "changed",
281 		    G_CALLBACK (categories_tree_selection_cb),
282 		    this);
283 
284   gtk_container_add (GTK_CONTAINER (sw), treeview);
285 
286   g_signal_connect (G_OBJECT (treeview), "realize",
287 		    G_CALLBACK (categories_tree_realize),
288 		    this);
289 
290   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
291 
292   categories_window=sw;
293 }
294 
setup_logo_page()295 void PrefsDlg::setup_logo_page()
296 {
297   GtkWidget *image = gtk_image_new_from_pixbuf(stardict_logo);
298   gtk_notebook_append_page(GTK_NOTEBOOK(notebook),image,NULL);
299 }
300 #endif
301 
prepare_page(GtkNotebook * notebook,const gchar * caption,const gchar * stock_id)302 static GtkWidget *prepare_page(GtkNotebook *notebook, const gchar *caption,
303 			       const gchar *stock_id)
304 {
305 #if GTK_MAJOR_VERSION >= 3
306 	GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
307 #else
308 	GtkWidget *vbox = gtk_vbox_new(FALSE, 12);
309 #endif
310 #ifdef CONFIG_GPE
311         gtk_container_set_border_width(GTK_CONTAINER (vbox), 5);
312         GtkWidget *nb_label = gtk_label_new(caption);
313         gtk_notebook_append_page(notebook, vbox, nb_label);
314 #else
315 	gtk_notebook_append_page(notebook, vbox, NULL);
316 #endif
317 
318 #if GTK_MAJOR_VERSION >= 3
319 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
320 #else
321 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
322 #endif
323 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 6);
324 #if GTK_MAJOR_VERSION >= 3
325 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
326 #else
327 	GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
328 #endif
329 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
330 	GtkWidget *image =
331 		gtk_image_new_from_stock(stock_id,
332 					 GTK_ICON_SIZE_LARGE_TOOLBAR);
333 	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
334 	GtkWidget *label = gtk_label_new(NULL);
335 	glib::CharStr label_caption(
336 		g_markup_printf_escaped("<span weight=\"bold\" size=\"x-large\">%s</span>", caption));
337 	gtk_label_set_markup(GTK_LABEL(label), get_impl(label_caption));
338 	gtk_box_pack_start(GTK_BOX(hbox),label, FALSE, FALSE, 0);
339 #if GTK_MAJOR_VERSION >= 3
340 	GtkWidget *hseparator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
341 #else
342 	GtkWidget *hseparator = gtk_hseparator_new();
343 #endif
344 	gtk_box_pack_start(GTK_BOX(vbox1),hseparator,FALSE,FALSE,0);
345 
346 	return vbox;
347 }
348 
on_setup_dictionary_scan_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)349 void PrefsDlg::on_setup_dictionary_scan_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
350 {
351 	gboolean b = gtk_toggle_button_get_active(button);
352 	gtk_widget_set_sensitive(oPrefsDlg->scan_modifier_key_vbox,b);
353 	conf->set_bool_at("dictionary/only_scan_while_modifier_key", b);
354 }
355 
356 #ifdef _WIN32
on_setup_dictionary_scan_clipboard_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)357 void PrefsDlg::on_setup_dictionary_scan_clipboard_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
358 {
359 	gboolean b = gtk_toggle_button_get_active(button);
360 	if (b) {
361 		if (conf->get_bool_at("dictionary/scan_selection"))
362 			gpAppFrame->oClipboard.start();
363 	} else {
364 		if (conf->get_bool_at("dictionary/scan_selection"))
365 			gpAppFrame->oClipboard.stop();
366 	}
367 	conf->set_bool_at("dictionary/scan_clipboard", b);
368 }
369 #endif
370 #ifndef CONFIG_DARWIN
on_setup_dictionary_use_scan_hotkey_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)371 void PrefsDlg::on_setup_dictionary_use_scan_hotkey_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
372 {
373 	gboolean b = gtk_toggle_button_get_active(button);
374 	if (b) {
375 		gtk_widget_set_sensitive(oPrefsDlg->scan_hotkey_editor, true);
376 		const std::string &hotkey = conf->get_string_at(
377 		  "dictionary/scan_hotkey");
378 		gpAppFrame->oHotkey.start_scan(hotkey.c_str());
379 	} else {
380 		gtk_widget_set_sensitive(oPrefsDlg->scan_hotkey_editor, false);
381 		gpAppFrame->oHotkey.stop_scan();
382 	}
383 	conf->set_bool_at("dictionary/use_scan_hotkey", b);
384 }
385 #endif
on_setup_dictionary_scan_combobox_changed(GtkComboBox * combobox,PrefsDlg * oPrefsDlg)386 void PrefsDlg::on_setup_dictionary_scan_combobox_changed(GtkComboBox *combobox, PrefsDlg *oPrefsDlg)
387 {
388   gint key = gtk_combo_box_get_active(combobox);
389   conf->set_int_at("dictionary/scan_modifier_key", key);
390 }
391 
on_setup_dictionary_scan_hide_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)392 void PrefsDlg::on_setup_dictionary_scan_hide_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
393 {
394 	gboolean hide = gtk_toggle_button_get_active(button);
395   conf->set_bool_at("dictionary/hide_floatwin_when_modifier_key_released", hide);
396 }
397 
scan_hotkey_changed(GtkWidget * widget,guint key,guint modifiers)398 void scan_hotkey_changed(GtkWidget *widget, guint key, guint modifiers)
399 {
400 	bool active = conf->get_bool_at("dictionary/use_scan_hotkey");
401 	const char *s = gtk_accelerator_name(key, GdkModifierType(modifiers));
402 	conf->set_string_at("dictionary/scan_hotkey", std::string(s));
403 	if (active) {
404 		gpAppFrame->oHotkey.stop_scan();
405 		gpAppFrame->oHotkey.start_scan(s);
406 	}
407 }
408 
mainwindow_hotkey_changed(GtkWidget * widget,guint key,guint modifiers)409 void mainwindow_hotkey_changed(GtkWidget *widget, guint key, guint modifiers)
410 {
411 	bool active = conf->get_bool_at("dictionary/use_mainwindow_hotkey");
412 	const char *s = gtk_accelerator_name(key, GdkModifierType(modifiers));
413 	conf->set_string_at("dictionary/mainwindow_hotkey", std::string(s));
414 	if (active) {
415 		gpAppFrame->oHotkey.stop_mainwindow();
416 		gpAppFrame->oHotkey.start_mainwindow(s);
417 	}
418 }
419 
setup_dictionary_scan_page()420 void PrefsDlg::setup_dictionary_scan_page()
421 {
422 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Scan Selection"), GTK_STOCK_CONVERT);
423 #if GTK_MAJOR_VERSION >= 3
424 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
425 #else
426 	GtkWidget *vbox1 = gtk_vbox_new(false, 0);
427 #endif
428 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
429 	GtkWidget *check_button = gtk_check_button_new_with_mnemonic(_("_Only scan while the modifier key is being pressed."));
430 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
431 	bool only_scan_while_modifier_key=
432 	conf->get_bool_at("dictionary/only_scan_while_modifier_key");
433 
434 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
435 															 only_scan_while_modifier_key);
436 	g_signal_connect(G_OBJECT(check_button), "toggled",
437 									 G_CALLBACK(on_setup_dictionary_scan_ckbutton_toggled), this);
438 
439 #if GTK_MAJOR_VERSION >= 3
440 	scan_modifier_key_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
441 #else
442 	scan_modifier_key_vbox = gtk_vbox_new(FALSE, 6);
443 #endif
444 	gtk_box_pack_start(GTK_BOX(vbox1), scan_modifier_key_vbox,
445 										 FALSE, FALSE, 12);
446 	gtk_widget_set_sensitive(scan_modifier_key_vbox,
447 													 only_scan_while_modifier_key);
448 
449 	check_button = gtk_check_button_new_with_mnemonic(_("H_ide floating window when modifier key released."));
450 	gtk_box_pack_start(GTK_BOX(scan_modifier_key_vbox),check_button,false,false,0);
451 
452 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
453 															 conf->get_bool_at("dictionary/hide_floatwin_when_modifier_key_released"));
454 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_scan_hide_ckbutton_toggled), this);
455 
456 #if GTK_MAJOR_VERSION >= 3
457 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
458 #else
459 	GtkWidget *hbox = gtk_hbox_new(false, 12);
460 #endif
461 	gtk_box_pack_start(GTK_BOX(scan_modifier_key_vbox), hbox,false,false,0);
462 	GtkWidget *label=gtk_label_new(NULL);
463 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("Scan modifier _key:"));
464 	gtk_box_pack_start(GTK_BOX(hbox),label,false,false,0);
465 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
466 	GtkWidget *combobox = gtk_combo_box_text_new();
467 	gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(combobox), FALSE);
468 
469 	for (std::list<std::string>::const_iterator p=key_combs.begin();
470 	     p!=key_combs.end(); ++p) {
471 	  gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), p->c_str());
472 	}
473 
474 	int scan_modifier_key=
475 		conf->get_int_at("dictionary/scan_modifier_key");
476 
477 	gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), scan_modifier_key);
478 
479 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), combobox);
480 	gtk_box_pack_start(GTK_BOX(hbox), combobox, FALSE, FALSE, 0);
481 	g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (on_setup_dictionary_scan_combobox_changed), this);
482 
483 #ifdef _WIN32
484 	check_button = gtk_check_button_new_with_mnemonic(_("_Scan clipboard."));
485 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
486 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), conf->get_bool_at("dictionary/scan_clipboard"));
487 	g_signal_connect(G_OBJECT(check_button), "toggled",
488 									 G_CALLBACK(on_setup_dictionary_scan_clipboard_ckbutton_toggled), this);
489 
490 #endif
491 #ifndef CONFIG_DARWIN
492 #if GTK_MAJOR_VERSION >= 3
493 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
494 #else
495 	hbox = gtk_hbox_new(false, 12);
496 #endif
497 	gtk_box_pack_start(GTK_BOX(vbox1),hbox,false,false,0);
498 	check_button = gtk_check_button_new_with_mnemonic(_("_Use scan hotkey: Ctrl+Alt+X."));
499 	gtk_box_pack_start(GTK_BOX(hbox),check_button,false,false,0);
500 	StardictHotkeyEditor *hkeditor = stardict_hotkey_editor_new();
501 	scan_hotkey_editor = GTK_WIDGET(hkeditor);
502 	g_signal_connect(G_OBJECT(hkeditor), "hotkey-changed", G_CALLBACK(scan_hotkey_changed), NULL);
503 	const std::string &hotkey = conf->get_string_at("dictionary/scan_hotkey");
504 
505 
506 	gtk_entry_set_text(GTK_ENTRY(hkeditor), hotkey.c_str());
507 	gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(hkeditor),true,true,0);
508 	bool hk_active = conf->get_bool_at("dictionary/use_scan_hotkey");
509 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), hk_active);
510 	gtk_widget_set_sensitive(scan_hotkey_editor, hk_active);
511 	g_signal_connect(G_OBJECT(check_button), "toggled",
512 									 G_CALLBACK(on_setup_dictionary_use_scan_hotkey_ckbutton_toggled), this);
513 #endif
514 }
515 
change_font_for_all_widgets(const std::string & fontname)516 void PrefsDlg::change_font_for_all_widgets(const std::string& fontname)
517 {
518 	gchar *aa =
519 		g_strdup_printf("style \"custom-font\" { font_name= \"%s\" }\n"
520 										"class \"GtkWidget\" style \"custom-font\"\n", fontname.c_str());
521 #if GTK_MAJOR_VERSION >= 3
522 	GtkCssProvider *css_provider = gtk_css_provider_get_default();
523 	gtk_css_provider_load_from_data(css_provider, aa, -1, NULL);
524 #else
525 	gtk_rc_parse_string(aa);
526 	GdkScreen *screen = gtk_window_get_screen(parent_window);
527 	GtkSettings *settings=gtk_settings_get_for_screen(screen);
528 	gtk_rc_reset_styles(settings);
529 #endif
530 	g_free(aa);
531 #ifndef CONFIG_GPE
532 	resize_categories_tree();
533 #endif
534 }
535 
on_setup_dictionary_font_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)536 void PrefsDlg::on_setup_dictionary_font_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
537 {
538   gboolean b = gtk_toggle_button_get_active(button);
539   gtk_widget_set_sensitive(oPrefsDlg->custom_font_hbox, b);
540   conf->set_bool_at("dictionary/use_custom_font", b);
541 	if (b) {
542 		const std::string &custom_font=
543 			conf->get_string_at("dictionary/custom_font");
544 		oPrefsDlg->change_font_for_all_widgets(custom_font);
545 	} else
546 		oPrefsDlg->change_font_for_all_widgets("");
547 }
548 
on_setup_dictionary_font_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)549 void PrefsDlg::on_setup_dictionary_font_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
550 {
551 #if GTK_MAJOR_VERSION >= 3
552 	GtkWidget *dlg = gtk_font_chooser_dialog_new(_("Choose dictionary font"), GTK_WINDOW (oPrefsDlg->window));
553 #else
554 	GtkWidget *dlg = gtk_font_selection_dialog_new(_("Choose dictionary font"));
555 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (oPrefsDlg->window));
556 #endif
557 	const gchar *text = gtk_button_get_label(GTK_BUTTON(widget));
558 	if (strcmp(text,_("Choose"))) {
559 #if GTK_MAJOR_VERSION >= 3
560 		gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dlg), text);
561 #else
562 		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dlg), text);
563 #endif
564 	}
565 #if GTK_MAJOR_VERSION >= 3
566 	gtk_font_chooser_set_preview_text(GTK_FONT_CHOOSER(dlg),_("Dictionary font"));
567 #else
568 	gtk_font_selection_dialog_set_preview_text(GTK_FONT_SELECTION_DIALOG(dlg),_("Dictionary font"));
569 #endif
570   gint result = gtk_dialog_run (GTK_DIALOG (dlg));
571   if (result==GTK_RESPONSE_OK) {
572 #if GTK_MAJOR_VERSION >= 3
573 	gchar *font_name = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dlg));
574 #else
575 	gchar *font_name = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dlg));
576 #endif
577     if (font_name) {
578       gtk_button_set_label(GTK_BUTTON(widget),font_name);
579       conf->set_string_at("dictionary/custom_font", std::string(font_name));
580     }
581     if (font_name && font_name[0]) {
582 			oPrefsDlg->change_font_for_all_widgets(font_name);
583     }
584   }
585   gtk_widget_destroy (dlg);
586 }
587 
setup_dictionary_font_page()588 void PrefsDlg::setup_dictionary_font_page()
589 {
590 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Font"), GTK_STOCK_SELECT_FONT);
591 #if GTK_MAJOR_VERSION >= 3
592 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
593 #else
594 	GtkWidget *vbox1 = gtk_vbox_new(false,6);
595 #endif
596 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
597 	GtkWidget *check_button = gtk_check_button_new_with_mnemonic(_("_Use custom font."));
598 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
599 	bool use_custom_font=
600 		conf->get_bool_at("dictionary/use_custom_font");
601 
602 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
603 															 use_custom_font);
604 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_font_ckbutton_toggled), this);
605 #if GTK_MAJOR_VERSION >= 3
606 	custom_font_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
607 #else
608 	custom_font_hbox = gtk_hbox_new(false, 12);
609 #endif
610 	gtk_box_pack_start(GTK_BOX(vbox1),custom_font_hbox,false,false,0);
611 	gtk_widget_set_sensitive(custom_font_hbox, use_custom_font);
612 	GtkWidget *label=gtk_label_new(NULL);
613 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("Dictionary _font:"));
614 	gtk_box_pack_start(GTK_BOX(custom_font_hbox),label,false,false,0);
615 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
616 	GtkWidget *button;
617 	const std::string &custom_font=
618 		conf->get_string_at("dictionary/custom_font");
619 
620 	if (!custom_font.empty())
621 		button = gtk_button_new_with_label(custom_font.c_str());
622 	else
623 		button=gtk_button_new_with_label(_("Choose"));
624 
625 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), button);
626 	gtk_box_pack_start(GTK_BOX(custom_font_hbox),button,false,false,0);
627 	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_setup_dictionary_font_button_clicked), this);
628 }
629 
on_setup_dictionary_cache_CreateCacheFile_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)630 void PrefsDlg::on_setup_dictionary_cache_CreateCacheFile_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
631 {
632 	gboolean enable = gtk_toggle_button_get_active(button);
633 	conf->set_bool_at("dictionary/create_cache_file",enable);
634 }
635 
on_setup_dictionary_cache_EnableCollation_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)636 void PrefsDlg::on_setup_dictionary_cache_EnableCollation_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
637 {
638 	gboolean enable = gtk_toggle_button_get_active(button);
639 	gtk_widget_set_sensitive(oPrefsDlg->collation_hbox, enable);
640 	conf->set_bool_at("dictionary/enable_collation",enable);
641 }
642 
on_setup_dictionary_collation_combobox_changed(GtkComboBox * combobox,PrefsDlg * oPrefsDlg)643 void PrefsDlg::on_setup_dictionary_collation_combobox_changed(GtkComboBox *combobox, PrefsDlg *oPrefsDlg)
644 {
645 	gint key = gtk_combo_box_get_active(combobox);
646 	conf->set_int_at("dictionary/collate_function", key);
647 }
648 
on_setup_dictionary_cache_cleanbutton_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)649 void PrefsDlg::on_setup_dictionary_cache_cleanbutton_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
650 {
651 	RemoveCacheFiles();
652 }
653 
setup_dictionary_cache_page()654 void PrefsDlg::setup_dictionary_cache_page()
655 {
656 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Cache"), GTK_STOCK_HARDDISK);
657 #if GTK_MAJOR_VERSION >= 3
658 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
659 #else
660 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
661 #endif
662 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
663 	GtkWidget *check_button;
664 	check_button = gtk_check_button_new_with_mnemonic(_("Create c_ache files to speed up loading."));
665 	bool enable = conf->get_bool_at("dictionary/create_cache_file");
666 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
667 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_cache_CreateCacheFile_ckbutton_toggled), (gpointer)this);
668 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
669 	check_button = gtk_check_button_new_with_mnemonic(_("_Sort word list by collation function."));
670 	enable = conf->get_bool_at("dictionary/enable_collation");
671 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
672 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_cache_EnableCollation_ckbutton_toggled), (gpointer)this);
673 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
674 #if GTK_MAJOR_VERSION >= 3
675 	collation_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
676 #else
677 	collation_hbox = gtk_hbox_new(false,6);
678 #endif
679 	gtk_box_pack_start(GTK_BOX(vbox1),collation_hbox,false,false,0);
680 	GtkWidget *label=gtk_label_new(NULL);
681 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
682 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("\tCollation _function:"));
683 	gtk_box_pack_start(GTK_BOX(collation_hbox),label,false,false,0);
684 	GtkWidget *combobox = gtk_combo_box_text_new();
685 	gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(combobox), FALSE);
686 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_general_ci");
687 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_unicode_ci");
688 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_bin");
689 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_czech_ci");
690 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_danish_ci");
691 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_esperanto_ci");
692 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_estonian_ci");
693 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_hungarian_ci");
694 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_icelandic_ci");
695 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_latvian_ci");
696 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_lithuanian_ci");
697 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_persian_ci");
698 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_polish_ci");
699 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_roman_ci");
700 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_romanian_ci");
701 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_slovak_ci");
702 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_slovenian_ci");
703 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_spanish_ci");
704 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_spanish2_ci");
705 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_swedish_ci");
706 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), "utf8_turkish_ci");
707 	int collate_function = conf->get_int_at("dictionary/collate_function");
708 	gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), collate_function);
709 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), combobox);
710 	gtk_box_pack_start(GTK_BOX(collation_hbox), combobox, FALSE, FALSE, 0);
711 	g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (on_setup_dictionary_collation_combobox_changed), this);
712 	gtk_widget_set_sensitive(collation_hbox, enable);
713 
714 	label = gtk_label_new(_("After enabled collation, when load the dictionaries for the first time, it will take some time for sorting, please wait for a moment."));
715 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
716 	gtk_box_pack_start(GTK_BOX(vbox1),label,false,false,0);
717 
718 #if GTK_MAJOR_VERSION >= 3
719 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
720 #else
721 	GtkWidget *hbox = gtk_hbox_new(false,6);
722 #endif
723 	gtk_box_pack_start(GTK_BOX(vbox1),hbox,false,false,0);
724 	GtkWidget *button = gtk_button_new_with_mnemonic(_("C_lean all cache files"));
725 	gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON));
726 	gtk_box_pack_end(GTK_BOX(hbox),button,false,false,0);
727 	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_setup_dictionary_cache_cleanbutton_clicked), this);
728 }
729 
730 
731 
on_setup_dictionary_export_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)732 void PrefsDlg::on_setup_dictionary_export_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
733 {
734 	gboolean enable = gtk_toggle_button_get_active(button);
735 	conf->set_bool_at("dictionary/only_export_word", enable);
736 }
737 
on_setup_dictionary_export_browse_button_clicked(GtkButton * button,PrefsDlg * oPrefsDlg)738 void PrefsDlg::on_setup_dictionary_export_browse_button_clicked(GtkButton *button, PrefsDlg *oPrefsDlg)
739 {
740 	GtkWidget *dialog;
741 	dialog = gtk_file_chooser_dialog_new (_("Open file..."),
742 			GTK_WINDOW(oPrefsDlg->window),
743 			GTK_FILE_CHOOSER_ACTION_OPEN,
744 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
745 			GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
746 			NULL);
747 	gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), gtk_entry_get_text(oPrefsDlg->eExportFile));
748 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
749 		gchar *filename;
750 		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
751 		gtk_entry_set_text(oPrefsDlg->eExportFile, filename);
752 		g_free (filename);
753 	}
754 	gtk_widget_destroy (dialog);
755 }
756 
setup_dictionary_export_page()757 void PrefsDlg::setup_dictionary_export_page()
758 {
759 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Export"), GTK_STOCK_SAVE);
760 #if GTK_MAJOR_VERSION >= 3
761 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
762 #else
763 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
764 #endif
765 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
766 
767 	GtkWidget *check_button;
768 	check_button = gtk_check_button_new_with_mnemonic(_("_Only export words."));
769 	bool enable= conf->get_bool_at("dictionary/only_export_word");
770 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
771 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_export_ckbutton_toggled), this);
772 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
773 
774 #if GTK_MAJOR_VERSION >= 3
775 	GtkWidget *hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
776 #else
777 	GtkWidget *hbox1 = gtk_hbox_new(FALSE, 6);
778 #endif
779 	GtkWidget *label=gtk_label_new(_("File name:"));
780 	gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 0);
781 	GtkWidget *e = gtk_entry_new();
782 	const std::string &exportfile = conf->get_string_at("dictionary/export_file");
783 #ifdef _WIN32
784 	gtk_entry_set_text(GTK_ENTRY(e), abs_path_to_data_dir(exportfile).c_str());
785 #else
786 	gtk_entry_set_text(GTK_ENTRY(e), exportfile.c_str());
787 #endif
788 	gtk_box_pack_start(GTK_BOX(hbox1), e, TRUE, TRUE, 0);
789 	eExportFile=GTK_ENTRY(e);
790 
791 	GtkWidget *button;
792 	button = gtk_button_new_with_mnemonic(_("_Browse..."));
793 	gtk_widget_set_can_focus (button, FALSE);
794 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_dictionary_export_browse_button_clicked), this);
795 	gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
796 	gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
797 }
798 
on_setup_bookname_style_changed(GtkComboBox * combobox,PrefsDlg * oPrefsDlg)799 void PrefsDlg::on_setup_bookname_style_changed(GtkComboBox *combobox, PrefsDlg *oPrefsDlg)
800 {
801         int style = gtk_combo_box_get_active(combobox);
802         conf->set_int_at("dictionary/bookname_style", style);
803 	gpAppFrame->oFloatWin.set_bookname_style((BookNameStyle)style);
804 	gpAppFrame->oMidWin.oTextWin.set_bookname_style((BookNameStyle)style);
805 }
806 
on_markup_search_word(GtkToggleButton * button,PrefsDlg *)807 void PrefsDlg::on_markup_search_word(GtkToggleButton *button, PrefsDlg *)
808 {
809 	conf->set_bool_at("dictionary/markup_search_word",
810 			  gtk_toggle_button_get_active(button));
811 }
812 
setup_dictionary_article_rendering()813 void PrefsDlg::setup_dictionary_article_rendering()
814 {
815 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Article rendering"),
816 				       GTK_STOCK_CONVERT);
817 #if GTK_MAJOR_VERSION >= 3
818 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
819 #else
820 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
821 #endif
822 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 0);
823 
824 #if GTK_MAJOR_VERSION >= 3
825         GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
826 #else
827         GtkWidget *hbox = gtk_hbox_new(FALSE, 12);
828 #endif
829         gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
830         GtkWidget *label = gtk_label_new(_("Dictionary name showing style:"));
831         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
832         GtkWidget *cb = gtk_combo_box_text_new();
833         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("Default"));
834         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("One blank line"));
835         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("Two blank lines"));
836         gtk_box_pack_start(GTK_BOX(hbox), cb, TRUE, TRUE, 0);
837         int style = conf->get_int_at("dictionary/bookname_style");
838         gtk_combo_box_set_active(GTK_COMBO_BOX(cb), style);
839         g_signal_connect(G_OBJECT(cb), "changed", G_CALLBACK(on_setup_bookname_style_changed), this);
840 
841 	GtkWidget *ck_btn =
842 		gtk_check_button_new_with_mnemonic(_("_Highlight search term"));
843 	gtk_box_pack_start(GTK_BOX(vbox1), ck_btn, FALSE, FALSE, 0);
844 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ck_btn),
845 				     conf->get_bool_at("dictionary/markup_search_word"));
846 	g_signal_connect(G_OBJECT(ck_btn), "toggled",
847 			 G_CALLBACK(on_markup_search_word), this);
848 }
849 
setup_dictionary_dict_management()850 void PrefsDlg::setup_dictionary_dict_management()
851 {
852 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Dictionary management"),
853 				       GTK_STOCK_CONVERT);
854 #if GTK_MAJOR_VERSION >= 3
855 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
856 #else
857 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
858 #endif
859 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 0);
860 
861 	GtkWidget *ck_btn =
862 		gtk_check_button_new_with_mnemonic(_("Don't load _bad dictionaries."));
863 	gtk_box_pack_start(GTK_BOX(vbox1), ck_btn, FALSE, FALSE, 6);
864 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ck_btn),
865 		conf->get_bool_at("dictionary/do_not_load_bad_dict"));
866 	g_signal_connect(G_OBJECT(ck_btn), "toggled",
867 			 G_CALLBACK(on_setup_dictionary_do_not_add_bad_dict_ckbutton_toggled), this);
868 
869 	ck_btn =
870 		gtk_check_button_new_with_mnemonic(_("Add new _dictionaries to active dictionary group."));
871 	gtk_box_pack_start(GTK_BOX(vbox1), ck_btn, FALSE, FALSE, 0);
872 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ck_btn),
873 		conf->get_bool_at("dictionary/add_new_dict_in_active_group"));
874 	g_signal_connect(G_OBJECT(ck_btn), "toggled",
875 			 G_CALLBACK(on_setup_dictionary_add_new_dict_in_active_group_ckbutton_toggled), this);
876 
877 	ck_btn = gtk_check_button_new_with_mnemonic(_("Add new _plug-ins to active dictionary group."));
878 	gtk_box_pack_start(GTK_BOX(vbox1), ck_btn, FALSE, FALSE, 0);
879 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ck_btn),
880 	conf->get_bool_at("dictionary/add_new_plugin_in_active_group"));
881 	g_signal_connect(G_OBJECT(ck_btn), "toggled",
882 		 G_CALLBACK(on_setup_dictionary_add_new_plugin_in_active_group_ckbutton_toggled), this);
883 }
884 
on_setup_dictionary_do_not_add_bad_dict_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)885 void PrefsDlg::on_setup_dictionary_do_not_add_bad_dict_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
886 {
887 	gboolean enable = gtk_toggle_button_get_active(button);
888 	conf->set_bool_at("dictionary/do_not_load_bad_dict", enable);
889 }
890 
on_setup_dictionary_add_new_dict_in_active_group_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)891 void PrefsDlg::on_setup_dictionary_add_new_dict_in_active_group_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
892 {
893 	gboolean enable = gtk_toggle_button_get_active(button);
894 	conf->set_bool_at("dictionary/add_new_dict_in_active_group", enable);
895 }
896 
on_setup_dictionary_add_new_plugin_in_active_group_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)897 void PrefsDlg::on_setup_dictionary_add_new_plugin_in_active_group_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
898 {
899 	gboolean enable = gtk_toggle_button_get_active(button);
900 	conf->set_bool_at("dictionary/add_new_plugin_in_active_group", enable);
901 }
902 
on_setup_dictionary_sound_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)903 void PrefsDlg::on_setup_dictionary_sound_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
904 {
905   gboolean enable = gtk_toggle_button_get_active(button);
906   conf->set_bool_at("dictionary/enable_sound_event",enable);
907 }
908 
909 #if defined(_WIN32)
on_setup_dictionary_always_sound_cmd_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)910 void PrefsDlg::on_setup_dictionary_always_sound_cmd_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
911 {
912   gboolean enable = gtk_toggle_button_get_active(button);
913   conf->set_bool_at("dictionary/always_use_sound_play_command",enable);
914 }
915 #endif
916 
917 #ifndef _WIN32
on_setup_dictionary_use_tts_program_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)918 void PrefsDlg::on_setup_dictionary_use_tts_program_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
919 {
920 	gboolean enable = gtk_toggle_button_get_active(button);
921 	gtk_widget_set_sensitive(oPrefsDlg->use_tts_program_hbox,enable);
922 	conf->set_bool("/apps/stardict/preferences/dictionary/use_tts_program", enable);
923 	gpAppFrame->oReadWord.use_command_tts = enable;
924 	gpAppFrame->oMidWin.oToolWin.UpdatePronounceMenu();
925 }
926 #endif
927 
setup_dictionary_sound_page()928 void PrefsDlg::setup_dictionary_sound_page()
929 {
930 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Sound"), GTK_STOCK_YES);
931 #if GTK_MAJOR_VERSION >= 3
932 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
933 #else
934 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
935 #endif
936 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
937 
938 	GtkWidget *check_button;
939 	check_button = gtk_check_button_new_with_mnemonic(_("_Enable sound event."));
940 	bool enable=
941 		conf->get_bool_at("dictionary/enable_sound_event");
942 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
943 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_sound_ckbutton_toggled), (gpointer)this);
944 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
945 	GtkWidget *label;
946 
947 #if GTK_MAJOR_VERSION >= 3
948 	GtkWidget *hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
949 #else
950 	GtkWidget *hbox2 = gtk_hbox_new(FALSE, 6);
951 #endif
952 	label=gtk_label_new(_("Command for playing sound files:"));
953 	gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
954 	GtkWidget *e = gtk_entry_new();
955 	gtk_widget_set_size_request(e, 50, -1);
956 	const std::string &playcmd=
957 		conf->get_string_at("dictionary/sound_play_command");
958 	gtk_entry_set_text(GTK_ENTRY(e), playcmd.c_str());
959 	gtk_box_pack_start(GTK_BOX(hbox2), e, TRUE, TRUE, 0);
960 	eSoundPlayCommand=GTK_ENTRY(e);
961 	gtk_box_pack_start(GTK_BOX(vbox1), hbox2, FALSE, FALSE, 0);
962 
963 #if defined(_WIN32)
964 	check_button = gtk_check_button_new_with_mnemonic(_("Always use sound play command."));
965 	enable = conf->get_bool_at("dictionary/always_use_sound_play_command");
966 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
967 	g_signal_connect(G_OBJECT (check_button), "toggled", G_CALLBACK(on_setup_dictionary_always_sound_cmd_ckbutton_toggled), (gpointer)this);
968 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
969 #endif
970 
971 	label = gtk_label_new(_("RealPeopleTTS search path:"));
972 	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
973 	gtk_box_pack_start(GTK_BOX(vbox1),label,false,false,0);
974 	tts_textview = gtk_text_view_new();
975 	gtk_widget_set_size_request(tts_textview, -1, 70);
976 	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tts_textview), GTK_WRAP_CHAR);
977 	std::string ttspath;
978 	{
979 #ifdef _WIN32
980 		/* Let's the user see paths as they are, that is relative paths. */
981 #endif
982 		const std::list<std::string> &ttspathlist = conf->get_strlist_at("dictionary/tts_path");
983 		for(std::list<std::string>::const_iterator it = ttspathlist.begin();
984 			it != ttspathlist.end(); ++it) {
985 			if(!ttspath.empty())
986 				ttspath += "\n";
987 			ttspath += *it;
988 		}
989 	}
990 	GtkTextBuffer *text_view_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tts_textview));
991 	gtk_text_buffer_set_text(text_view_buffer, ttspath.c_str(), -1);
992 	GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
993 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
994                                        GTK_SHADOW_ETCHED_IN);
995 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
996                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
997 	gtk_container_add(GTK_CONTAINER(scrolled_window), tts_textview);
998 	gtk_box_pack_start(GTK_BOX(vbox1),scrolled_window,false,false,0);
999 
1000 #ifndef _WIN32
1001 	check_button = gtk_check_button_new_with_mnemonic(_("Enable _TTS program."));
1002 	enable = conf->get_bool("/apps/stardict/preferences/dictionary/use_tts_program");
1003 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
1004 	g_signal_connect (G_OBJECT (check_button), "toggled", G_CALLBACK (on_setup_dictionary_use_tts_program_ckbutton_toggled), this);
1005 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
1006 #if GTK_MAJOR_VERSION >= 3
1007 	use_tts_program_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1008 #else
1009 	use_tts_program_hbox = gtk_hbox_new(FALSE, 6);
1010 #endif
1011 	gtk_box_pack_start(GTK_BOX(vbox1),use_tts_program_hbox,false,false,0);
1012 	gtk_widget_set_sensitive(use_tts_program_hbox,enable);
1013 	label = gtk_label_new(_("Command line:"));
1014 	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
1015 	gtk_box_pack_start(GTK_BOX(use_tts_program_hbox),label,false,false,0);
1016 	GtkWidget *comboboxentry = gtk_combo_box_text_new_with_entry();
1017 	gtk_widget_set_size_request(comboboxentry, 30, -1);
1018 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry), "echo %s | festival --tts &");
1019 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry), "espeak %s &");
1020 	eTTSCommandline = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(comboboxentry)));
1021 	const std::string &tts_program_cmdline = conf->get_string("/apps/stardict/preferences/dictionary/tts_program_cmdline");
1022 	gtk_entry_set_text(eTTSCommandline, tts_program_cmdline.c_str());
1023 	gtk_box_pack_start(GTK_BOX(use_tts_program_hbox),comboboxentry,true,true,0);
1024 #endif
1025 }
1026 
setup_dictionary_video_page()1027 void PrefsDlg::setup_dictionary_video_page()
1028 {
1029 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Video"), GTK_STOCK_YES);
1030 #if GTK_MAJOR_VERSION >= 3
1031 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1032 #else
1033 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
1034 #endif
1035 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
1036 
1037 #if GTK_MAJOR_VERSION >= 3
1038 	GtkWidget *hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1039 #else
1040 	GtkWidget *hbox2 = gtk_hbox_new(FALSE, 6);
1041 #endif
1042 	GtkWidget *label = gtk_label_new(_("Command for playing video files:"));
1043 	gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1044 	GtkWidget *entry = gtk_entry_new();
1045 	gtk_widget_set_size_request(entry, 50, -1);
1046 	const std::string &playcmd=
1047 		conf->get_string_at("dictionary/video_play_command");
1048 	gtk_entry_set_text(GTK_ENTRY(entry), playcmd.c_str());
1049 	gtk_box_pack_start(GTK_BOX(hbox2), entry, TRUE, TRUE, 0);
1050 	eVideoPlayCommand=GTK_ENTRY(entry);
1051 	gtk_box_pack_start(GTK_BOX(vbox1), hbox2, FALSE, FALSE, 0);
1052 }
1053 
on_setup_network_netdict_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1054 void PrefsDlg::on_setup_network_netdict_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1055 {
1056 	bool enable_netdict = gtk_toggle_button_get_active(button);
1057 	if(enable_netdict) {
1058 		if(!confirm_enable_network_dicts(oPrefsDlg->window)) {
1059 			enable_netdict = false;
1060 			// revert button state
1061 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
1062 		}
1063 	}
1064 	conf->set_bool_at("network/enable_netdict", enable_netdict);
1065 }
1066 
on_account_passwd_entry_activated(GtkEntry * entry,GtkDialog * dialog)1067 static void on_account_passwd_entry_activated(GtkEntry *entry, GtkDialog *dialog)
1068 {
1069 	gtk_dialog_response(dialog, GTK_RESPONSE_OK);
1070 }
1071 
on_setup_network_account_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1072 void PrefsDlg::on_setup_network_account_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1073 {
1074     GtkWidget *account_dialog;
1075     account_dialog =
1076         gtk_dialog_new_with_buttons (_("Account"),
1077                 GTK_WINDOW (oPrefsDlg->window),
1078                 GTK_DIALOG_DESTROY_WITH_PARENT,
1079                 GTK_STOCK_CANCEL,
1080                 GTK_RESPONSE_CANCEL,
1081                 GTK_STOCK_OK,
1082                 GTK_RESPONSE_OK,
1083                 NULL);
1084     GtkWidget *table = gtk_table_new(2, 2, FALSE);
1085     gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(account_dialog))), table);
1086     gtk_container_set_border_width(GTK_CONTAINER(table), 6);
1087     GtkWidget *label = gtk_label_new_with_mnemonic(_("_User Name:"));
1088     gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
1089     GtkWidget *user_entry = gtk_entry_new ();
1090     gtk_label_set_mnemonic_widget(GTK_LABEL(label), user_entry);
1091     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1092     gtk_table_attach(GTK_TABLE(table), user_entry, 1, 2, 0, 1, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1093     label = gtk_label_new_with_mnemonic(_("_Password:"));
1094     gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
1095     GtkWidget *passwd_entry = gtk_entry_new ();
1096     gtk_entry_set_visibility(GTK_ENTRY(passwd_entry), FALSE);
1097     g_signal_connect(G_OBJECT(passwd_entry),"activate", G_CALLBACK(on_account_passwd_entry_activated), account_dialog);
1098     gtk_label_set_mnemonic_widget (GTK_LABEL (label), passwd_entry);
1099     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1100     gtk_table_attach(GTK_TABLE(table), passwd_entry, 1, 2, 1, 2, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1101     gtk_dialog_set_default_response(GTK_DIALOG(account_dialog), GTK_RESPONSE_OK);
1102     gtk_window_set_resizable(GTK_WINDOW(account_dialog), FALSE);
1103     gtk_widget_show_all(GTK_WIDGET(account_dialog));
1104     while (gtk_dialog_run(GTK_DIALOG(account_dialog))==GTK_RESPONSE_OK) {
1105         const gchar *user = gtk_entry_get_text(GTK_ENTRY(user_entry));
1106         if (!user[0]) {
1107             conf->set_string_at("network/user", "");
1108             conf->set_string_at("network/md5passwd", "");
1109             gtk_button_set_label(oPrefsDlg->bAccount, "Guest");
1110             gpAppFrame->oStarDictClient.set_auth("", "");
1111             break;
1112         }
1113         gchar *error_msg = NULL;
1114         const gchar *passwd = gtk_entry_get_text(GTK_ENTRY(passwd_entry));
1115         if (!passwd[0])
1116             error_msg = _("Please input the password.");
1117         if (error_msg) {
1118             GtkWidget *message_dlg =
1119                 gtk_message_dialog_new(
1120                         GTK_WINDOW(account_dialog),
1121                         (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1122                         GTK_MESSAGE_INFO,  GTK_BUTTONS_OK,
1123                         "%s", error_msg);
1124             gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1125             gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1126             gtk_dialog_run(GTK_DIALOG(message_dlg));
1127             gtk_widget_destroy(message_dlg);
1128             continue;
1129         }
1130         conf->set_string_at("network/user", user);
1131         struct MD5Context ctx;
1132         unsigned char digest[16];
1133         MD5Init(&ctx);
1134         MD5Update(&ctx, (const unsigned char*)passwd, strlen(passwd));
1135         MD5Final(digest, &ctx );
1136         char hex[33];
1137         for (int i = 0; i < 16; i++)
1138             sprintf( hex+2*i, "%02x", digest[i] );
1139         hex[32] = '\0';
1140         conf->set_string_at("network/md5passwd", hex);
1141         gtk_button_set_label(oPrefsDlg->bAccount, user);
1142         gpAppFrame->oStarDictClient.set_auth(user, hex);
1143         break;
1144     }
1145     gtk_widget_destroy(account_dialog);
1146 }
1147 
on_register_end(const char * msg)1148 void PrefsDlg::on_register_end(const char *msg)
1149 {
1150 	gtk_button_set_label(bAccount, register_user.c_str());
1151 	conf->set_string_at("network/user", register_user);
1152 	conf->set_string_at("network/md5passwd", register_hex);
1153 	gpAppFrame->oStarDictClient.set_auth(register_user.c_str(), register_hex.c_str());
1154 
1155 	GtkWidget *message_dlg = gtk_message_dialog_new(GTK_WINDOW(window),
1156 			(GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1157 			GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", msg);
1158 	gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1159 	gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1160 	g_signal_connect_swapped (message_dlg, "response", G_CALLBACK (gtk_widget_destroy), message_dlg);
1161 	gtk_widget_show(message_dlg);
1162 }
1163 
on_register_email_button_activated(GtkEntry * entry,GtkDialog * dialog)1164 static void on_register_email_button_activated(GtkEntry *entry, GtkDialog *dialog)
1165 {
1166 	gtk_dialog_response(dialog, GTK_RESPONSE_OK);
1167 }
1168 
on_setup_network_register_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1169 void PrefsDlg::on_setup_network_register_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1170 {
1171     GtkWidget *register_dialog;
1172     register_dialog =
1173         gtk_dialog_new_with_buttons (_("Register"),
1174                 GTK_WINDOW (oPrefsDlg->window),
1175                 GTK_DIALOG_DESTROY_WITH_PARENT,
1176                 GTK_STOCK_CANCEL,
1177                 GTK_RESPONSE_CANCEL,
1178                 GTK_STOCK_OK,
1179                 GTK_RESPONSE_OK,
1180                 NULL);
1181     GtkWidget *table = gtk_table_new(3, 2, FALSE);
1182     gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(register_dialog))), table);
1183     gtk_container_set_border_width(GTK_CONTAINER(table), 6);
1184     GtkWidget *label = gtk_label_new_with_mnemonic(_("_User Name:"));
1185     gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
1186     GtkWidget *user_entry = gtk_entry_new ();
1187     gtk_label_set_mnemonic_widget(GTK_LABEL(label), user_entry);
1188     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1189     gtk_table_attach(GTK_TABLE(table), user_entry, 1, 2, 0, 1, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1190     label = gtk_label_new_with_mnemonic(_("_Password:"));
1191     gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
1192     GtkWidget *passwd_entry = gtk_entry_new ();
1193     gtk_entry_set_visibility(GTK_ENTRY(passwd_entry), FALSE);
1194     gtk_label_set_mnemonic_widget (GTK_LABEL (label), passwd_entry);
1195     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1196     gtk_table_attach(GTK_TABLE(table), passwd_entry, 1, 2, 1, 2, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1197     label = gtk_label_new_with_mnemonic(_("_Email:"));
1198     gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
1199     GtkWidget *email_entry = gtk_entry_new ();
1200     g_signal_connect(G_OBJECT(email_entry),"activate", G_CALLBACK(on_register_email_button_activated), register_dialog);
1201     gtk_label_set_mnemonic_widget(GTK_LABEL(label), email_entry);
1202     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1203     gtk_table_attach(GTK_TABLE(table), email_entry, 1, 2, 2, 3, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1204     gtk_dialog_set_default_response(GTK_DIALOG(register_dialog), GTK_RESPONSE_OK);
1205     gtk_window_set_resizable(GTK_WINDOW(register_dialog), FALSE);
1206     gtk_widget_show_all(GTK_WIDGET(register_dialog));
1207     while (gtk_dialog_run(GTK_DIALOG(register_dialog))==GTK_RESPONSE_OK) {
1208         gchar *error_msg = NULL;
1209         const gchar *user = gtk_entry_get_text(GTK_ENTRY(user_entry));
1210         const gchar *passwd = gtk_entry_get_text(GTK_ENTRY(passwd_entry));
1211         const gchar *email = gtk_entry_get_text(GTK_ENTRY(email_entry));
1212         if (!user[0])
1213             error_msg = _("Please input the user name.");
1214         else if (!passwd[0])
1215             error_msg = _("Please input the password.");
1216         else if (!email[0])
1217             error_msg = _("Please input the email.");
1218         else if (strchr(email, '@')==NULL)
1219             error_msg = _("Please input a valid email.");
1220         if (error_msg) {
1221             GtkWidget *message_dlg =
1222                 gtk_message_dialog_new(
1223                         GTK_WINDOW(register_dialog),
1224                         (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1225                         GTK_MESSAGE_INFO,  GTK_BUTTONS_OK,
1226                         "%s", error_msg);
1227             gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1228             gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1229             gtk_dialog_run(GTK_DIALOG(message_dlg));
1230             gtk_widget_destroy(message_dlg);
1231             continue;
1232         }
1233         struct MD5Context ctx;
1234         unsigned char digest[16];
1235         MD5Init(&ctx);
1236         MD5Update(&ctx, (const unsigned char*)passwd, strlen(passwd));
1237         MD5Final(digest, &ctx );
1238         char hex[33];
1239         for (int i = 0; i < 16; i++)
1240             sprintf( hex+2*i, "%02x", digest[i] );
1241         hex[32] = '\0';
1242 	const gchar *server = gtk_entry_get_text(oPrefsDlg->eStarDictServer);
1243 	int port = atoi(gtk_entry_get_text(oPrefsDlg->eStarDictServerPort));
1244 	gpAppFrame->oStarDictClient.set_server(server, port);
1245 	gpAppFrame->oStarDictClient.set_auth("", "");
1246 	oPrefsDlg->register_user = user;
1247 	oPrefsDlg->register_hex = hex;
1248         STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_REGISTER, user, hex, email);
1249         gpAppFrame->oStarDictClient.send_commands(1, c);
1250         break;
1251     }
1252     gtk_widget_destroy(register_dialog);
1253 }
1254 
setup_network_netdict()1255 void PrefsDlg::setup_network_netdict()
1256 {
1257 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Net Dict"),
1258 				       GTK_STOCK_NETWORK);
1259 #if GTK_MAJOR_VERSION >= 3
1260 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1261 #else
1262 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
1263 #endif
1264 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 0);
1265 
1266 	GtkWidget *ck_btn =
1267 		gtk_check_button_new_with_mnemonic(_("Enable _network dictionaries."));
1268 	gtk_box_pack_start(GTK_BOX(vbox1), ck_btn, FALSE, FALSE, 0);
1269 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ck_btn),
1270 				     conf->get_bool_at("network/enable_netdict"));
1271 	g_signal_connect(G_OBJECT(ck_btn), "toggled",
1272 			 G_CALLBACK(on_setup_network_netdict_ckbutton_toggled), this);
1273 
1274     GtkWidget *table;
1275     table = gtk_table_new(3, 2, FALSE);
1276     gtk_table_set_row_spacings(GTK_TABLE(table), 6);
1277     gtk_table_set_col_spacings(GTK_TABLE(table), 6);
1278     gtk_box_pack_start(GTK_BOX(vbox1),table,false,false,0);
1279     GtkWidget *label=gtk_label_new(_("StarDict server:"));
1280     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1281 	GtkWidget *comboboxentry = gtk_combo_box_text_new_with_entry();
1282 	gtk_table_attach(GTK_TABLE(table), comboboxentry, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1283 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry), "dict.stardict.org");
1284 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry), "dict.stardict.cn");
1285 	eStarDictServer=GTK_ENTRY(gtk_bin_get_child(GTK_BIN(comboboxentry)));
1286 	const std::string &server= conf->get_string_at("network/server");
1287 	gtk_entry_set_text(eStarDictServer, server.c_str());
1288     label=gtk_label_new(_("Port:"));
1289     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1290     GtkWidget *e = gtk_entry_new();
1291     int port = conf->get_int_at("network/port");
1292     gchar *str = g_strdup_printf("%d", port);
1293     gtk_entry_set_text(GTK_ENTRY(e), str);
1294     g_free(str);
1295     gtk_table_attach(GTK_TABLE(table), e, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1296     eStarDictServerPort=GTK_ENTRY(e);
1297     label=gtk_label_new(_("Account:"));
1298     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
1299     const std::string &user= conf->get_string_at("network/user");
1300     GtkWidget *button;
1301     if (user.empty())
1302         button = gtk_button_new_with_label("Guest");
1303     else
1304         button = gtk_button_new_with_label(user.c_str());
1305     g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_network_account_button_clicked), this);
1306     gtk_table_attach(GTK_TABLE(table), button, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
1307     bAccount = GTK_BUTTON(button);
1308     button = gtk_button_new_with_mnemonic(_("_Register an account"));
1309     g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_network_register_button_clicked), this);
1310 #if GTK_MAJOR_VERSION >= 3
1311 	GtkWidget *hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1312 #else
1313 	GtkWidget *hbox1 = gtk_hbox_new(FALSE, 6);
1314 #endif
1315     gtk_box_pack_start(GTK_BOX(hbox1),button,false,false,0);
1316     gtk_box_pack_start(GTK_BOX(vbox1),hbox1,false,false,0);
1317 
1318     label = gtk_label_new(_("Warning: Requests to remote StarDict server are sent over the network in an unencrypted form. Do not enable this if you are translating sensitive documents."));
1319     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1320     gtk_box_pack_start(GTK_BOX(vbox1),label,false,false,6);
1321 }
1322 
1323 #if defined(_WIN32) || defined(CONFIG_GNOME)
on_setup_dictionary_always_url_cmd_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1324 void PrefsDlg::on_setup_dictionary_always_url_cmd_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1325 {
1326 	conf->set_bool_at("dictionary/always_use_open_url_command",
1327 		gtk_toggle_button_get_active(button));
1328 }
1329 #endif
1330 
setup_network_web_browser()1331 void PrefsDlg::setup_network_web_browser()
1332 {
1333 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Web browser"), GTK_STOCK_EXECUTE);
1334 #if GTK_MAJOR_VERSION >= 3
1335 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1336 #else
1337 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
1338 #endif
1339 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
1340 
1341 #if GTK_MAJOR_VERSION >= 3
1342 	GtkWidget *hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1343 #else
1344 	GtkWidget *hbox2 = gtk_hbox_new(FALSE, 6);
1345 #endif
1346 	GtkWidget *label = gtk_label_new(_("Command for opening URLs:"));
1347 	gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1348 	GtkWidget *entry = gtk_entry_new();
1349 	gtk_widget_set_size_request(entry, 50, -1);
1350 	const std::string &cmd=
1351 		conf->get_string_at("dictionary/url_open_command");
1352 	gtk_entry_set_text(GTK_ENTRY(entry), cmd.c_str());
1353 	gtk_box_pack_start(GTK_BOX(hbox2), entry, TRUE, TRUE, 0);
1354 	eURLOpenCommand=GTK_ENTRY(entry);
1355 	gtk_box_pack_start(GTK_BOX(vbox1), hbox2, FALSE, FALSE, 0);
1356 
1357 #if defined(_WIN32) || defined(CONFIG_GNOME)
1358 	GtkWidget *check_button
1359 		= gtk_check_button_new_with_mnemonic(_("Always use this command for opening URLs."));
1360 	gboolean enable
1361 		= conf->get_bool_at("dictionary/always_use_open_url_command");
1362 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), enable);
1363 	g_signal_connect(G_OBJECT (check_button), "toggled",
1364 		G_CALLBACK(on_setup_dictionary_always_url_cmd_ckbutton_toggled), (gpointer)this);
1365 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,false,false,0);
1366 #endif
1367 }
1368 
on_setup_mainwin_searchWhileTyping_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1369 void PrefsDlg::on_setup_mainwin_searchWhileTyping_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1370 {
1371   conf->set_bool_at("main_window/search_while_typing",
1372 		    gtk_toggle_button_get_active(button));
1373 }
1374 
on_setup_mainwin_showfirstWhenNotfound_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1375 void PrefsDlg::on_setup_mainwin_showfirstWhenNotfound_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1376 {
1377   conf->set_bool_at("main_window/showfirst_when_notfound",
1378 		    gtk_toggle_button_get_active(button));
1379 }
1380 
on_setup_mainwin_input_timeout_spinbutton_changed(GtkSpinButton * button,PrefsDlg * oPrefsDlg)1381 void PrefsDlg::on_setup_mainwin_input_timeout_spinbutton_changed(GtkSpinButton *button, PrefsDlg *oPrefsDlg)
1382 {
1383 	gint timeout = gtk_spin_button_get_value_as_int(button);
1384 	conf->set_int_at("main_window/word_change_timeout", timeout);
1385 }
1386 
setup_mainwin_input_page()1387 void PrefsDlg::setup_mainwin_input_page()
1388 {
1389 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Input"),
1390 				       GTK_STOCK_EDIT);
1391 
1392 #if GTK_MAJOR_VERSION >= 3
1393 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1394 #else
1395 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
1396 #endif
1397 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,FALSE,FALSE, 0);
1398 
1399 	GtkWidget *check_button =
1400 		gtk_check_button_new_with_mnemonic(_("_Search while typing."));
1401 	gtk_box_pack_start(GTK_BOX(vbox1), check_button, FALSE, FALSE, 0);
1402 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
1403 				     conf->get_bool_at("main_window/search_while_typing"));
1404 	g_signal_connect(G_OBJECT(check_button), "toggled",
1405 			 G_CALLBACK(on_setup_mainwin_searchWhileTyping_ckbutton_toggled), this);
1406 #if GTK_MAJOR_VERSION >= 3
1407 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
1408 #else
1409 	GtkWidget *hbox = gtk_hbox_new(false, 5);
1410 #endif
1411 	gtk_box_pack_start(GTK_BOX(vbox1),hbox,FALSE,FALSE, 0);
1412 	GtkWidget *label=gtk_label_new(NULL);
1413 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("Word change _timeout:"));
1414 	gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE, 0);
1415 	GtkWidget *spin_button;
1416 	spin_button = gtk_spin_button_new_with_range(0,2000,50);
1417 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), spin_button);
1418 	gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin_button), GTK_UPDATE_IF_VALID);
1419 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_button), conf->get_int_at("main_window/word_change_timeout"));
1420 	g_signal_connect(G_OBJECT(spin_button), "value-changed", G_CALLBACK(on_setup_mainwin_input_timeout_spinbutton_changed), this);
1421 	gtk_box_pack_start(GTK_BOX(hbox),spin_button,FALSE,FALSE, 0);
1422 	label=gtk_label_new(_("(default:300 ms)"));
1423 	gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE, 0);
1424 	check_button = gtk_check_button_new_with_mnemonic(_("Show the _first word when not found."));
1425 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,FALSE,FALSE,0);
1426 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), conf->get_bool_at("main_window/showfirst_when_notfound"));
1427 	g_signal_connect(G_OBJECT(check_button), "toggled",
1428 			 G_CALLBACK(on_setup_mainwin_showfirstWhenNotfound_ckbutton_toggled), this);
1429 }
1430 
on_setup_mainwin_startup_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1431 void PrefsDlg::on_setup_mainwin_startup_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1432 {
1433   conf->set_bool_at("main_window/hide_on_startup",
1434 								 gtk_toggle_button_get_active(button));
1435 }
1436 
1437 #ifdef _WIN32
on_setup_mainwin_autorun_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1438 void PrefsDlg::on_setup_mainwin_autorun_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1439 {
1440 	if(CmdLineOptions::get_portable_mode())
1441 		return;
1442 	gboolean b = gtk_toggle_button_get_active(button);
1443 	HKEY hKEY;
1444 	LONG lRet;
1445 	if (b) {
1446 		lRet =RegOpenKeyEx(HKEY_CURRENT_USER,
1447 			TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0,
1448 			KEY_ALL_ACCESS, &hKEY);
1449 		if(lRet==ERROR_SUCCESS) {
1450 			std::string path = build_path(conf_dirs->get_data_dir(), "stardict.exe");
1451 			std::string path_utf8;
1452 			std_win_string path_win;
1453 			if(file_name_to_utf8(path, path_utf8)
1454 			&& utf8_to_windows(path_utf8, path_win)) {
1455 				RegSetValueEx(hKEY, TEXT("StarDict"), 0, REG_SZ,
1456 					(const BYTE*)path_win.c_str(), sizeof(TCHAR)*(path_win.length()+1));
1457 			}
1458 			RegCloseKey(hKEY);
1459 		}
1460 	} else {
1461 		lRet =RegOpenKeyEx(HKEY_CURRENT_USER,
1462 			TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0,
1463 			KEY_ALL_ACCESS, &hKEY);
1464 		if(lRet==ERROR_SUCCESS) {
1465 			RegDeleteValue(hKEY, TEXT("StarDict"));
1466 			RegCloseKey(hKEY);
1467 		}
1468 	}
1469 }
1470 #endif
1471 #ifndef CONFIG_DARWIN
on_setup_mainwin_use_mainwindow_hotkey_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)1472 void PrefsDlg::on_setup_mainwin_use_mainwindow_hotkey_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
1473 {
1474 	gboolean b = gtk_toggle_button_get_active(button);
1475 	if (b) {
1476 		gtk_widget_set_sensitive(oPrefsDlg->mainwindow_hotkey_editor, true);
1477 		const std::string &hotkey = conf->get_string_at(
1478 		  "dictionary/mainwindow_hotkey");
1479 		gpAppFrame->oHotkey.start_mainwindow(hotkey.c_str());
1480 	} else {
1481 		gtk_widget_set_sensitive(oPrefsDlg->mainwindow_hotkey_editor, false);
1482 		gpAppFrame->oHotkey.stop_mainwindow();
1483 	}
1484 	conf->set_bool_at("dictionary/use_mainwindow_hotkey", b);
1485 }
1486 #endif
on_setup_mainwin_transparent_scale_changed(GtkRange * range,PrefsDlg * oPrefsDlg)1487 void PrefsDlg::on_setup_mainwin_transparent_scale_changed(GtkRange *range, PrefsDlg *oPrefsDlg)
1488 {
1489 	gint transparent = (gint)gtk_range_get_value(range);
1490 	conf->set_int_at("main_window/transparent", transparent);
1491 	gtk_window_set_opacity(GTK_WINDOW(gpAppFrame->window), (100-transparent)/100.0);
1492 }
1493 
on_setup_mainwin_skin_changed(GtkComboBox * combobox,PrefsDlg * oPrefsDlg)1494 void PrefsDlg::on_setup_mainwin_skin_changed(GtkComboBox *combobox, PrefsDlg *oPrefsDlg)
1495 {
1496 	int index = gtk_combo_box_get_active(combobox);
1497 	if ((index >= 0) && (index < int(oPrefsDlg->skins.size()))) {
1498 		if (! oPrefsDlg->skin_changed) {
1499 			GtkWidget *message_dlg = gtk_message_dialog_new(
1500 				NULL,
1501 				(GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1502 				GTK_MESSAGE_INFO,  GTK_BUTTONS_OK,
1503 				_("Skin change will take effect after application restart"));
1504 			gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1505 			gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1506 			gtk_dialog_run(GTK_DIALOG(message_dlg));
1507 			gtk_widget_destroy(message_dlg);
1508 		}
1509 		oPrefsDlg->skin_changed = true;
1510 		const std::string skin_path(oPrefsDlg->skins[index].path);
1511 #ifdef _WIN32
1512 		conf->set_string_at("main_window/skin", rel_path_to_data_dir(skin_path));
1513 #else
1514 		conf->set_string_at("main_window/skin", skin_path);
1515 #endif
1516 	}
1517 }
1518 
1519 class SkinDetector {
1520 private:
1521 	std::vector<PrefsDlg::SkinEntry> *m_skins;
1522 public:
SkinDetector(std::vector<PrefsDlg::SkinEntry> & skins)1523 	SkinDetector(std::vector<PrefsDlg::SkinEntry> &skins) : m_skins(&skins) {}
1524 	void operator ()(const std::string &filename, bool disable);
1525 };
1526 
1527 
operator ()(const std::string & filename,bool disable)1528 void SkinDetector::operator ()(const std::string &filename, bool disable)
1529 {
1530 	if (! disable) {
1531 		SkinStorage skin(filename.c_str());
1532 		if (skin.is_valid()) {
1533 			int n = m_skins->size();
1534 			m_skins->resize(n+1);
1535 			(*m_skins)[n].path = filename;
1536 			(*m_skins)[n].name = skin.get_name();
1537 		}
1538 	}
1539 }
1540 
1541 
find_skins()1542 void PrefsDlg::find_skins()
1543 {
1544 	skins.resize(1);
1545 	skins[0].path = "";
1546 	skins[0].name = _("Default"); // i.e. no skin applied
1547 	std::list<std::string> dirs;
1548 	dirs.push_back(std::string(g_get_home_dir())+"/.stardict/skins");
1549 	dirs.push_back(build_path(conf_dirs->get_data_dir(), "skins"));
1550 	for_each_dir(dirs, SkinDetector(skins));
1551 }
1552 
1553 
setup_mainwin_options_page()1554 void PrefsDlg::setup_mainwin_options_page()
1555 {
1556 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Options"), GTK_STOCK_EXECUTE);
1557 #if GTK_MAJOR_VERSION >= 3
1558 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1559 #else
1560 	GtkWidget *vbox1 = gtk_vbox_new(FALSE, 6);
1561 #endif
1562 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,FALSE,FALSE, 0);
1563 
1564 	GtkWidget *check_button;
1565 	GtkWidget *hbox;
1566 #ifdef _WIN32
1567 	check_button = gtk_check_button_new_with_mnemonic(_("_Auto run StarDict after boot."));
1568 	gtk_box_pack_start(GTK_BOX(vbox1),check_button,FALSE,FALSE,0);
1569 	gboolean autorun;
1570 
1571 	HKEY hKEY;
1572 	LONG lRet =RegOpenKeyEx(HKEY_CURRENT_USER,
1573 		TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0,
1574 		KEY_QUERY_VALUE, &hKEY);
1575 	if(lRet!=ERROR_SUCCESS) {
1576 		autorun = false;
1577 	} else {
1578 		const size_t buf_size_c=MAX_PATH;
1579 		const size_t buf_size_b=buf_size_c*sizeof(TCHAR);
1580 		TCHAR run_path_win[buf_size_c];
1581 		DWORD cbData_1=buf_size_b;
1582 		DWORD type_1=REG_SZ;
1583 		lRet=RegQueryValueEx(hKEY, TEXT("StarDict"), NULL, &type_1,
1584 			(LPBYTE)run_path_win, &cbData_1);
1585 		RegCloseKey(hKEY);
1586 		if((lRet!=ERROR_SUCCESS)||(cbData_1 > buf_size_b)) {
1587 			autorun = false;
1588 		} else {
1589 			std::string path = build_path(conf_dirs->get_data_dir(), "stardict.exe");
1590 			std::string run_path_utf8;
1591 			std::string run_path;
1592 			if(windows_to_utf8(run_path_win, run_path_utf8)
1593 			&& utf8_to_file_name(run_path_utf8, run_path))
1594 				autorun = path == run_path;
1595 			else
1596 				autorun = false;
1597 		}
1598 	}
1599 
1600 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), autorun);
1601 	if(CmdLineOptions::get_portable_mode())
1602 		gtk_widget_set_sensitive(check_button, FALSE);
1603 	g_signal_connect(G_OBJECT(check_button), "toggled",
1604 		G_CALLBACK(on_setup_mainwin_autorun_ckbutton_toggled), this);
1605 #endif
1606 #if GTK_MAJOR_VERSION >= 3
1607 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
1608 #else
1609 	hbox = gtk_hbox_new(false, 12);
1610 #endif
1611 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
1612 	GtkWidget *lbl = gtk_label_new(_("Skin:"));
1613 	gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(lbl),FALSE,FALSE,0);
1614 	GtkWidget *cb = gtk_combo_box_text_new();
1615 #ifdef _WIN32
1616 	std::string current_skin_path = abs_path_to_data_dir(conf->get_string_at("main_window/skin"));
1617 #else
1618 	std::string current_skin_path = conf->get_string_at("main_window/skin");
1619 #endif
1620 	find_skins();
1621 	for (int i = 0; i < int(skins.size()); i++) {
1622 		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), skins[i].name.c_str());
1623 		if (skins[i].path == current_skin_path)
1624 			gtk_combo_box_set_active(GTK_COMBO_BOX(cb), i);
1625 	}
1626 	gtk_box_pack_start(GTK_BOX(hbox),cb,true,true,0);
1627 	g_signal_connect(G_OBJECT(cb), "changed", G_CALLBACK(on_setup_mainwin_skin_changed), this);
1628 
1629 	check_button = gtk_check_button_new_with_mnemonic(_("Hide main window when _starting StarDict."));
1630 	gtk_box_pack_start(GTK_BOX(vbox1), check_button, FALSE, FALSE, 0);
1631 	bool hide=
1632 		conf->get_bool_at("main_window/hide_on_startup");
1633 
1634 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), hide);
1635 	g_signal_connect(G_OBJECT(check_button), "toggled",
1636 									 G_CALLBACK(on_setup_mainwin_startup_ckbutton_toggled), this);
1637 
1638 #ifndef CONFIG_DARWIN
1639 
1640 #if GTK_MAJOR_VERSION >= 3
1641 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
1642 #else
1643 	hbox = gtk_hbox_new(false, 12);
1644 #endif
1645 	gtk_box_pack_start(GTK_BOX(vbox1), hbox,false,false,0);
1646 	check_button = gtk_check_button_new_with_mnemonic(_("_Use open main window hotkey: Ctrl+Alt+Z."));
1647 	gtk_box_pack_start(GTK_BOX(hbox),check_button,false,false,0);
1648 	StardictHotkeyEditor *hkeditor = stardict_hotkey_editor_new();
1649 	mainwindow_hotkey_editor = GTK_WIDGET(hkeditor);
1650 	g_signal_connect(G_OBJECT(hkeditor), "hotkey-changed", G_CALLBACK(mainwindow_hotkey_changed), NULL);
1651 	const std::string &hotkey = conf->get_string_at("dictionary/mainwindow_hotkey");
1652 	gtk_entry_set_text(GTK_ENTRY(hkeditor), hotkey.c_str());
1653 	gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(hkeditor),true,true,0);
1654 	bool hk_active = conf->get_bool_at("dictionary/use_mainwindow_hotkey");
1655 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), hk_active);
1656 	gtk_widget_set_sensitive(mainwindow_hotkey_editor, hk_active);
1657 	g_signal_connect(G_OBJECT(check_button), "toggled",
1658 									 G_CALLBACK(on_setup_mainwin_use_mainwindow_hotkey_ckbutton_toggled), this);
1659 #endif
1660 
1661 #if GTK_MAJOR_VERSION >= 3
1662 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
1663 #else
1664 	hbox = gtk_hbox_new(false, 5);
1665 #endif
1666 	gtk_box_pack_start(GTK_BOX(vbox1),hbox,FALSE,FALSE, 0);
1667 	GtkWidget *label=gtk_label_new(NULL);
1668 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Transparency:"));
1669 	gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE, 0);
1670 	GtkWidget *hscale;
1671 #if GTK_MAJOR_VERSION >= 3
1672 	hscale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 80, 1);
1673 #else
1674 	hscale = gtk_hscale_new_with_range(0,80,1);
1675 #endif
1676 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), hscale);
1677 	int transparent=conf->get_int_at("main_window/transparent");
1678 	gtk_range_set_value(GTK_RANGE(hscale), transparent);
1679 	g_signal_connect(G_OBJECT(hscale), "value-changed", G_CALLBACK(on_setup_mainwin_transparent_scale_changed), this);
1680 	gtk_box_pack_start(GTK_BOX(hbox),hscale,TRUE,TRUE, 0);
1681 }
1682 
write_mainwin_searchwebsite_list()1683 void PrefsDlg::write_mainwin_searchwebsite_list()
1684 {
1685 	GtkTreeIter iter;
1686 	gboolean have_iter;
1687 	gchar  *website_name, *website_link, *website_searchlink;
1688 	std::list<std::string> searchwebsite_list;
1689 	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW (searchwebsite_treeview));
1690 
1691 	have_iter = gtk_tree_model_get_iter_first(model, &iter);
1692 	while (have_iter) {
1693 		gtk_tree_model_get (model, &iter, 0, &website_name, 1, &website_link, 2, &website_searchlink, -1);
1694 		std::string website(std::string(website_name)+'\t'+website_link+'\t'+website_searchlink);
1695 		g_free(website_name);
1696 		g_free(website_link);
1697 		g_free(website_searchlink);
1698 		searchwebsite_list.push_back(website);
1699 		have_iter = gtk_tree_model_iter_next(model, &iter);
1700 	}
1701 	conf->set_strlist_at("main_window/search_website_list", searchwebsite_list);
1702 }
1703 
on_setup_mainwin_searchwebsite_moveup_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1704 void PrefsDlg::on_setup_mainwin_searchwebsite_moveup_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1705 {
1706 	GtkTreeSelection *selection;
1707 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview));
1708 	GtkTreeModel *model;
1709 	GtkTreeIter iter;
1710 	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
1711 		GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
1712 		if (gtk_tree_path_prev(path)) {
1713 			GtkTreeIter prev;
1714 			gtk_tree_model_get_iter(model, &prev, path);
1715 			gtk_list_store_swap(GTK_LIST_STORE(model), &iter, &prev);
1716 			gtk_tree_selection_select_path(selection, path);
1717 			gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview), path, NULL, false, 0, 0);
1718 			oPrefsDlg->write_mainwin_searchwebsite_list();
1719 		}
1720 		gtk_tree_path_free(path);
1721 	}
1722 }
1723 
on_setup_mainwin_searchwebsite_movedown_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1724 void PrefsDlg::on_setup_mainwin_searchwebsite_movedown_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1725 {
1726 	GtkTreeSelection *selection;
1727 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview));
1728 	GtkTreeModel *model;
1729 	GtkTreeIter iter;
1730 	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
1731 		GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
1732 		gtk_tree_path_next(path);
1733 		GtkTreeIter next;
1734 		if (gtk_tree_model_get_iter(model, &next, path)) {
1735 			gtk_list_store_swap(GTK_LIST_STORE(model), &iter, &next);
1736 			gtk_tree_selection_select_path(selection, path);
1737 			gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview), path, NULL, false, 0, 0);
1738 			oPrefsDlg->write_mainwin_searchwebsite_list();
1739 		}
1740 		gtk_tree_path_free(path);
1741 	}
1742 }
1743 
on_setup_mainwin_searchwebsite_add_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1744 void PrefsDlg::on_setup_mainwin_searchwebsite_add_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1745 {
1746   GtkWidget *searchwebsite_add_dialog;
1747   GtkWidget *searchwebsite_add_dialog_name_entry;
1748   GtkWidget *searchwebsite_add_dialog_link_entry;
1749   GtkWidget *searchwebsite_add_dialog_searchlink_entry;
1750 
1751 	searchwebsite_add_dialog =
1752 		gtk_dialog_new_with_buttons (_("Add"),
1753 																 GTK_WINDOW (oPrefsDlg->window),
1754 																 GTK_DIALOG_DESTROY_WITH_PARENT,
1755 																 GTK_STOCK_CANCEL,
1756 																 GTK_RESPONSE_CANCEL,
1757 																 GTK_STOCK_OK,
1758 																 GTK_RESPONSE_OK,
1759 																 NULL);
1760 	GtkWidget *table = gtk_table_new(3, 2, FALSE);
1761 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(searchwebsite_add_dialog))), table);
1762 #ifndef CONFIG_GPE
1763 	gtk_container_set_border_width(GTK_CONTAINER(table), 6);
1764 #endif
1765 	GtkWidget *label = gtk_label_new_with_mnemonic(_("Website Name"));
1766 	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
1767 	searchwebsite_add_dialog_name_entry = gtk_entry_new ();
1768 #ifdef CONFIG_GPE
1769 	gtk_widget_set_size_request(searchwebsite_add_dialog_name_entry, 100, -1);
1770 #endif
1771 	gtk_entry_set_activates_default(GTK_ENTRY(searchwebsite_add_dialog_name_entry), TRUE);
1772 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), searchwebsite_add_dialog_name_entry);
1773 	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1774 	gtk_table_attach(GTK_TABLE(table), searchwebsite_add_dialog_name_entry, 1, 2, 0, 1, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1775 
1776 
1777 	label = gtk_label_new_with_mnemonic(_("Website link"));
1778 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
1779 	searchwebsite_add_dialog_link_entry = gtk_entry_new ();
1780 #ifdef CONFIG_GPE
1781 	 gtk_widget_set_size_request(searchwebsite_add_dialog_link_entry, 100, -1);
1782 #endif
1783 	gtk_entry_set_activates_default (GTK_ENTRY (searchwebsite_add_dialog_link_entry), TRUE);
1784 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), searchwebsite_add_dialog_link_entry);
1785 	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1786 	gtk_table_attach(GTK_TABLE(table), searchwebsite_add_dialog_link_entry, 1, 2, 1, 2, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1787 
1788 	label = gtk_label_new_with_mnemonic(_("Website search link"));
1789 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
1790 	searchwebsite_add_dialog_searchlink_entry = gtk_entry_new ();
1791 #ifdef CONFIG_GPE
1792 	gtk_widget_set_size_request(searchwebsite_add_dialog_searchlink_entry, 100, -1);
1793 #endif
1794 	gtk_entry_set_activates_default (GTK_ENTRY (searchwebsite_add_dialog_searchlink_entry), TRUE);
1795 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), searchwebsite_add_dialog_searchlink_entry);
1796 	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, (GtkAttachOptions)0, 6, 4);
1797 	gtk_table_attach(GTK_TABLE(table), searchwebsite_add_dialog_searchlink_entry, 1, 2, 2, 3, GTK_EXPAND, (GtkAttachOptions)0, 0, 4);
1798 
1799 	gtk_dialog_set_default_response(GTK_DIALOG(searchwebsite_add_dialog), GTK_RESPONSE_OK);
1800 	gtk_window_set_resizable(GTK_WINDOW(searchwebsite_add_dialog), FALSE);
1801 
1802 	gtk_widget_show_all(GTK_WIDGET(searchwebsite_add_dialog));
1803 	while (gtk_dialog_run(GTK_DIALOG(searchwebsite_add_dialog))==GTK_RESPONSE_OK) {
1804 		gchar *error_msg = NULL;
1805 		const gchar *website_name = gtk_entry_get_text(GTK_ENTRY(searchwebsite_add_dialog_name_entry));
1806 		const gchar *website_link = gtk_entry_get_text(GTK_ENTRY(searchwebsite_add_dialog_link_entry));
1807 		const gchar *website_searchlink = gtk_entry_get_text(GTK_ENTRY(searchwebsite_add_dialog_searchlink_entry));
1808 		if (!website_name[0])
1809 			error_msg = _("Please input the website name.");
1810 		else if (!website_link[0])
1811 			error_msg = _("Please input the website link.");
1812 		else if (!website_searchlink[0])
1813 			error_msg = _("Please input the website search link.");
1814 		else if (!strstr(website_searchlink, "%s")) {
1815 			error_msg = _("The website search link should contain a \"%%s\" string for querying a word.");
1816 		}
1817 
1818 		if (error_msg) {
1819 			GtkWidget *message_dlg =
1820 				gtk_message_dialog_new(
1821 					GTK_WINDOW(searchwebsite_add_dialog),
1822 					 (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1823 					GTK_MESSAGE_INFO,	GTK_BUTTONS_OK,
1824 					"%s", error_msg);
1825 
1826 			gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1827 			gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1828 
1829 			gtk_dialog_run(GTK_DIALOG(message_dlg));
1830 			gtk_widget_destroy(message_dlg);
1831 			continue;
1832 		}
1833 		GtkListStore *model =
1834 			GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(oPrefsDlg->searchwebsite_treeview)));
1835 		GtkTreeIter iter;
1836 		gtk_list_store_prepend(model, &iter);
1837 		gtk_list_store_set(model, &iter,
1838 											 0, website_name,
1839 											 1, website_link,
1840 											 2, website_searchlink,
1841 											 3, TRUE,
1842 											 -1);
1843 		oPrefsDlg->write_mainwin_searchwebsite_list();
1844 		break;
1845 	}
1846 	gtk_widget_destroy(searchwebsite_add_dialog);
1847 }
1848 
on_setup_mainwin_searchwebsite_remove_button_clicked(GtkWidget * widget,PrefsDlg * oPrefsDlg)1849 void PrefsDlg::on_setup_mainwin_searchwebsite_remove_button_clicked(GtkWidget *widget, PrefsDlg *oPrefsDlg)
1850 {
1851 	GtkTreeSelection *selection;
1852 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview));
1853 	GtkTreeModel *model;
1854 	GtkTreeIter iter;
1855 	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
1856 		if (gtk_list_store_remove(GTK_LIST_STORE(model), &iter)) {
1857 			GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
1858 			gtk_tree_selection_select_path(selection, path);
1859 			gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview), path, NULL, false, 0, 0);
1860 			gtk_tree_path_free(path);
1861 		}
1862 		oPrefsDlg->write_mainwin_searchwebsite_list();
1863 	}
1864 }
1865 
on_setup_mainwin_searchwebsite_cell_edited(GtkCellRendererText * cell,const gchar * path_string,const gchar * new_text,PrefsDlg * oPrefsDlg)1866 void PrefsDlg::on_setup_mainwin_searchwebsite_cell_edited(GtkCellRendererText *cell, const gchar *path_string, const gchar *new_text, PrefsDlg *oPrefsDlg)
1867 {
1868 	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW (oPrefsDlg->searchwebsite_treeview));
1869 	GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
1870 	GtkTreeIter iter;
1871 
1872 	glong column;
1873 	column = (glong)(g_object_get_data (G_OBJECT (cell), "column"));
1874 	gtk_tree_model_get_iter (model, &iter, path);
1875 
1876 	switch (column) {
1877 	case 0:
1878 	case 1:
1879 		if (new_text[0]) {
1880 			gtk_list_store_set (GTK_LIST_STORE (model), &iter, column, new_text, -1);
1881 			oPrefsDlg->write_mainwin_searchwebsite_list();
1882 		}
1883 		break;
1884 	case 2:
1885 		if (new_text[0]) {
1886 			if (!strstr(new_text, "%s")) {
1887 				GtkWidget *message_dlg;
1888 
1889 				message_dlg = gtk_message_dialog_new (
1890 					GTK_WINDOW (oPrefsDlg->window),
1891 					(GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1892 					GTK_MESSAGE_INFO,
1893 					GTK_BUTTONS_OK,
1894 					_("The website search link should contain a \"%%s\" string for querying a word."));
1895 
1896 				gtk_dialog_set_default_response (GTK_DIALOG (message_dlg), GTK_RESPONSE_OK);
1897 
1898 				gtk_window_set_resizable (GTK_WINDOW (message_dlg), FALSE);
1899 
1900 				gtk_dialog_run (GTK_DIALOG (message_dlg));
1901 				gtk_widget_destroy (message_dlg);
1902 			}
1903 			else {
1904 				gtk_list_store_set (GTK_LIST_STORE (model), &iter, 2, new_text, -1);
1905 				oPrefsDlg->write_mainwin_searchwebsite_list();
1906 			}
1907 		}
1908 		break;
1909 
1910     }
1911 
1912 	gtk_tree_path_free (path);
1913 }
1914 
setup_mainwin_searchwebsite_page()1915 void PrefsDlg::setup_mainwin_searchwebsite_page()
1916 {
1917 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Search website"), GTK_STOCK_JUMP_TO);
1918 	GtkWidget *vbox2;
1919 #if GTK_MAJOR_VERSION >= 3
1920 	vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1921 #else
1922 	vbox2 = gtk_vbox_new(false, 6);
1923 #endif
1924 	gtk_box_pack_start(GTK_BOX(vbox), vbox2, true, true,0);
1925 
1926 	GtkListStore *model;
1927 	model = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
1928 
1929 	const std::list<std::string> &web_list=
1930 		conf->get_strlist_at("main_window/search_website_list");
1931 
1932 	GtkTreeIter iter;
1933 	for (std::list<std::string>::const_iterator wit=web_list.begin();
1934 			 wit!=web_list.end(); ++wit) {
1935 		std::vector<std::string> l=split(*wit, '\t');
1936 		if (l.size()==3) {
1937 			gtk_list_store_append(model, &iter);
1938 			gtk_list_store_set(model, &iter,
1939 												 0, l[0].c_str(),
1940 												 1, l[1].c_str(),
1941 												 2, l[2].c_str(),
1942 												 3, TRUE,
1943 												 -1);
1944 		}
1945 	}
1946 
1947 	GtkWidget *sw;
1948 	sw = gtk_scrolled_window_new (NULL, NULL);
1949 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
1950       	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1951 				      GTK_POLICY_AUTOMATIC,
1952 				      GTK_POLICY_AUTOMATIC);
1953 
1954 	gtk_widget_set_size_request (sw, 300, 180);
1955 
1956 	searchwebsite_treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(model));
1957 	g_object_unref (G_OBJECT (model));
1958 	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (searchwebsite_treeview), TRUE);
1959 
1960 	GtkTreeSelection *selection;
1961 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (searchwebsite_treeview));
1962 
1963 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
1964 
1965 	GtkCellRenderer *renderer;
1966 	GtkTreeViewColumn *column;
1967 
1968 	renderer = gtk_cell_renderer_text_new ();
1969 	g_signal_connect (renderer, "edited", G_CALLBACK (on_setup_mainwin_searchwebsite_cell_edited), this);
1970   	g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
1971 	g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER(0));
1972 	column = gtk_tree_view_column_new_with_attributes (_("Website Name"), renderer, "text", 0, "editable", 3, NULL);
1973 	gtk_tree_view_append_column (GTK_TREE_VIEW(searchwebsite_treeview), column);
1974   	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
1975 
1976 	renderer = gtk_cell_renderer_text_new ();
1977 	g_signal_connect (renderer, "edited", G_CALLBACK (on_setup_mainwin_searchwebsite_cell_edited), this);
1978   	g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
1979 	g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER(1));
1980 	column = gtk_tree_view_column_new_with_attributes (_("Website link"), renderer, "text", 1, "editable", 3, NULL);
1981 	gtk_tree_view_append_column (GTK_TREE_VIEW(searchwebsite_treeview), column);
1982   	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
1983 
1984 	renderer = gtk_cell_renderer_text_new ();
1985 	g_signal_connect (renderer, "edited", G_CALLBACK (on_setup_mainwin_searchwebsite_cell_edited), this);
1986   	g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
1987 	g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER(2));
1988 	column = gtk_tree_view_column_new_with_attributes (_("Website search link"), renderer, "text", 2, "editable", 3, NULL);
1989 	gtk_tree_view_append_column (GTK_TREE_VIEW(searchwebsite_treeview), column);
1990   	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
1991 
1992 	gtk_container_add (GTK_CONTAINER (sw), searchwebsite_treeview);
1993 	gtk_box_pack_start (GTK_BOX (vbox2), sw, TRUE, TRUE, 0);
1994 
1995 	GtkWidget *hbox1;
1996 #if GTK_MAJOR_VERSION >= 3
1997 	hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1998 #else
1999 	hbox1 = gtk_hbox_new(false,6);
2000 #endif
2001 	GtkWidget *button;
2002 	button = gtk_button_new();
2003 	GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
2004 	gtk_container_add(GTK_CONTAINER(button), image);
2005 	gtk_widget_set_can_focus (button, FALSE);
2006 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_mainwin_searchwebsite_moveup_button_clicked), this);
2007 	gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
2008 	button = gtk_button_new();
2009 	image = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
2010 	gtk_container_add(GTK_CONTAINER(button), image);
2011 	gtk_widget_set_can_focus (button, FALSE);
2012 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_mainwin_searchwebsite_movedown_button_clicked), this);
2013 	gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
2014 	button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
2015 	gtk_widget_set_can_focus (button, FALSE);
2016 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_mainwin_searchwebsite_remove_button_clicked), this);
2017 	gtk_box_pack_end (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
2018 
2019 /*	button = gtk_button_new();
2020 	GtkWidget *align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
2021 	gtk_container_add (GTK_CONTAINER (button), align);
2022 	GtkWidget *hbox2 = gtk_hbox_new (FALSE, 2);
2023 	gtk_container_add (GTK_CONTAINER (align), hbox2);
2024 	label = gtk_label_new(NULL);
2025 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Modify"));
2026 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), button);
2027 	image = gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_BUTTON);
2028 	gtk_box_pack_start (GTK_BOX (hbox2), image, FALSE, FALSE, 0);
2029 	gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
2030 	gtk_widget_set_can_focus (button, FALSE);
2031 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_mainwin_searchwebsite_edit_button_clicked), this);
2032 	gtk_box_pack_end (GTK_BOX (hbox1), button, FALSE, FALSE, 0);*/
2033 
2034 	button = gtk_button_new_from_stock(GTK_STOCK_ADD);
2035 	gtk_widget_set_can_focus (button, FALSE);
2036 	g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_setup_mainwin_searchwebsite_add_button_clicked), this);
2037 	gtk_box_pack_end (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
2038 
2039 	gtk_box_pack_start (GTK_BOX (vbox2), hbox1, false, false, 0);
2040 }
2041 
on_setup_NotificationAreaIcon_MiddleButtonClickAction_changed(GtkComboBox * combobox,PrefsDlg * oPrefsDlg)2042 void PrefsDlg::on_setup_NotificationAreaIcon_MiddleButtonClickAction_changed(GtkComboBox *combobox, PrefsDlg *oPrefsDlg)
2043 {
2044 	int index = gtk_combo_box_get_active(combobox);
2045 	conf->set_int_at("notification_area_icon/middle_click_action", index);
2046 }
2047 
setup_NotificationAreaIcon_options_page()2048 void PrefsDlg::setup_NotificationAreaIcon_options_page()
2049 {
2050 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Options"), GTK_STOCK_DND);
2051 
2052 #if GTK_MAJOR_VERSION >= 3
2053 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
2054 #else
2055 	GtkWidget *hbox = gtk_hbox_new(FALSE, 12);
2056 #endif
2057 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2058 	GtkWidget *label = gtk_label_new(_("When middle mouse button is clicked:"));
2059 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
2060 	GtkWidget *cb = gtk_combo_box_text_new();
2061 	/* order of items must match the TNotifAreaMiddleClickAction enum */
2062 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("Query selection in floating window"));
2063 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("Query selection in main window"));
2064 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb), _("Do nothing"));
2065 	gtk_box_pack_start(GTK_BOX(hbox), cb, TRUE, TRUE, 0);
2066 	int action = conf->get_int_at("notification_area_icon/middle_click_action");
2067 	gtk_combo_box_set_active(GTK_COMBO_BOX(cb), action);
2068 	g_signal_connect(G_OBJECT(cb), "changed", G_CALLBACK(on_setup_NotificationAreaIcon_MiddleButtonClickAction_changed), this);
2069 }
2070 
2071 
on_setup_floatwin_pronounce_ckbutton_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)2072 void PrefsDlg::on_setup_floatwin_pronounce_ckbutton_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
2073 {
2074   conf->set_bool_at("floating_window/pronounce_when_popup",
2075 								 gtk_toggle_button_get_active(button));
2076 }
2077 
on_setup_show_float_if_not_found(GtkToggleButton * button,PrefsDlg * oPrefsDlg)2078 void PrefsDlg::on_setup_show_float_if_not_found(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
2079 {
2080   conf->set_bool_at("floating_window/show_if_not_found",
2081 								 gtk_toggle_button_get_active(button));
2082 }
2083 
setup_floatwin_options_page()2084 void PrefsDlg::setup_floatwin_options_page()
2085 {
2086 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Options"), GTK_STOCK_DND);
2087 #if GTK_MAJOR_VERSION >= 3
2088 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
2089 #else
2090 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
2091 #endif
2092 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
2093 	GtkWidget *check_button = gtk_check_button_new_with_mnemonic(_("_Pronounce the word when it pops up."));
2094 	bool pronounce_when_popup=
2095 		conf->get_bool_at("floating_window/pronounce_when_popup");
2096 
2097 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
2098 															 pronounce_when_popup);
2099 	g_signal_connect(G_OBJECT(check_button), "toggled", G_CALLBACK(on_setup_floatwin_pronounce_ckbutton_toggled), this);
2100 	gtk_box_pack_start(GTK_BOX(vbox1), check_button, FALSE, FALSE, 0);
2101 
2102 	check_button = gtk_check_button_new_with_mnemonic(_("_Show floating window if word not found."));
2103 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), conf->get_bool_at("floating_window/show_if_not_found"));
2104 	g_signal_connect(G_OBJECT(check_button), "toggled", G_CALLBACK(on_setup_show_float_if_not_found), this);
2105 	gtk_box_pack_start(GTK_BOX(vbox1), check_button, FALSE, FALSE, 0);
2106 }
2107 
2108 #ifndef CONFIG_GPE
on_setup_floatwin_size_max_width_spinbutton_changed(GtkSpinButton * button,PrefsDlg * oPrefsDlg)2109 void PrefsDlg::on_setup_floatwin_size_max_width_spinbutton_changed(GtkSpinButton *button, PrefsDlg *oPrefsDlg)
2110 {
2111 	gint width = gtk_spin_button_get_value_as_int(button);
2112 	conf->set_int_at("floating_window/max_window_width", width);
2113 }
2114 
on_setup_floatwin_size_max_height_spinbutton_changed(GtkSpinButton * button,PrefsDlg * oPrefsDlg)2115 void PrefsDlg::on_setup_floatwin_size_max_height_spinbutton_changed(GtkSpinButton *button, PrefsDlg *oPrefsDlg)
2116 {
2117 	gint height = gtk_spin_button_get_value_as_int(button);
2118 	conf->set_int_at("floating_window/max_window_height", height);
2119 }
2120 
on_setup_floatwin_use_custom_bg_toggled(GtkToggleButton * button,PrefsDlg * oPrefsDlg)2121 void PrefsDlg::on_setup_floatwin_use_custom_bg_toggled(GtkToggleButton *button, PrefsDlg *oPrefsDlg)
2122 {
2123 	gboolean use = gtk_toggle_button_get_active(button);
2124 	conf->set_bool_at("floating_window/use_custom_bg", use);
2125 }
2126 
on_setup_floatwin_color_set(GtkColorButton * widget,PrefsDlg * oPrefsDlg)2127 void PrefsDlg::on_setup_floatwin_color_set(GtkColorButton *widget, PrefsDlg *oPrefsDlg)
2128 {
2129 #if GTK_MAJOR_VERSION >= 3
2130 	GdkRGBA color;
2131 	gtk_color_button_get_rgba(widget, &color);
2132 	conf->set_double_at("floating_window/bg_red", color.red);
2133 	conf->set_double_at("floating_window/bg_green", color.green);
2134 	conf->set_double_at("floating_window/bg_blue", color.blue);
2135 #else
2136 	GdkColor color;
2137 	gtk_color_button_get_color(widget, &color);
2138 	conf->set_int_at("floating_window/bg_red", color.red);
2139 	conf->set_int_at("floating_window/bg_green", color.green);
2140 	conf->set_int_at("floating_window/bg_blue", color.blue);
2141 #endif
2142 	gpAppFrame->oFloatWin.set_bg();
2143 }
2144 
on_setup_floatwin_transparent_scale_changed(GtkRange * range,PrefsDlg * oPrefsDlg)2145 void PrefsDlg::on_setup_floatwin_transparent_scale_changed(GtkRange *range, PrefsDlg *oPrefsDlg)
2146 {
2147 	gint transparent = (gint)gtk_range_get_value(range);
2148 	conf->set_int_at("floating_window/transparent", transparent);
2149 }
2150 
setup_floatwin_size_page()2151 void PrefsDlg::setup_floatwin_size_page()
2152 {
2153 	GtkWidget *vbox = prepare_page(GTK_NOTEBOOK(notebook), _("Settings"), GTK_STOCK_ZOOM_FIT);
2154 #if GTK_MAJOR_VERSION >= 3
2155 	GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
2156 #else
2157 	GtkWidget *vbox1 = gtk_vbox_new(false, 6);
2158 #endif
2159 	gtk_box_pack_start(GTK_BOX(vbox),vbox1,false,false, 0);
2160 	GtkWidget *table;
2161 	table = gtk_table_new(3, 2, FALSE);
2162 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
2163 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
2164 	gtk_box_pack_start(GTK_BOX(vbox1),table,false,false,0);
2165 
2166 	int max_width=
2167 		conf->get_int_at("floating_window/max_window_width");
2168 	int max_height=
2169 		conf->get_int_at("floating_window/max_window_height");
2170 
2171 	GdkScreen *screen = gtk_window_get_screen(parent_window);
2172 	gint screen_width = gdk_screen_get_width(screen);
2173 	gint screen_height = gdk_screen_get_height(screen);
2174 
2175 	GtkWidget *label=gtk_label_new(NULL);
2176 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("Max window _width:"));
2177 	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
2178 	GtkWidget *spin_button;
2179 	spin_button = gtk_spin_button_new_with_range(MIN_MAX_FLOATWIN_WIDTH,screen_width,1);
2180 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), spin_button);
2181 	gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin_button), GTK_UPDATE_IF_VALID);
2182 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_button), max_width);
2183 	g_signal_connect(G_OBJECT(spin_button), "value-changed",
2184 				 G_CALLBACK(on_setup_floatwin_size_max_width_spinbutton_changed), this);
2185 	gtk_table_attach(GTK_TABLE(table), spin_button, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
2186 	label=gtk_label_new(_("(default:320)"));
2187 	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
2188 
2189 	label=gtk_label_new(NULL);
2190 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("Max window hei_ght:"));
2191 	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
2192 	spin_button = gtk_spin_button_new_with_range(MIN_MAX_FLOATWIN_HEIGHT,screen_height,1);
2193 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), spin_button);
2194 	gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin_button), GTK_UPDATE_IF_VALID);
2195 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_button), max_height);
2196 	g_signal_connect (G_OBJECT (spin_button), "value-changed", G_CALLBACK (on_setup_floatwin_size_max_height_spinbutton_changed), (gpointer)this);
2197 	gtk_table_attach(GTK_TABLE(table), spin_button, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
2198 	label=gtk_label_new(_("(default:240)"));
2199 	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
2200 
2201 #if GTK_MAJOR_VERSION >= 3
2202 	GtkWidget*hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
2203 #else
2204 	GtkWidget*hbox1 = gtk_hbox_new(false, 5);
2205 #endif
2206 	gtk_box_pack_start(GTK_BOX(vbox1),hbox1,false,false,0);
2207 	GtkWidget *check_button = gtk_check_button_new_with_mnemonic(_("_Use custom background color:"));
2208 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), conf->get_bool_at("floating_window/use_custom_bg"));
2209 	g_signal_connect(G_OBJECT(check_button), "toggled", G_CALLBACK(on_setup_floatwin_use_custom_bg_toggled), this);
2210 	gtk_box_pack_start(GTK_BOX(hbox1),check_button,false,false,0);
2211 #if GTK_MAJOR_VERSION >= 3
2212 	GdkRGBA color;
2213 	color.red = conf->get_double_at("floating_window/bg_red");
2214 	color.green = conf->get_double_at("floating_window/bg_green");
2215 	color.blue = conf->get_double_at("floating_window/bg_blue");
2216 	color.alpha = 1;
2217 	GtkWidget *colorbutton = gtk_color_button_new_with_rgba(&color);
2218 #else
2219 	GdkColor color;
2220 	color.red = conf->get_int_at("floating_window/bg_red");
2221 	color.green = conf->get_int_at("floating_window/bg_green");
2222 	color.blue = conf->get_int_at("floating_window/bg_blue");
2223 	GtkWidget *colorbutton = gtk_color_button_new_with_color(&color);
2224 #endif
2225 	g_signal_connect(G_OBJECT(colorbutton), "color-set", G_CALLBACK(on_setup_floatwin_color_set), this);
2226 	gtk_box_pack_start(GTK_BOX(hbox1),colorbutton,false,false,0);
2227 
2228 #if GTK_MAJOR_VERSION >= 3
2229 	GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
2230 #else
2231 	GtkWidget *hbox = gtk_hbox_new(false, 5);
2232 #endif
2233 	gtk_box_pack_start(GTK_BOX(vbox1),hbox,FALSE,FALSE, 0);
2234 	label=gtk_label_new(NULL);
2235 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Transparency:"));
2236 	gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE, 0);
2237 	GtkWidget *hscale;
2238 #if GTK_MAJOR_VERSION >= 3
2239 	hscale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 80, 1);
2240 #else
2241 	hscale = gtk_hscale_new_with_range(0,80,1);
2242 #endif
2243 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), hscale);
2244 	int transparent=conf->get_int_at("floating_window/transparent");
2245 	gtk_range_set_value(GTK_RANGE(hscale), transparent);
2246 	g_signal_connect(G_OBJECT(hscale), "value-changed", G_CALLBACK(on_setup_floatwin_transparent_scale_changed), this);
2247 	gtk_box_pack_start(GTK_BOX(hbox),hscale,TRUE,TRUE, 0);
2248 }
2249 #endif
2250 
create_notebook()2251 GtkWidget* PrefsDlg::create_notebook ()
2252 {
2253 	notebook = gtk_notebook_new();
2254 	GtkNotebook *nb = GTK_NOTEBOOK(notebook);
2255 #ifdef CONFIG_GPE
2256 	gtk_notebook_set_scrollable(nb, true);
2257 #else
2258 	gtk_notebook_set_show_tabs(nb,false);
2259 	gtk_notebook_set_show_border(nb,false);
2260 	setup_logo_page ();
2261 #endif
2262 	setup_dictionary_scan_page ();
2263 	setup_dictionary_font_page ();
2264 	setup_dictionary_cache_page ();
2265 	setup_dictionary_export_page ();
2266 	setup_dictionary_sound_page();
2267 	setup_dictionary_video_page();
2268 	setup_dictionary_article_rendering();
2269 	setup_dictionary_dict_management();
2270 	setup_network_netdict();
2271 	setup_network_web_browser();
2272 	setup_mainwin_input_page ();
2273 	setup_mainwin_options_page ();
2274 	setup_mainwin_searchwebsite_page();
2275 	setup_NotificationAreaIcon_options_page();
2276 	setup_floatwin_options_page ();
2277 #ifdef CONFIG_GPE
2278 	gtk_notebook_set_current_page (nb, 0);
2279 #else
2280 	setup_floatwin_size_page ();
2281 	gtk_notebook_set_current_page (nb, LOGO);
2282 #endif
2283 	return notebook;
2284 }
2285 
2286 
PrefsDlg(GtkWindow * parent,GdkPixbuf * logo,const std::list<std::string> & key_combs_)2287 PrefsDlg::PrefsDlg(GtkWindow *parent, GdkPixbuf *logo, const std::list<std::string>& key_combs_) :
2288 	key_combs(key_combs_)
2289 {
2290   parent_window=parent;
2291 #ifndef CONFIG_GPE
2292   stardict_logo=logo;
2293 #endif
2294 
2295   window = NULL;
2296   skin_changed = false;
2297 }
2298 
ShowModal()2299 bool PrefsDlg::ShowModal()
2300 {
2301   window = gtk_dialog_new();
2302   gtk_window_set_transient_for(GTK_WINDOW(window), parent_window);
2303   gtk_window_set_default_size(GTK_WINDOW(window), -1, 390);
2304 
2305   gtk_dialog_add_button(GTK_DIALOG(window),
2306 			GTK_STOCK_HELP,
2307 			GTK_RESPONSE_HELP);
2308 
2309   gtk_dialog_add_button(GTK_DIALOG(window),
2310 			GTK_STOCK_CLOSE,
2311 			GTK_RESPONSE_CLOSE);
2312   gtk_dialog_set_default_response(GTK_DIALOG(window),
2313 				  GTK_RESPONSE_CLOSE);
2314   g_signal_connect(G_OBJECT(window), "response",
2315 		   G_CALLBACK(response_handler), this);
2316 #ifndef CONFIG_GPE
2317   GtkWidget *hbox;
2318 #if GTK_MAJOR_VERSION >= 3
2319 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
2320 #else
2321 	hbox = gtk_hbox_new (FALSE, 18);
2322 #endif
2323   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
2324   GtkWidget *r;
2325 #if GTK_MAJOR_VERSION >= 3
2326 	r = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
2327 #else
2328 	r = gtk_vbox_new (FALSE, 6);
2329 #endif
2330 
2331   GtkWidget *label;
2332   label = gtk_label_new_with_mnemonic (_("Cat_egories:"));
2333   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2334   g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
2335   create_categories_tree();
2336 
2337 
2338   gtk_box_pack_start(GTK_BOX(r), label, FALSE, FALSE, 0);
2339   gtk_box_pack_start(GTK_BOX(r), categories_window, TRUE, TRUE, 0);
2340 #endif
2341 
2342   GtkWidget *l = create_notebook ();
2343 
2344 #ifdef CONFIG_GPE
2345 	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), l, true, true, 0);
2346 #else
2347 	gtk_box_pack_start (GTK_BOX (hbox), r, FALSE, FALSE, 0);
2348 	gtk_box_pack_start (GTK_BOX (hbox), l, TRUE, TRUE, 0);
2349 	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG (window))), hbox, true, true, 0);
2350 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), categories_tree);
2351 #endif
2352 
2353   gtk_widget_show_all (gtk_dialog_get_content_area(GTK_DIALOG (window)));
2354   gtk_window_set_title (GTK_WINDOW (window), _("Preferences"));
2355 
2356 #ifndef CONFIG_GPE
2357   resize_categories_tree();
2358 #endif
2359 	gint result;
2360 	while ((result = gtk_dialog_run(GTK_DIALOG(window)))==GTK_RESPONSE_HELP)
2361 		;
2362 	if (result != GTK_RESPONSE_NONE) {
2363 		const gchar *ch;
2364 		ch = gtk_entry_get_text(eExportFile);
2365 		if (ch) {
2366 #ifdef _WIN32
2367 			conf->set_string_at("dictionary/export_file", rel_path_to_data_dir(ch));
2368 #else
2369 			conf->set_string_at("dictionary/export_file", ch);
2370 #endif
2371 		}
2372 #ifndef _WIN32
2373 		ch = gtk_entry_get_text(eTTSCommandline);
2374 		if (ch) {
2375 			conf->set_string("/apps/stardict/preferences/dictionary/tts_program_cmdline", ch);
2376 			gpAppFrame->oReadWord.tts_program_cmdline = ch;
2377 		}
2378 #endif
2379 		const gchar *server;
2380 		ch = gtk_entry_get_text(eStarDictServer);
2381 		if (ch && ch[0])
2382 			server = ch;
2383 		else
2384 			server = _("dict.stardict.org");
2385 		conf->set_string_at("network/server", server);
2386 		int port;
2387 		ch = gtk_entry_get_text(eStarDictServerPort);
2388 		if (ch && ch[0])
2389 			port = atoi(ch);
2390 		else
2391 			port = 2628;
2392 		conf->set_int_at("network/port", port);
2393 		gpAppFrame->oStarDictClient.set_server(server, port);
2394 		ch = gtk_entry_get_text(eSoundPlayCommand);
2395 		if (ch)
2396 			conf->set_string_at("dictionary/sound_play_command", ch);
2397 		ch = gtk_entry_get_text(eVideoPlayCommand);
2398 		if (ch)
2399 			conf->set_string_at("dictionary/video_play_command", ch);
2400 		ch = gtk_entry_get_text(eURLOpenCommand);
2401 		if (ch)
2402 			conf->set_string_at("dictionary/url_open_command", ch);
2403 		GtkTextBuffer *text_view_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tts_textview));
2404 		GtkTextIter start_iter;
2405 		GtkTextIter end_iter;
2406 		gtk_text_buffer_get_start_iter(text_view_buffer, &start_iter);
2407 		gtk_text_buffer_get_end_iter(text_view_buffer, &end_iter);
2408 		gchar *text = gtk_text_buffer_get_text(text_view_buffer, &start_iter, &end_iter, FALSE);
2409 		std::list<std::string> ttspathlist;
2410 		{
2411 			const gchar* p = text;
2412 			const gchar* q;
2413 			while(true)
2414 			{
2415 				q = strchr(p, '\n');
2416 				if(!q)
2417 					q = strchr(p, '\0');
2418 				if(p<q)
2419 					ttspathlist.push_back(std::string(p, q-p));
2420 				if(!*q)
2421 					break;
2422 				p = q + 1;
2423 			}
2424 		}
2425 #ifdef _WIN32
2426 		/* Convert paths to relative paths.
2427 		The text buffer was initialized with relative paths.
2428 		If the user has not changed them, convertion will not mangle paths, they'll be unchanged.
2429 		When the user added a new path it'll be converted to a relative path if possible. */
2430 		{
2431 			std::list<std::string> paths;
2432 			rel_path_to_data_dir(ttspathlist, paths);
2433 			std::swap(paths, ttspathlist);
2434 		}
2435 #endif
2436 		conf->set_strlist_at("dictionary/tts_path", ttspathlist);
2437 		gpAppFrame->oReadWord.LoadRealTtsPath(ttspathlist);
2438 		g_free(text);
2439 		gtk_widget_destroy(GTK_WIDGET(window));
2440 		window = NULL;
2441 		return false;
2442 	} else {
2443 		return true;
2444 	}
2445 }
2446 
Close()2447 void PrefsDlg::Close()
2448 {
2449 	if (window) {
2450 		gtk_widget_destroy (window);
2451 		window = NULL;
2452 	}
2453 }
2454 
2455 #ifndef CONFIG_GPE
resize_categories_tree(void)2456 void PrefsDlg::resize_categories_tree(void)
2457 {
2458   //this is hack for prevet horizontaly scrolling
2459   //if you know how it make better, just write
2460   GtkRequisition rtv, rsw;
2461 #if GTK_MAJOR_VERSION >= 3
2462   gtk_widget_get_preferred_size(categories_tree, NULL, &rtv);
2463   gtk_widget_get_preferred_size(gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(categories_window)), NULL, &rsw);
2464 #else
2465 	gtk_widget_size_request(categories_tree, &rtv);
2466 	gtk_widget_size_request(GTK_SCROLLED_WINDOW(categories_window)->vscrollbar, &rsw);
2467 #endif
2468   gtk_widget_set_size_request(categories_window, rtv.width+rsw.width+25, -1);
2469 }
2470 #endif
2471