1 /*
2  * Xiphos Bible Study Tool
3  * settings.c - Guess what?
4  *
5  * Copyright (C) 2000-2020 Xiphos Developer Team
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <gtk/gtk.h>
27 
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 
37 #include "gui/bookmarks.h"
38 #include "gui/dialog.h"
39 #include "gui/gui.h"
40 #include "gui/mod_mgr.h"
41 #include "gui/utilities.h"
42 #include "gui/preferences_dialog.h"
43 
44 #include "main/lists.h"
45 #include "main/settings.h"
46 #include "main/sword.h"
47 #include "main/xml.h"
48 
49 #include "editor/template.h"
50 
51 #include <glib/gstdio.h>
52 
53 #include "gui/debug_glib_null.h"
54 #include <locale.h>
55 
56 /******************************************************************************
57  * defines
58  */
59 #define XI_DIR ".xiphos"
60 
61 /******************************************************************************
62  * globals
63  */
64 SETTINGS settings;
65 
66 /******************************************************************************
67  * static
68  */
69 static int init_bookmarks(int new_bookmarks);
70 
71 /******************************************************************************
72  * Name
73  *   settings_init
74  *
75  * Synopsis
76  *   #include "main/settings.h"
77  *
78  *   gint settings_init(void)
79  *
80  * Description
81  *   check for Xiphos dir
82  *   if not found - create it and
83  *   the files needed to run program
84  *
85  * Return value
86  *   gint
87  */
88 
settings_init(int argc,char ** argv,int new_configs,int new_bookmarks)89 int settings_init(int argc, char **argv, int new_configs,
90 		  int new_bookmarks)
91 {
92 	int retval = 0;
93 	char *sword_dir = NULL;
94 	char *tmp = NULL;
95 	char *env;
96 	struct stat buf;
97 	gboolean buf_says_empty = FALSE;
98 
99 	settings.first_run = FALSE;
100 	/* set program title */
101 	strcpy(settings.program_title, "Xiphos");
102 
103 	/* Get home dir */
104 	if ((settings.homedir = (char *)g_getenv(HOMEVAR)) == NULL) {
105 		gui_init(argc, argv);
106 		gui_generic_warning_modal(_("$HOME is not set!"));
107 		/* if not found in env exit */
108 		exit(0);
109 	}
110 
111 	/* set gSwordDir to $home + .xiphos */
112 	settings.gSwordDir =
113 	    g_build_filename(settings.homedir, XI_DIR, NULL);
114 
115 	/* if gSwordDir does not exist, create it. */
116 	if (g_access(settings.gSwordDir, F_OK) == -1) {
117 		if ((Mkdir(settings.gSwordDir, S_IRWXU)) != 0) {
118 			char msg[300];
119 			gui_init(argc, argv);
120 			sprintf(msg, _("Xiphos can not create directory " XI_DIR
121 				       ":\n%s\n\nXiphos cannot continue."),
122 				strerror(errno));
123 			gui_generic_warning_modal(msg);
124 			/* if we can not create gSwordDir exit */
125 			exit(1);
126 		}
127 	}
128 
129 	/* if .sword does not exist create it */
130 	sword_dir = g_strdup_printf("%s/%s", settings.homedir, DOTSWORD);
131 	if (g_access(sword_dir, F_OK) == -1) {
132 		if ((Mkdir(sword_dir, S_IRWXU)) != 0) {
133 			gui_init(argc, argv);
134 			gui_generic_warning_modal(_("can not create " DOTSWORD));
135 		}
136 	}
137 	g_free(sword_dir);
138 	/* if .sword/mods.d does not exist create it */
139 	sword_dir =
140 	    g_strdup_printf("%s/%s", settings.homedir, DOTSWORD "/mods.d");
141 	if (g_access(sword_dir, F_OK) == -1) {
142 		if ((Mkdir(sword_dir, S_IRWXU)) != 0) {
143 			gui_init(argc, argv);
144 			gui_generic_warning_modal(_("can not create " DOTSWORD "/mods.d"));
145 		}
146 	}
147 	g_free(sword_dir);
148 	/* if .sword/modules does not exist create it */
149 	sword_dir =
150 	    g_strdup_printf("%s/%s", settings.homedir,
151 			    DOTSWORD "/modules");
152 	if (g_access(sword_dir, F_OK) == -1) {
153 		if ((Mkdir(sword_dir, S_IRWXU)) != 0) {
154 			gui_init(argc, argv);
155 			gui_generic_warning_modal(_("can not create " DOTSWORD "/modules"));
156 		}
157 	}
158 	g_free(sword_dir);
159 
160 	/* moved here from crud locations in backend. */
161 	main_init_language_map();
162 
163 	language_init();
164 
165 	init_bookmarks(new_bookmarks);
166 
167 	/* get the first cut at the set of modules available. */
168 	/* maybe insufficient, contain no bibles: ok for now. */
169 	main_init_lists();
170 
171 	/* set fnconfigure to gSwordDir and settings.xml */
172 	settings.fnconfigure =
173 	    g_strdup_printf("%s/settings.xml", settings.gSwordDir);
174 
175 	/* check for a bad settings file. */
176 	if ((stat(settings.fnconfigure, &buf) == 0) && /* exists... */
177 	    (buf.st_size == 0)) {		       /* ...but empty? */
178 		char *backup_name =
179 		    g_strdup_printf("%s.SAVE", settings.fnconfigure);
180 
181 		/* toss out the bad one and look for recovery. */
182 		unlink(settings.fnconfigure);
183 		if (stat(backup_name, &buf) == 0) {
184 			buf_says_empty = (buf.st_size == 0);
185 			rename(backup_name, settings.fnconfigure);
186 			gui_init(argc, argv);
187 			gui_generic_warning_modal(_("Empty settings file -- backup recovery attempted.\n"
188 						    "Some information may have been lost."));
189 		} else {
190 			gui_generic_warning_modal(_("Empty settings file -- no backup?!? Information lost!"));
191 		}
192 		g_free(backup_name);
193 	}
194 
195 	/* if settings.xml does not exist create it */
196 	if (buf_says_empty ||
197 	    (g_access(settings.fnconfigure, F_OK) == -1) || new_configs) {
198 		/* must be first run */
199 		XI_print((buf_says_empty
200 			      ? "\nSETTINGS FILE EXISTS BUT IS EMPTY - RECREATING.\n"
201 			      : "\nFirst Run: need to create settings!\n"));
202 		settings.first_run = TRUE;
203 
204 		xml_create_settings_file(settings.fnconfigure);
205 		xml_save_settings_doc(settings.fnconfigure);
206 		xml_free_settings_doc();
207 	}
208 	xml_parse_settings_file(settings.fnconfigure);
209 
210 	/* ensure that the user has a bible with which to work */
211 	if (settings.havebible == 0) {
212 		gui_init(argc, argv);
213 		main_shutdown_list();
214 		gui_open_mod_mgr_initial_run();
215 		main_init_lists();
216 		if (settings.havebible == 0) {
217 			gui_generic_warning_modal(_("There are no Bibles installed.\n"
218 						    "Evidently, you declined to install any.\n\n"
219 						    "Without any Bible modules to display,\n"
220 						    "Xiphos cannot proceed,\nand will now exit."));
221 			exit(1);
222 		}
223 		gui_generic_warning_modal(_("Bible module installation complete."));
224 	}
225 
226 	/* check for template.pad file for studypad */
227 	tmp = g_strdup_printf("%s/%s", settings.gSwordDir, "template.pad");
228 	if ((g_access(tmp, F_OK) == -1)) {
229 		g_file_set_contents(tmp, " ", 1, NULL);
230 	}
231 	g_free(tmp);
232 
233 	/* check for studypad.spt template file for studypad */
234 	tmp = g_build_filename(settings.gSwordDir, "studypad.spt", NULL);
235 	if (g_access(tmp, F_OK) == -1) {
236 		g_file_set_contents(tmp, studypad_template, -1, NULL);
237 	}
238 	g_free(tmp);
239 
240 	load_settings_structure();
241 
242 	/* BibleSync */
243 	settings.bs_mode = 0;
244 	settings.bs_privacy = FALSE;
245 	settings.bs_navdirect = TRUE;
246 	settings.bs_debug = FALSE;
247 	settings.bs_presence = FALSE;
248 	settings.bs_mismatch = FALSE;
249 	settings.bs_group_tab = TRUE;
250 	settings.bs_warned_bad_mod = FALSE;
251 	settings.bs_keyboard = FALSE;
252 	settings.bs_receiving = FALSE;
253 	settings.bs_listen_set = 0; // selective
254 	settings.bs_passphrase = g_strdup("BibleSync");
255 
256 	/* if the user had forced a locale, we must set it now. */
257 	if (settings.special_locale && strcmp(settings.special_locale, NONE)) {
258 		g_setenv("LANG", settings.special_locale, TRUE);
259 		gchar *test = setlocale(LC_ALL, settings.special_locale);
260 		if (test == NULL) {
261 			gchar lfix[32];
262 			sprintf(lfix, "%s.UTF-8", settings.special_locale); //for Ubuntu
263 			test = setlocale(LC_ALL, lfix);
264 		}
265 		if (test != NULL) {
266 			g_setenv("LC_ALL", test, TRUE);
267 			XI_message(("set locale to %s",
268 				    settings.special_locale));
269 		}
270 	}
271 
272 	/* find out what kind of peculiar language environment we have */
273 	re_encode_digits = FALSE;
274 	if (((env = (char *)g_getenv("LANG")) != NULL) &&
275 	    // for now, farsi-sensitive only
276 	    (strncmp(env, "fa", 2) == 0)) {
277 		re_encode_digits = TRUE;
278 	}
279 
280 	return retval;
281 }
282 
283 /******************************************************************************
284  * Name
285  *
286  *
287  * Synopsis
288  *   #include "main/settings.h"
289  *
290  *
291  *
292  * Description
293  *
294  *
295  * Return value
296  *
297  */
298 
init_bookmarks(int new_bookmarks)299 int init_bookmarks(int new_bookmarks)
300 {
301 	//GNode *bookmark_tree = NULL;
302 	char *file_buf = NULL;
303 
304 	settings.load_xml_bookmarks = FALSE;
305 
306 	/* set bookmarks dir to settings.gSwordDir + /bookmarks */
307 	settings.swbmDir =
308 	    g_strdup_printf("%s/%s", settings.gSwordDir, "bookmarks");
309 
310 	/* if .xiphos/bookmarks does not exist create it */
311 	if (g_access(settings.swbmDir, F_OK) == -1) {
312 		if ((Mkdir(settings.swbmDir, S_IRWXU)) == -1) {
313 			g_warning("can't create bookmarks dir");
314 			return 0;
315 		}
316 	}
317 
318 	if (new_bookmarks)
319 		xml_new_bookmark_file();
320 
321 	/* check for xml bookmarks */
322 	file_buf = g_strdup_printf("%s/bookmarks.xml", settings.swbmDir);
323 
324 	if (g_access(file_buf, F_OK) == 0) {
325 		settings.load_xml_bookmarks = TRUE;
326 	}
327 	g_free(file_buf);
328 
329 	if (!settings.load_xml_bookmarks) {
330 		xml_new_bookmark_file();
331 		settings.load_xml_bookmarks = TRUE;
332 	}
333 
334 	return 1;
335 }
336 
337 /******************************************************************************
338  * Name
339  *
340  *
341  * Synopsis
342  *   #include "main/settings.h"
343  *
344  *
345  *
346  * Description
347  *
348  *
349  * Return value
350  *
351  */
352 
load_settings_structure(void)353 void load_settings_structure(void)
354 {
355 	char *buf = NULL, *parallels;
356 
357 	settings.gs_version = VERSION;
358 	if ((settings.MainWindowModule =
359 		 xml_get_value("modules", "bible")) == NULL) {
360 		/* by the time we are here, we *must* have at least 1 bible */
361 		settings.MainWindowModule =
362 		    g_strdup(get_list(TEXT_LIST)->data);
363 	}
364 	settings.CommWindowModule = xml_get_value("modules", "comm");
365 	settings.DictWindowModule = xml_get_value("modules", "dict");
366 
367 	parallels = xml_get_value("modules", "parallels");
368 	/* if no parallels are known, convert old fixed parallel set */
369 	if (!parallels || (*parallels == '\0')) {
370 		char intN[] = "intN", i, *newhold;
371 
372 		g_free(parallels); /* in case it was real but empty */
373 		parallels = g_strdup("");
374 		for (i = '1'; i <= '5'; ++i) { /* the old set */
375 			intN[3] = i;
376 			char *oldparallel = xml_get_value("modules", intN);
377 			if (oldparallel && *oldparallel) {
378 				newhold =
379 				    g_strconcat(parallels, oldparallel,
380 						",", NULL);
381 				g_free(parallels);
382 				parallels = newhold;
383 				g_free(oldparallel);
384 				xml_remove_node("modules", intN, NULL); /* ? */
385 			}
386 		}
387 
388 		/* trim off the last comma */
389 		if (*parallels) {
390 			*(parallels + strlen(parallels) - 1) = '\0';
391 			xml_set_new_element("modules", "parallels",
392 					    parallels);
393 		}
394 	}
395 	if (parallels && *parallels)
396 		settings.parallel_list = g_strsplit(parallels, ",", -1);
397 	else
398 		settings.parallel_list = NULL;
399 	g_free(parallels);
400 
401 	settings.personalcommentsmod = xml_get_value("modules", "percomm");
402 	settings.devotionalmod = xml_get_value("modules", "devotional");
403 	settings.book_mod = xml_get_value("modules", "book");
404 
405 	/* we will assume reasonable module names, if not otherwise set */
406 	settings.lex_greek = xml_get_value("lexicons", "greek");
407 	settings.lex_hebrew = xml_get_value("lexicons", "hebrew");
408 	if (!settings.lex_greek) {
409 		settings.lex_greek = g_strdup("StrongsGreek");
410 		xml_set_value("Xiphos", "lexicons", "greek",
411 			      settings.lex_greek);
412 	}
413 	if (!settings.lex_hebrew) {
414 		settings.lex_hebrew = g_strdup("StrongsHebrew");
415 		xml_set_value("Xiphos", "lexicons", "hebrew",
416 			      settings.lex_hebrew);
417 	}
418 
419 	settings.DefaultDict =
420 	    xml_get_value("lexicons", "defaultdictionary");
421 	if (!settings.DefaultDict) {
422 		settings.DefaultDict = g_strdup("WebstersDict");
423 		xml_set_value("Xiphos", "lexicons", "defaultdictionary",
424 			      settings.DefaultDict);
425 	}
426 	settings.useDefaultDict =
427 	    atoi((buf = xml_get_value("lexicons", "usedefaultdict"))
428 		     ? buf
429 		     : "0");
430 
431 	/* unusual locale setting */
432 	if ((buf = xml_get_value("locale", "special")))
433 		settings.special_locale = g_strdup(buf);
434 	else {
435 		xml_add_new_section_to_settings_doc("locale");
436 		xml_add_new_item_to_section("locale", "special", NONE);
437 		settings.special_locale = g_strdup(NONE);
438 	}
439 
440 	/* mod mgr stuff */
441 	if ((buf = xml_get_value("modmgr", "mod_mgr_source")))
442 		settings.mod_mgr_source = atoi(buf);
443 	else {
444 		xml_add_new_section_to_settings_doc("modmgr");
445 		xml_add_new_item_to_section("modmgr", "mod_mgr_source",
446 					    "1");
447 		settings.mod_mgr_source = 1;
448 	}
449 	if ((buf = xml_get_value("modmgr", "mod_mgr_destination")))
450 		settings.mod_mgr_destination = atoi(buf);
451 	else {
452 		xml_add_new_item_to_section("modmgr",
453 					    "mod_mgr_destination", "0");
454 		settings.mod_mgr_destination = 0;
455 	}
456 	if ((buf = xml_get_value("modmgr", "mod_mgr_local_source_index")))
457 		settings.mod_mgr_local_source_index = atoi(buf);
458 	else {
459 		xml_add_new_item_to_section("modmgr",
460 					    "mod_mgr_local_source_index",
461 					    "0");
462 		settings.mod_mgr_local_source_index = 0;
463 	}
464 	if ((buf = xml_get_value("modmgr", "mod_mgr_remote_source_index")))
465 		settings.mod_mgr_remote_source_index = atoi(buf);
466 	else {
467 		xml_add_new_item_to_section("modmgr",
468 					    "mod_mgr_remote_source_index",
469 					    "0");
470 		settings.mod_mgr_remote_source_index = 0;
471 	}
472 
473 	/* current verse & keys */
474 	settings.currentverse = xml_get_value("keys", "verse");
475 	settings.dictkey = xml_get_value("keys", "dictionary");
476 
477 	if (xml_get_value("keys", "book")) {
478 		settings.book_key = xml_get_value("keys", "book");
479 	} else {
480 		xml_add_new_item_to_section("keys", "book", "0");
481 		settings.book_key = xml_get_value("keys", "book");
482 	}
483 	if (xml_get_value("keys", "offset"))
484 		settings.book_offset =
485 		    atol(xml_get_value("keys", "offset"));
486 	else {
487 		xml_add_new_item_to_section("keys", "offset", "");
488 		settings.book_offset = 0;
489 	}
490 
491 	if (xml_get_value("tab", "page"))
492 		settings.tab_page = atol(xml_get_value("tab", "page"));
493 	else {
494 		xml_add_new_item_to_section("tab", "page", "0");
495 		settings.tab_page = 0;
496 	}
497 
498 	/* layout */
499 	settings.sidebar_width =
500 	    atoi((buf = xml_get_value("layout", "shortcutbar"))
501 		     ? buf
502 		     : "100");
503 	if ((buf = xml_get_value("layout", "vltoppaneheight")))
504 		settings.verselist_toppane_height = atoi(buf);
505 	else {
506 		xml_add_new_item_to_section("layout", "vltoppaneheight",
507 					    "210");
508 		settings.verselist_toppane_height = 210;
509 	}
510 	if ((buf = xml_get_value("layout", "sidebar_notebook_height")))
511 		settings.sidebar_notebook_height = atoi(buf);
512 	else {
513 		if ((buf = xml_get_value("layout", "sidebar_notebook_hight"))) { /* backward compatible */
514 			settings.sidebar_notebook_height = atoi(buf);
515 			xml_remove_node("layout", "sidebar_notebook_hight",
516 					0);
517 		} else
518 			settings.sidebar_notebook_height = 250;
519 		buf =
520 		    g_strdup_printf("%d",
521 				    settings.sidebar_notebook_height);
522 		xml_add_new_item_to_section("layout",
523 					    "sidebar_notebook_height",
524 					    buf);
525 		g_free(buf);
526 	}
527 
528 	/* whether to open saved windows at startup */
529 	if ((buf = xml_get_value("layout", "parallelopen")))
530 		settings.display_parallel = atoi(buf);
531 	else {
532 		xml_add_new_item_to_section("layout", "parallelopen", "0");
533 		settings.display_parallel = 0;
534 	}
535 
536 	if ((buf = xml_get_value("layout", "modmgropen")))
537 		settings.display_modmgr = atoi(buf);
538 	else {
539 		xml_add_new_item_to_section("layout", "modmgropen", "0");
540 		settings.display_modmgr = 0;
541 	}
542 
543 	if ((buf = xml_get_value("layout", "advsearchopen")))
544 		settings.display_advsearch = atoi(buf);
545 	else {
546 		xml_add_new_item_to_section("layout", "advsearchopen",
547 					    "0");
548 		settings.display_advsearch = 0;
549 	}
550 
551 	if ((buf = xml_get_value("layout", "prefsopen")))
552 		settings.display_prefs = atoi(buf);
553 	else {
554 		xml_add_new_item_to_section("layout", "prefsopen", "0");
555 		settings.display_prefs = 0;
556 	}
557 
558 	/* main window geometry */
559 	if ((buf = xml_get_value("layout", "height")))
560 		settings.gs_height = atoi(buf);
561 	else {
562 		if ((buf = xml_get_value("layout", "hight"))) { /* backward compatible */
563 			settings.gs_height = atoi(buf);
564 			xml_remove_node("layout", "hight", 0);
565 		} else
566 			settings.gs_height = 500;
567 		buf = g_strdup_printf("%d", settings.gs_height);
568 		xml_add_new_item_to_section("layout", "height", buf);
569 		g_free(buf);
570 	}
571 	if ((buf = xml_get_value("layout", "width")))
572 		settings.gs_width = atoi(buf);
573 	else {
574 		xml_add_new_item_to_section("layout", "width", "500");
575 		settings.gs_width = 500;
576 	}
577 
578 	/* other panes' sizes */
579 	/* some of these sizes come out of the glade/gtkbuilder files */
580 	/* must maintain them in parallel */
581 	if ((buf = xml_get_value("layout", "parallel_height")))
582 		settings.parallel_height = atoi(buf);
583 	else {
584 		xml_add_new_item_to_section("layout", "parallel_height",
585 					    "361");
586 		settings.parallel_height = 361;
587 	}
588 	if ((buf = xml_get_value("layout", "parallel_width")))
589 		settings.parallel_width = atoi(buf);
590 	else {
591 		xml_add_new_item_to_section("layout", "parallel_width",
592 					    "657");
593 		settings.parallel_width = 657;
594 	}
595 
596 	if ((buf = xml_get_value("layout", "modmgr_height")))
597 		settings.modmgr_height = atoi(buf);
598 	else {
599 		xml_add_new_item_to_section("layout", "modmgr_height",
600 					    "450");
601 		settings.modmgr_height = 450;
602 	}
603 	if ((buf = xml_get_value("layout", "modmgr_width")))
604 		settings.modmgr_width = atoi(buf);
605 	else {
606 		xml_add_new_item_to_section("layout", "modmgr_width",
607 					    "710");
608 		settings.modmgr_width = 710;
609 	}
610 
611 	if ((buf = xml_get_value("layout", "advsearch_height")))
612 		settings.advsearch_height = atoi(buf);
613 	else {
614 		xml_add_new_item_to_section("layout", "advsearch_height",
615 					    "465");
616 		settings.advsearch_height = 465;
617 	}
618 	if ((buf = xml_get_value("layout", "advsearch_width")))
619 		settings.advsearch_width = atoi(buf);
620 	else {
621 		xml_add_new_item_to_section("layout", "advsearch_width",
622 					    "665");
623 		settings.advsearch_width = 665;
624 	}
625 
626 	if ((buf = xml_get_value("layout", "prefs_height")))
627 		settings.prefs_height = atoi(buf);
628 	else {
629 		xml_add_new_item_to_section("layout", "prefs_height",
630 					    "300");
631 		settings.prefs_height = 300;
632 	}
633 	if ((buf = xml_get_value("layout", "prefs_width")))
634 		settings.prefs_width = atoi(buf);
635 	else {
636 		xml_add_new_item_to_section("layout", "prefs_width",
637 					    "590");
638 		settings.prefs_width = 590;
639 	}
640 
641 	/* main window placement */
642 	if ((buf = xml_get_value("layout", "maximized")))
643 		settings.app_x = atoi(buf);
644 	else {
645 		xml_add_new_item_to_section("layout", "maximized", "0");
646 		settings.maximized = 0;
647 	}
648 	if ((buf = xml_get_value("layout", "app_x")))
649 		settings.app_x = atoi(buf);
650 	else {
651 		xml_add_new_item_to_section("layout", "app_x", "40");
652 		settings.app_x = 40;
653 	}
654 	if ((buf = xml_get_value("layout", "app_y")))
655 		settings.app_y = atoi(buf);
656 	else {
657 		xml_add_new_item_to_section("layout", "app_y", "40");
658 		settings.app_y = 40;
659 	}
660 
661 	/* other windows' placement */
662 	if ((buf = xml_get_value("layout", "parallel_x")))
663 		settings.parallel_x = atoi(buf);
664 	else {
665 		xml_add_new_item_to_section("layout", "parallel_x", "40");
666 		settings.parallel_x = 40;
667 	}
668 	if ((buf = xml_get_value("layout", "parallel_y")))
669 		settings.parallel_y = atoi(buf);
670 	else {
671 		xml_add_new_item_to_section("layout", "parallel_y", "40");
672 		settings.parallel_y = 40;
673 	}
674 
675 	if ((buf = xml_get_value("layout", "modmgr_x")))
676 		settings.modmgr_x = atoi(buf);
677 	else {
678 		xml_add_new_item_to_section("layout", "modmgr_x", "40");
679 		settings.modmgr_x = 40;
680 	}
681 	if ((buf = xml_get_value("layout", "modmgr_y")))
682 		settings.modmgr_y = atoi(buf);
683 	else {
684 		xml_add_new_item_to_section("layout", "modmgr_y", "40");
685 		settings.modmgr_y = 40;
686 	}
687 
688 	if ((buf = xml_get_value("layout", "advsearch_x")))
689 		settings.advsearch_x = atoi(buf);
690 	else {
691 		xml_add_new_item_to_section("layout", "advsearch_x", "40");
692 		settings.advsearch_x = 40;
693 	}
694 	if ((buf = xml_get_value("layout", "advsearch_y")))
695 		settings.advsearch_y = atoi(buf);
696 	else {
697 		xml_add_new_item_to_section("layout", "advsearch_y", "40");
698 		settings.advsearch_y = 40;
699 	}
700 
701 	if ((buf = xml_get_value("layout", "prefs_x")))
702 		settings.prefs_x = atoi(buf);
703 	else {
704 		xml_add_new_item_to_section("layout", "prefs_x", "40");
705 		settings.prefs_x = 40;
706 	}
707 	if ((buf = xml_get_value("layout", "prefs_y")))
708 		settings.prefs_y = atoi(buf);
709 	else {
710 		xml_add_new_item_to_section("layout", "prefs_y", "40");
711 		settings.prefs_y = 40;
712 	}
713 
714 	/* random geometry stuff */
715 	settings.biblepane_width =
716 	    atoi((buf = xml_get_value("layout", "textpane"))
717 		     ? buf
718 		     : "0");
719 
720 	if ((buf = xml_get_value("layout", "bibleheight")))
721 		settings.biblepane_height = atoi(buf);
722 	else {
723 		if ((buf = xml_get_value("layout", "biblehight"))) { /* backward compatible */
724 			settings.biblepane_height = atoi(buf);
725 			xml_remove_node("layout", "biblehight", 0);
726 		} else
727 			settings.biblepane_height = 250;
728 		buf = g_strdup_printf("%d", settings.biblepane_height);
729 		xml_add_new_item_to_section("layout", "bibleheight", buf);
730 		g_free(buf);
731 	}
732 
733 	if ((buf = xml_get_value("layout", "commentaryheight")))
734 		settings.commpane_height = atoi(buf);
735 	else {
736 		if ((buf = xml_get_value("layout", "commentaryhight"))) { /* backward compatible */
737 			settings.commpane_height = atoi(buf);
738 			xml_remove_node("layout", "commentaryhight", 0);
739 		} else
740 			settings.commpane_height = 240;
741 		buf = g_strdup_printf("%d", settings.commpane_height);
742 		xml_add_new_item_to_section("layout", "commentaryheight",
743 					    buf);
744 		g_free(buf);
745 	}
746 
747 	/* font sizes */
748 	if ((buf = xml_get_value("fontsize", "versenum"))) {
749 		settings.verse_num_font_size_str = buf;
750 		settings.verse_num_font_size = atoi(buf);
751 	} else {
752 		settings.verse_num_font_size_str = g_strdup("-1");
753 		settings.verse_num_font_size = -1;
754 	}
755 
756 	if ((buf = xml_get_value("fontsize", "basefontsize"))) {
757 		settings.base_font_size_str = buf;
758 		settings.base_font_size =
759 		    atoi(settings.base_font_size_str);
760 	} else {
761 #ifndef WIN32
762 		xml_add_new_item_to_section("fontsize", "basefontsize",
763 					    "+0");
764 		settings.base_font_size_str = g_strdup("+0");
765 		settings.base_font_size = 0;
766 #else
767 		xml_add_new_item_to_section("fontsize", "basefontsize",
768 					    "+1");
769 		settings.base_font_size_str = g_strdup("+1");
770 		settings.base_font_size = 1;
771 #endif /* WIN32 */
772 	}
773 
774 	/* colors */
775 	settings.bible_text_color = xml_get_value("HTMLcolors", "text_fg");
776 	settings.bible_bg_color =
777 	    xml_get_value("HTMLcolors", "background");
778 	settings.currentverse_color =
779 	    xml_get_value("HTMLcolors", "currentverse");
780 	settings.link_color = xml_get_value("HTMLcolors", "link");
781 	settings.bible_verse_num_color =
782 	    xml_get_value("HTMLcolors", "versenum");
783 	settings.found_color = xml_get_value("HTMLcolors", "found");
784 
785 	if ((buf = xml_get_value("HTMLcolors", "highlight_fg")))
786 		settings.highlight_fg = g_strdup(buf);
787 	else {
788 		xml_add_new_item_to_section("HTMLcolors", "highlight_fg",
789 					    "#FFFF00");
790 		settings.highlight_fg = g_strdup("#FFFF00");
791 	}
792 	if ((buf = xml_get_value("HTMLcolors", "highlight_bg")))
793 		settings.highlight_bg = g_strdup(buf);
794 	else {
795 		xml_add_new_item_to_section("HTMLcolors", "highlight_bg",
796 					    "#060680");
797 		settings.highlight_bg = g_strdup("#060680");
798 	}
799 
800 	/*  parallel ops  */
801 	if ((buf = xml_get_value("parallel", "Strong_s_Numbers")))
802 		settings.parallel_strongs = atoi(buf);
803 	else {
804 		xml_add_new_item_to_section("parallel", "Strong_s_Numbers",
805 					    "0");
806 		settings.parallel_strongs = 0;
807 	}
808 
809 	if ((buf = xml_get_value("parallel", "Morphological_Tags")))
810 		settings.parallel_morphs = atoi(buf);
811 	else {
812 		xml_add_new_item_to_section("parallel",
813 					    "Morphological_Tags", "0");
814 		settings.parallel_morphs = 0;
815 	}
816 
817 	if ((buf = xml_get_value("parallel", "Hebrew_Vowel_Points")))
818 		settings.parallel_hebrewpoints = atoi(buf);
819 	else {
820 		xml_add_new_item_to_section("parallel",
821 					    "Hebrew_Vowel_Points", "1");
822 		settings.parallel_hebrewpoints = 1;
823 	}
824 
825 	if ((buf = xml_get_value("parallel", "Hebrew_Cantillation")))
826 		settings.parallel_cantillationmarks = atoi(buf);
827 	else {
828 		xml_add_new_item_to_section("parallel",
829 					    "Hebrew_Cantillation", "0");
830 		settings.parallel_cantillationmarks = 0;
831 	}
832 
833 	if ((buf = xml_get_value("parallel", "Footnotes")))
834 		settings.parallel_footnotes = atoi(buf);
835 	else {
836 		xml_add_new_item_to_section("parallel", "Footnotes", "1");
837 		settings.parallel_footnotes = 1;
838 	}
839 
840 	if ((buf = xml_get_value("parallel", "Cross-references")))
841 		settings.parallel_crossref = atoi(buf);
842 	else {
843 		xml_add_new_item_to_section("parallel", "Cross-references",
844 					    "1");
845 		settings.parallel_crossref = 1;
846 	}
847 
848 	if ((buf = xml_get_value("parallel", "Transliteration")))
849 		settings.parallel_transliteration = atoi(buf);
850 	else {
851 		xml_add_new_item_to_section("parallel", "Transliteration",
852 					    "0");
853 		settings.parallel_transliteration = 0;
854 	}
855 
856 	if ((buf = xml_get_value("parallel", "Words_of_Christ_in_Red")))
857 		settings.parallel_red_words = atoi(buf);
858 	else {
859 		xml_add_new_item_to_section("parallel",
860 					    "Words_of_Christ_in_Red", "1");
861 		settings.parallel_red_words = 1;
862 	}
863 
864 	if ((buf = xml_get_value("parallel", "Morpheme_Segmentation")))
865 		settings.parallel_segmentation = atoi(buf);
866 	else {
867 		xml_add_new_item_to_section("parallel",
868 					    "Morpheme_Segmentation", "0");
869 		settings.parallel_segmentation = 0;
870 	}
871 
872 	if ((buf = xml_get_value("parallel", "Headings")))
873 		settings.parallel_headings = atoi(buf);
874 	else {
875 		xml_add_new_item_to_section("parallel", "Headings", "1");
876 		settings.parallel_headings = 1;
877 	}
878 
879 	if ((buf = xml_get_value("parallel", "Lemmas")))
880 		settings.parallel_lemmas = atoi(buf);
881 	else {
882 		xml_add_new_item_to_section("parallel", "Lemmas", "0");
883 		settings.parallel_lemmas = 0;
884 	}
885 
886 	if ((buf = xml_get_value("parallel", "Primary_Reading")))
887 		settings.parallel_variants_primary = atoi(buf);
888 	else {
889 		xml_add_new_item_to_section("parallel", "Primary_Reading",
890 					    "1");
891 		settings.parallel_variants_primary = 1;
892 	}
893 
894 	if ((buf = xml_get_value("parallel", "Secondary_Reading")))
895 		settings.parallel_variants_secondary = atoi(buf);
896 	else {
897 		xml_add_new_item_to_section("parallel",
898 					    "Secondary_Reading", "0");
899 		settings.parallel_variants_secondary = 0;
900 	}
901 
902 	if ((buf = xml_get_value("parallel", "All_Readings")))
903 		settings.parallel_variants_all = atoi(buf);
904 	else {
905 		xml_add_new_item_to_section("parallel", "All_Readings",
906 					    "0");
907 		settings.parallel_variants_all = 0;
908 	}
909 
910 	if ((buf = xml_get_value("parallel", "Greek_Accents")))
911 		settings.parallel_greekaccents = atoi(buf);
912 	else {
913 		xml_add_new_item_to_section("parallel", "Greek_Accents",
914 					    "1");
915 		settings.parallel_greekaccents = 1;
916 	}
917 
918 	if ((buf = xml_get_value("parallel", "Transliterated_Forms")))
919 		settings.parallel_xlit = atoi(buf);
920 	else {
921 		xml_add_new_item_to_section("parallel",
922 					    "Transliterated_Forms", "0");
923 		settings.parallel_xlit = 0;
924 	}
925 
926 	if ((buf = xml_get_value("parallel", "Enumerations")))
927 		settings.parallel_enumerated = atoi(buf);
928 	else {
929 		xml_add_new_item_to_section("parallel", "Enumerations",
930 					    "0");
931 		settings.parallel_enumerated = 0;
932 	}
933 
934 	if ((buf = xml_get_value("parallel", "Glosses")))
935 		settings.parallel_glosses = atoi(buf);
936 	else {
937 		xml_add_new_item_to_section("parallel", "Glosses", "0");
938 		settings.parallel_glosses = 0;
939 	}
940 
941 	if ((buf = xml_get_value("parallel", "Morpheme_Segmentation")))
942 		settings.parallel_morphseg = atoi(buf);
943 	else {
944 		xml_add_new_item_to_section("parallel",
945 					    "Morpheme_Segmentation", "0");
946 		settings.parallel_morphseg = 0;
947 	}
948 
949 	/*  Misc stuff  */
950 
951 	settings.showtexts =
952 	    atoi((buf = xml_get_value("misc", "showtexts")) ? buf : "1");
953 	settings.showcomms =
954 	    atoi((buf = xml_get_value("misc", "showcomms")) ? buf : "1");
955 	settings.showdicts =
956 	    atoi((buf = xml_get_value("misc", "showdicts")) ? buf : "1");
957 	if (xml_get_value("misc", "showpreview"))
958 		settings.showpreview =
959 		    atol(xml_get_value("misc", "showpreview"));
960 	else {
961 		xml_add_new_item_to_section("misc", "showpreview", "1");
962 		settings.showpreview = 1;
963 	}
964 
965 	if (xml_get_value("misc", "show_side_preview"))
966 		settings.show_previewer_in_sidebar =
967 		    atol(xml_get_value("misc", "show_side_preview"));
968 	else {
969 		xml_add_new_item_to_section("misc", "show_side_preview",
970 					    "1");
971 		settings.show_previewer_in_sidebar = 1;
972 	}
973 
974 	if (xml_get_value("misc", "showparatab"))
975 		settings.showparatab =
976 		    atol(xml_get_value("misc", "showparatab"));
977 	else {
978 		xml_add_new_item_to_section("misc", "showparatab", "0");
979 		settings.showparatab = 0;
980 	}
981 
982 	settings.showsplash =
983 	    atoi((buf = xml_get_value("misc", "splash")) ? buf : "1");
984 
985 	settings.showdevotional =
986 	    atoi((buf =
987 		      xml_get_value("misc", "dailydevotional"))
988 		     ? buf
989 		     : "1");
990 	settings.versestyle =
991 	    atoi((buf = xml_get_value("misc", "versestyle")) ? buf : "1");
992 
993 	if ((buf = xml_get_value("misc", "pinnedtabs")))
994 		settings.linkedtabs = atoi(buf);
995 	else {
996 		xml_add_new_item_to_section("misc", "pinnedtabs", "0");
997 		settings.linkedtabs = 0;
998 	}
999 
1000 	if ((buf = xml_get_value("misc", "readaloud")))
1001 		settings.readaloud = atoi(buf);
1002 	else {
1003 		xml_add_new_item_to_section("misc", "readaloud", "0");
1004 		settings.readaloud = 0;
1005 	}
1006 
1007 	if ((buf = xml_get_value("misc", "showversenum")))
1008 		settings.showversenum = atoi(buf);
1009 	else {
1010 		xml_add_new_item_to_section("misc", "showversenum", "1");
1011 		settings.showversenum = 1;
1012 	}
1013 
1014 	if ((buf = xml_get_value("misc", "verse_num_bold")))
1015 		settings.verse_num_bold = atoi(buf);
1016 	else {
1017 		xml_add_new_item_to_section("misc", "verse_num_bold", "0");
1018 		settings.verse_num_bold = 0;
1019 	}
1020 
1021 	if ((buf = xml_get_value("misc", "verse_num_bracket")))
1022 		settings.verse_num_bracket = atoi(buf);
1023 	else {
1024 		xml_add_new_item_to_section("misc", "verse_num_bracket",
1025 					    "0");
1026 		settings.verse_num_bracket = 0;
1027 	}
1028 
1029 	if ((buf = xml_get_value("misc", "verse_num_superscript")))
1030 		settings.verse_num_superscript = atoi(buf);
1031 	else {
1032 		xml_add_new_item_to_section("misc",
1033 					    "verse_num_superscript", "0");
1034 		settings.verse_num_superscript = 0;
1035 	}
1036 
1037 	if ((buf = xml_get_value("misc", "versehighlight")))
1038 		settings.versehighlight = atoi(buf);
1039 	else {
1040 		xml_add_new_item_to_section("misc", "versehighlight", "0");
1041 		settings.versehighlight = 0;
1042 	}
1043 
1044 	if ((buf = xml_get_value("misc", "annotatehighlight")))
1045 		settings.annotate_highlight = atoi(buf);
1046 	else {
1047 		xml_add_new_item_to_section("misc", "annotatehighlight",
1048 					    "1");
1049 		settings.annotate_highlight = 1;
1050 	}
1051 
1052 	if ((buf = xml_get_value("misc", "xrefsinverselist")))
1053 		settings.xrefs_in_verse_list = atoi(buf);
1054 	else {
1055 		xml_add_new_item_to_section("misc", "xrefsinverselist",
1056 					    "1");
1057 		settings.xrefs_in_verse_list = 1;
1058 	}
1059 
1060 	if ((buf = xml_get_value("misc", "chapter-scroll"))) {
1061 		settings.chapter_scroll = atoi(buf);
1062 	} else {
1063 		xml_add_new_item_to_section("misc", "chapter-scroll", "0");
1064 		settings.chapter_scroll = 0;
1065 	}
1066 
1067 	if ((buf = xml_get_value("misc", "imageresize"))) {
1068 		settings.imageresize = atoi(buf);
1069 	} else {
1070 		xml_add_new_item_to_section("misc", "imageresize", "1");
1071 		settings.imageresize = 1;
1072 	}
1073 #ifdef WIN32
1074 	/* due to hackery caused by webkit "no images" bug */
1075 	settings.imageresize = 1;
1076 #endif
1077 
1078 	if ((buf = xml_get_value("editor", "spell_language")))
1079 		settings.spell_language = g_strdup(buf);
1080 	else {
1081 		xml_add_new_item_to_section("editor", "spell_language",
1082 					    "unknown");
1083 		settings.spell_language = "unknown";
1084 	}
1085 
1086 	settings.studypadfilename = xml_get_value("studypad", "lastfile");
1087 	settings.studypaddir = xml_get_value("studypad", "directory");
1088 
1089 	if ((buf = xml_get_value("misc", "show_sidebar"))) {
1090 		settings.showshortcutbar = atoi(buf);
1091 	} else {
1092 		xml_add_new_item_to_section("misc", "show_sidebar", "1");
1093 		settings.showshortcutbar = 1;
1094 	}
1095 	if ((buf = xml_get_value("misc", "sidebar_docked"))) {
1096 		settings.docked = atoi(buf);
1097 	} else {
1098 		xml_add_new_item_to_section("misc", "sidebar_docked", "1");
1099 		settings.docked = 1;
1100 	}
1101 
1102 	if ((buf = xml_get_value("misc", "prayerlist"))) {
1103 		settings.prayerlist = atoi(buf);
1104 	} else {
1105 		xml_add_new_item_to_section("misc", "prayerlist", "1");
1106 		settings.prayerlist = 1;
1107 	}
1108 
1109 	if ((buf = xml_get_value("misc", "statusbar"))) {
1110 		settings.statusbar = atoi(buf);
1111 	} else {
1112 		xml_add_new_item_to_section("misc", "statusbar", "1");
1113 		settings.statusbar = 1;
1114 	}
1115 
1116 	if ((buf = xml_get_value("misc", "alternation"))) {
1117 		settings.alternation = atoi(buf);
1118 	} else {
1119 		xml_add_new_item_to_section("misc", "alternation", "1");
1120 		settings.alternation = 1;
1121 	}
1122 
1123 #if 1
1124 	settings.browsing = 1; /* unconditional - no longer toggle-able. */
1125 #else
1126 	if ((buf = xml_get_value("tabs", "browsing"))) {
1127 		settings.browsing = atoi(buf);
1128 	} else {
1129 		xml_add_new_item_to_section("tabs", "browsing", "1");
1130 		settings.browsing = 1;
1131 	}
1132 #endif
1133 }
1134