
/*
 * Osmo - a handy personal organizer
 *
 * Copyright (C) 2007 Tomasz Maka <pasp@users.sourceforge.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <errno.h>

#include "options_prefs.h"
#include "i18n.h"
#include "utils.h"
#include "utils_date.h"
#include "contacts.h"
#include "contacts_import.h"
#include "contacts_export.h"
#include "calendar.h"
#include "calendar_widget.h"
#include "calendar_notes.h"
#include "calendar_utils.h"

/*------------------------------------------------------------------------------*/
static gchar *
build_app_specific_dir(const gchar *basedir) {
    static gchar result[PATH_MAX];
    gchar *dirname = g_build_filename(basedir, CONFIG_SUBDIR, NULL);
    g_strlcpy(result, dirname, PATH_MAX);
    g_free(dirname);
    return result;
}

gchar *
prefs_get_config_dir(GUI *appGUI) {
    return (build_app_specific_dir(g_get_user_config_dir()));
}

gchar *
prefs_get_data_dir(GUI *appGUI) {
    return (build_app_specific_dir(g_get_user_data_dir()));
}
/*------------------------------------------------------------------------------*/

static gchar *
get_filename(const gchar *filename, const gchar *basedir) {
    static gchar result[PATH_MAX];
    gchar *file, *dir;
    struct stat st;

    g_return_val_if_fail(basedir != NULL, NULL);
    file = g_build_filename(basedir, filename, NULL);
    dir = g_path_get_dirname(file);

    if (g_stat(dir, &st) < 0) {
        gint rc = g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR);
        if (rc) {
            g_free(dir);
            g_free(file);
            return NULL;
        }
    }

    if (g_access(dir, R_OK | W_OK) == -1) {
        g_free(dir);
        g_free(file);
        return NULL;
    }

    g_strlcpy(result, file, PATH_MAX);
    g_free(dir);
    g_free(file);

    return result;
}

gchar *
prefs_get_config_filename(gchar *filename, GUI *appGUI) {
    return get_filename(filename, prefs_get_config_dir(appGUI));
}

gchar *
prefs_get_data_filename(gchar *filename, GUI *appGUI) {
    return get_filename(filename, prefs_get_data_dir(appGUI));
}

gchar*
prefs_get_cache_filename(gchar *filename) {
    return get_filename(filename, build_app_specific_dir(g_get_user_cache_dir()));
}

gchar*
prefs_get_runtime_filename(gchar *filename, GUI *appGUI) {
    return get_filename("lockfile", prefs_get_config_dir(appGUI));
}

/*------------------------------------------------------------------------------*/

void 
prefs_set_default_values (void) {

gint i;

    /* general */
    config.window_x = 0;
    config.window_y = 0;
    config.window_size_x = 950;
    config.window_size_y = 560;
    config.fullscreen = 0;
    config.enable_tooltips = TRUE;
    config.latest_tab = 0;      /* calendar */
    config.tabs_position = GTK_POS_TOP;
    config.remember_latest_tab = TRUE;
    config.save_data_after_modification = TRUE;
    config.disable_underline_links = FALSE;
    config.toolbar_exit_button = FALSE;
    config.date_format = DATE_YYYY_MM_DD;
    config.time_format = TIME_24;
    config.enable_systray = TRUE;
    config.start_minimised_in_systray = FALSE;
    config.ignore_day_note_events = FALSE;
    config.run_counter = 0;
    config.lastrun_date = utl_date_get_current_julian ();
    config.lastrun_time = utl_time_get_current_seconds ();
    config.hide_calendar = FALSE;
    config.hide_tasks = FALSE;
    config.hide_contacts = FALSE;
    config.hide_notes = FALSE;
    config.override_locale_settings = FALSE;
    config.gui_layout = 1;      /* 0 - vertical, 1 - horizontal */
    config.sound_alarm_repeat = 1;
	g_strlcpy (config.link_color, "blue", MAXCOLORNAME);
    g_strlcpy (config.spell_lang, g_getenv("LANG"), MAXNAME);
    /* FIXME: DO NOT USE xdg-open AS IT CANNOT OPEN MULTIPLE LINKS AT ONCE */
	/*g_strlcpy (config.web_browser, "xdg-open %s", MAXHELPERCMD);*/
	g_strlcpy (config.web_browser, "firefox %s", MAXHELPERCMD);
	g_strlcpy (config.email_client, "xdg-email %s", MAXHELPERCMD);
	/* play command requires SoX */
	/*g_strlcpy (config.sound_player, "play %s", MAXHELPERCMD);*/
	g_strlcpy (config.sound_player, "aplay %s", MAXHELPERCMD);

    /* calendar */
    config.fy_window_size_x = 750;
    config.fy_window_size_y = 550;
    config.fy_simple_view = TRUE;
    config.fy_alternative_view = FALSE;
    config.cb_window_size_x = 570;
    config.cb_window_size_y = 680;
    config.ib_window_size_x = 550;
    config.ib_window_size_y = 650;
    config.display_options = GUI_CALENDAR_SHOW_DAY_NAMES | GUI_CALENDAR_NO_MONTH_CHANGE | GUI_CALENDAR_WEEK_START_MONDAY;
    config.day_notes_visible = FALSE;
    config.timeline_start = 8*60;
    config.timeline_end = 15*60;
    config.timeline_step = 60;
    config.di_show_current_time = TRUE;
    config.di_show_current_time_seconds = TRUE;
    config.di_show_day_number = TRUE;
    config.di_show_current_day_distance = TRUE;
    config.di_show_marked_days = TRUE;
    config.di_show_week_number = TRUE;
    config.di_show_weekend_days = TRUE;
    config.di_show_day_category = TRUE;
    config.di_show_moon_phase = TRUE;
    config.di_show_notes = TRUE;
    config.di_show_zodiac_sign = FALSE;
    config.cursor_type = CURSOR_FRAME;
    config.frame_cursor_thickness = 2;
    config.enable_auxiliary_calendars = TRUE;
    config.enable_day_mark = TRUE;
    config.strikethrough_past_notes = FALSE;
    config.ascending_sorting_in_day_notes_browser = FALSE;
    config.auxiliary_calendars_state = FALSE;
    config.day_note_spell_checker = FALSE;
    g_strlcpy (config.day_note_marker, "\'", MAXNAME);
    g_strlcpy (config.date_header_format, DEFAULT_DATE_HEADER_FORMAT, MAXNAME);
    config.event_marker_type = EVENT_MARKER_CIRCLE;
    config.today_marker_type = TODAY_MARKER_FREEHAND_CIRCLE;
    config.day_notes_browser_filter = DN_FILTER_CURRENT_MONTH;
    config.ical_export_pane_pos = 180;
	g_strlcpy (config.background_color, "#FFFFFF", MAXCOLORNAME);
	g_strlcpy (config.header_bg_color, "#404048", MAXCOLORNAME);
	g_strlcpy (config.header_fg_color, "#DDDDDD", MAXCOLORNAME);
	g_strlcpy (config.day_color, "#555555", MAXCOLORNAME);
	g_strlcpy (config.pf_day_color, "#CCCCCC", MAXCOLORNAME);
	g_strlcpy (config.weekend_color, "#880000", MAXCOLORNAME);
	g_strlcpy (config.selection_color, "#86ABD9", MAXCOLORNAME);
	g_strlcpy (config.mark_color, "#CBE140", MAXCOLORNAME);
	g_strlcpy (config.mark_current_day_color, "#E37751", MAXCOLORNAME);
	g_strlcpy (config.birthday_mark_color, "#EDD400", MAXCOLORNAME);
    config.mark_current_day_alpha = 32768;
    config.selector_alpha = 32768;
	g_strlcpy (config.day_name_font, "Sans Bold 20", MAXFONTNAME);
	g_strlcpy (config.calendar_font, "Sans 18", MAXFONTNAME);
	g_strlcpy (config.notes_font, "Sans 11", MAXFONTNAME);
	g_strlcpy (config.cal_print_month_name_font, "Sans Bold 40", MAXFONTNAME);
	g_strlcpy (config.cal_print_day_name_font, "Sans Bold 10", MAXFONTNAME);
	g_strlcpy (config.cal_print_day_num_font, "Sans Bold 16", MAXFONTNAME);
	g_strlcpy (config.cal_print_event_font, "Sans 7", MAXFONTNAME);
	config.cal_print_event_length = 256;
	config.cal_print_padding = 4;
	config.cal_print_page_orientation = PORTRAIT;
	config.cal_print_tasks = TRUE;
	config.cal_print_birthdays = TRUE;
	config.cal_print_namedays = TRUE;
	config.cal_print_day_notes = TRUE;
	config.cal_print_ical = TRUE;
	config.cal_print_disable_background	= FALSE;

    /* tasks */
    config.tasks_high_in_bold = TRUE;
    config.hide_completed = FALSE;
    config.delete_completed = FALSE;
    config.add_edit = FALSE;
    config.remember_category_in_tasks = FALSE;
    config.current_category_in_tasks = 0;
    config.tasks_pane_pos = DEFAULT_PANED_SPLIT_POSITION;
    config.tasks_sorting_order = GTK_SORT_ASCENDING;
    config.tasks_sorting_column = TA_COLUMN_DUE_DATE;
    config.tsk_visible_due_date_column = TRUE;
    config.tsk_visible_type_column = TRUE;
    config.tsk_visible_priority_column = FALSE;
    config.tsk_visible_category_column = FALSE;
    config.tasks_addedit_win_w = 370;
    config.tasks_addedit_win_h = 440;
    config.tasks_addedit_win_x = config.window_x+config.window_size_x/2-config.tasks_addedit_win_w/2;
    config.tasks_addedit_win_y = config.window_y+20;
    config.postpone_time = 10;
	config.tasks_column_idx_0 = 0;
	config.tasks_column_idx_0_width = 50;
	config.tasks_column_idx_1 = 1;
	config.tasks_column_idx_1_width = 50;
	config.tasks_column_idx_2 = 2;
	config.tasks_column_idx_2_width = 100;
	config.tasks_column_idx_3 = 3;
	config.tasks_column_idx_3_width = 100;
	config.tasks_column_idx_4 = 4;
	config.tasks_column_idx_4_width = 100;
	config.tasks_column_idx_5 = 5;
	config.tasks_column_idx_5_width = 100;
	g_strlcpy (config.due_today_color, "#00981E", MAXCOLORNAME);
	g_strlcpy (config.due_7days_color, "#0047B7", MAXCOLORNAME);
	g_strlcpy (config.past_due_color, "#CB362C", MAXCOLORNAME);
	g_strlcpy (config.task_info_font, "Sans 14", MAXFONTNAME);
	config.global_notification_command[0] = '\0';

    /* contacts */
    config.find_mode = CONTACTS_FF_FIRST_NAME;
    config.maps_provider = 0;
    config.contacts_pane_pos = DEFAULT_PANED_SPLIT_POSITION;
    config.photo_width = 80;
    config.cnt_visible_age_column = TRUE;
    config.cnt_visible_birthday_date_column = TRUE;
    config.cnt_visible_zodiac_sign_column = TRUE;
    config.contacts_sorting_order = GTK_SORT_ASCENDING;
    config.contacts_sorting_column = COLUMN_GROUP;
    config.contacts_addedit_win_w = 500;
    config.contacts_addedit_win_h = 600;
    config.contacts_addedit_win_x = config.window_x+config.window_size_x/2-config.contacts_addedit_win_w/2;
    config.contacts_addedit_win_y = config.window_y+20;
    config.contacts_export_win_w = 500;
    config.contacts_export_win_h = 400;
    config.contacts_export_win_x = config.window_x+config.window_size_x/2-config.contacts_export_win_w/2;
    config.contacts_export_win_y = config.window_y+20;
    config.contacts_import_win_w = 650;
    config.contacts_import_win_h = 450;
    config.contacts_import_win_x = config.window_x+config.window_size_x/2-config.contacts_import_win_w/2;
    config.contacts_import_win_y = config.window_y+20;
    config.contacts_import_sel_win_x = config.window_x+60;
    config.contacts_import_sel_win_y = config.window_y+20;
    config.contacts_birthdays_win_w = 650;
    config.contacts_birthdays_win_h = 700;
    config.import_type = IMPORT_TYPE_FILE;
    config.import_interface_type = 0;
    config.import_bluetooth_channel = 1;
    config.import_usb_interface = 0;
    config.import_binary_xml = 0;
	config.contact_name_font_size = 18;
	config.contact_item_font_size = 11;
	g_strlcpy (config.import_bluetooth_address, "00:00:00:00:00:00", MAXADDRESS);
	g_strlcpy (config.contact_tag_color, "#228B22", MAXCOLORNAME);
	g_strlcpy (config.contact_link_color, "blue", MAXCOLORNAME);

    config.export_format = EXPORT_TO_CSV;

    for(i=0; i < CONTACTS_NUM_COLUMNS; i++) {
        config.export_fields[i] = '-';
        config.contacts_visible_columns[i] = '-';
    }
    config.export_fields[COLUMN_GROUP] = '+';
    config.export_fields[COLUMN_FIRST_NAME] = '+';
    config.export_fields[COLUMN_LAST_NAME] = '+';
    config.export_fields[COLUMN_NICK_NAME] = '+';
    config.contacts_visible_columns[COLUMN_GROUP] = '+';
    config.contacts_visible_columns[COLUMN_FIRST_NAME] = '+';
    config.contacts_visible_columns[COLUMN_LAST_NAME] = '+';

    config.contacts_column_positions[COLUMN_GROUP] = 0;
    config.contacts_column_positions[COLUMN_FIRST_NAME] = 1;
    config.contacts_column_positions[COLUMN_LAST_NAME] = 2;
    config.contacts_column_widths[COLUMN_GROUP] = 150;
    config.contacts_column_widths[COLUMN_FIRST_NAME] = 150;
    config.contacts_column_widths[COLUMN_LAST_NAME] = 150;

    /* notes */
    config.notes_enc_algorithm = 1;         /* Serpent */
    config.notes_enc_hashing = 1;           /* RIPEMD-160 */
    config.notes_comp_algorithm = 0;        /* ZLib */
    config.notes_comp_ratio = 3;            /* BEST */
    config.notes_sorting_order = GTK_SORT_ASCENDING;
    config.notes_sorting_column = N_COLUMN_NAME;
    config.nte_visible_type_column = TRUE;
    config.nte_visible_category_column = TRUE;
    config.nte_visible_last_changes_column = TRUE;
    config.nte_visible_created_column = TRUE;
	config.notes_column_idx_0 = 0;
	config.notes_column_idx_0_width = 50;
	config.notes_column_idx_1 = 1;
	config.notes_column_idx_1_width = 200;
	config.notes_column_idx_2 = 2;
	config.notes_column_idx_2_width = 80;
	config.notes_column_idx_3 = 3;
	config.notes_column_idx_3_width = 150;
	config.notes_column_idx_4 = 4;
	config.notes_column_idx_4_width = 150;
    config.remember_category_in_notes = FALSE;
    config.current_category_in_notes = 0;
    config.use_system_date_in_notes = FALSE;
    config.text_separator = '=';
	g_strlcpy (config.notes_editor_font, "Sans 11", MAXFONTNAME);
}

/*------------------------------------------------------------------------------*/

void 
prefs_read_config (GUI *appGUI)
{
gboolean cfg_file;
xmlDocPtr doc;
xmlNodePtr node, general_node, calendar_node, tasks_node, contacts_node, notes_node;

	cfg_file = g_file_test (prefs_get_config_filename (CONFIG_FILENAME, appGUI), G_FILE_TEST_IS_REGULAR);

	if (cfg_file == TRUE) {
		doc = xmlParseFile (prefs_get_config_filename (CONFIG_FILENAME, appGUI));
		if (doc == NULL) return;

		node = xmlDocGetRootElement (doc);
		if (node == NULL) {
			xmlFreeDoc (doc);
			return;
		}

		if (xmlStrcmp (node->name, (const xmlChar *) CONFIG_NAME)) {
			xmlFreeDoc (doc);
			return;
		}

		prefs_set_default_values ();
		node = node->xmlChildrenNode;

		while (node != NULL) {

			/*---------------------------------------------------------------------------------------*/
			/* general */

			if ((!xmlStrcmp (node->name, (const xmlChar *) "general"))) {
				general_node = node->xmlChildrenNode;

				while (general_node != NULL) {
					utl_xml_get_int ("window_x", &config.window_x, general_node);
					utl_xml_get_int ("window_y", &config.window_y, general_node);
					utl_xml_get_int ("window_size_x", &config.window_size_x, general_node);
					utl_xml_get_int ("window_size_y", &config.window_size_y, general_node);
					utl_xml_get_int ("fullscreen", &config.fullscreen, general_node);
					utl_xml_get_int ("enable_tooltips", &config.enable_tooltips, general_node);
					utl_xml_get_int ("latest_tab", &config.latest_tab, general_node);
					utl_xml_get_int ("tabs_position", &config.tabs_position, general_node);
					utl_xml_get_int ("remember_latest_tab", &config.remember_latest_tab, general_node);
					utl_xml_get_int ("save_data_after_modification", &config.save_data_after_modification, general_node);
					utl_xml_get_int ("disable_underline_links", &config.disable_underline_links, general_node);
					utl_xml_get_int ("toolbar_exit_button", &config.toolbar_exit_button, general_node);
					utl_xml_get_int ("date_format", &config.date_format, general_node);
					utl_xml_get_int ("time_format", &config.time_format, general_node);
					utl_xml_get_int ("enable_systray", &config.enable_systray, general_node);
					utl_xml_get_int ("start_minimised_in_systray", &config.start_minimised_in_systray, general_node);
					utl_xml_get_int ("ignore_day_note_events", &config.ignore_day_note_events, general_node);
					utl_xml_get_int ("run_counter", &config.run_counter, general_node);
					utl_xml_get_int ("lastrun_date", &config.lastrun_date, general_node);
					utl_xml_get_int ("lastrun_time", &config.lastrun_time, general_node);
					utl_xml_get_int ("hide_calendar", &config.hide_calendar, general_node);
					utl_xml_get_int ("hide_tasks", &config.hide_tasks, general_node);
					utl_xml_get_int ("hide_contacts", &config.hide_contacts, general_node);
					utl_xml_get_int ("hide_notes", &config.hide_notes, general_node);
					utl_xml_get_int ("override_locale_settings", &config.override_locale_settings, general_node);
					utl_xml_get_int ("gui_layout", &config.gui_layout, general_node);
					utl_xml_get_int ("sound_alarm_repeat", &config.sound_alarm_repeat, general_node);
					utl_xml_get_strn ("spell_lang", config.spell_lang, MAXNAME, general_node);
					utl_xml_get_strn ("web_browser", config.web_browser, MAXHELPERCMD, general_node);
					utl_xml_get_strn ("email_client", config.email_client, MAXHELPERCMD, general_node);
					utl_xml_get_strn ("sound_player", config.sound_player, MAXHELPERCMD, general_node);

					general_node = general_node->next;
				}

			}

			/*---------------------------------------------------------------------------------------*/
			/* calendar */

			if ((!xmlStrcmp (node->name, (const xmlChar *) "calendar"))) {
				calendar_node = node->xmlChildrenNode;

				while (calendar_node != NULL) {
					utl_xml_get_int ("fy_window_size_x", &config.fy_window_size_x, calendar_node);
					utl_xml_get_int ("fy_window_size_y", &config.fy_window_size_y, calendar_node);
					utl_xml_get_int ("fy_simple_view", &config.fy_simple_view, calendar_node);
					utl_xml_get_int ("fy_alternative_view", &config.fy_alternative_view, calendar_node);
					utl_xml_get_int ("cb_window_size_x", &config.cb_window_size_x, calendar_node);
					utl_xml_get_int ("cb_window_size_y", &config.cb_window_size_y, calendar_node);
					utl_xml_get_int ("ib_window_size_x", &config.ib_window_size_x, calendar_node);
					utl_xml_get_int ("ib_window_size_y", &config.ib_window_size_y, calendar_node);
					utl_xml_get_int ("display_options", &config.display_options, calendar_node);
					utl_xml_get_int ("day_notes_visible", &config.day_notes_visible, calendar_node);
					utl_xml_get_int ("timeline_start", &config.timeline_start, calendar_node);
					utl_xml_get_int ("timeline_end", &config.timeline_end, calendar_node);
					utl_xml_get_int ("timeline_step", &config.timeline_step, calendar_node);
					utl_xml_get_int ("di_show_current_time", &config.di_show_current_time, calendar_node);
					utl_xml_get_int ("di_show_current_time_seconds", &config.di_show_current_time_seconds, calendar_node);
					utl_xml_get_int ("di_show_day_number", &config.di_show_day_number, calendar_node);
					utl_xml_get_int ("di_show_current_day_distance", &config.di_show_current_day_distance, calendar_node);
					utl_xml_get_int ("di_show_marked_days", &config.di_show_marked_days, calendar_node);
					utl_xml_get_int ("di_show_week_number", &config.di_show_week_number, calendar_node);
					utl_xml_get_int ("di_show_weekend_days", &config.di_show_weekend_days, calendar_node);
					utl_xml_get_int ("di_show_day_category", &config.di_show_day_category, calendar_node);
					utl_xml_get_int ("di_show_moon_phase", &config.di_show_moon_phase, calendar_node);
					utl_xml_get_int ("di_show_notes", &config.di_show_notes, calendar_node);
					utl_xml_get_int ("di_show_zodiac_sign", &config.di_show_zodiac_sign, calendar_node);
					utl_xml_get_int ("cursor_type", &config.cursor_type, calendar_node);
					utl_xml_get_int ("frame_cursor_thickness", &config.frame_cursor_thickness, calendar_node);
					utl_xml_get_int ("enable_auxiliary_calendars", &config.enable_auxiliary_calendars, calendar_node);
					utl_xml_get_int ("enable_day_mark", &config.enable_day_mark, calendar_node);
					utl_xml_get_int ("strikethrough_past_notes", &config.strikethrough_past_notes, calendar_node);
					utl_xml_get_int ("ascending_sorting_in_day_notes_browser", &config.ascending_sorting_in_day_notes_browser, calendar_node);
					utl_xml_get_int ("auxiliary_calendars_state", &config.auxiliary_calendars_state, calendar_node);
					utl_xml_get_int ("day_note_spell_checker", &config.day_note_spell_checker, calendar_node);
					utl_xml_get_strn ("day_note_marker", config.day_note_marker, MAXNAME, calendar_node);
					utl_xml_get_strn ("date_header_format", config.date_header_format, MAXNAME, calendar_node);
					utl_xml_get_int ("event_marker_type", &config.event_marker_type, calendar_node);
					utl_xml_get_int ("today_marker_type", &config.today_marker_type, calendar_node);
					utl_xml_get_int ("day_notes_browser_filter", &config.day_notes_browser_filter, calendar_node);
					utl_xml_get_int ("ical_export_pane_pos", &config.ical_export_pane_pos, calendar_node);
					utl_xml_get_strn ("background_color", config.background_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("header_bg_color", config.header_bg_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("header_fg_color", config.header_fg_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("day_color", config.day_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("pf_day_color", config.pf_day_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("weekend_color", config.weekend_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("selection_color", config.selection_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("mark_color", config.mark_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_strn ("mark_current_day_color", config.mark_current_day_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_int ("mark_current_day_alpha", &config.mark_current_day_alpha, calendar_node);
					utl_xml_get_strn ("birthday_mark_color", config.birthday_mark_color, MAXCOLORNAME, calendar_node);
					utl_xml_get_int ("selector_alpha", &config.selector_alpha, calendar_node);
					utl_xml_get_strn ("day_name_font", config.day_name_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("calendar_font", config.calendar_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("notes_font", config.notes_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("cal_print_month_name_font", config.cal_print_month_name_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("cal_print_day_name_font", config.cal_print_day_name_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("cal_print_day_num_font", config.cal_print_day_num_font, MAXFONTNAME, calendar_node);
					utl_xml_get_strn ("cal_print_event_font", config.cal_print_event_font, MAXFONTNAME, calendar_node);
					utl_xml_get_int ("cal_print_event_length", &config.cal_print_event_length, calendar_node);
					utl_xml_get_int ("cal_print_padding", &config.cal_print_padding, calendar_node);
					utl_xml_get_int ("cal_print_page_orientation", &config.cal_print_page_orientation, calendar_node);
					utl_xml_get_int ("cal_print_tasks", &config.cal_print_tasks, calendar_node);
					utl_xml_get_int ("cal_print_birthdays", &config.cal_print_birthdays, calendar_node);
					utl_xml_get_int ("cal_print_namedays", &config.cal_print_namedays, calendar_node);
					utl_xml_get_int ("cal_print_day_notes", &config.cal_print_day_notes, calendar_node);
					utl_xml_get_int ("cal_print_ical", &config.cal_print_ical, calendar_node);
					utl_xml_get_int ("cal_print_disable_background", &config.cal_print_disable_background, calendar_node);

                                        // TODO backward compatibility with Osmo 0.4.4 or older
					utl_xml_get_int("enable_auxilary_calendars", &config.enable_auxiliary_calendars, calendar_node);
					utl_xml_get_int("auxilary_calendars_state", &config.auxiliary_calendars_state, calendar_node);

					calendar_node = calendar_node->next;
				}
			}

			/*---------------------------------------------------------------------------------------*/
			/* tasks */

			if ((!xmlStrcmp (node->name, (const xmlChar *) "tasks"))) {
				tasks_node = node->xmlChildrenNode;

				while (tasks_node != NULL) {
					utl_xml_get_int ("high_priority_in_bold", &config.tasks_high_in_bold, tasks_node);
					utl_xml_get_int ("hide_completed", &config.hide_completed, tasks_node);
					utl_xml_get_int ("delete_completed", &config.delete_completed, tasks_node);
					utl_xml_get_int ("add_edit", &config.add_edit, tasks_node);
					utl_xml_get_int ("remember_category", &config.remember_category_in_tasks, tasks_node);
					utl_xml_get_int ("current_category", &config.current_category_in_tasks, tasks_node);
					utl_xml_get_int ("pane_pos", &config.tasks_pane_pos, tasks_node);
					utl_xml_get_int ("tasks_sorting_order", &config.tasks_sorting_order, tasks_node);
					utl_xml_get_int ("tasks_sorting_column", &config.tasks_sorting_column, tasks_node);
					utl_xml_get_int ("visible_due_date_column", &config.tsk_visible_due_date_column, tasks_node);
					utl_xml_get_int ("visible_type_column", &config.tsk_visible_type_column, tasks_node);
					utl_xml_get_int ("visible_priority_column", &config.tsk_visible_priority_column, tasks_node);
					utl_xml_get_int ("visible_category_column", &config.tsk_visible_category_column, tasks_node);
					utl_xml_get_int ("tasks_addedit_win_x", &config.tasks_addedit_win_x, tasks_node);
					utl_xml_get_int ("tasks_addedit_win_y", &config.tasks_addedit_win_y, tasks_node);
					utl_xml_get_int ("tasks_addedit_win_w", &config.tasks_addedit_win_w, tasks_node);
					utl_xml_get_int ("tasks_addedit_win_h", &config.tasks_addedit_win_h, tasks_node);
					utl_xml_get_int ("postpone_time", &config.postpone_time, tasks_node);
					utl_xml_get_int ("column_idx_0", &config.tasks_column_idx_0, tasks_node);
					utl_xml_get_int ("column_idx_0_width", &config.tasks_column_idx_0_width, tasks_node);
					utl_xml_get_int ("column_idx_1", &config.tasks_column_idx_1, tasks_node);
					utl_xml_get_int ("column_idx_1_width", &config.tasks_column_idx_1_width, tasks_node);
					utl_xml_get_int ("column_idx_2", &config.tasks_column_idx_2, tasks_node);
					utl_xml_get_int ("column_idx_2_width", &config.tasks_column_idx_2_width, tasks_node);
					utl_xml_get_int ("column_idx_3", &config.tasks_column_idx_3, tasks_node);
					utl_xml_get_int ("column_idx_3_width", &config.tasks_column_idx_3_width, tasks_node);
					utl_xml_get_int ("column_idx_4", &config.tasks_column_idx_4, tasks_node);
					utl_xml_get_int ("column_idx_4_width", &config.tasks_column_idx_4_width, tasks_node);
					utl_xml_get_int ("column_idx_5", &config.tasks_column_idx_5, tasks_node);
					utl_xml_get_int ("column_idx_5_width", &config.tasks_column_idx_5_width, tasks_node);
					utl_xml_get_strn ("due_today_color", config.due_today_color, MAXCOLORNAME, tasks_node);
					utl_xml_get_strn ("due_7days_color", config.due_7days_color, MAXCOLORNAME, tasks_node);
					utl_xml_get_strn ("past_due_color", config.past_due_color, MAXCOLORNAME, tasks_node);
					utl_xml_get_strn ("task_info_font", config.task_info_font, MAXFONTNAME, tasks_node);
					utl_xml_get_strn ("global_notification_command", config.global_notification_command, MAXHELPERCMD, tasks_node);

					tasks_node = tasks_node->next;
				}
			}

			/*---------------------------------------------------------------------------------------*/
			/* contacts */

			if ((!xmlStrcmp (node->name, (const xmlChar *) "contacts"))) {
				contacts_node = node->xmlChildrenNode;

				while (contacts_node != NULL) {
					gint i;
					utl_xml_get_int ("find_mode", &config.find_mode, contacts_node);
					utl_xml_get_int ("maps_provider", &config.maps_provider, contacts_node);
					utl_xml_get_int ("pane_pos", &config.contacts_pane_pos, contacts_node);
					utl_xml_get_int ("photo_width", &config.photo_width, contacts_node);
					utl_xml_get_int ("visible_age_column", &config.cnt_visible_age_column, contacts_node);
					utl_xml_get_int ("visible_birthday_date_column", &config.cnt_visible_birthday_date_column, contacts_node);
					utl_xml_get_int ("visible_zodiac_sign_column", &config.cnt_visible_zodiac_sign_column, contacts_node);
                                        utl_xml_get_strn ("visible_columns", config.contacts_visible_columns, CONTACTS_NUM_COLUMNS, contacts_node);
                                        for (i = 0; i < CONTACTS_NUM_COLUMNS; i++) {
                                            gchar *position_element, *width_element;
                                            position_element = g_strdup_printf("visible_column_%d_position", i);
                                            width_element = g_strdup_printf("visible_column_%d_width", i);
                                            utl_xml_get_int(position_element, &config.contacts_column_positions[i], contacts_node);
                                            utl_xml_get_int(width_element, &config.contacts_column_widths[i], contacts_node);
                                            g_free(position_element);
                                            g_free(width_element);
                                        }
					utl_xml_get_strn ("contact_tag_color", config.contact_tag_color, MAXCOLORNAME, contacts_node);
					utl_xml_get_strn ("contact_link_color", config.contact_link_color, MAXCOLORNAME, contacts_node);
					utl_xml_get_int ("contact_name_font_size", &config.contact_name_font_size, contacts_node);
					utl_xml_get_int ("contact_item_font_size", &config.contact_item_font_size, contacts_node);
					utl_xml_get_int ("export_format", &config.export_format, contacts_node);
					utl_xml_get_strn ("export_fields", config.export_fields, MAXCONTACTFIELDS, contacts_node);
					utl_xml_get_int ("contacts_sorting_order", &config.contacts_sorting_order, contacts_node);
					utl_xml_get_int ("contacts_sorting_column", &config.contacts_sorting_column, contacts_node);
					utl_xml_get_int ("contacts_addedit_win_x", &config.contacts_addedit_win_x, contacts_node);
					utl_xml_get_int ("contacts_addedit_win_y", &config.contacts_addedit_win_y, contacts_node);
					utl_xml_get_int ("contacts_addedit_win_w", &config.contacts_addedit_win_w, contacts_node);
					utl_xml_get_int ("contacts_addedit_win_h", &config.contacts_addedit_win_h, contacts_node);
					utl_xml_get_int ("contacts_export_win_x", &config.contacts_export_win_x, contacts_node);
					utl_xml_get_int ("contacts_export_win_y", &config.contacts_export_win_y, contacts_node);
					utl_xml_get_int ("contacts_export_win_w", &config.contacts_export_win_w, contacts_node);
					utl_xml_get_int ("contacts_export_win_h", &config.contacts_export_win_h, contacts_node);
					utl_xml_get_int ("contacts_import_sel_win_x", &config.contacts_import_sel_win_x, contacts_node);
					utl_xml_get_int ("contacts_import_sel_win_y", &config.contacts_import_sel_win_y, contacts_node);
					utl_xml_get_int ("contacts_import_win_x", &config.contacts_import_win_x, contacts_node);
					utl_xml_get_int ("contacts_import_win_y", &config.contacts_import_win_y, contacts_node);
					utl_xml_get_int ("contacts_import_win_w", &config.contacts_import_win_w, contacts_node);
					utl_xml_get_int ("contacts_import_win_h", &config.contacts_import_win_h, contacts_node);
					utl_xml_get_int ("contacts_birthdays_win_w", &config.contacts_birthdays_win_w, contacts_node);
					utl_xml_get_int ("contacts_birthdays_win_h", &config.contacts_birthdays_win_h, contacts_node);
					utl_xml_get_int ("import_type", &config.import_type, contacts_node);
					utl_xml_get_int ("import_interface_type", &config.import_interface_type, contacts_node);
					utl_xml_get_int ("import_bluetooth_channel", &config.import_bluetooth_channel, contacts_node);
					utl_xml_get_int ("import_usb_interface", &config.import_usb_interface, contacts_node);
					utl_xml_get_int ("import_binary_xml", &config.import_binary_xml, contacts_node);
					utl_xml_get_strn ("import_bluetooth_address", config.import_bluetooth_address, MAXADDRESS, contacts_node);

					contacts_node = contacts_node->next;
				}
			}

			/*---------------------------------------------------------------------------------------*/
			/* notes */

			if ((!xmlStrcmp (node->name, (const xmlChar *) "notes"))) {
				notes_node = node->xmlChildrenNode;

				while (notes_node != NULL) {
					utl_xml_get_int ("enc_algorithm", &config.notes_enc_algorithm, notes_node);
					utl_xml_get_int ("enc_hashing", &config.notes_enc_hashing, notes_node);
					utl_xml_get_int ("comp_algorithm", &config.notes_comp_algorithm, notes_node);
					utl_xml_get_int ("comp_ratio", &config.notes_comp_ratio, notes_node);
					utl_xml_get_int ("sorting_order", &config.notes_sorting_order, notes_node);
					utl_xml_get_int ("sorting_column", &config.notes_sorting_column, notes_node);
					utl_xml_get_int ("visible_type_column", &config.nte_visible_type_column, notes_node);
					utl_xml_get_int ("visible_category_column", &config.nte_visible_category_column, notes_node);
					utl_xml_get_int ("visible_last_changes_column", &config.nte_visible_last_changes_column, notes_node);
					utl_xml_get_int ("visible_created_column", &config.nte_visible_created_column, notes_node);
					utl_xml_get_int ("column_idx_0", &config.notes_column_idx_0, notes_node);
					utl_xml_get_int ("column_idx_0_width", &config.notes_column_idx_0_width, notes_node);
					utl_xml_get_int ("column_idx_1", &config.notes_column_idx_1, notes_node);
					utl_xml_get_int ("column_idx_1_width", &config.notes_column_idx_1_width, notes_node);
					utl_xml_get_int ("column_idx_2", &config.notes_column_idx_2, notes_node);
					utl_xml_get_int ("column_idx_2_width", &config.notes_column_idx_2_width, notes_node);
					utl_xml_get_int ("column_idx_3", &config.notes_column_idx_3, notes_node);
					utl_xml_get_int ("column_idx_3_width", &config.notes_column_idx_3_width, notes_node);
					utl_xml_get_int ("column_idx_4", &config.notes_column_idx_4, notes_node);
					utl_xml_get_int ("column_idx_4_width", &config.notes_column_idx_4_width, notes_node);
					utl_xml_get_int ("remember_category", &config.remember_category_in_notes, notes_node);
					utl_xml_get_int ("current_category", &config.current_category_in_notes, notes_node);
					utl_xml_get_int ("use_system_date", &config.use_system_date_in_notes, notes_node);
					utl_xml_get_char ("text_separator", &config.text_separator, notes_node);
					utl_xml_get_strn ("editor_font", config.notes_editor_font, MAXFONTNAME, notes_node);

					notes_node = notes_node->next;
				}
				
				if (config.notes_comp_ratio == 0 /* GRG_LVL_NONE */) {      /* ignore 'None' option */
					config.notes_comp_ratio = 1 /* GRG_LVL_FAST */;
				}
			}

			/*---------------------------------------------------------------------------------------*/

			node = node->next;
		}

		xmlFreeDoc (doc);
	} else {
		prefs_set_default_values ();
		prefs_write_config (appGUI);
	}

}

/*------------------------------------------------------------------------------*/

void
prefs_write_config (GUI *appGUI)
{
xmlDocPtr doc;
xmlNodePtr node, general_node, calendar_node, tasks_node, contacts_node, notes_node;
gint i;

	doc = xmlNewDoc ((const xmlChar *) "1.0");
	node = xmlNewNode (NULL, (const xmlChar *) CONFIG_NAME);
	xmlDocSetRootElement (doc, node);

	/*---------------------------------------------------------------------------------------*/
	/* general */

	general_node = xmlNewNode (NULL, (const xmlChar *) "general");
	xmlAddChild (node, general_node);

	utl_xml_put_int ("window_x", config.window_x, general_node);
	utl_xml_put_int ("window_y", config.window_y, general_node);
	utl_xml_put_int ("window_size_x", config.window_size_x, general_node);
	utl_xml_put_int ("window_size_y", config.window_size_y, general_node);
	utl_xml_put_int ("fullscreen", config.fullscreen, general_node);
	utl_xml_put_int ("enable_tooltips", config.enable_tooltips, general_node);
	utl_xml_put_int ("latest_tab", config.latest_tab, general_node);
	utl_xml_put_int ("tabs_position", config.tabs_position, general_node);
	utl_xml_put_int ("remember_latest_tab", config.remember_latest_tab, general_node);
	utl_xml_put_int ("save_data_after_modification", config.save_data_after_modification, general_node);
	utl_xml_put_int ("disable_underline_links", config.disable_underline_links, general_node);
	utl_xml_put_int ("toolbar_exit_button", config.toolbar_exit_button, general_node);
	utl_xml_put_int ("date_format", config.date_format, general_node);
	utl_xml_put_int ("time_format", config.time_format, general_node);
	utl_xml_put_int ("enable_systray", config.enable_systray, general_node);
	utl_xml_put_int ("start_minimised_in_systray", config.start_minimised_in_systray, general_node);
	utl_xml_put_int ("ignore_day_note_events", config.ignore_day_note_events, general_node);
	utl_xml_put_int ("run_counter", config.run_counter, general_node);
	utl_xml_put_int ("lastrun_date", config.lastrun_date, general_node);
	utl_xml_put_int ("lastrun_time", config.lastrun_time, general_node);
	utl_xml_put_int ("hide_calendar", config.hide_calendar, general_node);
	utl_xml_put_int ("hide_tasks", config.hide_tasks, general_node);
	utl_xml_put_int ("hide_contacts", config.hide_contacts, general_node);
	utl_xml_put_int ("hide_notes", config.hide_notes, general_node);
	utl_xml_put_int ("override_locale_settings", config.override_locale_settings, general_node);
	utl_xml_put_int ("gui_layout", config.gui_layout, general_node);
	utl_xml_put_int ("sound_alarm_repeat", config.sound_alarm_repeat, general_node);
	utl_xml_put_strn ("spell_lang", config.spell_lang, MAXNAME, general_node);
	utl_xml_put_strn ("web_browser", config.web_browser, MAXHELPERCMD, general_node);
	utl_xml_put_strn ("email_client", config.email_client, MAXHELPERCMD, general_node);
	utl_xml_put_strn ("sound_player", config.sound_player, MAXHELPERCMD, general_node);

	/*---------------------------------------------------------------------------------------*/
	/* calendar */

	calendar_node = xmlNewNode (NULL, (const xmlChar *) "calendar");
	xmlAddChild (node, calendar_node);

	utl_xml_put_int ("fy_window_size_x", config.fy_window_size_x, calendar_node);
	utl_xml_put_int ("fy_window_size_y", config.fy_window_size_y, calendar_node);
	utl_xml_put_int ("fy_simple_view", config.fy_simple_view, calendar_node);
	utl_xml_put_int ("fy_alternative_view", config.fy_alternative_view, calendar_node);
	utl_xml_put_int ("cb_window_size_x", config.cb_window_size_x, calendar_node);
	utl_xml_put_int ("cb_window_size_y", config.cb_window_size_y, calendar_node);
	utl_xml_put_int ("ib_window_size_x", config.ib_window_size_x, calendar_node);
	utl_xml_put_int ("ib_window_size_y", config.ib_window_size_y, calendar_node);
	utl_xml_put_int ("display_options", config.display_options, calendar_node);
	utl_xml_put_int ("day_notes_visible", config.day_notes_visible, calendar_node);
	utl_xml_put_int ("timeline_start", config.timeline_start, calendar_node);
	utl_xml_put_int ("timeline_end", config.timeline_end, calendar_node);
	utl_xml_put_int ("timeline_step", config.timeline_step, calendar_node);
	utl_xml_put_int ("di_show_current_time", config.di_show_current_time, calendar_node);
	utl_xml_put_int ("di_show_current_time_seconds", config.di_show_current_time_seconds, calendar_node);
	utl_xml_put_int ("di_show_day_number", config.di_show_day_number, calendar_node);
	utl_xml_put_int ("di_show_current_day_distance", config.di_show_current_day_distance, calendar_node);
	utl_xml_put_int ("di_show_marked_days", config.di_show_marked_days, calendar_node);
	utl_xml_put_int ("di_show_week_number", config.di_show_week_number, calendar_node);
	utl_xml_put_int ("di_show_weekend_days", config.di_show_weekend_days, calendar_node);
	utl_xml_put_int ("di_show_day_category", config.di_show_day_category, calendar_node);
	utl_xml_put_int ("di_show_moon_phase", config.di_show_moon_phase, calendar_node);
	utl_xml_put_int ("di_show_notes", config.di_show_notes, calendar_node);
	utl_xml_put_int ("di_show_zodiac_sign", config.di_show_zodiac_sign, calendar_node);
	utl_xml_put_int ("cursor_type", config.cursor_type, calendar_node);
	utl_xml_put_int ("frame_cursor_thickness", config.frame_cursor_thickness, calendar_node);
	utl_xml_put_int ("enable_auxiliary_calendars", config.enable_auxiliary_calendars, calendar_node);
	utl_xml_put_int ("enable_day_mark", config.enable_day_mark, calendar_node);
	utl_xml_put_int ("strikethrough_past_notes", config.strikethrough_past_notes, calendar_node);
	utl_xml_put_int ("ascending_sorting_in_day_notes_browser", config.ascending_sorting_in_day_notes_browser, calendar_node);
	utl_xml_put_int ("auxiliary_calendars_state", config.auxiliary_calendars_state, calendar_node);
	utl_xml_put_int ("day_note_spell_checker", config.day_note_spell_checker, calendar_node);
	utl_xml_put_strn ("day_note_marker", config.day_note_marker, MAXNAME, calendar_node);
	utl_xml_put_strn ("date_header_format", config.date_header_format, MAXNAME, calendar_node);
	utl_xml_put_int ("event_marker_type", config.event_marker_type, calendar_node);
	utl_xml_put_int ("today_marker_type", config.today_marker_type, calendar_node);
	utl_xml_put_int ("day_notes_browser_filter", config.day_notes_browser_filter, calendar_node);
	utl_xml_put_int ("ical_export_pane_pos", config.ical_export_pane_pos, calendar_node);
	utl_xml_put_strn ("background_color", config.background_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("header_bg_color", config.header_bg_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("header_fg_color", config.header_fg_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("day_color", config.day_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("pf_day_color", config.pf_day_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("weekend_color", config.weekend_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("selection_color", config.selection_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("mark_color", config.mark_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_strn ("mark_current_day_color", config.mark_current_day_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_int ("mark_current_day_alpha", config.mark_current_day_alpha, calendar_node);
	utl_xml_put_strn ("birthday_mark_color", config.birthday_mark_color, MAXCOLORNAME, calendar_node);
	utl_xml_put_int ("selector_alpha", config.selector_alpha, calendar_node);
	utl_xml_put_strn ("day_name_font", config.day_name_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("calendar_font", config.calendar_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("notes_font", config.notes_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("cal_print_month_name_font", config.cal_print_month_name_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("cal_print_day_name_font", config.cal_print_day_name_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("cal_print_day_num_font", config.cal_print_day_num_font, MAXFONTNAME, calendar_node);
	utl_xml_put_strn ("cal_print_event_font", config.cal_print_event_font, MAXFONTNAME, calendar_node);
	utl_xml_put_int ("cal_print_event_length", config.cal_print_event_length, calendar_node);
	utl_xml_put_int ("cal_print_padding", config.cal_print_padding, calendar_node);
	utl_xml_put_int ("cal_print_page_orientation", config.cal_print_page_orientation, calendar_node);
	utl_xml_put_int ("cal_print_tasks", config.cal_print_tasks, calendar_node);
	utl_xml_put_int ("cal_print_birthdays", config.cal_print_birthdays, calendar_node);
	utl_xml_put_int ("cal_print_namedays", config.cal_print_namedays, calendar_node);
	utl_xml_put_int ("cal_print_day_notes", config.cal_print_day_notes, calendar_node);
	utl_xml_put_int ("cal_print_ical", config.cal_print_ical, calendar_node);
	utl_xml_put_int ("cal_print_disable_background", config.cal_print_disable_background, calendar_node);

	/*---------------------------------------------------------------------------------------*/
	/* tasks */

	tasks_node = xmlNewNode (NULL, (const xmlChar *) "tasks");
	xmlAddChild (node, tasks_node);

	utl_xml_put_int ("high_priority_in_bold", config.tasks_high_in_bold, tasks_node);
	utl_xml_put_int ("hide_completed", config.hide_completed, tasks_node);
	utl_xml_put_int ("delete_completed", config.delete_completed, tasks_node);
	utl_xml_put_int ("add_edit", config.add_edit, tasks_node);
	utl_xml_put_int ("remember_category", config.remember_category_in_tasks, tasks_node);
	utl_xml_put_int ("current_category", config.current_category_in_tasks, tasks_node);
	utl_xml_put_int ("pane_pos", config.tasks_pane_pos, tasks_node);
	utl_xml_put_int ("tasks_sorting_order", config.tasks_sorting_order, tasks_node);
	utl_xml_put_int ("tasks_sorting_column", config.tasks_sorting_column, tasks_node);
	utl_xml_put_int ("visible_due_date_column", config.tsk_visible_due_date_column, tasks_node);
	utl_xml_put_int ("visible_type_column", config.tsk_visible_type_column, tasks_node);
	utl_xml_put_int ("visible_priority_column", config.tsk_visible_priority_column, tasks_node);
	utl_xml_put_int ("visible_category_column", config.tsk_visible_category_column, tasks_node);
	utl_xml_put_int ("tasks_addedit_win_x", config.tasks_addedit_win_x, tasks_node);
	utl_xml_put_int ("tasks_addedit_win_y", config.tasks_addedit_win_y, tasks_node);
	utl_xml_put_int ("tasks_addedit_win_w", config.tasks_addedit_win_w, tasks_node);
	utl_xml_put_int ("tasks_addedit_win_h", config.tasks_addedit_win_h, tasks_node);
	utl_xml_put_int ("postpone_time", config.postpone_time, tasks_node);
	utl_xml_put_int ("column_idx_0", config.tasks_column_idx_0, tasks_node);
	utl_xml_put_int ("column_idx_0_width", config.tasks_column_idx_0_width, tasks_node);
	utl_xml_put_int ("column_idx_1", config.tasks_column_idx_1, tasks_node);
	utl_xml_put_int ("column_idx_1_width", config.tasks_column_idx_1_width, tasks_node);
	utl_xml_put_int ("column_idx_2", config.tasks_column_idx_2, tasks_node);
	utl_xml_put_int ("column_idx_2_width", config.tasks_column_idx_2_width, tasks_node);
	utl_xml_put_int ("column_idx_3", config.tasks_column_idx_3, tasks_node);
	utl_xml_put_int ("column_idx_3_width", config.tasks_column_idx_3_width, tasks_node);
	utl_xml_put_int ("column_idx_4", config.tasks_column_idx_4, tasks_node);
	utl_xml_put_int ("column_idx_4_width", config.tasks_column_idx_4_width, tasks_node);
	utl_xml_put_int ("column_idx_5", config.tasks_column_idx_5, tasks_node);
	utl_xml_put_int ("column_idx_5_width", config.tasks_column_idx_5_width, tasks_node);
	utl_xml_put_strn ("due_today_color", config.due_today_color, MAXCOLORNAME, tasks_node);
	utl_xml_put_strn ("due_7days_color", config.due_7days_color, MAXCOLORNAME, tasks_node);
	utl_xml_put_strn ("past_due_color", config.past_due_color, MAXCOLORNAME, tasks_node);
	utl_xml_put_strn ("task_info_font", config.task_info_font, MAXFONTNAME, tasks_node);
	utl_xml_put_strn ("global_notification_command", config.global_notification_command, MAXHELPERCMD, tasks_node);

	/*---------------------------------------------------------------------------------------*/
	/* contacts */

	contacts_node = xmlNewNode (NULL, (const xmlChar *) "contacts");
	xmlAddChild (node, contacts_node);

	utl_xml_put_int ("find_mode", config.find_mode, contacts_node);
	utl_xml_put_int ("maps_provider", config.maps_provider, contacts_node);
	utl_xml_put_int ("pane_pos", config.contacts_pane_pos, contacts_node);
	utl_xml_put_int ("photo_width", config.photo_width, contacts_node);
	utl_xml_put_int ("visible_age_column", config.cnt_visible_age_column, contacts_node);
	utl_xml_put_int ("visible_birthday_date_column", config.cnt_visible_birthday_date_column, contacts_node);
	utl_xml_put_int ("visible_zodiac_sign_column", config.cnt_visible_zodiac_sign_column, contacts_node);
	utl_xml_put_strn ("visible_columns", config.contacts_visible_columns, CONTACTS_NUM_COLUMNS, contacts_node);
        for (i = 0; i < CONTACTS_NUM_COLUMNS; i++) {
            if (config.contacts_visible_columns[i] == '+') {
                gchar *position_element, *width_element;
                position_element = g_strdup_printf("visible_column_%d_position", i);
                width_element = g_strdup_printf("visible_column_%d_width", i);
                utl_xml_put_int (position_element, config.contacts_column_positions[i], contacts_node);
                utl_xml_put_int (width_element, config.contacts_column_widths[i], contacts_node);
                g_free(position_element);
                g_free(width_element);
            }
        }
	utl_xml_put_strn ("contact_tag_color", config.contact_tag_color, MAXCOLORNAME, contacts_node);
	utl_xml_put_strn ("contact_link_color", config.contact_link_color, MAXCOLORNAME, contacts_node);
	utl_xml_put_int ("contact_name_font_size", config.contact_name_font_size, contacts_node);
	utl_xml_put_int ("contact_item_font_size", config.contact_item_font_size, contacts_node);
	utl_xml_put_int ("export_format", config.export_format, contacts_node);
	utl_xml_put_strn ("export_fields", config.export_fields, MAXCONTACTFIELDS, contacts_node);
	utl_xml_put_int ("contacts_sorting_order", config.contacts_sorting_order, contacts_node);
	utl_xml_put_int ("contacts_sorting_column", config.contacts_sorting_column, contacts_node);
	utl_xml_put_int ("contacts_addedit_win_x", config.contacts_addedit_win_x, contacts_node);
	utl_xml_put_int ("contacts_addedit_win_y", config.contacts_addedit_win_y, contacts_node);
	utl_xml_put_int ("contacts_addedit_win_w", config.contacts_addedit_win_w, contacts_node);
	utl_xml_put_int ("contacts_addedit_win_h", config.contacts_addedit_win_h, contacts_node);
	utl_xml_put_int ("contacts_export_win_x", config.contacts_export_win_x, contacts_node);
	utl_xml_put_int ("contacts_export_win_y", config.contacts_export_win_y, contacts_node);
	utl_xml_put_int ("contacts_export_win_w", config.contacts_export_win_w, contacts_node);
	utl_xml_put_int ("contacts_export_win_h", config.contacts_export_win_h, contacts_node);
	utl_xml_put_int ("contacts_import_sel_win_x", config.contacts_import_sel_win_x, contacts_node);
	utl_xml_put_int ("contacts_import_sel_win_y", config.contacts_import_sel_win_y, contacts_node);
	utl_xml_put_int ("contacts_import_win_x", config.contacts_import_win_x, contacts_node);
	utl_xml_put_int ("contacts_import_win_y", config.contacts_import_win_y, contacts_node);
	utl_xml_put_int ("contacts_import_win_w", config.contacts_import_win_w, contacts_node);
	utl_xml_put_int ("contacts_import_win_h", config.contacts_import_win_h, contacts_node);
	utl_xml_put_int ("contacts_birthdays_win_w", config.contacts_birthdays_win_w, contacts_node);
	utl_xml_put_int ("contacts_birthdays_win_h", config.contacts_birthdays_win_h, contacts_node);
	utl_xml_put_int ("import_type", config.import_type, contacts_node);
	utl_xml_put_int ("import_interface_type", config.import_interface_type, contacts_node);
	utl_xml_put_int ("import_bluetooth_channel", config.import_bluetooth_channel, contacts_node);
	utl_xml_put_int ("import_usb_interface", config.import_usb_interface, contacts_node);
	utl_xml_put_int ("import_binary_xml", config.import_binary_xml, contacts_node);
	utl_xml_put_strn ("import_bluetooth_address", config.import_bluetooth_address, MAXADDRESS, contacts_node);

	/*---------------------------------------------------------------------------------------*/
	/* notes */

	notes_node = xmlNewNode (NULL, (const xmlChar *) "notes");
	xmlAddChild (node, notes_node);

	utl_xml_put_int ("enc_algorithm", config.notes_enc_algorithm, notes_node);
	utl_xml_put_int ("enc_hashing", config.notes_enc_hashing, notes_node);
	utl_xml_put_int ("comp_algorithm", config.notes_comp_algorithm, notes_node);
	utl_xml_put_int ("comp_ratio", config.notes_comp_ratio, notes_node);
	utl_xml_put_int ("sorting_order", config.notes_sorting_order, notes_node);
	utl_xml_put_int ("sorting_column", config.notes_sorting_column, notes_node);
	utl_xml_put_int ("visible_type_column", config.nte_visible_type_column, notes_node);
	utl_xml_put_int ("visible_category_column", config.nte_visible_category_column, notes_node);
	utl_xml_put_int ("visible_last_changes_column", config.nte_visible_last_changes_column, notes_node);
	utl_xml_put_int ("visible_created_column", config.nte_visible_created_column, notes_node);
	utl_xml_put_int ("column_idx_0", config.notes_column_idx_0, notes_node);
	utl_xml_put_int ("column_idx_0_width", config.notes_column_idx_0_width, notes_node);
	utl_xml_put_int ("column_idx_1", config.notes_column_idx_1, notes_node);
	utl_xml_put_int ("column_idx_1_width", config.notes_column_idx_1_width, notes_node);
	utl_xml_put_int ("column_idx_2", config.notes_column_idx_2, notes_node);
	utl_xml_put_int ("column_idx_2_width", config.notes_column_idx_2_width, notes_node);
	utl_xml_put_int ("column_idx_3", config.notes_column_idx_3, notes_node);
	utl_xml_put_int ("column_idx_3_width", config.notes_column_idx_3_width, notes_node);
	utl_xml_put_int ("column_idx_4", config.notes_column_idx_4, notes_node);
	utl_xml_put_int ("column_idx_4_width", config.notes_column_idx_4_width, notes_node);
	utl_xml_put_int ("remember_category", config.remember_category_in_notes, notes_node);
	utl_xml_put_int ("current_category", config.current_category_in_notes, notes_node);
	utl_xml_put_int ("use_system_date", config.use_system_date_in_notes, notes_node);
	utl_xml_put_char ("text_separator", config.text_separator, notes_node);
	utl_xml_put_strn ("editor_font", config.notes_editor_font, MAXFONTNAME, notes_node);

	/*---------------------------------------------------------------------------------------*/

	utl_xml_write_doc (prefs_get_config_filename (CONFIG_FILENAME, appGUI), doc);
	xmlFreeDoc (doc);
}
/*------------------------------------------------------------------------------*/
static int
copy(gchar *source, gchar *target) {
    int source_fd, target_fd;
    ssize_t len;
    gchar buff[8192];
    struct stat st;
    mode_t perm;

    if (stat(source, &st)) {
        return -1;
    }
    perm = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
    source_fd = open(source, O_RDONLY);
    if (source_fd == -1) {
        return -1;
    }
    g_remove(target);
    target_fd = open(target, O_WRONLY | O_CREAT | O_EXCL, perm);
    if (target_fd == -1) {
        close(source_fd);
        return -1;
    }

    len = read(source_fd, buff, sizeof (buff));
    while (len > 0) {
        write(target_fd, buff, len);
        len = read(source_fd, buff, sizeof (buff));
    }
    close(source_fd);
    close(target_fd);

    return 0;
}

static gboolean
restore_from_dir(gchar *source_dirname, gchar *target_name, GUI *appGUI) {
    GDir *source_dir = g_dir_open(source_dirname, 0, NULL);
    if (source_dir) {
        const gchar *old_name = g_dir_read_name(source_dir);
        for (; old_name; old_name = g_dir_read_name(source_dir)) {
            gchar *old_fullname = g_build_filename(source_dirname, old_name, NULL);

            if (g_file_test(old_fullname, G_FILE_TEST_IS_REGULAR)) {
                gchar *new_name = g_build_filename(target_name, old_name, NULL);
                gboolean is_config = utl_text_strcmp(CONFIG_FILENAME, new_name) == 0;
                gchar *new_fullname = is_config ? prefs_get_config_filename(new_name, appGUI) : prefs_get_data_filename(new_name, appGUI);
                int rc = copy(old_fullname, new_fullname);
                g_free(new_name);
                if (rc == -1) {
                    g_warning("Failed to move the old file %s to the new location %s. Aborting migration.", old_fullname, new_fullname);
                    g_free(old_fullname);
                    return FALSE;
                }
            } else if (g_file_test(old_fullname, G_FILE_TEST_IS_DIR)) {
                gchar *new_target_name = g_build_filename(target_name, old_name, NULL);
                gboolean rc = restore_from_dir(old_fullname, new_target_name, appGUI);
                g_free(new_target_name);
                if (rc == FALSE) {
                    return FALSE;
                }
            } else {
                g_warning("Do not know how to handle entry %s. Aborting migration.", old_fullname);
                g_free(old_fullname);
                return FALSE;
            }

            g_free(old_fullname);
        }

        g_dir_close(source_dir);
    }
    return TRUE;
}

gboolean
prefs_restore (gchar *source_dir, GUI *appGUI) {
    return restore_from_dir(source_dir, "", appGUI);
}
/*------------------------------------------------------------------------------*/


