about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJosh Rickmar <jrick@devio.us>2012-07-31 16:46:43 -0400
committerJosh Rickmar <jrick@devio.us>2012-07-31 16:46:43 -0400
commit7d377d0d8dc75fc51040127dff495988f2b184af (patch)
treea7610997edca4fd402254ea96b758618cf8173d1
parentd38f66db03cf801fb1b4e01acb2f15d91280b248 (diff)
downloadxombrero-7d377d0d8dc75fc51040127dff495988f2b184af.tar.gz
Implement an about:runtime page and :runtime command to view and
change runtime settings.  Settings that have been modified show in a
highlighted color in the table.  Tooltips describe the setting's
function, as well as the default values.
-rw-r--r--Makefile9
-rw-r--r--about.c264
-rw-r--r--ascii2txt.pl192
-rw-r--r--freebsd/Makefile10
-rw-r--r--linux/Makefile8
-rw-r--r--settings.c1312
-rw-r--r--txt2tooltip.pl93
-rw-r--r--unix.c2
-rw-r--r--xombrero.11
-rw-r--r--xombrero.c67
-rw-r--r--xombrero.h83
11 files changed, 1719 insertions, 322 deletions
diff --git a/Makefile b/Makefile
index e9ada1a..f9b4c49 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@ CPPFLAGS+= -DXOMBRERO_BUILDSTR=\"$(BUILDVERSION)\"
 
 MANDIR= ${PREFIX}/man/man
 
-CLEANFILES += ${.CURDIR}/javascript.h javascript.h xombrero.cat1 xombrero.core
+CLEANFILES += ${.CURDIR}/javascript.h javascript.h tooltip.h xombrero.cat1 xombrero.core
 
 JSFILES += hinting.js
 JSFILES += input-focus.js
@@ -49,6 +49,11 @@ javascript.h: ${JSFILES} js-merge-helper.pl
 	perl ${.CURDIR}/js-merge-helper.pl \
 		${JSCURDIR} > javascript.h
 
+tooltip.h: ${MAN} ascii2txt.pl txt2tooltip.pl
+	mandoc -Tascii ${.CURDIR}/${MAN} | \
+		perl ${.CURDIR}/ascii2txt.pl | \
+		perl ${.CURDIR}/txt2tooltip.pl > tooltip.h
+
 beforeinstall:
 	install -m 755 -d ${PREFIX}/bin
 	install -m 755 -d ${PREFIX}/man/man1/
@@ -64,7 +69,7 @@ beforeinstall:
 	install -m 644 ${.CURDIR}/style.css ${PREFIX}/share/xombrero
 	install -m 644 ${.CURDIR}/hsts-preload ${PREFIX}/share/xombrero
 
-${PROG} ${OBJS} beforedepend: javascript.h
+${PROG} ${OBJS} beforedepend: javascript.h tooltip.h
 
 # clang targets
 .if ${.TARGETS:M*analyze*}
diff --git a/about.c b/about.c
index ed3673c..10e2bd4 100644
--- a/about.c
+++ b/about.c
@@ -58,54 +58,25 @@
 				" background: green}\n"			\
 				".dlstatus{font-size: small;"		\
 				" text-align: center}\n"		\
+				"table#settings{background-color: #eee;"\
+				" border: 0px;"				\
+				" margin: 15px;}\n"			\
+				"table#settings td{border: 0px;}\n"	\
+				"table#settings th{border: 0px;}\n"	\
+				"table#settings tr{"			\
+				" background: #f6f6f6;}\n"		\
+				"table#settings tr:nth-child(even){"	\
+				" background: #eeeeee;}\n"		\
+				"table#settings tr#modified{"		\
+				" background: #FFFFBA;}\n"		\
+				"table#settings tr#modified:nth-child(even){"	\
+				" background: #ffffA0;}\n"		\
 				"</style>\n"
 
-/* XTP classes (xxxt://<class>) */
-#define XT_XTP_INVALID		(0)	/* invalid */
-#define XT_XTP_DL		(1)	/* downloads */
-#define XT_XTP_HL		(2)	/* history */
-#define XT_XTP_CL		(3)	/* cookies */
-#define XT_XTP_FL		(4)	/* favorites */
-#define XT_XTP_SL		(5)	/* search */
-#define XT_XTP_AB		(6)	/* about */
-#define XT_XTP_SV		(7)	/* security violation */
-
-/* XTP download actions */
-#define XT_XTP_DL_LIST		(1)
-#define XT_XTP_DL_CANCEL	(2)
-#define XT_XTP_DL_REMOVE	(3)
-#define XT_XTP_DL_UNLINK	(4)
-#define XT_XTP_DL_START		(5)
-
-/* XTP history actions */
-#define XT_XTP_HL_LIST		(1)
-#define XT_XTP_HL_REMOVE	(2)
-#define XT_XTP_HL_REMOVE_ALL	(3)
-
-/* XTP cookie actions */
-#define XT_XTP_CL_LIST		(1)
-#define XT_XTP_CL_REMOVE	(2)
-#define XT_XTP_CL_REMOVE_DOMAIN	(3)
-#define XT_XTP_CL_REMOVE_ALL	(4)
-
-/* XTP cookie actions */
-#define XT_XTP_FL_LIST		(1)
-#define XT_XTP_FL_REMOVE	(2)
-
-/* XPT search actions */
-#define XT_XTP_SL_SET		(1)
-
-/* XPT about actions */
-#define XT_XTP_AB_EDIT_CONF	(1)
-
-/* XTP security violation actions */
-#define XT_XTP_SV_SHOW_CERT	(1)
-#define XT_XTP_SV_ALLOW_SESSION	(2)
-#define XT_XTP_SV_CACHE		(3)
-
 int			js_show_wl(struct tab *, struct karg *);
 int			pl_show_wl(struct tab *, struct karg *);
-int			set(struct tab *, struct karg *);
+int			xtp_page_set(struct tab *, struct karg *);
+int			xtp_page_rt(struct tab *, struct karg *);
 int			marco(struct tab *, struct karg *);
 int			startpage(struct tab *, struct karg *);
 const char *		marco_message(int *);
@@ -125,13 +96,14 @@ struct about_type about_list[] = {
 	{ XT_URI_ABOUT_HELP,		help },
 	{ XT_URI_ABOUT_HISTORY,		xtp_page_hl },
 	{ XT_URI_ABOUT_JSWL,		js_show_wl },
-	{ XT_URI_ABOUT_SET,		set },
+	{ XT_URI_ABOUT_SET,		xtp_page_set },
 	{ XT_URI_ABOUT_STATS,		stats },
 	{ XT_URI_ABOUT_MARCO,		marco },
 	{ XT_URI_ABOUT_STARTPAGE,	startpage },
 	{ XT_URI_ABOUT_PLUGINWL,	pl_show_wl },
 	{ XT_URI_ABOUT_WEBKIT,		about_webkit },
 	{ XT_URI_ABOUT_SEARCH,		xtp_page_sl },
+	{ XT_URI_ABOUT_RUNTIME,		xtp_page_rt },
 	{ XT_URI_ABOUT_SECVIOLATION,	NULL },
 };
 
@@ -165,6 +137,7 @@ char			*fl_session_key;	/* favorites list */
 char			*sl_session_key;	/* search */
 char			*ab_session_key;	/* about */
 char			*sv_session_key;	/* secviolation */
+char			*rt_session_key;	/* set */
 
 int			updating_ab_tabs = 0;
 int			updating_fl_tabs = 0;
@@ -173,6 +146,7 @@ int			updating_hl_tabs = 0;
 int			updating_cl_tabs = 0;
 int			updating_sl_tabs = 0;
 int			updating_sv_tabs = 0;
+int			updating_set_tabs = 0;
 struct download_list	downloads;
 
 size_t
@@ -228,7 +202,7 @@ load_webkit_string(struct tab *t, const char *str, gchar *title)
 			}
 
 		webkit_web_view_load_string(t->wv, str, NULL, encoding,
-		    "file://");
+		    XT_XTP_STR);
 #if GTK_CHECK_VERSION(2, 20, 0)
 		gtk_spinner_stop(GTK_SPINNER(t->spinner));
 		gtk_widget_hide(t->spinner);
@@ -485,7 +459,7 @@ pl_cmd(struct tab *t, struct karg *args)
  * cancel, remove, etc. downloads
  */
 void
-xtp_handle_dl(struct tab *t, uint8_t cmd, int id)
+xtp_handle_dl(struct tab *t, uint8_t cmd, int id, const char *query)
 {
 	struct download		find, *d = NULL;
 #ifndef	__MINGW32__
@@ -548,7 +522,7 @@ xtp_handle_dl(struct tab *t, uint8_t cmd, int id)
 }
 
 void
-xtp_handle_hl(struct tab *t, uint8_t cmd, int id)
+xtp_handle_hl(struct tab *t, uint8_t cmd, int id, const char *query)
 {
 	struct history		*h, *next, *ht;
 	int			i = 1;
@@ -737,7 +711,7 @@ search_engine_add(char *body, const char *name, const char *url, int select)
 }
 
 void
-xtp_handle_ab(struct tab *t, uint8_t cmd, int arg)
+xtp_handle_ab(struct tab *t, uint8_t cmd, int arg, const char *query)
 {
 	char			config[PATH_MAX];
 	char			*cmdstr;
@@ -771,7 +745,7 @@ xtp_handle_ab(struct tab *t, uint8_t cmd, int arg)
 	xtp_page_ab(t, NULL);
 }
 void
-xtp_handle_fl(struct tab *t, uint8_t cmd, int arg)
+xtp_handle_fl(struct tab *t, uint8_t cmd, int arg, const char *query)
 {
 	switch (cmd) {
 	case XT_XTP_FL_LIST:
@@ -789,7 +763,7 @@ xtp_handle_fl(struct tab *t, uint8_t cmd, int arg)
 }
 
 void
-xtp_handle_cl(struct tab *t, uint8_t cmd, int arg)
+xtp_handle_cl(struct tab *t, uint8_t cmd, int arg, const char *query)
 {
 	switch (cmd) {
 	case XT_XTP_CL_LIST:
@@ -813,66 +787,17 @@ xtp_handle_cl(struct tab *t, uint8_t cmd, int arg)
 }
 
 void
-xtp_handle_sl(struct tab *t, uint8_t cmd, int arg)
+xtp_handle_sl(struct tab *t, uint8_t cmd, int arg, const char *query)
 {
-	struct stat		sb;
-	FILE			*f;
-	size_t			linelen;
-	int			found = 0;
 	const char		*search;
-	char			file[PATH_MAX];
-	char			delim[3] = { '\0', '\0', '\0' };
-	char			*line, *lt, *enc_search, *uri;
-	char			*contents, *tmp;
+	char			*enc_search, *uri;
 	char			**sv;
 
 	switch (cmd) {
 	case XT_XTP_SL_SET:
 		set_search_string((char *)search_list[arg].url);
-		if (runtime_settings == NULL || strlen(runtime_settings) == 0) {
-			show_oops(t, "could not set search_string in "
-			    "runtime");
-			break;
-		}
-		snprintf(file, sizeof file, "%s" PS "%s", work_dir,
-		    runtime_settings);
-		if (stat(file, &sb) || (f = fopen(file, "r+")) == NULL) {
+		if (save_runtime_setting("search_string", search_list[arg].url))
 			show_oops(t, "could not set search_string in runtime");
-			break;
-		}
-		lt = g_strdup_printf("search_string=%s",
-		    (char *)search_list[arg].url);
-		contents = g_strdup("");
-		while (!feof(f)) {
-			line = fparseln(f, &linelen, NULL, delim, 0);
-			if (line == NULL || linelen == 0)
-				continue;
-			tmp = contents;
-			if (strstr(line, "search_string=") == NULL)
-				contents = g_strdup_printf("%s%s\n", contents,
-				    line);
-			else {
-				found = 1;
-				contents = g_strdup_printf("%s%s\n", contents,
-				    lt);
-			}
-			g_free(tmp);
-			free(line);
-			line = NULL;
-		}
-		if (found == 0) {
-			tmp = contents;
-			contents = g_strdup_printf("%s%s\n", contents, lt);
-			g_free(tmp);
-		}
-		if ((f = freopen(file, "w", f)) == NULL)
-			show_oops(t, "could not set search_string in runtime");
-		else {
-			fputs(contents, f);
-			fclose(f);
-		}
-		g_free(lt);
-		g_free(contents);
 		break;
 	default:
 		show_oops(t, "%s: unknown search xtp command", __func__);
@@ -890,7 +815,7 @@ xtp_handle_sl(struct tab *t, uint8_t cmd, int arg)
 }
 
 void
-xtp_handle_sv(struct tab *t, uint8_t cmd, int id)
+xtp_handle_sv(struct tab *t, uint8_t cmd, int id, const char *query)
 {
 	SoupURI			*soupuri = NULL;
 	struct karg		args = {0};
@@ -934,11 +859,81 @@ xtp_handle_sv(struct tab *t, uint8_t cmd, int id)
 	RB_REMOVE(secviolation_list, &svl, sv);
 }
 
+void
+xtp_handle_rt(struct tab *t, uint8_t cmd, int id, const char *query)
+{
+	struct set_reject	*sr;
+	GHashTable		*new_settings = NULL;
+	int			modify;
+	char			*val, *curval, *s;
+	int			i = 0;
+
+	switch (cmd) {
+	case XT_XTP_RT_SAVE:
+		if (query == NULL)
+			break;
+		new_settings = soup_form_decode(query);
+		for (i = 0; i < get_settings_size(); ++i) {
+			if (!rs[i].activate)
+				continue;
+			sr = g_malloc(sizeof *sr);
+			val = (char *)g_hash_table_lookup(new_settings,
+			    rs[i].name);
+			modify = 0;
+			switch (rs[i].type) {
+			case XT_S_INT: /* FALLTHROUGH */
+			case XT_S_BOOL:
+				if (atoi(val) != *rs[i].ival)
+					modify = 1;
+				break;
+			case XT_S_FLOAT:
+				if (atof(val) != *rs[i].fval)
+					modify = 1;
+				break;
+			case XT_S_STR:
+				s = (rs[i].sval == NULL || *rs[i].sval == NULL)
+				    ? "" : *rs[i].sval;
+				if (rs[i].sval && g_strcmp0(val, s))
+					modify = 1;
+				else if (rs[i].s && rs[i].s->get) {
+					curval = rs[i].s->get(NULL);
+					if (g_strcmp0(val, curval))
+						modify = 1;
+					g_free(curval);
+				}
+				break;
+			case XT_S_INVALID: /* FALLTHROUGH */
+			default:
+				break;
+			}
+			if (rs[i].activate(val)) {
+				sr->name = g_strdup(rs[i].name);
+				sr->value = g_strdup(val);
+				TAILQ_INSERT_TAIL(&srl, sr, entry);
+				continue;
+			}
+			if (modify)
+				if (save_runtime_setting(rs[i].name, val))
+					show_oops(t, "error");
+		}
+		break;
+	default:
+		show_oops(t, "%s: invalid set command", __func__);
+		break;
+	}
+
+	if (new_settings)
+		g_hash_table_destroy(new_settings);
+
+	xtp_page_rt(t, NULL);
+}
+
 /* link an XTP class to it's session key and handler function */
 struct xtp_despatch {
 	uint8_t			xtp_class;
 	char			**session_key;
-	void			(*handle_func)(struct tab *, uint8_t, int);
+	void			(*handle_func)(struct tab *, uint8_t, int,
+				    const char *query);
 };
 
 struct xtp_despatch		xtp_despatches[] = {
@@ -949,6 +944,7 @@ struct xtp_despatch		xtp_despatches[] = {
 	{ XT_XTP_SL, &sl_session_key, xtp_handle_sl },
 	{ XT_XTP_AB, &ab_session_key, xtp_handle_ab },
 	{ XT_XTP_SV, &sv_session_key, xtp_handle_sv },
+	{ XT_XTP_RT, &rt_session_key, xtp_handle_rt },
 	{ XT_XTP_INVALID, NULL, NULL }
 };
 
@@ -1008,45 +1004,41 @@ validate_xtp_session_key(struct tab *t, char *trusted, char *untrusted)
  * if so, parse and despatch correct bahvior
  */
 int
-parse_xtp_url(struct tab *t, const char *url)
+parse_xtp_url(struct tab *t, const char *uri_str)
 {
-	char			*dup = NULL, *p, *last = NULL;
-	uint8_t			n_tokens = 0;
-	char			*tokens[4] = {NULL, NULL, NULL, ""};
+	SoupURI			*uri = NULL;
 	struct xtp_despatch	*dsp, *dsp_match = NULL;
-	uint8_t			req_class;
 	int			ret = FALSE;
+	int			class = 0;
+	char			**sv = NULL;
 
 	/*
-	 * tokens array meaning:
-	 *   tokens[0] = class
-	 *   tokens[1] = session key
-	 *   tokens[2] = action
-	 *   tokens[3] = optional argument
+	 *   uri->host	= class
+	 *   sv[0]	= session key
+	 *   sv[1]	= command
+	 *   sv[2]	= optional argument
 	 */
 
 	DNPRINTF(XT_D_URL, "%s: url %s\n", __func__, url);
 
-	if (strncmp(url, XT_XTP_STR, strlen(XT_XTP_STR)))
+	if ((uri = soup_uri_new(uri_str)) == NULL)
+		goto clean;
+	if (strncmp(uri->scheme, XT_XTP_SCHEME, strlen(XT_XTP_SCHEME)))
+		goto clean;
+	if (uri->host == NULL || strlen(uri->host) == 0)
+		goto clean;
+	else
+		class = atoi(uri->host);
+	if ((sv = g_strsplit(uri->path + 1, "/", 3)) == NULL)
 		goto clean;
 
-	dup = g_strdup(url + strlen(XT_XTP_STR));
-
-	/* split out the url */
-	for ((p = strtok_r(dup, "/", &last)); p;
-	    (p = strtok_r(NULL, "/", &last))) {
-		if (n_tokens < 4)
-			tokens[n_tokens++] = p;
-	}
-
-	/* should be atleast three fields 'class/seskey/command/arg' */
-	if (n_tokens < 3)
+	if (sv[0] == NULL || sv[1] == NULL)
 		goto clean;
 
 	dsp = xtp_despatches;
-	req_class = atoi(tokens[0]);
+	class = atoi(uri->host);
 	while (dsp->xtp_class) {
-		if (dsp->xtp_class == req_class) {
+		if (dsp->xtp_class == class) {
 			dsp_match = dsp;
 			break;
 		}
@@ -1060,14 +1052,20 @@ parse_xtp_url(struct tab *t, const char *url)
 	}
 
 	/* check session key and call despatch function */
-	if (validate_xtp_session_key(t, *(dsp_match->session_key), tokens[1])) {
+	if (validate_xtp_session_key(t, *(dsp_match->session_key), sv[0])) {
 		ret = TRUE; /* all is well, this was a valid xtp request */
-		dsp_match->handle_func(t, atoi(tokens[2]), atoi(tokens[3]));
+		if (sv[2])
+			dsp_match->handle_func(t, atoi(sv[1]), atoi(sv[2]),
+			    uri->query);
+		else
+			dsp_match->handle_func(t, atoi(sv[1]), 0, uri->query);
 	}
 
 clean:
-	if (dup)
-		g_free(dup);
+	if (uri)
+		soup_uri_free(uri);
+	if (sv)
+		g_strfreev(sv);
 
 	return (ret);
 }
diff --git a/ascii2txt.pl b/ascii2txt.pl
new file mode 100644
index 0000000..cc949e8
--- /dev/null
+++ b/ascii2txt.pl
@@ -0,0 +1,192 @@
+#!/bin/perl
+
+# Copyright (c) 2010,2011,2012 Todd T. Fries <todd@fries.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# read in 'mandoc -Tascii' formatted man pages, spit out txt useful for further
+# processing by other utilities
+
+use strict;
+use warnings;
+
+our $fileinfo = $ARGV[0];
+
+our $verbose = 0;
+
+my $line;
+my @lines;
+while(<STDIN>) {
+	$line = $_;
+	push @lines,$line;
+}
+my $oline = "";
+my $fmtline = "%s";
+foreach $line (@lines) {
+
+	my $newline = "";
+	foreach my $seg (split(/(.\x08.)/,$line)) {
+		my $newseg = $seg;
+		$newseg =~ m/^(.)\x08(.)$/;
+		if (!defined($1) || !defined($2)) {
+			$newline .= $seg;
+			next;
+		}
+		if ($1 eq $2) {
+			$newline .= "${2}";
+			next;
+		}
+		if ($1 eq "_") {
+			$newline .= "${2}";
+			next;
+		}
+		$newline .= $seg;
+		next;
+	}
+	if ($verbose > 0) {
+		printf STDERR "==> text{bf,it}\n   line: <%s>\nnewline: <%s>\n",$line,$newline;
+	}
+	$line = $newline;
+	$line =~ m/(.)\x08/;
+	if (defined($1)) {
+		printf STDERR "Removing %s\\x08\n",$1;
+	}
+	$line =~ s/.\x08//g;
+
+	# combine adjacent entries
+	foreach my $macro (("textbf", "textit")) {
+		$oline = "";
+		while ($oline ne $line) {
+			#printf STDERR "combine adjacent\n";
+			$oline = $line;
+			$line =~ s/\xab\\${macro}\{([^\}]*)\}\xbb\xab\\${macro}\{([^\}]*)\}\xbb/\xab\\${macro}\{$1$2\}\xbb/g;
+		}
+	}
+	# combine space separated
+	foreach my $macro (("textbf")) {
+		#printf STDERR "combine space\n";
+		$oline = "";
+		while ($oline ne $line) {
+			$oline = $line;
+			$line =~ s/\xab\\${macro}\{([^\}]*)\}\xbb[ ]+\xab\\${macro}\{([^\}]*)\}\xbb/\xab\\${macro}\{$1 $2\}\xbb/g;
+		}
+	}
+
+	# do the substitution one at a time to be sure to add all man pages, not just the last ones per line.
+	# XXX provide an exceptions list, audio(9) has mono(1) and stereo(2)
+	# XXX references, which are _not_ man pages
+	$oline = "";
+	while ($oline ne $line) {
+		$oline=$line;
+		$line =~ s/\{(http|ftp|https):\/\/(.*)\}/ $1:\/\/$2 /;
+		if (0) {
+		if ($line =~ m/ ([a-z][a-z0-9\.\-\_]*)\(([1-9])\)([,\.\) ])/) {
+			my $quote = texquote($1);
+			$line =~ s/ ([a-z][a-z0-9\.\-\_]*)\(([1-9])\)([,\.\) ])/ \xab\\man{$quote}{$2}\xbb$3/;
+		}
+		
+		if ($line =~ m/ ([a-z][a-z0-9\.\-\_]*)\(([1-9])\)$/) {
+			my $quote = texquote($1);
+			$line =~ s/ ([a-z][a-z0-9\.\-\_]*)\(([1-9])\)$/ \xab\\man{$quote}{$2}\xbb/;
+		}
+		}
+	}
+	my @macros = ("textbf","textit","man","href");
+	# quote arguments for tex
+	foreach my $macro (@macros) {
+		my $newline = "";
+		foreach my $seg (split(/(\xab\\${macro}\{[^\xbb]*\}\xbb)/,$line)) {
+			#printf STDERR "quote args\n";
+			my $newseg = $seg;
+			# check for nesting first; we only want to escape the
+			# inner most argument, process nested macro if it has a nested macro
+			# since the nested macro won't catch in the other regex cases
+			my $foundnest = 0;
+			foreach my $nest (@macros) {
+				if ($macro eq $nest) {
+					next;
+				}
+				
+				$newseg =~ m/^\xab\\${macro}\{[ ]*\\${nest}\{([^\xbb]*)\}\{([^\xbb]*)\}\}\xbb$/;
+				if (defined($2)) {
+					$foundnest = 1;
+					$newline .= "\xab\\${macro}\{\\${nest}\{".texquote($1)."\}\{".texquote(${2})."\}\}\xbb";
+					last;
+				}
+				$newseg =~ m/^\xab\\${macro}\{[ ]*\\${nest}\{([^\xbb]*)\}\}\xbb$/;
+				if (defined($1)) {
+					$foundnest = 1;
+					$newline .= "\xab\\${macro}\{\\${nest}\{".texquote($1)."\}\}\xbb";
+					last;
+				}
+			}
+			if ($foundnest > 0) {
+				next;
+			}
+				
+			# check for 2 args first
+			$newseg =~ m/^\xab\\${macro}\{([^\xbb]*)\}\{([^\xbb]*)\}\xbb$/;
+			if (defined($2)) {
+				$newline .= "\xab\\${macro}\{".texquote($1)."\}\{".texquote(${2})."\}\xbb";
+				next;
+			}
+			$newseg =~ m/^\xab\\${macro}\{([^\xbb]*)\}\xbb$/;
+			if (defined($1)) {
+				$newline .= "\xab\\${macro}\{".texquote($1)."\}\xbb";
+				next;
+			}
+			$newline .= $seg;
+		}
+		$line = $newline;
+	}
+	printf $fmtline,$line;
+}
+
+1;
+
+sub texquote {
+        my ($text) = @_;
+        my ($ret) = "";
+        my ($esctest) = "";
+        my ($escbase) = "BaCkSlAsH";
+        my ($esccount) = 0;
+
+	#$verbose++;
+	if ($verbose > 0) {
+        	printf STDERR "\ntexquote: '%s' -> ",$text;
+	}
+
+        if ($text =~ m/\\/) {
+                $esctest=sprintf "%s%d",$escbase,$esccount++;
+                while ($text =~ m/$esctest/) {
+                        $esctest=sprintf "%s%d",$escbase,$esccount++;
+                }
+                $text =~ s/\\/$esctest/g;
+		if ($verbose > 0) {
+                	printf STDERR "'%s' -> ",$text;
+		}
+        }
+
+        $text =~ s/([%\{\}_#\&\$\^])/\\$1/g;
+        $text =~ s/([<>\|\*~])/\{\$$1\$\}/g;
+
+        if ($esccount > 0) {
+                $text =~ s/$esctest/\$\\backslash\$/g;
+        }
+	if ($verbose > 0) {
+        	printf STDERR "'%s'\n",$text;
+	}
+	#$verbose--;
+
+        return $text;
+}
diff --git a/freebsd/Makefile b/freebsd/Makefile
index 9ed119b..011354c 100644
--- a/freebsd/Makefile
+++ b/freebsd/Makefile
@@ -19,12 +19,17 @@ MANDIR?= $(PREFIX)/man
 
 CC?= cc
 
-all: ../javascript.h xombrero
+all: ../javascript.h ../tooltip.h xombrero
 
 ../javascript.h: ../js-merge-helper.pl ../hinting.js ../autoscroll.js
 	perl ../js-merge-helper.pl ../hinting.js ../input-focus.js \
 	../autoscroll.js > ../javascript.h
 
+../tooltip.h: ../ascii2txt.pl ../txt2tooltip.pl ../xombrero.1
+	nroff -c -Tascii -mandoc ../xombrero.1 | \
+	perl ../ascii2txt.pl | \
+	perl ../txt2tooltip.pl > ../tooltip.h
+
 xombrero.o: ../xombrero.o
 
 unix.o: ../unix.o
@@ -51,7 +56,7 @@ externaleditor.o: ../externaleditor.o
 
 tldlist.o: ../tldlist.o
 
-../xombrero.o: ../javascript.h
+../xombrero.o: ../javascript.h ../tooltip.h
 
 xombrero: xombrero.o freebsd.o marco.o about.o inspector.o whitelist.o settings.o \
 	cookie.o history.o completion.o inputfocus.o tldlist.o externaleditor.o \
@@ -77,5 +82,6 @@ install: all
 clean:
 	rm -f xombrero *.o
 	rm -f javascript.h
+	rm -f tooltip.h
 
 .PHONY: all install clean
diff --git a/linux/Makefile b/linux/Makefile
index 8d4e3cf..6a93843 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -31,12 +31,17 @@ ifneq ("${BUILDVERSION}", "")
 CFLAGS+= -DXOMBRERO_BUILDSTR=\"$(BUILDVERSION)\"
 endif
 
-all: javascript.h xombrero
+all: javascript.h tooltip.h xombrero
 
 javascript.h: ../js-merge-helper.pl ../hinting.js ../autoscroll.js
 	perl ../js-merge-helper.pl ../hinting.js ../input-focus.js \
 	../autoscroll.js > javascript.h
 
+tooltip.h: ../ascii2txt.pl ../txt2tooltip.pl ../xombrero.1
+	nroff -c -Tascii -mandoc ../xombrero.1 | \
+	perl ../ascii2txt.pl | \
+	perl ../txt2tooltip.pl > tooltip.h
+
 xombrero: $(OBJS)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LDADD)
 
@@ -79,6 +84,7 @@ uninstall:
 clean:
 	rm -f xombrero $(OBJS) $(DEPS)
 	rm -f javascript.h
+	rm -f tooltip.h
 
 
 -include $(DEPS)
diff --git a/settings.c b/settings.c
index 0850b4e..ebb01fe 100644
--- a/settings.c
+++ b/settings.c
@@ -21,6 +21,7 @@
  */
 
 #include <xombrero.h>
+#include "tooltip.h"
 
 /* globals */
 SoupURI			*proxy_uri = NULL;
@@ -206,8 +207,85 @@ int		set_external_editor(char *);
 int		set_warn_cert_changes(char *);
 int		set_allow_insecure_content(char *);
 int		set_allow_insecure_scripts(char *);
+int		set_http_proxy(char *);
 int		set_do_not_track(char *);
 
+int		check_allow_insecure_content(char **);
+int		check_allow_insecure_scripts(char **);
+int		check_allow_volatile_cookies(char **);
+int		check_append_next(char **);
+int		check_auto_load_images(char **);
+int		check_autofocus_onload(char **);
+int		check_browser_mode(char **);
+int		check_cmd_font(char **);
+int		check_color_visited_uris(char **);
+int		check_cookie_policy(char **);
+int		check_cookies_enabled(char **);
+int		check_ctrl_click_focus(char **);
+int		check_default_script(char **);
+int		check_default_zoom_level(char **);
+int		check_download_dir(char **);
+int		check_download_mode(char **);
+int		check_download_notifications(char **);
+int		check_edit_mode(char **);
+int		check_enable_autoscroll(char **);
+int		check_enable_cookie_whitelist(char **);
+int		check_enable_favicon_entry(char **);
+int		check_enable_favicon_tabs(char **);
+int		check_enable_js_autorun(char **);
+int		check_enable_js_whitelist(char **);
+int		check_enable_localstorage(char **);
+int		check_enable_plugin_whitelist(char **);
+int		check_enable_plugins(char **);
+int		check_enable_scripts(char **);
+int		check_enable_socket(char **);
+int		check_enable_spell_checking(char **);
+int		check_enable_strict_transport(char **);
+int		check_encoding(char **);
+int		check_external_editor(char **);
+int		check_fancy_bar(char **);
+int		check_guess_search(char **);
+int		check_gui_mode(char **);
+int		check_history_autosave(char **);
+int		check_home(char **);
+int		check_http_proxy(char **);
+int		check_http_proxy_starts_enabled(char **);
+int		check_icon_size(char **);
+int		check_max_connections(char **);
+int		check_max_host_connections(char **);
+int		check_oops_font(char **);
+int		check_read_only_cookies(char **);
+int		check_referer(char **);
+int		check_refresh_interval(char **);
+int		check_resource_dir(char **);
+int		check_save_global_history(char **);
+int		check_save_rejected_cookies(char **);
+int		check_search_string(char **);
+int		check_session_autosave(char **);
+int		check_session_timeout(char **);
+int		check_show_scrollbars(char **);
+int		check_show_statusbar(char **);
+int		check_show_tabs(char **);
+int		check_show_url(char **);
+int		check_single_instance(char **);
+int		check_spell_check_languages(char **);
+int		check_ssl_ca_file(char **);
+int		check_ssl_strict_certs(char **);
+int		check_statusbar_elems(char **);
+int		check_statusbar_font(char **);
+int		check_statusbar_style(char **);
+int		check_tab_style(char **);
+int		check_tabbar_font(char **);
+int		check_url_regex(char **);
+int		check_userstyle(char **);
+int		check_userstyle_global(char **);
+int		check_warn_cert_changes(char **);
+int		check_window_height(char **);
+int		check_window_maximize(char **);
+int		check_window_width(char **);
+int		check_work_dir(char **);
+int		check_do_not_track(char **);
+
 void		walk_mime_type(struct settings *, void (*)(struct settings *,
 		    char *, void *), void *);
 void		walk_alias(struct settings *, void (*)(struct settings *,
@@ -231,172 +309,165 @@ void		walk_custom_uri(struct settings *, void (*)(struct settings *,
 void		walk_force_https(struct settings *, void (*)(struct settings *,
 		    char *, void *), void *);
 
-int
-set_http_proxy(char *proxy)
-{
-	SoupURI			*uri;
-
-	/* see if we need to clear it */
-	if (proxy == NULL || strlen(proxy) == 0) {
-		setup_proxy(NULL);
-		return (0);
-	}
-
-	uri = soup_uri_new(proxy);
-	if (uri == NULL || !SOUP_URI_VALID_FOR_HTTP(uri))
-		return (1);
-
-	setup_proxy(proxy);
-
-	soup_uri_free(uri);
-
-	return (0);
-}
-
-struct special {
-	int		(*set)(struct settings *, char *);
-	char		*(*get)(struct settings *);
-	void		(*walk)(struct settings *,
-			    void (*cb)(struct settings *, char *, void *),
-			    void *);
-};
-
 struct special		s_browser_mode = {
 	set_browser_mode,
 	get_browser_mode,
-	NULL
+	NULL,
+	{ "kiosk", "normal", "whitelist", NULL }
 };
 
 struct special		s_gui_mode = {
 	set_gui_mode,
 	get_gui_mode,
-	NULL
+	NULL,
+	{ "classic", "minimal", NULL }
 };
 
 struct special		s_cookie = {
 	set_cookie_policy,
 	get_cookie_policy,
-	NULL
+	NULL,
+	{ "accept", "no3rdparty", "reject", NULL }
 };
 
 struct special		s_alias = {
 	add_alias,
 	NULL,
-	walk_alias
+	walk_alias,
+	{ NULL }
 };
 
 struct special		s_cmd_alias = {
 	add_cmd_alias,
 	NULL,
-	walk_cmd_alias
+	walk_cmd_alias,
+	{ NULL }
 };
 
 struct special		s_mime = {
 	add_mime_type,
 	NULL,
-	walk_mime_type
+	walk_mime_type,
+	{ NULL }
 };
 
 struct special		s_js = {
 	add_js_wl,
 	NULL,
-	walk_js_wl
+	walk_js_wl,
+	{ NULL }
 };
 
 struct special		s_pl = {
 	add_pl_wl,
 	NULL,
-	walk_pl_wl
+	walk_pl_wl,
+	{ NULL }
 };
 
 struct special		s_kb = {
 	add_kb,
 	NULL,
-	walk_kb
+	walk_kb,
+	{ NULL }
 };
 
 struct special		s_cookie_wl = {
 	add_cookie_wl,
 	NULL,
-	walk_cookie_wl
+	walk_cookie_wl,
+	{ NULL }
 };
 
 struct special		s_uri = {
 	add_custom_uri,
 	NULL,
 	walk_custom_uri,
+	{ NULL }
 };
 
 struct special		s_default_script = {
 	set_default_script,
 	get_default_script,
-	NULL
+	NULL,
+	{ NULL }
 };
 
 struct special		s_ssl_ca_file = {
 	set_ssl_ca_file,
 	get_ssl_ca_file,
-	NULL
+	NULL,
+	{ NULL }
 };
 
 struct special		s_download_dir = {
 	set_download_dir,
 	get_download_dir,
-	NULL
+	NULL,
+	{ NULL }
 };
 
 struct special		s_work_dir = {
 	set_work_dir,
 	get_work_dir,
-	NULL
+	NULL,
+	{ NULL }
 };
 
 struct special		s_tab_style = {
 	set_tab_style,
 	get_tab_style,
-	NULL
+	NULL,
+	{ "compact", "normal", NULL }
 };
 
 struct special		s_statusbar_style = {
 	set_statusbar_style,
 	get_statusbar_style,
-	NULL
+	NULL,
+	{ "title", "url", NULL }
 };
 
 struct special		s_edit_mode = {
 	set_edit_mode,
 	get_edit_mode,
-	NULL
+	NULL,
+	{ "hybrid", "vi", NULL }
 };
 
 struct special		s_download_mode = {
 	set_download_mode,
 	get_download_mode,
-	NULL
+	NULL,
+	{ "add", "ask", "start", NULL }
 };
 
 struct special		s_ua = {
 	add_ua,
 	NULL,
-	walk_ua
+	walk_ua,
+	{ NULL }
 };
 
 struct special		s_http_accept = {
 	add_http_accept,
 	NULL,
-	walk_http_accept
+	walk_http_accept,
+	{ NULL }
 };
 
 struct special		s_referer = {
 	set_referer,
 	get_referer,
-	NULL
+	NULL,
+	{ "always", "never", "same-domain", "same-fqdn", NULL }
 };
 
 struct special		s_userstyle = {
 	set_userstyle,
 	get_userstyle,
-	NULL
+	NULL,
+	{ NULL }
 };
 
 struct special		s_force_https = {
@@ -406,83 +477,83 @@ struct special		s_force_https = {
 };
 
 struct settings		rs[] = {
-	{ "allow_insecure_content",	XT_S_INT, 0,		&allow_insecure_content, NULL, NULL, NULL, set_allow_insecure_content },
-	{ "allow_insecure_scripts",	XT_S_INT, 0,		&allow_insecure_scripts, NULL, NULL, NULL, set_allow_insecure_scripts },
-	{ "allow_volatile_cookies",	XT_S_INT, 0,		&allow_volatile_cookies, NULL, NULL, NULL, NULL},
-	{ "append_next",		XT_S_INT, 0,		&append_next, NULL, NULL, NULL, set_append_next },
-	{ "auto_load_images",		XT_S_INT, 0,		&auto_load_images, NULL, NULL, NULL, set_auto_load_images },
-	{ "autofocus_onload",		XT_S_INT, 0,		&autofocus_onload, NULL, NULL, NULL, set_autofocus_onload },
-	{ "browser_mode",		XT_S_INT, 0, NULL, NULL,&s_browser_mode, NULL, NULL },
-	{ "cmd_font",			XT_S_STR, 0, NULL, &cmd_font_name, NULL, NULL, set_cmd_font },
-	{ "color_visited_uris",		XT_S_INT, 0,		&color_visited_uris , NULL, NULL, NULL, set_color_visited_uris },
-	{ "cookie_policy",		XT_S_INT, 0, NULL, NULL,&s_cookie, NULL, set_cookie_policy_rt },
-	{ "cookies_enabled",		XT_S_INT, 0,		&cookies_enabled, NULL, NULL, NULL, set_cookies_enabled },
-	{ "ctrl_click_focus",		XT_S_INT, 0,		&ctrl_click_focus, NULL, NULL, NULL, set_ctrl_click_focus },
-	{ "default_script",		XT_S_STR, 1, NULL, NULL,&s_default_script, NULL, set_default_script_rt },
-	{ "default_zoom_level",		XT_S_FLOAT, 0,		NULL, NULL, NULL, &default_zoom_level, set_default_zoom_level },
-	{ "do_not_track",		XT_S_INT, 0,		&do_not_track, NULL, NULL, NULL, set_do_not_track },
-	{ "download_dir",		XT_S_STR, 0, NULL, NULL,&s_download_dir, NULL, NULL },
-	{ "download_mode",		XT_S_STR, 0, NULL, NULL,&s_download_mode, NULL, set_download_mode_rt },
-	{ "download_notifications",	XT_S_INT, 0,		&download_notifications, NULL, NULL, NULL, set_download_notifications },
-	{ "edit_mode",			XT_S_STR, 0, NULL, NULL,&s_edit_mode, NULL, NULL},
-	{ "enable_autoscroll",		XT_S_INT, 0,		&enable_autoscroll, NULL, NULL, NULL, set_enable_autoscroll },
-	{ "enable_cookie_whitelist",	XT_S_INT, 0,		&enable_cookie_whitelist, NULL, NULL, NULL, set_enable_cookie_whitelist },
-	{ "enable_favicon_entry",	XT_S_INT, 0,		&enable_favicon_entry, NULL, NULL, NULL, set_enable_favicon_entry },
-	{ "enable_favicon_tabs",	XT_S_INT, 0,		&enable_favicon_tabs, NULL, NULL, NULL, set_enable_favicon_tabs },
-	{ "enable_js_autorun",		XT_S_INT, 0,		&enable_js_autorun, NULL, NULL, NULL, set_enable_js_autorun },
-	{ "enable_js_whitelist",	XT_S_INT, 0,		&enable_js_whitelist, NULL, NULL, NULL, set_enable_js_whitelist },
-	{ "enable_localstorage",	XT_S_INT, 0,		&enable_localstorage, NULL, NULL, NULL, set_enable_localstorage },
-	{ "enable_plugin_whitelist",	XT_S_INT, 0,		&enable_plugin_whitelist, NULL, NULL, NULL, set_enable_plugin_whitelist },
-	{ "enable_plugins",		XT_S_INT, 0,		&enable_plugins, NULL, NULL, NULL, set_enable_plugins },
-	{ "enable_scripts",		XT_S_INT, 0,		&enable_scripts, NULL, NULL, NULL, set_enable_scripts },
-	{ "enable_socket",		XT_S_INT, XT_SF_RESTART,&enable_socket, NULL, NULL, NULL, NULL },
-	{ "enable_spell_checking",	XT_S_INT, 0,		&enable_spell_checking, NULL, NULL, NULL, set_enable_spell_checking },
-	{ "enable_strict_transport",	XT_S_INT, 0,		&enable_strict_transport, NULL, NULL, NULL, set_enable_strict_transport },
-	{ "encoding",			XT_S_STR, 0, NULL,	&encoding, NULL, NULL, NULL },
-	{ "external_editor",		XT_S_STR,0, NULL,	&external_editor, NULL, NULL, set_external_editor },
-	{ "fancy_bar",			XT_S_INT, XT_SF_RESTART,&fancy_bar, NULL, NULL, NULL, set_fancy_bar },
-	{ "guess_search",		XT_S_INT, 0,		&guess_search, NULL, NULL, NULL, set_guess_search },
-	{ "gui_mode",			XT_S_INT, 0, NULL, NULL,&s_gui_mode, NULL, NULL },
-	{ "history_autosave",		XT_S_INT, 0,		&history_autosave, NULL, NULL, NULL, NULL },
-	{ "home",			XT_S_STR, 0, NULL,	&home, NULL, NULL, set_home },
-	{ "http_proxy",			XT_S_STR, 0, NULL,	&http_proxy, NULL, NULL, set_http_proxy },
-	{ "http_proxy_starts_enabled",	XT_S_INT, 0,		&http_proxy_starts_enabled, NULL, NULL, NULL, NULL },
-	{ "icon_size",			XT_S_INT, 0,		&icon_size, NULL, NULL, NULL, NULL },
-	{ "include_config",		XT_S_STR, 0, NULL,	&include_config, NULL, NULL, NULL },
-	{ "max_connections",		XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL, NULL, NULL },
-	{ "max_host_connections",	XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL, NULL, NULL },
-	{ "oops_font",			XT_S_STR, 0, NULL, &oops_font_name, NULL, NULL, set_oops_font },
-	{ "preload_strict_transport",	XT_S_INT, 0,		&preload_strict_transport, NULL, NULL, NULL, NULL },
-	{ "read_only_cookies",		XT_S_INT, 0,		&read_only_cookies, NULL, NULL, NULL, set_read_only_cookies },
-	{ "referer",			XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt },
-	{ "refresh_interval",		XT_S_INT, 0,		&refresh_interval, NULL, NULL, NULL, set_refresh_interval },
-	{ "resource_dir",		XT_S_STR, 0, NULL,	&resource_dir, NULL, NULL, NULL },
-	{ "save_global_history",	XT_S_INT, XT_SF_RESTART,&save_global_history, NULL, NULL, NULL, NULL },
-	{ "save_rejected_cookies",	XT_S_INT, XT_SF_RESTART,&save_rejected_cookies, NULL, NULL, NULL, NULL },
-	{ "search_string",		XT_S_STR, 0, NULL,	&search_string, NULL, NULL, set_search_string },
-	{ "session_autosave",		XT_S_INT, 0,		&session_autosave, NULL, NULL, NULL, set_session_autosave },
-	{ "session_timeout",		XT_S_INT, 0,		&session_timeout, NULL, NULL, NULL, set_session_timeout },
-	{ "show_scrollbars",		XT_S_INT, 0,		&show_scrollbars, NULL, NULL, NULL, set_show_scrollbars },
-	{ "show_statusbar",		XT_S_INT, 0,		&show_statusbar, NULL, NULL, NULL, set_show_statusbar },
-	{ "show_tabs",			XT_S_INT, 0,		&show_tabs, NULL, NULL, NULL, set_show_tabs },
-	{ "show_url",			XT_S_INT, 0,		&show_url, NULL, NULL, NULL, set_show_url },
-	{ "single_instance",		XT_S_INT, XT_SF_RESTART,&single_instance, NULL, NULL, NULL, NULL },
-	{ "spell_check_languages",	XT_S_STR, 0, NULL,	&spell_check_languages, NULL, NULL, set_spell_check_languages },
-	{ "ssl_ca_file",		XT_S_STR, 0, NULL, NULL,&s_ssl_ca_file, NULL, set_ssl_ca_file_rt },
-	{ "ssl_strict_certs",		XT_S_INT, 0,		&ssl_strict_certs, NULL, NULL, NULL, set_ssl_strict_certs },
-	{ "statusbar_elems",		XT_S_STR, 0, NULL,	&statusbar_elems, NULL, NULL, NULL },
-	{ "statusbar_font",		XT_S_STR, 0, NULL, &statusbar_font_name, NULL, NULL, set_statusbar_font },
-	{ "statusbar_style",		XT_S_STR, 0, NULL, NULL,&s_statusbar_style, NULL, set_statusbar_style_rt },
-	{ "tab_style",			XT_S_STR, 0, NULL, NULL,&s_tab_style, NULL, set_tab_style_rt },
-	{ "tabbar_font",		XT_S_STR, 0, NULL, &tabbar_font_name, NULL, NULL, set_tabbar_font },
-	{ "url_regex",			XT_S_STR, 0, NULL,	&url_regex, NULL, NULL, set_url_regex },
-	{ "userstyle",			XT_S_STR, 0, NULL, NULL,&s_userstyle, NULL, set_userstyle_rt },
-	{ "userstyle_global",		XT_S_INT, 0,		&userstyle_global, NULL, NULL, NULL, set_userstyle_global },
-	{ "warn_cert_changes",		XT_S_INT, 0,		&warn_cert_changes, NULL, NULL, NULL, set_warn_cert_changes },
-	{ "window_height",		XT_S_INT, 0,		&window_height, NULL, NULL, NULL, NULL },
-	{ "window_maximize",		XT_S_INT, 0,		&window_maximize, NULL, NULL, NULL, NULL },
-	{ "window_width",		XT_S_INT, 0,		&window_width, NULL, NULL, NULL, NULL },
-	{ "work_dir",			XT_S_STR, 0, NULL, NULL,&s_work_dir, NULL, NULL },
+	{ "allow_insecure_content",	XT_S_BOOL, 0,		&allow_insecure_content, NULL, NULL, NULL, set_allow_insecure_content, check_allow_insecure_content, TT_ALLOW_INSECURE_CONTENT },
+	{ "allow_insecure_scripts",	XT_S_BOOL, 0,		&allow_insecure_scripts, NULL, NULL, NULL, set_allow_insecure_scripts, check_allow_insecure_scripts, TT_ALLOW_INSECURE_SCRIPTS},
+	{ "allow_volatile_cookies",	XT_S_BOOL, 0,		&allow_volatile_cookies, NULL, NULL, NULL, NULL, check_allow_volatile_cookies, TT_ALLOW_VOLATILE_COOKIES},
+	{ "append_next",		XT_S_BOOL, 0,		&append_next, NULL, NULL, NULL, set_append_next, check_append_next, TT_APPEND_NEXT},
+	{ "auto_load_images",		XT_S_BOOL, 0,		&auto_load_images, NULL, NULL, NULL, set_auto_load_images, check_auto_load_images, TT_AUTO_LOAD_IMAGES },
+	{ "autofocus_onload",		XT_S_BOOL, 0,		&autofocus_onload, NULL, NULL, NULL, set_autofocus_onload, check_autofocus_onload, TT_AUTOFOCUS_ONLOAD },
+	{ "browser_mode",		XT_S_STR, 0, NULL, NULL,&s_browser_mode, NULL, NULL, check_browser_mode, TT_BROWSER_MODE },
+	{ "cmd_font",			XT_S_STR, 0, NULL, &cmd_font_name, NULL, NULL, set_cmd_font, check_cmd_font, TT_CMD_FONT},
+	{ "color_visited_uris",		XT_S_BOOL, 0,		&color_visited_uris , NULL, NULL, NULL, set_color_visited_uris, check_color_visited_uris, TT_COLOR_VISITED_URIS },
+	{ "cookie_policy",		XT_S_STR, 0, NULL, NULL,&s_cookie, NULL, set_cookie_policy_rt, check_cookie_policy, TT_COOKIE_POLICY},
+	{ "cookies_enabled",		XT_S_BOOL, 0,		&cookies_enabled, NULL, NULL, NULL, set_cookies_enabled, check_cookies_enabled, TT_COOKIES_ENABLED },
+	{ "ctrl_click_focus",		XT_S_BOOL, 0,		&ctrl_click_focus, NULL, NULL, NULL, set_ctrl_click_focus, check_ctrl_click_focus, TT_CTRL_CLICK_FOCUS },
+	{ "default_script",		XT_S_STR, 1, NULL, NULL,&s_default_script, NULL, set_default_script_rt, check_default_script, TT_DEFAULT_SCRIPT },
+	{ "default_zoom_level",		XT_S_FLOAT, 0,		NULL, NULL, NULL, &default_zoom_level, set_default_zoom_level, check_default_zoom_level, TT_DEFAULT_ZOOM_LEVEL },
+	{ "do_not_track",		XT_S_BOOL, 0,		&do_not_track, NULL, NULL, NULL, set_do_not_track, check_do_not_track, TT_DO_NOT_TRACK },
+	{ "download_dir",		XT_S_STR, 0, NULL, NULL,&s_download_dir, NULL, NULL, check_download_dir, TT_DOWNLOAD_DIR },
+	{ "download_mode",		XT_S_STR, 0, NULL, NULL,&s_download_mode, NULL, set_download_mode_rt, check_download_mode, TT_DOWNLOAD_MODE },
+	{ "download_notifications",	XT_S_BOOL, 0,		&download_notifications, NULL, NULL, NULL, set_download_notifications, check_download_notifications, TT_DOWNLOAD_NOTIFICATIONS },
+	{ "edit_mode",			XT_S_STR, 0, NULL, NULL,&s_edit_mode, NULL, NULL, check_edit_mode, NULL },
+	{ "enable_autoscroll",		XT_S_BOOL, 0,		&enable_autoscroll, NULL, NULL, NULL, set_enable_autoscroll, check_enable_autoscroll, TT_ENABLE_AUTOSCROLL },
+	{ "enable_cookie_whitelist",	XT_S_BOOL, 0,		&enable_cookie_whitelist, NULL, NULL, NULL, set_enable_cookie_whitelist, check_enable_cookie_whitelist, TT_ENABLE_COOKIE_WHITELIST },
+	{ "enable_favicon_entry",	XT_S_BOOL, 0,		&enable_favicon_entry, NULL, NULL, NULL, set_enable_favicon_entry, check_enable_favicon_entry, TT_ENABLE_FAVICON_ENTRY },
+	{ "enable_favicon_tabs",	XT_S_BOOL, 0,		&enable_favicon_tabs, NULL, NULL, NULL, set_enable_favicon_tabs, check_enable_favicon_tabs, TT_ENABLE_FAVICON_TABS },
+	{ "enable_js_autorun",		XT_S_BOOL, 0,		&enable_js_autorun, NULL, NULL, NULL, set_enable_js_autorun, check_enable_js_autorun, TT_ENABLE_JS_AUTORUN },
+	{ "enable_js_whitelist",	XT_S_BOOL, 0,		&enable_js_whitelist, NULL, NULL, NULL, set_enable_js_whitelist, check_enable_js_whitelist, TT_ENABLE_JS_WHITELIST },
+	{ "enable_localstorage",	XT_S_BOOL, 0,		&enable_localstorage, NULL, NULL, NULL, set_enable_localstorage, check_enable_localstorage, TT_ENABLE_LOCALSTORAGE },
+	{ "enable_plugin_whitelist",	XT_S_BOOL, 0,		&enable_plugin_whitelist, NULL, NULL, NULL, set_enable_plugin_whitelist, check_enable_plugin_whitelist, TT_ENABLE_PLUGIN_WHITELIST },
+	{ "enable_plugins",		XT_S_BOOL, 0,		&enable_plugins, NULL, NULL, NULL, set_enable_plugins, check_enable_plugins, TT_ENABLE_PLUGINS },
+	{ "enable_scripts",		XT_S_BOOL, 0,		&enable_scripts, NULL, NULL, NULL, set_enable_scripts, check_enable_scripts, TT_ENABLE_SCRIPTS },
+	{ "enable_socket",		XT_S_BOOL,XT_SF_RESTART,&enable_socket, NULL, NULL, NULL, NULL, check_enable_socket, TT_ENABLE_SOCKET },
+	{ "enable_spell_checking",	XT_S_BOOL, 0,		&enable_spell_checking, NULL, NULL, NULL, set_enable_spell_checking, check_enable_spell_checking, TT_ENABLE_SPELL_CHECKING },
+	{ "enable_strict_transport",	XT_S_BOOL, 0,		&enable_strict_transport, NULL, NULL, NULL, set_enable_strict_transport, check_enable_strict_transport, TT_ENABLE_STRICT_TRANSPORT },
+	{ "encoding",			XT_S_STR, 0, NULL,	&encoding, NULL, NULL, NULL, check_encoding, TT_ENCODING },
+	{ "external_editor",		XT_S_STR,0, NULL,	&external_editor, NULL, NULL, set_external_editor, check_external_editor, TT_EXTERNAL_EDITOR },
+	{ "fancy_bar",			XT_S_BOOL,XT_SF_RESTART,&fancy_bar, NULL, NULL, NULL, set_fancy_bar, check_fancy_bar, TT_FANCY_BAR },
+	{ "guess_search",		XT_S_BOOL, 0,		&guess_search, NULL, NULL, NULL, set_guess_search, check_guess_search, TT_GUESS_SEARCH },
+	{ "gui_mode",			XT_S_STR, 0, NULL, NULL,&s_gui_mode, NULL, NULL, check_gui_mode, TT_GUI_MODE },
+	{ "history_autosave",		XT_S_BOOL, 0,		&history_autosave, NULL, NULL, NULL, NULL, check_history_autosave, TT_HISTORY_AUTOSAVE },
+	{ "home",			XT_S_STR, 0, NULL,	&home, NULL, NULL, set_home, check_home, TT_HOME },
+	{ "http_proxy",			XT_S_STR, 0, NULL,	&http_proxy, NULL, NULL, set_http_proxy, check_http_proxy, TT_HTTP_PROXY },
+	{ "http_proxy_starts_enabled",	XT_S_BOOL, 0,		&http_proxy_starts_enabled, NULL, NULL, NULL, NULL, check_http_proxy_starts_enabled, TT_HTTP_PROXY_STARTS_ENABLED },
+	{ "icon_size",			XT_S_INT, 0,		&icon_size, NULL, NULL, NULL, NULL, check_icon_size, TT_ICON_SIZE },
+	{ "include_config",		XT_S_STR, XT_SF_INVISIBLE, NULL, &include_config, NULL, NULL, NULL, NULL },
+	{ "max_connections",		XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL, NULL, NULL, check_max_connections, TT_MAX_CONNECTIONS },
+	{ "max_host_connections",	XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL, NULL, NULL, check_max_host_connections, TT_MAX_HOST_CONNECTIONS },
+	{ "oops_font",			XT_S_STR, 0, NULL, &oops_font_name, NULL, NULL, set_oops_font, check_oops_font, TT_OOPS_FONT },
+	{ "preload_strict_transport",	XT_S_BOOL, 0,		&preload_strict_transport, NULL, NULL, NULL, NULL, NULL, TT_PRELOAD_STRICT_TRANSPORT },
+	{ "read_only_cookies",		XT_S_BOOL, 0,		&read_only_cookies, NULL, NULL, NULL, NULL, check_read_only_cookies, TT_READ_ONLY_COOKIES },
+	{ "referer",			XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt, check_referer, TT_REFERER },
+	{ "refresh_interval",		XT_S_INT, 0,		&refresh_interval, NULL, NULL, NULL, set_refresh_interval, check_refresh_interval, TT_REFRESH_INTERVAL },
+	{ "resource_dir",		XT_S_STR, 0, NULL,	&resource_dir, NULL, NULL, NULL, check_resource_dir, TT_RESOURCE_DIR },
+	{ "save_global_history",	XT_S_BOOL,XT_SF_RESTART,&save_global_history, NULL, NULL, NULL, NULL, check_save_global_history, TT_SAVE_GLOBAL_HISTORY },
+	{ "save_rejected_cookies",	XT_S_BOOL,XT_SF_RESTART,&save_rejected_cookies, NULL, NULL, NULL, NULL, check_save_rejected_cookies, TT_SAVE_REJECTED_COOKIES },
+	{ "search_string",		XT_S_STR, 0, NULL,	&search_string, NULL, NULL, set_search_string, check_search_string, TT_SEARCH_STRING },
+	{ "session_autosave",		XT_S_BOOL, 0,		&session_autosave, NULL, NULL, NULL, set_session_autosave, check_session_autosave, TT_SESSION_AUTOSAVE },
+	{ "session_timeout",		XT_S_INT, 0,		&session_timeout, NULL, NULL, NULL, set_session_timeout, check_session_timeout, TT_SESSION_TIMEOUT },
+	{ "show_scrollbars",		XT_S_BOOL, 0,		&show_scrollbars, NULL, NULL, NULL, set_show_scrollbars, check_show_scrollbars, TT_SHOW_SCROLLBARS },
+	{ "show_statusbar",		XT_S_BOOL, 0,		&show_statusbar, NULL, NULL, NULL, set_show_statusbar, check_show_statusbar, TT_SHOW_STATUSBAR },
+	{ "show_tabs",			XT_S_BOOL, 0,		&show_tabs, NULL, NULL, NULL, set_show_tabs, check_show_tabs, TT_SHOW_TABS },
+	{ "show_url",			XT_S_BOOL, 0,		&show_url, NULL, NULL, NULL, set_show_url, check_show_url, TT_SHOW_URL },
+	{ "single_instance",		XT_S_BOOL,XT_SF_RESTART,&single_instance, NULL, NULL, NULL, NULL, check_single_instance, TT_SINGLE_INSTANCE },
+	{ "spell_check_languages",	XT_S_STR, 0, NULL,	&spell_check_languages, NULL, NULL, set_spell_check_languages, check_spell_check_languages, TT_SPELL_CHECK_LANGUAGES },
+	{ "ssl_ca_file",		XT_S_STR, 0, NULL, NULL,&s_ssl_ca_file, NULL, set_ssl_ca_file_rt, check_ssl_ca_file, TT_SSL_CA_FILE },
+	{ "ssl_strict_certs",		XT_S_BOOL, 0,		&ssl_strict_certs, NULL, NULL, NULL, set_ssl_strict_certs, check_ssl_strict_certs, TT_SSL_STRICT_CERTS },
+	{ "statusbar_elems",		XT_S_STR, 0, NULL,	&statusbar_elems, NULL, NULL, NULL, check_statusbar_elems, TT_STATUSBAR_ELEMS },
+	{ "statusbar_font",		XT_S_STR, 0, NULL, &statusbar_font_name, NULL, NULL, set_statusbar_font, check_statusbar_font, TT_STATUSBAR_FONT },
+	{ "statusbar_style",		XT_S_STR, 0, NULL, NULL,&s_statusbar_style, NULL, set_statusbar_style_rt, check_statusbar_style, TT_STATUSBAR_STYLE },
+	{ "tab_style",			XT_S_STR, 0, NULL, NULL,&s_tab_style, NULL, set_tab_style_rt, check_tab_style, TT_TAB_STYLE },
+	{ "tabbar_font",		XT_S_STR, 0, NULL, &tabbar_font_name, NULL, NULL, set_tabbar_font, check_tabbar_font, TT_TABBAR_FONT },
+	{ "url_regex",			XT_S_STR, 0, NULL,	&url_regex, NULL, NULL, set_url_regex, check_url_regex, TT_URL_REGEX },
+	{ "userstyle",			XT_S_STR, 0, NULL, NULL,&s_userstyle, NULL, set_userstyle_rt, check_userstyle, TT_USERSTYLE },
+	{ "userstyle_global",		XT_S_BOOL, 0,		&userstyle_global, NULL, NULL, NULL, set_userstyle_global, check_userstyle_global, TT_USERSTYLE_GLOBAL },
+	{ "warn_cert_changes",		XT_S_BOOL, 0,		&warn_cert_changes, NULL, NULL, NULL, set_warn_cert_changes, check_warn_cert_changes, TT_WARN_CERT_CHANGES },
+	{ "window_height",		XT_S_INT, 0,		&window_height, NULL, NULL, NULL, NULL, check_window_height, TT_WINDOW_HEIGHT },
+	{ "window_maximize",		XT_S_BOOL, 0,		&window_maximize, NULL, NULL, NULL, NULL, check_window_maximize, TT_WINDOW_MAXIMIZE },
+	{ "window_width",		XT_S_INT, 0,		&window_width, NULL, NULL, NULL, NULL, check_window_width, TT_WINDOW_WIDTH },
+	{ "work_dir",			XT_S_STR, 0, NULL, NULL,&s_work_dir, NULL, NULL, check_work_dir, TT_WORK_DIR },
 
 	/* special settings */
 	{ "alias",			XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_alias, NULL, NULL },
@@ -499,6 +570,63 @@ struct settings		rs[] = {
 };
 
 int
+set_http_proxy(char *proxy)
+{
+	SoupURI			*uri;
+
+	/* see if we need to clear it */
+	if (proxy == NULL || strlen(proxy) == 0) {
+		setup_proxy(NULL);
+		return (0);
+	}
+
+	uri = soup_uri_new(proxy);
+	if (uri == NULL || !SOUP_URI_VALID_FOR_HTTP(uri))
+		return (1);
+
+	setup_proxy(proxy);
+
+	soup_uri_free(uri);
+
+	return (0);
+}
+
+int
+check_http_proxy(char **tt)
+{
+	*tt = g_strdup("Default: (empty)");
+	return (g_strcmp0(http_proxy, NULL));
+}
+
+int
+check_http_proxy_starts_enabled(char **tt)
+{
+	*tt = g_strdup("Default: Enabled");
+	return (http_proxy_starts_enabled != 1);
+}
+
+int
+check_icon_size(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", 2);
+	return (icon_size != 2);
+}
+
+int
+check_max_connections(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", 25);
+	return (max_connections != 25);
+}
+
+int
+check_max_host_connections(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", 5);
+	return (max_host_connections != 5);
+}
+
+int
 set_default_zoom_level(char *value)
 {
 	struct karg		args = {0};
@@ -515,6 +643,13 @@ set_default_zoom_level(char *value)
 }
 
 int
+check_default_zoom_level(char **tt)
+{
+	*tt = g_strdup_printf("Default: %f", XT_DS_DEFAULT_ZOOM_LEVEL);
+	return (default_zoom_level != XT_DS_DEFAULT_ZOOM_LEVEL);
+}
+
+int
 set_cookies_enabled(char *value)
 {
 	int			tmp;
@@ -532,6 +667,14 @@ set_cookies_enabled(char *value)
 }
 
 int
+check_cookies_enabled(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_COOKIES_ENABLED ? "Enabled" : "Disabled");
+	return (cookies_enabled != XT_DS_COOKIES_ENABLED);
+}
+
+int
 set_append_next(char *value)
 {
 	int			tmp;
@@ -549,6 +692,14 @@ set_append_next(char *value)
 }
 
 int
+check_append_next(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_APPEND_NEXT ? "Enabled" : "Disabled");
+	return (append_next != XT_DS_APPEND_NEXT);
+}
+
+int
 set_cmd_font(char *value)
 {
 	struct tab		*t;
@@ -568,6 +719,13 @@ set_cmd_font(char *value)
 }
 
 int
+check_cmd_font(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_CMD_FONT_NAME);
+	return (g_strcmp0(cmd_font_name, XT_DS_CMD_FONT_NAME));
+}
+
+int
 set_oops_font(char *value)
 {
 	struct tab		*t;
@@ -587,6 +745,21 @@ set_oops_font(char *value)
 }
 
 int
+check_oops_font(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_OOPS_FONT_NAME);
+	return (g_strcmp0(oops_font_name, XT_DS_OOPS_FONT_NAME));
+}
+
+int
+check_read_only_cookies(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_READ_ONLY_COOKIES ? "Enabled" : "Disabled");
+	return (read_only_cookies != XT_DS_READ_ONLY_COOKIES);
+}
+
+int
 set_statusbar_font(char *value)
 {
 	struct tab		*t;
@@ -617,6 +790,13 @@ set_statusbar_font(char *value)
 }
 
 int
+check_statusbar_font(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_STATUSBAR_FONT_NAME);
+	return (g_strcmp0(statusbar_font_name, XT_DS_STATUSBAR_FONT_NAME));
+}
+
+int
 set_tabbar_font(char *value)
 {
 	struct tab		*t;
@@ -637,6 +817,13 @@ set_tabbar_font(char *value)
 }
 
 int
+check_tabbar_font(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_TABBAR_FONT_NAME);
+	return (g_strcmp0(tabbar_font_name, XT_DS_TABBAR_FONT_NAME));
+}
+
+int
 set_color_visited_uris(char *value)
 {
 	int			tmp;
@@ -654,6 +841,14 @@ set_color_visited_uris(char *value)
 }
 
 int
+check_color_visited_uris(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_COLOR_VISITED_URIS ? "Enabled" : "Disabled");
+	return (color_visited_uris != XT_DS_COLOR_VISITED_URIS);
+}
+
+int
 set_home(char *value)
 {
 	if (home)
@@ -666,6 +861,13 @@ set_home(char *value)
 }
 
 int
+check_home(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_HOME);
+	return (g_strcmp0(home, XT_DS_HOME));
+}
+
+int
 set_search_string(char *value)
 {
 	struct tab		*t;
@@ -684,6 +886,13 @@ set_search_string(char *value)
 	return (0);
 }
 
+int
+check_search_string(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_SEARCH_STRING);
+	return (g_strcmp0(search_string, XT_DS_SEARCH_STRING));
+}
+
 size_t
 get_settings_size(void)
 {
@@ -706,17 +915,16 @@ get_as_string(struct settings *s)
 	if (s == NULL)
 		return (NULL);
 
-	if (s->s) {
-		if (s->s->get)
-			r = s->s->get(s);
-		else
-			warnx("get_as_string skip %s\n", s->name);
-	} else if (s->type == XT_S_INT)
+	if (s->s && s->s->get)
+		r = s->s->get(s);
+	else if (s->type == XT_S_INT)
 		r = g_strdup_printf("%d", *s->ival);
 	else if (s->type == XT_S_STR)
 		r = g_strdup(*s->sval);
 	else if (s->type == XT_S_FLOAT)
 		r = g_strdup_printf("%f", *s->fval);
+	else if (s->type == XT_S_BOOL)
+		r = g_strdup_printf("%d", *s->ival);
 	else
 		r = g_strdup_printf("INVALID TYPE");
 
@@ -741,6 +949,13 @@ settings_walk(void (*cb)(struct settings *, char *, void *), void *cb_args)
 }
 
 int
+check_allow_volatile_cookies(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (allow_volatile_cookies != 0);
+}
+
+int
 set_browser_mode(struct settings *s, char *val)
 {
 	if (!strcmp(val, "whitelist")) {
@@ -823,6 +1038,13 @@ get_browser_mode(struct settings *s)
 }
 
 int
+check_browser_mode(char **tt)
+{
+	*tt = g_strdup("Default: normal");
+	return (browser_mode != XT_BM_NORMAL);
+}
+
+int
 set_gui_mode(struct settings *s, char *val)
 {
 	if (!strcmp(val, "classic")) {
@@ -861,6 +1083,20 @@ get_gui_mode(struct settings *s)
 }
 
 int
+check_gui_mode(char **tt)
+{
+	*tt = g_strdup("Default: classic");
+	return (gui_mode != XT_GM_CLASSIC);
+}
+
+int
+check_history_autosave(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (history_autosave != 0);
+}
+
+int
 set_cookie_policy(struct settings *s, char *val)
 {
 	if (!strcmp(val, "no3rdparty"))
@@ -887,6 +1123,25 @@ set_cookie_policy_rt(char *value)
 	return (0);
 }
 
+int
+check_cookie_policy(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\talways\n"
+	    "\twhitelist:\tno3rdparty\n"
+	    "\tkiosk:\talways");
+	if (browser_mode == XT_BM_WHITELIST &&
+	    cookie_policy != SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL &&
+	    cookie_policy != SOUP_COOKIE_JAR_ACCEPT_ALWAYS)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK &&
+	    cookie_policy != SOUP_COOKIE_JAR_ACCEPT_ALWAYS)
+		return (1);
+	return (0);
+}
+
 char *
 get_cookie_policy(struct settings *s)
 {
@@ -920,6 +1175,13 @@ set_default_script(struct settings *s, char *val)
 }
 
 int
+check_default_script(char **tt)
+{
+	*tt = g_strdup("Default: (empty)");
+	return (g_strcmp0(default_script, XT_DS_DEFAULT_SCRIPT));
+}
+
+int
 set_default_script_rt(char *value)
 {
 	if (value == NULL || strlen(value) == 0)
@@ -944,6 +1206,22 @@ set_do_not_track(char *value)
 	return (0);
 }
 
+int
+check_do_not_track(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tDisabled\n"
+	    "\twhitelist:\tEnabled\n"
+	    "\tkiosk:\tDisabled");
+	if (browser_mode == XT_BM_WHITELIST && do_not_track != 1)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && do_not_track != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && do_not_track != 0)
+		return (1);
+	return (0);
+}
+
 char *
 get_download_dir(struct settings *s)
 {
@@ -960,6 +1238,20 @@ set_download_dir(struct settings *s, char *val)
 }
 
 int
+check_download_dir(char **tt)
+{
+	struct passwd		*pwd;
+	char			buf[PATH_MAX] = {0};
+
+	/* XXX this might need some additonal magic on windows */
+	if ((pwd = getpwuid(getuid())) == NULL)
+		return (-1);
+	snprintf(buf, sizeof buf, "%s" PS "downloads", pwd->pw_dir);
+	*tt = g_strdup_printf("Default: %s", buf);
+	return (g_strcmp0(download_dir, buf));
+}
+
+int
 add_alias(struct settings *s, char *line)
 {
 	char			*l, *alias;
@@ -1586,6 +1878,22 @@ set_allow_insecure_content(char *value)
 }
 
 int
+check_allow_insecure_content(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tEnabled\n"
+	    "\twhitelist:\tDisabled\n"
+	    "\tkiosk:\tEnabled");
+	if (browser_mode == XT_BM_NORMAL && allow_insecure_content != 1)
+		return (1);
+	if (browser_mode == XT_BM_WHITELIST && allow_insecure_content != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && allow_insecure_content != 1)
+		return (1);
+	return (0);
+}
+
+int
 set_allow_insecure_scripts(char *value)
 {
 	struct tab		*t;
@@ -1612,6 +1920,22 @@ set_allow_insecure_scripts(char *value)
 }
 
 int
+check_allow_insecure_scripts(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tEnabled\n"
+	    "\twhitelist:\tDisabled\n"
+	    "\tkiosk:\tEnabled");
+	if (browser_mode == XT_BM_NORMAL && allow_insecure_scripts != 1)
+		return (1);
+	if (browser_mode == XT_BM_WHITELIST && allow_insecure_scripts != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && allow_insecure_scripts != 1)
+		return (1);
+	return (0);
+}
+
+int
 set_auto_load_images(char *value)
 {
 	struct tab		*t;
@@ -1635,6 +1959,14 @@ set_auto_load_images(char *value)
 }
 
 int
+check_auto_load_images(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_AUTO_LOAD_IMAGES ? "Enabled" : "Disabled");
+	return (auto_load_images != XT_DS_AUTO_LOAD_IMAGES);
+}
+
+int
 set_autofocus_onload(char *value)
 {
 	int			tmp;
@@ -1652,6 +1984,14 @@ set_autofocus_onload(char *value)
 }
 
 int
+check_autofocus_onload(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_AUTOFOCUS_ONLOAD ? "Enabled" : "Disabled");
+	return (autofocus_onload != XT_DS_AUTOFOCUS_ONLOAD);
+}
+
+int
 set_ctrl_click_focus(char *value)
 {
 	int			tmp;
@@ -1669,6 +2009,14 @@ set_ctrl_click_focus(char *value)
 }
 
 int
+check_ctrl_click_focus(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_CTRL_CLICK_FOCUS ? "Enabled" : "Disabled");
+	return (ctrl_click_focus != XT_DS_CTRL_CLICK_FOCUS);
+}
+
+int
 set_download_notifications(char *value)
 {
 	int			tmp;
@@ -1686,6 +2034,14 @@ set_download_notifications(char *value)
 }
 
 int
+check_download_notifications(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_DOWNLOAD_NOTIFICATIONS ? "Enabled" : "Disabled");
+	return (download_notifications != XT_DS_DOWNLOAD_NOTIFICATIONS);
+}
+
+int
 set_enable_autoscroll(char *value)
 {
 	int			tmp;
@@ -1703,6 +2059,14 @@ set_enable_autoscroll(char *value)
 }
 
 int
+check_enable_autoscroll(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_AUTOSCROLL ? "Enabled" : "Disabled");
+	return (enable_autoscroll != XT_DS_ENABLE_AUTOSCROLL);
+}
+
+int
 set_enable_cookie_whitelist(char *value)
 {
 	int			tmp;
@@ -1720,6 +2084,22 @@ set_enable_cookie_whitelist(char *value)
 }
 
 int
+check_enable_cookie_whitelist(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tDisabled\n"
+	    "\twhitelist:\tEnabled\n"
+	    "\tkiosk:\tDisabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_cookie_whitelist != 1)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_cookie_whitelist != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_cookie_whitelist != 0)
+		return (1);
+	return (0);
+}
+
+int
 set_enable_js_autorun(char *value)
 {
 	int			tmp;
@@ -1737,6 +2117,14 @@ set_enable_js_autorun(char *value)
 }
 
 int
+check_enable_js_autorun(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_JS_AUTORUN ? "Enabled" : "Disabled");
+	return (enable_js_autorun != XT_DS_ENABLE_JS_AUTORUN);
+}
+
+int
 set_enable_js_whitelist(char *value)
 {
 	int			tmp;
@@ -1754,6 +2142,22 @@ set_enable_js_whitelist(char *value)
 }
 
 int
+check_enable_js_whitelist(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tDisabled\n"
+	    "\twhitelist:\tEnabled\n"
+	    "\tkiosk:\tDisabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_js_whitelist != 1)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_js_whitelist != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_js_whitelist != 0)
+		return (1);
+	return (0);
+}
+
+int
 set_enable_favicon_entry(char *value)
 {
 	int			tmp;
@@ -1771,6 +2175,14 @@ set_enable_favicon_entry(char *value)
 }
 
 int
+check_enable_favicon_entry(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_FAVICON_ENTRY ? "Enabled" : "Disabled");
+	return (enable_favicon_entry != XT_DS_ENABLE_FAVICON_ENTRY);
+}
+
+int
 set_enable_favicon_tabs(char *value)
 {
 	int			tmp;
@@ -1788,6 +2200,14 @@ set_enable_favicon_tabs(char *value)
 }
 
 int
+check_enable_favicon_tabs(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_FAVICON_TABS ? "Enabled" : "Disabled");
+	return (enable_favicon_tabs != XT_DS_ENABLE_FAVICON_TABS);
+}
+
+int
 set_enable_localstorage(char *value)
 {
 	struct tab		*t;
@@ -1810,6 +2230,22 @@ set_enable_localstorage(char *value)
 }
 
 int
+check_enable_localstorage(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tEnabled\n"
+	    "\twhitelist:\tDisabled\n"
+	    "\tkiosk:\tEnabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_localstorage != 0)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_localstorage != 1)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_localstorage != 1)
+		return (1);
+	return (0);
+}
+
+int
 set_enable_plugins(char *value)
 {
 	struct tab		*t;
@@ -1831,6 +2267,22 @@ set_enable_plugins(char *value)
 }
 
 int
+check_enable_plugins(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tEnabled\n"
+	    "\twhitelist:\tDisabled\n"
+	    "\tkiosk:\tEnabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_plugins != 0)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_plugins != 1)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_plugins != 1)
+		return (1);
+	return (0);
+}
+
+int
 set_enable_plugin_whitelist(char *value)
 {
 	int			tmp;
@@ -1848,6 +2300,22 @@ set_enable_plugin_whitelist(char *value)
 }
 
 int
+check_enable_plugin_whitelist(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tDisabled\n"
+	    "\twhitelist:\tEnabled\n"
+	    "\tkiosk:\tDisabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_plugin_whitelist != 1)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_plugin_whitelist != 0)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_plugin_whitelist != 0)
+		return (1);
+	return (0);
+}
+
+int
 set_enable_scripts(char *value)
 {
 	struct tab		*t;
@@ -1869,6 +2337,29 @@ set_enable_scripts(char *value)
 }
 
 int
+check_enable_scripts(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\tEnabled\n"
+	    "\twhitelist:\tDisabled\n"
+	    "\tkiosk:\tEnabled");
+	if (browser_mode == XT_BM_WHITELIST && enable_scripts != 0)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && enable_scripts != 1)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && enable_scripts != 1)
+		return (1);
+	return (0);
+}
+
+int
+check_enable_socket(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (enable_socket != 0);
+}
+
+int
 set_enable_spell_checking(char *value)
 {
 	struct tab		*t;
@@ -1890,6 +2381,14 @@ set_enable_spell_checking(char *value)
 }
 
 int
+check_enable_spell_checking(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_SPELL_CHECKING ? "Enabled" : "Disabled");
+	return (enable_spell_checking != XT_DS_ENABLE_SPELL_CHECKING);
+}
+
+int
 set_enable_strict_transport(char *value)
 {
 	int			tmp;
@@ -1906,6 +2405,14 @@ set_enable_strict_transport(char *value)
 	return (0);
 }
 
+int
+check_enable_strict_transport(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_ENABLE_STRICT_TRANSPORT ? "Enabled" : "Disabled");
+	return (enable_strict_transport != XT_DS_ENABLE_STRICT_TRANSPORT);
+}
+
 #if 0
 /*
  * XXX: this is currently broken.  Need to figure out what to do with
@@ -1931,6 +2438,13 @@ set_encoding_rt(char *value)
 #endif
 
 int
+check_encoding(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_ENCODING);
+	return (g_strcmp0(encoding, XT_DS_ENCODING));
+}
+
+int
 set_guess_search(char *value)
 {
 	int			tmp;
@@ -1948,22 +2462,11 @@ set_guess_search(char *value)
 }
 
 int
-set_read_only_cookies(char *value)
+check_guess_search(char **tt)
 {
-	int			tmp;
-	const char		*errstr;
-
-	if (value == NULL || strlen(value) == 0)
-		read_only_cookies = XT_DS_READ_ONLY_COOKIES;
-	else {
-		tmp = strtonum(value, 0, 1, &errstr);
-		if (errstr)
-			return (-1);
-		read_only_cookies = tmp;
-	}
-	g_object_set(G_OBJECT(p_cookiejar), SOUP_COOKIE_JAR_READ_ONLY,
-	    read_only_cookies, (void *)NULL);
-	return (0);
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_GUESS_SEARCH ? "Enabled" : "Disabled");
+	return (guess_search != XT_DS_GUESS_SEARCH);
 }
 
 char *
@@ -2024,6 +2527,23 @@ set_referer_rt(char *value)
 	return (set_referer(NULL, value));
 }
 
+int
+check_referer(char **tt)
+{
+	*tt = g_strdup("Default (depends on browser_mode):\n"
+	    "\tnormal:\talways\n"
+	    "\twhitelist:\tsame-domain\n"
+	    "\tkiosk:\talways");
+	if (browser_mode == XT_BM_WHITELIST &&
+	    referer_mode != XT_REFERER_SAME_DOMAIN)
+		return (1);
+	if (browser_mode == XT_BM_NORMAL && referer_mode != XT_REFERER_ALWAYS)
+		return (1);
+	if (browser_mode == XT_BM_KIOSK && referer_mode != XT_REFERER_ALWAYS)
+		return (1);
+	return (0);
+}
+
 char *
 get_ssl_ca_file(struct settings *s)
 {
@@ -2050,6 +2570,34 @@ set_refresh_interval(char *value)
 }
 
 int
+check_resource_dir(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_RESOURCE_DIR);
+	return (g_strcmp0(resource_dir, XT_DS_RESOURCE_DIR));
+}
+
+int
+check_save_global_history(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (save_global_history != 0);
+}
+
+int
+check_save_rejected_cookies(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (save_rejected_cookies != 0);
+}
+
+int
+check_refresh_interval(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", XT_DS_REFRESH_INTERVAL);
+	return (refresh_interval != XT_DS_REFRESH_INTERVAL);
+}
+
+int
 set_session_autosave(char *value)
 {
 	int			tmp;
@@ -2067,6 +2615,14 @@ set_session_autosave(char *value)
 }
 
 int
+check_session_autosave(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_SESSION_AUTOSAVE ? "Enabled" : "Disabled");
+	return (session_autosave != XT_DS_SESSION_AUTOSAVE);
+}
+
+int
 set_session_timeout(char *value)
 {
 	int			tmp;
@@ -2084,6 +2640,13 @@ set_session_timeout(char *value)
 }
 
 int
+check_session_timeout(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", XT_DS_SESSION_TIMEOUT);
+	return (session_timeout != XT_DS_SESSION_TIMEOUT);
+}
+
+int
 set_show_scrollbars(char *value)
 {
 	struct tab		*t;
@@ -2105,6 +2668,19 @@ set_show_scrollbars(char *value)
 }
 
 int
+check_show_scrollbars(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tEnabled\n"
+	    "\tminimal:\tDisabled");
+	if (gui_mode == XT_GM_CLASSIC && show_scrollbars != 1)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && show_scrollbars != 0)
+		return (1);
+	return (0);
+}
+
+int
 set_show_statusbar(char *value)
 {
 	int			tmp;
@@ -2123,6 +2699,19 @@ set_show_statusbar(char *value)
 }
 
 int
+check_show_statusbar(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tDisabled\n"
+	    "\tminimal:\tEnabled");
+	if (gui_mode == XT_GM_CLASSIC && show_statusbar != 0)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && show_statusbar != 1)
+		return (1);
+	return (0);
+}
+
+int
 set_show_tabs(char *value)
 {
 	struct karg		args = {0};
@@ -2142,6 +2731,19 @@ set_show_tabs(char *value)
 }
 
 int
+check_show_tabs(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tEnabled\n"
+	    "\tminimal:\tDisabled");
+	if (gui_mode == XT_GM_CLASSIC && show_tabs != 1)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && show_tabs != 0)
+		return (1);
+	return (0);
+}
+
+int
 set_show_url(char *value)
 {
 	struct karg		args = {0};
@@ -2161,6 +2763,26 @@ set_show_url(char *value)
 }
 
 int
+check_show_url(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tEnabled\n"
+	    "\tminimal:\tDisabled");
+	if (gui_mode == XT_GM_CLASSIC && show_url != 1)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && show_url != 0)
+		return (1);
+	return (0);
+}
+
+int
+check_single_instance(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (single_instance != 0);
+}
+
+int
 set_spell_check_languages(char *value)
 {
 	struct tab		*t;
@@ -2178,6 +2800,13 @@ set_spell_check_languages(char *value)
 }
 
 int
+check_spell_check_languages(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_SPELL_CHECK_LANGUAGES);
+	return (g_strcmp0(spell_check_languages, XT_DS_SPELL_CHECK_LANGUAGES));
+}
+
+int
 check_valid_file(char *name)
 {
 	struct stat		sb;
@@ -2199,6 +2828,13 @@ set_ssl_ca_file_rt(char *value)
 }
 
 int
+check_ssl_ca_file(char **tt)
+{
+	*tt = g_strdup("Default: (empty)");
+	return (g_strcmp0(ssl_ca_file, XT_DS_SSL_CA_FILE));
+}
+
+int
 set_ssl_strict_certs(char *value)
 {
 	int			tmp;
@@ -2217,6 +2853,21 @@ set_ssl_strict_certs(char *value)
 }
 
 int
+check_ssl_strict_certs(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_SSL_STRICT_CERTS ? "Enabled" : "Disabled");
+	return (ssl_strict_certs != XT_DS_SSL_STRICT_CERTS);
+}
+
+int
+check_statusbar_elems(char **tt)
+{
+	*tt = g_strdup("Default: BP");
+	return (g_strcmp0(statusbar_elems, "BP"));
+}
+
+int
 set_external_editor(char *editor)
 {
 	if (external_editor)
@@ -2229,6 +2880,13 @@ set_external_editor(char *editor)
 }
 
 int
+check_external_editor(char **tt)
+{
+	*tt = g_strdup("Default: (empty)");
+	return (g_strcmp0(external_editor, NULL));
+}
+
+int
 set_fancy_bar(char *value)
 {
 	struct tab		*t;
@@ -2261,6 +2919,19 @@ set_fancy_bar(char *value)
 	return (0);
 }
 
+int
+check_fancy_bar(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tEnabled\n"
+	    "\tminimal:\tDisabled");
+	if (gui_mode == XT_GM_CLASSIC && fancy_bar != 1)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && fancy_bar != 0)
+		return (1);
+	return (0);
+}
+
 void
 setup_proxy(char *uri)
 {
@@ -2317,6 +2988,19 @@ set_tab_style(struct settings *s, char *val)
 }
 
 int
+check_tab_style(char **tt)
+{
+	*tt = g_strdup("Default (depends on gui_mode):\n"
+	    "\tclassic:\tnormal\n"
+	    "\tminimal:\tcompact");
+	if (gui_mode == XT_GM_CLASSIC && tab_style != XT_TABS_NORMAL)
+		return (1);
+	if (gui_mode == XT_GM_MINIMAL && tab_style != XT_TABS_COMPACT)
+		return (1);
+	return (0);
+}
+
+int
 set_tab_style_rt(char *value)
 {
 	struct karg		args = {0};
@@ -2391,6 +3075,13 @@ set_statusbar_style_rt(char *value)
 }
 
 int
+check_statusbar_style(char **tt)
+{
+	*tt = g_strdup("Default: url");
+	return (statusbar_style != XT_DS_STATUSBAR_STYLE);
+}
+
+int
 set_url_regex(char *value)
 {
 	if (value == NULL || strlen(value) == 0) {
@@ -2408,31 +3099,52 @@ set_url_regex(char *value)
 }
 
 int
+check_url_regex(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s", XT_DS_URL_REGEX);
+	return (g_strcmp0(url_regex, XT_DS_URL_REGEX));
+}
+
+int
 set_userstyle(struct settings *s, char *value)
 {
+	int		rv = 0;
 	char		script[PATH_MAX] = {'\0'};
-	char		*path;
+	char		*tmp;
 
-	if (userstyle)
-		g_free(userstyle);
 	if (value == NULL || strlen(value) == 0) {
-		path = g_strdup_printf("%s" PS "style.css", resource_dir);
-		userstyle = g_filename_to_uri(path, NULL, NULL);
-		g_free(path);
+		snprintf(script, sizeof script, "%s" PS "style.css", resource_dir);
+		tmp = g_filename_to_uri(script, NULL, NULL);
+		if (tmp == NULL)
+			rv = -1;
+		else {
+			if (userstyle)
+				g_free(userstyle);
+			userstyle = tmp;
+		}
 	} else {
 		expand_tilde(script, sizeof script, value);
-		userstyle = g_filename_to_uri(script, NULL, NULL);
+		tmp = g_filename_to_uri(script, NULL, NULL);
+		if (tmp == NULL)
+			rv = -1;
+		else {
+			if (userstyle)
+				g_free(userstyle);
+			userstyle = tmp;
+		}
 	}
 	if (stylesheet)
 		g_free(stylesheet);
 	stylesheet = g_strdup(userstyle);
-	return (0);
+	return (rv);
 }
 
 char *
 get_userstyle(struct settings *s)
 {
-	return (g_filename_from_uri(userstyle, NULL, NULL));
+	if (userstyle)
+		return (g_filename_from_uri(userstyle, NULL, NULL));
+	return (NULL);
 }
 
 int
@@ -2442,6 +3154,22 @@ set_userstyle_rt(char *value)
 }
 
 int
+check_userstyle(char **tt)
+{
+	int			rv = 0;
+	char			buf[PATH_MAX];
+	char			*file = NULL;
+
+	snprintf(buf, sizeof buf, "%s" PS "%s", resource_dir, "style.css");
+	*tt = g_strdup_printf("Default: %s", buf);
+	file = g_filename_from_uri(userstyle, NULL, NULL);
+	rv = g_strcmp0(file, buf);
+	if (file)
+		g_free(file);
+	return (rv);
+}
+
+int
 set_userstyle_global(char *value)
 {
 	struct karg		args = {0};
@@ -2468,18 +3196,72 @@ set_userstyle_global(char *value)
 }
 
 int
+check_userstyle_global(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_USERSTYLE_GLOBAL ? "Enabled" : "Disabled");
+	return (userstyle_global != XT_DS_USERSTYLE_GLOBAL);
+}
+
+int
 set_warn_cert_changes(char *value)
 {
 	int			tmp;
 	const char		*errstr;
 
-	tmp = strtonum(value, 0, 1, &errstr);
-	if (errstr)
-		return (-1);
-	warn_cert_changes = tmp;
+	if (value == NULL || strlen(value) == 0)
+		warn_cert_changes = XT_DS_WARN_CERT_CHANGES;
+	else {
+		tmp = strtonum(value, 0, 1, &errstr);
+		if (errstr)
+			return (-1);
+		warn_cert_changes = tmp;
+	}
 	return (0);
 }
 
+int
+check_warn_cert_changes(char **tt)
+{
+	*tt = g_strdup_printf("Default: %s",
+	    XT_DS_WARN_CERT_CHANGES ? "Enabled" : "Disabled");
+	return (warn_cert_changes != XT_DS_WARN_CERT_CHANGES);
+}
+
+int
+check_window_height(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", 768);
+	return (window_height != 768);
+}
+
+int
+check_window_maximize(char **tt)
+{
+	*tt = g_strdup("Default: Disabled");
+	return (window_maximize != 0);
+}
+
+int
+check_window_width(char **tt)
+{
+	*tt = g_strdup_printf("Default: %d", 768);
+	return (window_width != 1024);
+}
+
+int
+check_work_dir(char **tt)
+{
+	struct passwd		*pwd;
+	char			buf[PATH_MAX];
+
+	if ((pwd = getpwuid(getuid())) == NULL)
+		return (-1);
+	snprintf(buf, sizeof buf, "%s" PS ".xombrero", pwd->pw_dir);
+	*tt = g_strdup_printf("Default: %s", buf);
+	return (g_strcmp0(work_dir, buf));
+}
+
 char *
 get_edit_mode(struct settings *s)
 {
@@ -2502,6 +3284,13 @@ set_edit_mode(struct settings *s, char *val)
 	return (0);
 }
 
+int
+check_edit_mode(char **tt)
+{
+	*tt = g_strdup("Default: hybrid");
+	return (edit_mode != XT_EM_HYBRID);
+}
+
 char *
 get_download_mode(struct settings *s)
 {
@@ -2522,7 +3311,7 @@ get_download_mode(struct settings *s)
 int
 set_download_mode(struct settings *s, char *val)
 {
-	if (!strcmp(val, "start"))
+	if (val == NULL || strlen(val) == 0 || !strcmp(val, "start"))
 		download_mode = XT_DM_START;
 	else if (!strcmp(val, "ask"))
 		download_mode = XT_DM_ASK;
@@ -2537,11 +3326,16 @@ set_download_mode(struct settings *s, char *val)
 int
 set_download_mode_rt(char *val)
 {
-	if (val == NULL || strlen(val) == 0)
-		return (-1);
 	return (set_download_mode(NULL, val));
 }
 
+int
+check_download_mode(char **tt)
+{
+	*tt = g_strdup("Default: start");
+	return (download_mode != XT_DM_START);
+}
+
 char *
 get_work_dir(struct settings *s)
 {
@@ -2644,7 +3438,8 @@ settings_add(char *var, char *val)
 			break;
 		} else
 			switch (rs[i].type) {
-			case XT_S_INT:
+			case XT_S_INT:	/* FALLTHROUGH */
+			case XT_S_BOOL:
 				p = rs[i].ival;
 				*p = atoi(val);
 				rv = 1;
@@ -2755,7 +3550,7 @@ print_setting(struct settings *s, char *val, void *cb_args)
 	char			*enc_val, *tmp, *color;
 	struct settings_args	*sa = cb_args;
 
-	if (sa == NULL)
+	if (sa == NULL || s->flags & XT_SF_INVISIBLE)
 		return;
 
 	if (s->flags & XT_SF_RUNTIME)
@@ -2781,8 +3576,120 @@ print_setting(struct settings *s, char *val, void *cb_args)
 	sa->i++;
 }
 
+void
+print_runtime_setting(struct settings *s, char *val, void *cb_args)
+{
+	char			*tmp, *tt = NULL;
+	struct settings_args	*sa = cb_args;
+	int			i;
+
+	if (sa == NULL)
+		return;
+
+	if (s == NULL || s->flags & XT_SF_INVISIBLE || s->activate == NULL)
+		return;
+
+	tmp = *sa->body;
+	*sa->body = g_strdup_printf(
+	    "%s\n<tr %s>"
+	    "<td title=\"%s\" style='width: 240px;'><div style='width: 100%%;'>%s</div></td>"
+	    "<td title=\"%s\"><div style='width: 100%%; word-break:break-all'>",
+	    *sa->body,
+	    (s->ismodified && s->ismodified(&tt)) ? "id='modified'" : "",
+	    s->tt ? s->tt : "",
+	    s->name,
+	    tt);
+	g_free(tmp);
+	g_free(tt);
+
+	tmp = *sa->body;
+	if (s->type == XT_S_STR && s->s && s->s->valid_options[0]) {
+		*sa->body = g_strdup_printf("%s<select name='%s'>",
+		    *sa->body,
+		    s->name);
+		for (i = 0; s->s->valid_options[i]; ++i) {
+			g_free(tmp);
+			tmp = *sa->body;
+			*sa->body = g_strdup_printf("%s"
+			    "<option value='%s' %s>%s</option>",
+			    *sa->body,
+			    s->s->valid_options[i],
+			    !strcmp(s->s->valid_options[i], val) ? "selected" : "",
+			    s->s->valid_options[i]);
+		}
+	} else if (s->type == XT_S_STR)
+		*sa->body = g_strdup_printf(
+		    "%s<input style='width: 98%%' type='text' name='%s' value='%s'>"
+		    "</div></td></tr>",
+		    *sa->body,
+		    s->name,
+		    val ? val : "");
+	else if (s->type == XT_S_INT)
+		*sa->body = g_strdup_printf(
+		    "%s<input type='number' name='%s' value='%s'>"
+		    "</div></td></tr>",
+		    *sa->body,
+		    s->name,
+		    val);
+	else if (s->type == XT_S_FLOAT)
+		*sa->body = g_strdup_printf(
+		    "%s<input type='number' step='0.000001' name='%s' value='%s'>"
+		    "</div></td></tr>",
+		    *sa->body,
+		    s->name,
+		    val);
+	else if (s->type == XT_S_BOOL)
+		*sa->body = g_strdup_printf(
+		    "%s<input type='hidden' name='%s' value='0'>"
+		    "<input type='checkbox' name='%s' value='1''%s>"
+		    "</div></td></tr>",
+		    *sa->body,
+		    s->name,
+		    s->name,
+		    atoi(val) ? " checked='checked'" : "");
+	else {
+		*sa->body = g_strdup(*sa->body);
+		warnx("Did not print setting %s", s->name);
+	}
+	g_free(tmp);
+	sa->i++;
+}
+
+char *
+print_set_rejects(void)
+{
+	struct set_reject	*sr, *st;
+	char			*body = NULL, *tmp;
+
+	if (TAILQ_EMPTY(&srl))
+		return (NULL);
+
+	body = g_strdup_printf("The following settings were invalid and could "
+	    "not be set:<br><div align='center'><table id='settings'>"
+	    "<th align='left'>Setting</th>"
+	    "<th align='left'>Value</th>");
+	TAILQ_FOREACH_SAFE(sr, &srl, entry, st) {
+		tmp = body;
+		body = g_strdup_printf("%s\n<tr>"
+		    "<td style='width:240px'><div>%s</div></td>"
+		    "<td><div style='word-break:break-all'>%s</div></td></tr>",
+		    body,
+		    sr->name,
+		    sr->value);
+		g_free(tmp);
+		TAILQ_REMOVE(&srl, sr, entry);
+		g_free(sr->name);
+		g_free(sr->value);
+		g_free(sr);
+	}
+	tmp = body;
+	body = g_strdup_printf("%s</table></div><br>", body);
+	g_free(tmp);
+	return (body);
+}
+
 int
-set_show(struct tab *t, struct karg *args)
+xtp_page_set(struct tab *t, struct karg *args)
 {
 	char			*body, *page, *tmp;
 	int			i = 1;
@@ -2823,19 +3730,79 @@ set_show(struct tab *t, struct karg *args)
 }
 
 int
+xtp_page_rt(struct tab *t, struct karg *args)
+{
+	char			*body = NULL, *page, *tmp;
+	int			i = 1;
+	struct settings_args	sa;
+
+	/*
+	 * We intentionally do *not* update other about:set tabs here as
+	 * there may be modifications and we don't want to lose those.
+	 */
+	generate_xtp_session_key(&rt_session_key);
+
+	bzero(&sa, sizeof sa);
+	sa.body = &body;
+
+	/* body */
+	body = print_set_rejects();	
+
+	tmp = body;
+	body = g_strdup_printf("%s<div align='center'>"
+	    "<form method='GET' action='%s%d/%s/%d'>"
+	    "<input type='submit' value='Save Settings'>"
+	    "<table id='settings'>"
+	    "<th align='left'>Setting</th>"
+	    "<th align='left'>Value</th>\n",
+	    body ? body : "",
+	    XT_XTP_STR,
+	    XT_XTP_RT,
+	    rt_session_key,
+	    XT_XTP_RT_SAVE);
+	g_free(tmp);
+
+	settings_walk(print_runtime_setting, &sa);
+	i = sa.i;
+
+	/* small message if there are none */
+	if (i == 1) {
+		tmp = body;
+		body = g_strdup_printf("%s\n<tr><td style='text-align:center'"
+		    "colspan='2'>No settings</td></tr>\n", body);
+		g_free(tmp);
+	}
+
+	tmp = body;
+	body = g_strdup_printf("%s</table>"
+	    "<input type='submit' value='Save Settings'></form></div>", body);
+	g_free(tmp);
+
+	page = get_html_page("Runtime Settings", body, "", 1);
+
+	g_free(body);
+
+	load_webkit_string(t, page, XT_URI_ABOUT_RUNTIME);
+
+	g_free(page);
+
+	return (XT_CB_PASSTHROUGH);
+}
+
+int
 set(struct tab *t, struct karg *args)
 {
 	char			*p, *val;
 	int			i;
 
 	if (args == NULL || args->s == NULL)
-		return (set_show(t, args));
+		return (xtp_page_set(t, args));
 
 	/* strip spaces */
 	p = g_strstrip(args->s);
 
 	if (strlen(p) == 0)
-		return (set_show(t, args));
+		return (xtp_page_set(t, args));
 
 	/* we got some sort of string */
 	val = g_strstr_len(p, strlen(p), "=");
@@ -2870,7 +3837,8 @@ set(struct tab *t, struct karg *args)
 
 			/* XXX this could use some cleanup */
 			switch (rs[i].type) {
-			case XT_S_INT:
+			case XT_S_INT:	/* FALLTHROUGH */
+			case XT_S_BOOL:
 				if (rs[i].ival)
 					show_oops(t, "%s = %d",
 					    rs[i].name, *rs[i].ival);
diff --git a/txt2tooltip.pl b/txt2tooltip.pl
new file mode 100644
index 0000000..313b236
--- /dev/null
+++ b/txt2tooltip.pl
@@ -0,0 +1,93 @@
+#!/bin/perl
+
+# Copyright (c) 2012 Todd T. Fries <todd@fries.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# read in 'ascii2txt.pl' formatted man pages, spit out #defines for tooltips
+
+use strict;
+use warnings;
+
+our $verbose = 0;
+
+my $line;
+my @lines;
+my @states = ("prekewords", "keywords", "postkeywords");
+my $state = 0;
+
+my $tipname;
+my @tipinfo;
+my $tiplines;
+while(<STDIN>) {
+	chomp($line = $_);
+	if ($state == 0) {
+		if ($line =~ /following keywords:$/) {
+			$state++;
+		}
+		next;
+	}
+	if ($state == 1) {
+		if ($line =~ /^$/) {
+			next;
+		}
+		if ($line =~ /^[A-Z]/) {
+			showtip($tipname,@tipinfo);
+			$state++;
+			next;
+		}
+		if ($line =~ /^ {11,11}([a-z_]+)[ ]*(.*)$/) {
+			showtip($tipname,@tipinfo);
+			$tiplines = 1;
+			$tipname = $1;
+			@tipinfo = ($2);
+			next;
+		}
+		if ($line =~ /^ {39,39}(.*)$/) {
+			push @tipinfo, $1;
+		}
+	}
+}
+
+sub showtip {
+	my ($tip,@info) = @_;
+
+	my $text;
+	my $count = 1;
+
+	if (length($tip) < 1) {
+		return;
+	}
+
+	my $fmt;
+	for my $line (@info) {
+		$line =~ s/&/&amp;/g;
+		$line =~ s/</&lt;/g;
+		$line =~ s/>/&gt;/g;
+		$line =~ s/"/&quot;/g;
+		$line =~ s/^ {6,6}/\\t/g;
+		$line =~ s/\\t {6,6}/\\t\\t/g;
+		$line =~ s/\\t {6,6}/\\t\\t/g;
+		if ($count > $#info) {
+			$fmt = "	\"%s\"\n";
+		} else {
+			$fmt = "	\"%s\\n\" \\\n";
+		}
+		$text .= sprintf $fmt,$line;
+		$count++;
+	}
+
+	$tip = uc($tip);
+	printf "#define TT_%s%s",$tip,$text;
+}
+exit(0);
diff --git a/unix.c b/unix.c
index 93d0b1c..df3c913 100644
--- a/unix.c
+++ b/unix.c
@@ -19,7 +19,7 @@
 void
 init_unix(void)
 {
-	resource_dir = g_strdup("/usr/local/share/xombrero");
+	resource_dir = g_strdup(XT_DS_RESOURCE_DIR);
 }
 
 void	(*os_init)(void) = init_unix;
diff --git a/xombrero.1 b/xombrero.1
index a896599..0d9a409 100644
--- a/xombrero.1
+++ b/xombrero.1
@@ -1113,7 +1113,6 @@ Not all sites currently support this header, and this is only a
 suggestion of a user preference.
 Sites may still perform 3rd-party tracking even when this feature is
 enabled.
-Default is 0.
 .It Cm download_dir
 Locations where files are downloaded to.
 This directory must exist and
diff --git a/xombrero.c b/xombrero.c
index e6c50e0..53ac093 100644
--- a/xombrero.c
+++ b/xombrero.c
@@ -82,7 +82,6 @@ struct command_entry {
 TAILQ_HEAD(command_list, command_entry);
 
 /* defines */
-#define XT_DIR			(".xombrero")
 #define XT_CACHE_DIR		("cache")
 #define XT_CERT_DIR		("certs")
 #define XT_CERT_CACHE_DIR	("certs_cache")
@@ -231,6 +230,7 @@ struct command_entry	*history_at;
 struct command_entry	*search_at;
 struct secviolation_list	svl;
 struct sv_ignore_list	svil;
+struct set_reject_list	srl;
 int			undo_count;
 int			cmd_history_count = 0;
 int			search_history_count = 0;
@@ -968,11 +968,11 @@ html_escape(const char *val)
 		return NULL;
 
 	sv = g_strsplit(val, "&", -1);
-	s = g_strjoinv("&amp", sv);
+	s = g_strjoinv("&amp;", sv);
 	g_strfreev(sv);
 	sp = s;
 	sv = g_strsplit(val, "<", -1);
-	s = g_strjoinv("&lt", sv);
+	s = g_strjoinv("&lt;", sv);
 	g_strfreev(sv);
 	g_free(sp);
 	return (s);
@@ -3382,6 +3382,7 @@ struct cmd {
 
 	/* settings */
 	{ "set",		0,	set,			0,			XT_SETARG },
+	{ "runtime",		0,	xtp_page_rt,		0,			0 },
 
 	{ "fullscreen",		0,	fullscreen,		0,			0 },
 	{ "f",			0,	fullscreen,		0,			0 },
@@ -3513,10 +3514,6 @@ activate_uri_entry_cb(GtkWidget* entry, struct tab *t)
 
 	uri += strspn(uri, "\t ");
 
-	/* if xxxt:// treat specially */
-	if (parse_xtp_url(t, uri))
-		return;
-
 	if (parse_custom_uri(t, uri))
 		return;
 
@@ -6405,6 +6402,60 @@ done:
 }
 
 int
+save_runtime_setting(const char *name, const char *val)
+{
+	struct stat		sb;
+	FILE			*f;
+	size_t			linelen;
+	int			found = 0;
+	char			file[PATH_MAX];
+	char			delim[3] = { '\0', '\0', '\0' };
+	char			*line, *lt, *start;
+	char			*contents, *tmp;
+
+	if (runtime_settings == NULL || strlen(runtime_settings) == 0)
+		return (-1);
+
+	snprintf(file, sizeof file, "%s" PS "%s", work_dir, runtime_settings);
+	if (stat(file, &sb) || (f = fopen(file, "r+")) == NULL)
+		return (-1);
+	lt = g_strdup_printf("%s=%s", name, val);
+	contents = g_strdup("");
+	while (!feof(f)) {
+		line = fparseln(f, &linelen, NULL, delim, 0);
+		if (line == NULL || linelen == 0)
+			continue;
+		tmp = contents;
+		start = g_strdup_printf("%s=", name);
+		if (strstr(line, start) == NULL)
+			contents = g_strdup_printf("%s%s\n", contents, line);
+		else {
+			found = 1;
+			contents = g_strdup_printf("%s%s\n", contents, lt);
+		}
+		g_free(tmp);
+		g_free(start);
+		free(line);
+		line = NULL;
+	}
+	if (found == 0) {
+		tmp = contents;
+		contents = g_strdup_printf("%s%s\n", contents, lt);
+		g_free(tmp);
+	}
+	if ((f = freopen(file, "w", f)) == NULL)
+		return (-1);
+	else {
+		fputs(contents, f);
+		fclose(f);
+	}
+	g_free(lt);
+	g_free(contents);
+
+	return (0);
+}
+
+int
 entry_key_cb(GtkEntry *w, GdkEventKey *e, struct tab *t)
 {
 	if (t == NULL) {
@@ -7989,7 +8040,6 @@ create_canvas(void)
 	gtk_box_set_spacing(GTK_BOX(vbox), 0);
 	gtk_widget_set_can_focus(vbox, FALSE);
 	notebook = GTK_NOTEBOOK(gtk_notebook_new());
-	gtk_widget_set_name(notebook, "notebook");
 #if !GTK_CHECK_VERSION(3, 0, 0)
 	/* XXX seems to be needed with gtk+2 */
 	g_object_set(G_OBJECT(notebook), "tab-border", 0, NULL);
@@ -8410,6 +8460,7 @@ main(int argc, char **argv)
 	TAILQ_INIT(&chl);
 	TAILQ_INIT(&shl);
 	TAILQ_INIT(&cul);
+	TAILQ_INIT(&srl);
 
 #ifndef XT_RESOURCE_LIMITS_DISABLE
 	struct rlimit		rlp;
diff --git a/xombrero.h b/xombrero.h
index cd8f4c7..0e5328a 100644
--- a/xombrero.h
+++ b/xombrero.h
@@ -364,6 +364,7 @@ RB_PROTOTYPE(http_accept_list, http_accept, entry, http_accept_rb_cmp);
 
 /* utility */
 #define XT_NAME			("xombrero")
+#define XT_DIR			(".xombrero")
 #define XT_CB_HANDLED		(TRUE)
 #define XT_CB_PASSTHROUGH	(FALSE)
 #define XT_CONF_FILE		("xombrero.conf")
@@ -433,6 +434,7 @@ char			*tld_get_suffix(const char *);
 
 /* about */
 #define XT_XTP_STR		"xxxt://"
+#define XT_XTP_SCHEME		"xxxt"
 #define XT_URI_ABOUT		("about:")
 #define XT_URI_ABOUT_LEN	(strlen(XT_URI_ABOUT))
 #define XT_URI_ABOUT_ABOUT	("about")
@@ -454,6 +456,7 @@ char			*tld_get_suffix(const char *);
 #define XT_URI_ABOUT_WEBKIT	("webkit")
 #define XT_URI_ABOUT_SEARCH	("search")
 #define XT_URI_ABOUT_SECVIOLATION ("secviolation")
+#define XT_URI_ABOUT_RUNTIME	("runtime")
 
 struct about_type {
 	char		*name;
@@ -641,7 +644,7 @@ int		command_mode(struct tab *, struct karg *);
 #define XT_DS_ENABLE_AUTOSCROLL	(0)
 #define XT_DS_ENABLE_FAVICON_ENTRY	(1)
 #define XT_DS_ENABLE_FAVICON_TABS	(0)
-#define XT_DS_EXTERNAL_EDITOR	("")
+#define XT_DS_EXTERNAL_EDITOR	(NULL)
 #define XT_DS_REFERER_MODE	XT_REFERER_ALWAYS
 #define XT_DS_REFERER_CUSTOM	("always")
 #define XT_DS_DOWNLOAD_NOTIFICATIONS	(0)
@@ -651,6 +654,8 @@ int		command_mode(struct tab *, struct karg *);
 #define XT_DS_TABBAR_FONT_NAME	("monospace normal 9")
 #define XT_DS_ALLOW_INSECURE_CONTENT	(TRUE)
 #define XT_DS_ALLOW_INSECURE_SCRIPTS	(TRUE)
+#define XT_DS_WARN_CERT_CHANGES	(0)
+#define XT_DS_RESOURCE_DIR	("/usr/local/share/xombrero")
 #define XT_DS_DO_NOT_TRACK	(0)
 #define XT_DS_PRELOAD_STRICT_TRANSPORT	(1)
 
@@ -678,6 +683,57 @@ int		command_mode(struct tab *, struct karg *);
 #define XT_URL_SHOW		(1)
 #define XT_URL_HIDE		(2)
 
+/* XTP classes (xxxt://<class>) */
+#define XT_XTP_INVALID		(0)	/* invalid */
+#define XT_XTP_DL		(1)	/* downloads */
+#define XT_XTP_HL		(2)	/* history */
+#define XT_XTP_CL		(3)	/* cookies */
+#define XT_XTP_FL		(4)	/* favorites */
+#define XT_XTP_SL		(5)	/* search */
+#define XT_XTP_AB		(6)	/* about */
+#define XT_XTP_SV		(7)	/* security violation */
+#define XT_XTP_RT		(8)	/* set */
+
+/* XTP download actions */
+#define XT_XTP_DL_LIST		(1)
+#define XT_XTP_DL_CANCEL	(2)
+#define XT_XTP_DL_REMOVE	(3)
+#define XT_XTP_DL_UNLINK	(4)
+#define XT_XTP_DL_START		(5)
+
+/* XTP history actions */
+#define XT_XTP_HL_LIST		(1)
+#define XT_XTP_HL_REMOVE	(2)
+#define XT_XTP_HL_REMOVE_ALL	(3)
+
+/* XTP cookie actions */
+#define XT_XTP_CL_LIST		(1)
+#define XT_XTP_CL_REMOVE	(2)
+#define XT_XTP_CL_REMOVE_DOMAIN	(3)
+#define XT_XTP_CL_REMOVE_ALL	(4)
+
+/* XTP cookie actions */
+#define XT_XTP_FL_LIST		(1)
+#define XT_XTP_FL_REMOVE	(2)
+
+/* XPT search actions */
+#define XT_XTP_SL_SET		(1)
+
+/* XPT about actions */
+#define XT_XTP_AB_EDIT_CONF	(1)
+
+/* XTP security violation actions */
+#define XT_XTP_SV_SHOW_CERT	(1)
+#define XT_XTP_SV_ALLOW_SESSION	(2)
+#define XT_XTP_SV_CACHE		(3)
+
+/* XTP set actions */
+#define XT_XTP_RT_SAVE		(1)
+
+/* needed for xtp_page_rt in settings.c */
+void			generate_xtp_session_key(char **);
+extern char		*rt_session_key;
+
 struct key_binding {
 	char				*cmd;
 	guint				mask;
@@ -701,6 +757,13 @@ struct cmd_alias {
 };
 TAILQ_HEAD(cmd_alias_list, cmd_alias);
 
+struct set_reject {
+	char			*name;
+	char			*value;
+	TAILQ_ENTRY(set_reject)	entry;
+};
+TAILQ_HEAD(set_reject_list, set_reject);
+
 struct settings {
 	char		*name;
 	int		type;
@@ -708,17 +771,31 @@ struct settings {
 #define XT_S_INT	(1)
 #define XT_S_STR	(2)
 #define XT_S_FLOAT	(3)
+#define XT_S_BOOL	(4)
 	uint32_t	flags;
 #define XT_SF_RESTART	(1<<0)
 #define XT_SF_RUNTIME	(1<<1)
+#define XT_SF_INVISIBLE	(1<<2)
 	int		*ival;
 	char		**sval;
 	struct special	*s;
 	gfloat		*fval;
 	int		(*activate)(char *);
+	int		(*ismodified)(char **);
+	char		*tt;
+};
+
+struct special {
+	int		(*set)(struct settings *, char *);
+	char		*(*get)(struct settings *);
+	void		(*walk)(struct settings *,
+			    void (*cb)(struct settings *, char *, void *),
+			    void *);
+	char		*valid_options[];
 };
 
 int		set(struct tab *, struct karg *);
+int		xtp_page_rt(struct tab *, struct karg *);
 size_t		get_settings_size(void);
 int		settings_add(char *, char *);
 void		setup_proxy(char *);
@@ -744,8 +821,8 @@ int		cert_cmd(struct tab *, struct karg *);
 void		focus_webview(struct tab *);
 int		is_g_object_setting(GObject *, char *);
 int		set_scrollbar_visibility(struct tab *, int);
+int		save_runtime_setting(const char *, const char *);
 void		wl_add(const char *, struct domain_list *, int);
-void		preload_hsts(void);
 
 #define		XT_DL_START	(0)
 #define		XT_DL_RESTART	(1)
@@ -874,6 +951,8 @@ extern struct cmd_alias_list	cal;
 extern struct custom_uri_list	cul;
 extern struct secviolation_list	svl;
 extern struct sv_ignore_list	svil;
+extern struct set_reject_list	srl;
+extern struct settings		rs[];
 
 extern PangoFontDescription	*cmd_font;
 extern PangoFontDescription	*oops_font;