NetSurf
preferences.c
Go to the documentation of this file.
1/*
2 * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf 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; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <math.h>
22#include <string.h>
23
24#include "utils/messages.h"
25#include "utils/nsoption.h"
26#include "utils/file.h"
27#include "utils/log.h"
28#include "utils/nsurl.h"
30#include "desktop/searchweb.h"
31
32#include "gtk/compat.h"
33#include "gtk/toolbar_items.h"
34#include "gtk/window.h"
35#include "gtk/gui.h"
36#include "gtk/scaffolding.h"
37#include "gtk/resources.h"
38#include "gtk/preferences.h"
39
40/* private prefs */
41struct ppref {
42 /** dialog handle created when window first accessed */
43 GObject *dialog;
44
46
47 /* widgets which are accessed from outside their own signal handlers */
49 GtkEntry *entryProxyHost;
50 GtkEntry *entryProxyUser;
53 GtkSpinButton *spinProxyPort;
54
55 /* dynamic list stores */
56 GtkListStore *content_language;
57 GtkListStore *search_providers;
58};
59
60static struct ppref ppref;
61
62
63/* Set netsurf option based on toggle button state
64 *
65 * This works for any widget which subclasses togglebutton (checkbox,
66 * radiobutton etc.)
67 */
68#define TOGGLEBUTTON_SIGNALS(WIDGET, OPTION) \
69G_MODULE_EXPORT void \
70nsgtk_preferences_##WIDGET##_toggled(GtkToggleButton *togglebutton, \
71 struct ppref *priv); \
72G_MODULE_EXPORT void \
73nsgtk_preferences_##WIDGET##_toggled(GtkToggleButton *togglebutton, \
74 struct ppref *priv) \
75{ \
76 nsoption_set_bool(OPTION, \
77 gtk_toggle_button_get_active(togglebutton)); \
78} \
79 \
80G_MODULE_EXPORT void \
81nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, \
82 struct ppref *priv); \
83G_MODULE_EXPORT void \
84nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, \
85 struct ppref *priv) \
86{ \
87 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), \
88 nsoption_bool(OPTION)); \
89}
90
91#define SPINBUTTON_SIGNALS(WIDGET, OPTION, MULTIPLIER) \
92G_MODULE_EXPORT void \
93nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \
94 struct ppref *priv); \
95G_MODULE_EXPORT void \
96nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \
97 struct ppref *priv) \
98{ \
99 nsoption_set_int(OPTION, \
100 round(gtk_spin_button_get_value(spinbutton) * MULTIPLIER)); \
101} \
102 \
103G_MODULE_EXPORT void \
104nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \
105G_MODULE_EXPORT void \
106nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \
107{ \
108 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), \
109 ((gdouble)nsoption_int(OPTION)) / MULTIPLIER); \
110}
111
112#define SPINBUTTON_UINT_SIGNALS(WIDGET, OPTION, MULTIPLIER) \
113G_MODULE_EXPORT void \
114nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \
115 struct ppref *priv); \
116G_MODULE_EXPORT void \
117nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \
118 struct ppref *priv) \
119{ \
120 nsoption_set_uint(OPTION, \
121 round(gtk_spin_button_get_value(spinbutton) * MULTIPLIER)); \
122} \
123 \
124G_MODULE_EXPORT void \
125nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \
126G_MODULE_EXPORT void \
127nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \
128{ \
129 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), \
130 ((gdouble)nsoption_uint(OPTION)) / MULTIPLIER); \
131}
132
133#define ENTRY_SIGNALS(WIDGET, OPTION) \
134G_MODULE_EXPORT void \
135nsgtk_preferences_##WIDGET##_changed(GtkEditable *editable, struct ppref *priv); \
136G_MODULE_EXPORT void \
137nsgtk_preferences_##WIDGET##_changed(GtkEditable *editable, struct ppref *priv)\
138{ \
139 nsoption_set_charp(OPTION, \
140 strdup(gtk_entry_get_text(GTK_ENTRY(editable)))); \
141} \
142 \
143G_MODULE_EXPORT void \
144nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \
145G_MODULE_EXPORT void \
146nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \
147{ \
148 const char *OPTION; \
149 OPTION = nsoption_charp(OPTION); \
150 if (OPTION != NULL) { \
151 gtk_entry_set_text(GTK_ENTRY(widget), OPTION); \
152 } \
153}
154
155/* GTK module requires these to be exported symbols so these all need
156 * forward declaring to avoid warnings
157 */
158G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_changed(GtkComboBox *combo, struct ppref *priv);
159G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_realize(GtkWidget *widget, struct ppref *priv);
160G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo, struct ppref *priv);
161G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget, struct ppref *priv);
162G_MODULE_EXPORT void nsgtk_preferences_comboDefault_changed(GtkComboBox *combo, struct ppref *priv);
163G_MODULE_EXPORT void nsgtk_preferences_comboDefault_realize(GtkWidget *widget, struct ppref *priv);
164G_MODULE_EXPORT void nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv);
165G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_changed(GtkComboBox *combo, struct ppref *priv);
166G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_realize(GtkWidget *widget, struct ppref *priv);
167G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton, struct ppref *priv);
168G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_realize(GtkWidget *widget, struct ppref *priv);
169G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget, struct ppref *priv);
170G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_realize(GtkWidget *widget, struct ppref *priv);
171G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_changed(GtkComboBox *widget, struct ppref *priv);
172G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_realize(GtkWidget *widget, struct ppref *priv);
173G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget, struct ppref *priv);
174G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_realize(GtkWidget *widget, struct ppref *priv);
175G_MODULE_EXPORT void nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv);
176G_MODULE_EXPORT void nsgtk_preferences_setDefaultPage_clicked(GtkButton *button, struct ppref *priv);
177G_MODULE_EXPORT void nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv);
178G_MODULE_EXPORT void nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv);
179G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_selectionchanged(GtkFileChooser *chooser, struct ppref *priv);
180G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_realize(GtkWidget *widget, struct ppref *priv);
181G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_response(GtkDialog *dlg, gint resid);
182G_MODULE_EXPORT gboolean nsgtk_preferences_dialogPreferences_deleteevent(GtkDialog *dlg, struct ppref *priv);
183G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_destroy(GtkDialog *dlg, struct ppref *priv);
184
185
186/********* PDF **********/
187
188/* Appearance */
189
190/* no images in output */
191TOGGLEBUTTON_SIGNALS(checkSuppressImages, suppress_images)
192
193/* no background images */
194TOGGLEBUTTON_SIGNALS(checkRemoveBackgrounds, remove_backgrounds)
195
196/* scale to fit page */
197TOGGLEBUTTON_SIGNALS(checkFitPage, enable_loosening)
198
199/* port */
200SPINBUTTON_SIGNALS(spinExportScale, export_scale, 1.0)
201
202/* Margins */
203SPINBUTTON_SIGNALS(spinMarginTop, margin_top, 1.0)
204SPINBUTTON_SIGNALS(spinMarginBottom, margin_bottom, 1.0)
205SPINBUTTON_SIGNALS(spinMarginLeft, margin_left, 1.0)
206SPINBUTTON_SIGNALS(spinMarginRight, margin_right, 1.0)
207
208
209/* Generation */
210
211/* output is compressed */
212TOGGLEBUTTON_SIGNALS(checkCompressPDF, enable_PDF_compression)
213
214/* output has a password */
215TOGGLEBUTTON_SIGNALS(checkPasswordPDF, enable_PDF_password)
216
217/********* Network **********/
218
219/* HTTP proxy */
220static void set_proxy_widgets_sensitivity(int proxyval, struct ppref *priv)
221{
222 gboolean host;
223 gboolean port;
224 gboolean user;
225 gboolean pass;
226 gboolean noproxy;
227
228 switch (proxyval) {
229 case 0: /* no proxy */
230 host = FALSE;
231 port = FALSE;
232 user = FALSE;
233 pass = FALSE;
234 noproxy = FALSE;
235 break;
236
237 case 1: /* proxy with no auth */
238 host = TRUE;
239 port = TRUE;
240 user = FALSE;
241 pass = FALSE;
242 noproxy = TRUE;
243 break;
244
245 case 2: /* proxy with basic auth */
246 host = TRUE;
247 port = TRUE;
248 user = TRUE;
249 pass = TRUE;
250 noproxy = TRUE;
251 break;
252
253 case 3: /* proxy with ntlm auth */
254 host = TRUE;
255 port = TRUE;
256 user = TRUE;
257 pass = TRUE;
258 noproxy = TRUE;
259 break;
260
261 case 4: /* system proxy */
262 host = FALSE;
263 port = FALSE;
264 user = FALSE;
265 pass = FALSE;
266 noproxy = FALSE;
267 break;
268
269 default:
270 return;
271 }
272
273 gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyHost), host);
274 gtk_widget_set_sensitive(GTK_WIDGET(priv->spinProxyPort), port);
275 gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyUser), user);
276 gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyPassword), pass);
277 gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyNoproxy), noproxy);
278
279}
280
281G_MODULE_EXPORT void
282nsgtk_preferences_comboProxyType_changed(GtkComboBox *combo, struct ppref *priv)
283{
284 int proxy_sel;
285 proxy_sel = gtk_combo_box_get_active(combo);
286
287 switch (proxy_sel) {
288 case 0: /* no proxy */
289 nsoption_set_bool(http_proxy, false);
290 break;
291
292 case 1: /* proxy with no auth */
293 nsoption_set_bool(http_proxy, true);
295 break;
296
297 case 2: /* proxy with basic auth */
298 nsoption_set_bool(http_proxy, true);
300 break;
301
302 case 3: /* proxy with ntlm auth */
303 nsoption_set_bool(http_proxy, true);
305 break;
306
307 case 4: /* system proxy */
308 nsoption_set_bool(http_proxy, true);
310 break;
311 }
312
313 set_proxy_widgets_sensitivity(proxy_sel, priv);
314}
315
316G_MODULE_EXPORT void
317nsgtk_preferences_comboProxyType_realize(GtkWidget *widget, struct ppref *priv)
318{
319 int proxytype = 0; /* no proxy by default */
320
321 if (nsoption_bool(http_proxy) == true) {
322 /* proxy type combo box starts with disabled, to allow
323 * for this the http_proxy option needs combining with
324 * the http_proxy_auth option
325 */
326 proxytype = nsoption_int(http_proxy_auth) + 1;
327 if (nsoption_charp(http_proxy_host) == NULL) {
328 /* set to use a proxy without a host, turn proxy off */
329 proxytype = 0;
330 } else if (((proxytype == 2) ||
331 (proxytype == 3)) &&
332 ((nsoption_charp(http_proxy_auth_user) == NULL) ||
333 (nsoption_charp(http_proxy_auth_pass) == NULL))) {
334 /* authentication selected with empty credentials, turn proxy off */
335 proxytype = 0;
336 }
337 }
338 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), proxytype);
339
340 set_proxy_widgets_sensitivity(proxytype, priv);
341}
342
343/* host */
344ENTRY_SIGNALS(entryProxyHost, http_proxy_host)
345
346/* port */
347SPINBUTTON_SIGNALS(spinProxyPort, http_proxy_port, 1.0)
348
349/* user */
350ENTRY_SIGNALS(entryProxyUser, http_proxy_auth_user)
351
352/* password */
353ENTRY_SIGNALS(entryProxyPassword, http_proxy_auth_pass)
354
355/* no proxy */
356ENTRY_SIGNALS(entryProxyNoproxy, http_proxy_noproxy)
357
358/* Fetching */
359
360/* maximum fetchers */
361SPINBUTTON_SIGNALS(spinMaxFetchers, max_fetchers, 1.0)
362
363/* fetches per host */
364SPINBUTTON_SIGNALS(spinFetchesPerHost, max_fetchers_per_host, 1.0)
365
366/* cached connections */
367SPINBUTTON_SIGNALS(spinCachedConnections, max_cached_fetch_handles, 1.0)
368
369
370/********* Privacy **********/
371
372/* General */
373
374/* enable referral submission */
375TOGGLEBUTTON_SIGNALS(checkSendReferer, send_referer)
376
377/* send do not track */
378TOGGLEBUTTON_SIGNALS(checkSendDNT, do_not_track)
379
380/* History */
381
382/* local history shows url tooltips */
383TOGGLEBUTTON_SIGNALS(checkHoverURLs, hover_urls)
384
385/* remember browsing history */
386SPINBUTTON_SIGNALS(spinHistoryAge, history_age, 1.0)
387
388/* Cache */
389
390/* memory cache size */
391SPINBUTTON_SIGNALS(spinMemoryCacheSize, memory_cache_size, (1024*1024))
392
393/* disc cache size */
394SPINBUTTON_UINT_SIGNALS(spinDiscCacheSize, disc_cache_size, (1024*1024))
395
396
397/* disc cache age */
398SPINBUTTON_SIGNALS(spinDiscCacheAge, disc_cache_age, 1.0)
399
400
401/********* Content **********/
402
403/* Control */
404
405
406/* prevent popups */
407TOGGLEBUTTON_SIGNALS(checkDisablePopups, disable_popups)
408
409/* hide adverts */
410TOGGLEBUTTON_SIGNALS(checkHideAdverts, block_advertisements)
411
412/* enable javascript */
413TOGGLEBUTTON_SIGNALS(checkEnableJavascript, enable_javascript)
414
415/* load and display of images */
416G_MODULE_EXPORT void
418 struct ppref *priv)
419{
420 int img_sel;
421 /* get the row number for the selection */
422 img_sel = gtk_combo_box_get_active(combo);
423 switch (img_sel) {
424 case 0:
425 /* background and foreground */
426 nsoption_set_bool(foreground_images, true);
427 nsoption_set_bool(background_images, true);
428 break;
429
430 case 1:
431 /* foreground only */
432 nsoption_set_bool(foreground_images, true);
433 nsoption_set_bool(background_images, false);
434 break;
435
436 case 2:
437 /* background only */
438 nsoption_set_bool(foreground_images, false);
439 nsoption_set_bool(background_images, true);
440 break;
441
442 case 3:
443 /* no images */
444 nsoption_set_bool(foreground_images, false);
445 nsoption_set_bool(background_images, false);
446 break;
447 }
448}
449
450G_MODULE_EXPORT void
452 struct ppref *priv)
453{
454 if (nsoption_bool(foreground_images)) {
455 if (nsoption_bool(background_images)) {
456 /* background and foreground */
457 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
458 } else {
459 /* foreground only */
460 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 1);
461 }
462 } else {
463 if (nsoption_bool(background_images)) {
464 /* background only */
465 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 2);
466 } else {
467 /* no images */
468 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 3);
469 }
470 }
471}
472
473/* Animation */
474
475/* enable animation */
476TOGGLEBUTTON_SIGNALS(checkEnableAnimations, animate_images)
477
478/* Fonts */
479
480/* default font */
481G_MODULE_EXPORT void
482nsgtk_preferences_comboDefault_changed(GtkComboBox *combo, struct ppref *priv)
483{
484 int font_sel;
485 /* get the row number for the selection */
486 font_sel = gtk_combo_box_get_active(combo);
487 if ((font_sel >= 0) && (font_sel <= 4)) {
488 nsoption_set_int(font_default, font_sel);
489 }
490}
491
492G_MODULE_EXPORT void
493nsgtk_preferences_comboDefault_realize(GtkWidget *widget, struct ppref *priv)
494{
495 gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
496 nsoption_int(font_default));
497}
498
499/* default font size */
500SPINBUTTON_SIGNALS(spinDefaultSize, font_size, 10.0)
501
502/* preview - actually reflow all views */
503G_MODULE_EXPORT void
504nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv)
505{
507}
508
509
510/* Language */
511
512/* accept language */
513G_MODULE_EXPORT void
515 struct ppref *priv)
516{
517 gchar *lang = NULL;
518 GtkTreeIter iter;
519 GtkTreeModel *model;
520
521 /* Obtain currently selected item from combo box.
522 * If nothing is selected, do nothing.
523 */
524 if (gtk_combo_box_get_active_iter(combo, &iter)) {
525 /* Obtain data model from combo box. */
526 model = gtk_combo_box_get_model(combo);
527
528 /* Obtain string from model. */
529 gtk_tree_model_get(model, &iter, 0, &lang, -1);
530 }
531
532 if (lang != NULL) {
533 nsoption_set_charp(accept_language, strdup(lang));
534 g_free(lang);
535 }
536}
537
538/**
539 * populate language combo from data
540 */
541static nserror
542comboboxLanguage_add_from_data(GtkListStore *liststore,
543 GtkComboBox *combobox,
544 const char *accept_language,
545 const uint8_t *data,
546 size_t data_size)
547{
548 int active_language = -1;
549 GtkTreeIter iter;
550 int combo_row_count = 0;
551 const uint8_t *s;
552 const uint8_t *nl;
553 char buf[50];
554 int bufi = 0;
555
556 gtk_list_store_clear(liststore);
557 s = data;
558
559 while (s < (data + data_size)) {
560 /* find nl and copy buffer */
561 for (nl = s; nl < data + data_size; nl++) {
562 if ((*nl == '\n') || (bufi == (sizeof(buf) - 2))) {
563 buf[bufi] = 0; /* null terminate */
564 break;
565 }
566 buf[bufi++] = *nl;
567 }
568 if (bufi > 0) {
569 gtk_list_store_append(liststore, &iter);
570 gtk_list_store_set(liststore, &iter, 0, buf, -1 );
571
572 if (strcmp(buf, accept_language) == 0) {
573 active_language = combo_row_count;
574 }
575
576 combo_row_count++;
577 }
578 bufi = 0;
579 s = nl + 1; /* skip newline */
580 }
581
582 /* if configured language was not in list, add it */
583 if (active_language == -1) {
584 gtk_list_store_append(liststore, &iter);
585 gtk_list_store_set(liststore, &iter, 0, accept_language, -1);
586 active_language = combo_row_count;
587 }
588
589 gtk_combo_box_set_active(combobox, active_language);
590
591 return NSERROR_OK;
592}
593
594/**
595 * populate language combo from file
596 */
597static nserror
598comboboxLanguage_add_from_file(GtkListStore *liststore,
599 GtkComboBox *combobox,
600 const char *accept_language,
601 const char *file_location)
602{
603 int active_language = -1;
604 GtkTreeIter iter;
605 int combo_row_count = 0;
606 FILE *fp;
607 char buf[50];
608
609 fp = fopen(file_location, "r");
610 if (fp == NULL) {
611 return NSERROR_NOT_FOUND;
612 }
613
614 gtk_list_store_clear(liststore);
615
616 NSLOG(netsurf, INFO, "Used %s for languages", file_location);
617 while (fgets(buf, sizeof(buf), fp)) {
618 /* Ignore blank lines */
619 if (buf[0] == '\0')
620 continue;
621
622 /* Remove trailing \n */
623 buf[strlen(buf) - 1] = '\0';
624
625 gtk_list_store_append(liststore, &iter);
626 gtk_list_store_set(liststore, &iter, 0, buf, -1 );
627
628 if (strcmp(buf, accept_language) == 0) {
629 active_language = combo_row_count;
630 }
631
632 combo_row_count++;
633 }
634
635 /* if configured language was not in list, add it */
636 if (active_language == -1) {
637 gtk_list_store_append(liststore, &iter);
638 gtk_list_store_set(liststore, &iter, 0, accept_language, -1);
639 active_language = combo_row_count;
640 }
641
642 fclose(fp);
643
644 gtk_combo_box_set_active(combobox, active_language);
645
646 return NSERROR_OK;
647}
648
649/**
650 * Fill content language list store.
651 */
652G_MODULE_EXPORT void
654 struct ppref *priv)
655{
656 nserror res;
657 const uint8_t *data;
658 size_t data_size;
659 const char *languages_file;
660 const char *accept_language;
661
662 if (priv->content_language == NULL) {
663 NSLOG(netsurf, INFO, "content language list store unavailable");
664 return;
665 }
666
667 /* get current accept language */
668 accept_language = nsoption_charp(accept_language);
669 if (accept_language == NULL) {
670 accept_language = "en";
671 }
672
673 /* attempt to read languages from inline resource */
674 res = nsgtk_data_from_resname("languages", &data, &data_size);
675 if (res == NSERROR_OK) {
677 GTK_COMBO_BOX(widget),
678 accept_language,
679 data,
680 data_size);
681 } else {
682 /* attempt to read languages from file */
683 res = nsgtk_path_from_resname("languages", &languages_file);
684 if (res == NSERROR_OK) {
686 GTK_COMBO_BOX(widget),
687 accept_language,
688 languages_file);
689 }
690 }
691 if (res != NSERROR_OK) {
692 NSLOG(netsurf, INFO, "error populatiung languages combo");
693 }
694}
695
696
697/********* Apperance **********/
698
699/* Tabs */
700
701/* always show tab bar */
702G_MODULE_EXPORT void
704 struct ppref *priv)
705{
706 nsoption_set_bool(show_single_tab,
707 gtk_toggle_button_get_active(togglebutton));
709}
710
711G_MODULE_EXPORT void
713 struct ppref *priv)
714{
715 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
716 nsoption_bool(show_single_tab));
717}
718
719/* switch to newly opened tabs immediately */
720TOGGLEBUTTON_SIGNALS(checkFocusNew, focus_new)
721
722/* newly opened tabs are blank */
723TOGGLEBUTTON_SIGNALS(checkNewBlank, new_blank)
724
725/* tab position */
726G_MODULE_EXPORT void
728 struct ppref *priv)
729{
730 /* set the option */
731 nsoption_set_int(position_tab, gtk_combo_box_get_active(widget));
732
733 /* update all windows */
735}
736
737G_MODULE_EXPORT void
739 struct ppref *priv)
740{
741 gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
742 nsoption_int(position_tab));
743}
744
745/* Tools */
746
747/* developer view opening */
748G_MODULE_EXPORT void
750 struct ppref *priv)
751{
752 /* set the option */
753 nsoption_set_int(developer_view, gtk_combo_box_get_active(widget));
754}
755
756G_MODULE_EXPORT void
758 struct ppref *priv)
759{
760 gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
761 nsoption_int(developer_view));
762}
763
764
765/* URLbar */
766
767/* show recently visited urls as you type */
768TOGGLEBUTTON_SIGNALS(checkDisplayRecentURLs, url_suggestion)
769
770/* Toolbar */
771
772/* button position */
773G_MODULE_EXPORT void
775 struct ppref *priv)
776{
777 nsoption_set_int(button_type, gtk_combo_box_get_active(widget) + 1);
778
779 /* update all windows to adopt change */
781}
782
783G_MODULE_EXPORT void
785 struct ppref *priv)
786{
787 gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
788 nsoption_int(button_type) - 1);
789}
790
791
792
793/************ Main ************/
794
795/* Startup */
796
797/* entry HomePageURL widget */
798ENTRY_SIGNALS(entryHomePageURL, homepage_url)
799
800/* put current page into homepage url */
801G_MODULE_EXPORT void
802nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv)
803{
804 const gchar *url = nsurl_access(browser_window_access_url(priv->bw));
805
806 if (priv->entryHomePageURL != NULL) {
807 gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url);
808 nsoption_set_charp(homepage_url, strdup(url));
809 }
810}
811
812/* put default page into homepage */
813G_MODULE_EXPORT void
814nsgtk_preferences_setDefaultPage_clicked(GtkButton *button, struct ppref *priv)
815{
816 const gchar *url = NETSURF_HOMEPAGE;
817
818 if (priv->entryHomePageURL != NULL) {
819 gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url);
820 nsoption_set_charp(homepage_url, strdup(url));
821 }
822}
823
824/* Search */
825
826/* Url Search widget */
827TOGGLEBUTTON_SIGNALS(checkUrlSearch, search_url_bar)
828
829/* provider combo */
830G_MODULE_EXPORT void
831nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv)
832{
833 int provider;
834
835 provider = gtk_combo_box_get_active(widget);
836
837 /* set the option */
839
840 /* set search provider */
842}
843
844G_MODULE_EXPORT void
845nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv)
846{
847 int iter;
848 const char *name;
849 int provider = nsoption_int(search_provider);
850
851 if (priv->search_providers != NULL) {
852 gtk_list_store_clear(priv->search_providers);
853 for (iter = search_web_iterate_providers(0, &name);
854 iter != -1;
855 iter = search_web_iterate_providers(iter, &name)) {
856 gtk_list_store_insert_with_values(priv->search_providers,
857 NULL, -1,
858 0, name, -1);
859 }
860 }
861
862 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), provider);
863}
864
865
866/* Downloads */
867
868/* clear downloads */
869TOGGLEBUTTON_SIGNALS(checkClearDownloads, downloads_clear)
870
871/* request overwite */
872TOGGLEBUTTON_SIGNALS(checkRequestOverwrite, request_overwrite)
873
874/* download location
875 *
876 * note selection-changed is used instead of file-set as the returned
877 * filename when that signal are used is incorrect. Though this signal
878 * does update frequently often with the same data.
879 */
880G_MODULE_EXPORT void
882 struct ppref *priv)
883{
884 gchar *dir;
885 dir = gtk_file_chooser_get_filename(chooser);
886 nsoption_set_charp(downloads_directory, strdup(dir));
887 g_free(dir);
888}
889
890G_MODULE_EXPORT void
892 struct ppref *priv)
893{
894 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget),
895 nsoption_charp(downloads_directory));
896}
897
898
899/************* Dialog window ***********/
900
901/* dialog close and destroy events */
902G_MODULE_EXPORT void
904{
905 char *choices = NULL;
906
907 if (resid == GTK_RESPONSE_CLOSE) {
908 netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
909 if (choices != NULL) {
910 nsoption_write(choices, NULL, NULL);
911 free(choices);
912 }
913 gtk_widget_hide(GTK_WIDGET(dlg));
914 }
915}
916
917G_MODULE_EXPORT gboolean
919 struct ppref *priv)
920{
921 char *choices = NULL;
922
923 netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
924 if (choices != NULL) {
925 nsoption_write(choices, NULL, NULL);
926 free(choices);
927 }
928
929 gtk_widget_hide(GTK_WIDGET(dlg));
930
931 /* Delt with it by hiding window, no need to destory widget by
932 * default.
933 */
934 return TRUE;
935}
936
937G_MODULE_EXPORT void
939{
940 char *choices = NULL;
941
942 netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
943 if (choices != NULL) {
944 nsoption_write(choices, NULL, NULL);
945 free(choices);
946 }
947}
948
949
950/* exported interface documented in gtk/preferences.h */
951GtkWidget* nsgtk_preferences(struct browser_window *bw, GtkWindow *parent)
952{
953 GtkBuilder *preferences_builder;
954 struct ppref *priv = &ppref;
955 nserror res;
956
957 priv->bw = bw; /* for setting "current" page */
958
959 /* memoised dialog creation */
960 if (priv->dialog != NULL) {
961 gtk_window_set_transient_for(GTK_WINDOW(priv->dialog), parent);
962 return GTK_WIDGET(priv->dialog);
963 }
964
965 res = nsgtk_builder_new_from_resname("options", &preferences_builder);
966 if (res != NSERROR_OK) {
967 NSLOG(netsurf, INFO, "Preferences UI builder init failed");
968 return NULL;
969 }
970
971 priv->dialog = gtk_builder_get_object(preferences_builder,
972 "dialogPreferences");
973 if (priv->dialog == NULL) {
974 NSLOG(netsurf, INFO,
975 "Unable to get object for preferences dialog");
976 /* release builder as were done with it */
977 g_object_unref(G_OBJECT(preferences_builder));
978 return NULL;
979 }
980
981 /* need to explicitly obtain handles for some widgets enabling
982 * updates by other widget events
983 */
984#define GB(TYPE, NAME) GTK_##TYPE(gtk_builder_get_object(preferences_builder, #NAME))
985 priv->entryHomePageURL = GB(ENTRY, entryHomePageURL);
986 priv->content_language = GB(LIST_STORE, liststore_content_language);
987 priv->search_providers = GB(LIST_STORE, liststore_search_provider);
988 priv->entryProxyHost = GB(ENTRY, entryProxyHost);
989 priv->spinProxyPort = GB(SPIN_BUTTON, spinProxyPort);
990 priv->entryProxyUser = GB(ENTRY, entryProxyUser);
992 priv->entryProxyNoproxy = GB(ENTRY, entryProxyNoproxy);
993#undef GB
994
995 /* connect all signals ready to use */
996 gtk_builder_connect_signals(preferences_builder, priv);
997
998 /* release builder as were done with it */
999 g_object_unref(G_OBJECT(preferences_builder));
1000
1001 /* mark dialog as transient on parent */
1002 gtk_window_set_transient_for(GTK_WINDOW(priv->dialog), parent);
1003
1004 return GTK_WIDGET(priv->dialog);
1005}
1006
Browser window creation and manipulation interface.
struct nsurl * browser_window_access_url(const struct browser_window *bw)
Access a browser window's URL.
Compatibility functions for older GTK versions (interface)
ssize_t search_web_iterate_providers(ssize_t from, const char **name)
Iterate the search providers, returning their names.
Definition: searchweb.c:502
nserror search_web_select_provider(int selection)
Change the currently selected web search provider.
Definition: searchweb.c:397
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_OK
No error.
Definition: errors.h:30
char * nsgtk_config_home
Directory where all configuration files are held.
Definition: gui.c:80
nserror nsgtk_window_update_all(void)
Every window will have its tab, toolbar and drawing area updated.
Definition: window.c:1657
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Localised message support (interface).
NetSurf URL handling (interface).
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
static void set_proxy_widgets_sensitivity(int proxyval, struct ppref *priv)
Definition: preferences.c:220
#define GB(TYPE, NAME)
G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:891
G_MODULE_EXPORT gboolean nsgtk_preferences_dialogPreferences_deleteevent(GtkDialog *dlg, struct ppref *priv)
Definition: preferences.c:918
G_MODULE_EXPORT void nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv)
Definition: preferences.c:504
G_MODULE_EXPORT void nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv)
Definition: preferences.c:831
G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:784
G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton, struct ppref *priv)
Definition: preferences.c:703
G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_selectionchanged(GtkFileChooser *chooser, struct ppref *priv)
Definition: preferences.c:881
G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget, struct ppref *priv)
Definition: preferences.c:774
G_MODULE_EXPORT void nsgtk_preferences_comboDefault_changed(GtkComboBox *combo, struct ppref *priv)
Definition: preferences.c:482
G_MODULE_EXPORT void nsgtk_preferences_comboDefault_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:493
#define SPINBUTTON_SIGNALS(WIDGET, OPTION, MULTIPLIER)
Definition: preferences.c:91
G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_realize(GtkWidget *widget, struct ppref *priv)
Fill content language list store.
Definition: preferences.c:653
G_MODULE_EXPORT void nsgtk_preferences_setDefaultPage_clicked(GtkButton *button, struct ppref *priv)
Definition: preferences.c:814
G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget, struct ppref *priv)
Definition: preferences.c:727
G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:738
G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_response(GtkDialog *dlg, gint resid)
Definition: preferences.c:903
G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_changed(GtkComboBox *widget, struct ppref *priv)
Definition: preferences.c:749
static nserror comboboxLanguage_add_from_data(GtkListStore *liststore, GtkComboBox *combobox, const char *accept_language, const uint8_t *data, size_t data_size)
populate language combo from data
Definition: preferences.c:542
#define SPINBUTTON_UINT_SIGNALS(WIDGET, OPTION, MULTIPLIER)
Definition: preferences.c:112
#define TOGGLEBUTTON_SIGNALS(WIDGET, OPTION)
Definition: preferences.c:68
GtkWidget * nsgtk_preferences(struct browser_window *bw, GtkWindow *parent)
Initialise prefernces window.
Definition: preferences.c:951
G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:757
G_MODULE_EXPORT void nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv)
Definition: preferences.c:802
G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:451
#define ENTRY_SIGNALS(WIDGET, OPTION)
Definition: preferences.c:133
static nserror comboboxLanguage_add_from_file(GtkListStore *liststore, GtkComboBox *combobox, const char *accept_language, const char *file_location)
populate language combo from file
Definition: preferences.c:598
G_MODULE_EXPORT void nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:845
G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:317
static struct ppref ppref
Definition: preferences.c:60
G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_realize(GtkWidget *widget, struct ppref *priv)
Definition: preferences.c:712
G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_changed(GtkComboBox *combo, struct ppref *priv)
Definition: preferences.c:514
G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_changed(GtkComboBox *combo, struct ppref *priv)
Definition: preferences.c:282
G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo, struct ppref *priv)
Definition: preferences.c:417
G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_destroy(GtkDialog *dlg, struct ppref *priv)
Definition: preferences.c:938
nserror nsgtk_data_from_resname(const char *resname, const uint8_t **data_out, size_t *data_size_out)
Get direct pointer to resource data.
Definition: resources.c:574
nserror nsgtk_builder_new_from_resname(const char *resname, GtkBuilder **builder_out)
Create gtk builder object for the named ui resource.
Definition: resources.c:526
nserror nsgtk_path_from_resname(const char *resname, const char **path_out)
Get path to resource data.
Definition: resources.c:613
Interface to gtk builtin resource handling.
core web search facilities interface.
Interface to utility string handling.
Browser window data.
GtkListStore * content_language
Definition: preferences.c:56
GtkListStore * search_providers
Definition: preferences.c:57
GtkEntry * entryProxyPassword
Definition: preferences.c:51
GtkSpinButton * spinProxyPort
Definition: preferences.c:53
GtkEntry * entryProxyHost
Definition: preferences.c:49
GtkEntry * entryProxyNoproxy
Definition: preferences.c:52
GtkEntry * entryHomePageURL
Definition: preferences.c:48
GObject * dialog
dialog handle created when window first accessed
Definition: preferences.c:43
GtkEntry * entryProxyUser
Definition: preferences.c:50
struct browser_window * bw
Definition: preferences.c:45
nserror netsurf_mkpath(char **str, size_t *size, size_t nelm,...)
Generate a path from one or more component elemnts.
Definition: file.c:288
Default operations table for files.
nserror nsoption_write(const char *path, struct nsoption_s *opts, struct nsoption_s *defs)
Write options that have changed from the defaults to a file.
Definition: nsoption.c:763
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:297
#define nsoption_int(OPTION)
Get the value of an integer option.
Definition: nsoption.h:279
#define nsoption_set_int(OPTION, VALUE)
set an integer option in the default table
Definition: nsoption.h:314
#define nsoption_set_bool(OPTION, VALUE)
set a boolean option in the default table
Definition: nsoption.h:310
#define nsoption_set_charp(OPTION, VALUE)
set string option in default table
Definition: nsoption.h:338
@ OPTION_HTTP_PROXY_AUTH_NONE
Definition: nsoption.h:86
@ OPTION_HTTP_PROXY_AUTH_NTLM
Definition: nsoption.h:88
@ OPTION_HTTP_PROXY_AUTH_BASIC
Definition: nsoption.h:87
#define nsoption_bool(OPTION)
Get the value of a boolean option.
Definition: nsoption.h:270