
/*
 * Osmo - a handy personal organizer
 *
 * Copyright (C) 2007-2014 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 "notes_items.h"
#include "i18n.h"
#include "options_prefs.h"
#include "notes.h"
#include "notes_preferences_gui.h"
#include "calendar.h"
#include "calendar_notes.h"
#include "calendar_widget.h"
#include "calendar_utils.h"
#include "utils.h"
#include "utils_gui.h"
#include "utils_date.h"
#include "stock_icons.h"

#ifdef NOTES_ENABLED

#ifdef HAVE_LIBGRINGOTTS
#include <libgringotts.h>
#endif  /* HAVE_LIBGRINGOTTS */

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

gboolean
notes_get_active_state (GUI *appGUI) {

gint b, c;

    gint a = strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->note_name_entry)));
    if (appGUI->nte->encrypted == FALSE) {
        return a;
    }
    if (appGUI->nte->password_entry != NULL) {
        b = strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->password_entry)));
    } else {
        b = 1;
    }
    if (appGUI->nte->spassword_entry != NULL) {
        c = strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->spassword_entry)));
    } else {
        c = 1;
    }

    return (a && b && c);
}

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

void
notes_edit_close_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) {

    GUI *appGUI = (GUI *)user_data;

    appGUI->nte->password_entry = NULL;
    appGUI->nte->spassword_entry = NULL;

    gtk_widget_destroy(appGUI->nte->edit_entry_window);
}

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

void
button_notes_edit_close_cb (GtkWidget *widget, gpointer data) {

    notes_edit_close_cb (widget, NULL, data);
}

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

void
notes_edit_action_cb (GtkWidget *widget, gpointer data) {

GtkTreePath *path, *sort_path, *filter_path;
GtkTreeIter iter;
gchar *category;
gboolean remember_cursor;

    GUI *appGUI = (GUI *)data;

    gtk_tree_view_get_cursor (GTK_TREE_VIEW (appGUI->nte->notes_list), &sort_path, NULL);

    if (sort_path == NULL) return;
    filter_path = gtk_tree_model_sort_convert_path_to_child_path (GTK_TREE_MODEL_SORT(appGUI->nte->notes_sort), sort_path);
    gtk_tree_path_free (sort_path);

    if (filter_path == NULL) return;
    path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER(appGUI->nte->notes_filter), filter_path);
    gtk_tree_path_free (filter_path);

    if (path != NULL) {

        category = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(appGUI->nte->category_combobox));
        remember_cursor = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(appGUI->nte->remember_cursor_checkbutton));

        gtk_tree_model_get_iter (GTK_TREE_MODEL(appGUI->nte->notes_list_store), &iter, path);
        gtk_list_store_set(appGUI->nte->notes_list_store, &iter, 
                           N_COLUMN_NAME, gtk_entry_get_text(GTK_ENTRY(appGUI->nte->note_name_entry)), 
                           N_COLUMN_CATEGORY, category, N_COLUMN_REMEMBER_EDITOR_LINE, remember_cursor, -1);

        g_free (category);
        gtk_tree_path_free (path);

        notes_edit_close_cb (widget, NULL, data);

        if (config.save_data_after_modification) {
            write_notes_entries (appGUI);
        }
    }

}

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

gint 
notes_edit_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data) {

    GUI *appGUI = (GUI *)data;

    if (event->keyval == GDK_KEY_Escape) {
            notes_edit_close_cb (NULL, NULL, appGUI);
            return TRUE;
    } else if (event->keyval == GDK_KEY_Return) {
            notes_edit_action_cb (NULL, appGUI);
            return TRUE;
    }
    return FALSE;
}

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

gint 
notes_add_entry_changed_cb (GtkEditable *editable, gpointer data) {

    GUI *appGUI = (GUI *)data;

    gtk_widget_set_sensitive(appGUI->nte->add_entry_ok_button, notes_get_active_state (appGUI));

    return FALSE;
}

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

void
notes_edit_dialog_show (GtkWidget *list, GtkTreeModel *model, GUI *appGUI)
{
	GtkWidget *vbox1;
	GtkWidget *hseparator;
	GtkWidget *hbuttonbox;
	GtkWidget *cancel_button;
	GtkWidget *label;
	GtkWidget *frame;
	GtkWidget *table;

	GtkTreeIter iter;
	gchar *category, *name;
	gchar tmpbuf[BUFFER_SIZE];
	gboolean remember_cursor;

	appGUI->nte->edit_entry_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_container_set_border_width (GTK_CONTAINER (appGUI->nte->edit_entry_window), 4);
	gtk_window_set_title (GTK_WINDOW (appGUI->nte->edit_entry_window), _("Edit entry"));
	gtk_window_set_default_size (GTK_WINDOW (appGUI->nte->edit_entry_window), 400, -1);
	if (config.fullscreen == FALSE) {
		gtk_window_set_transient_for (GTK_WINDOW (appGUI->nte->edit_entry_window), GTK_WINDOW (appGUI->main_window));
	}
	gtk_window_set_position (GTK_WINDOW (appGUI->nte->edit_entry_window), GTK_WIN_POS_CENTER_ON_PARENT);
	gtk_window_set_modal (GTK_WINDOW (appGUI->nte->edit_entry_window), TRUE);
	g_signal_connect (G_OBJECT (appGUI->nte->edit_entry_window), "delete_event",
	                  G_CALLBACK (notes_edit_close_cb), appGUI);
	g_signal_connect (G_OBJECT (appGUI->nte->edit_entry_window), "key_press_event",
	                  G_CALLBACK (notes_edit_key_press_cb), appGUI);

	vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
	gtk_container_add (GTK_CONTAINER (appGUI->nte->edit_entry_window), vbox1);

	table = gtk_grid_new ();
	gtk_box_pack_start (GTK_BOX (vbox1), table, FALSE, TRUE, 0);

	frame = gtk_frame_new (NULL);
        gtk_widget_set_hexpand(frame, TRUE);
        gtk_widget_set_vexpand(frame, TRUE);
	gtk_grid_attach (GTK_GRID (table), frame, 0, 0, 1, 1);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

	appGUI->nte->note_name_entry = gtk_entry_new ();
	gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->note_name_entry);
        gtk_widget_set_margin_left(appGUI->nte->note_name_entry, 16);
        gtk_widget_set_margin_right(appGUI->nte->note_name_entry, 4);
        gtk_widget_set_margin_top(appGUI->nte->note_name_entry, 4);
        gtk_widget_set_margin_bottom(appGUI->nte->note_name_entry, 4);
	gtk_entry_set_invisible_char (GTK_ENTRY (appGUI->nte->note_name_entry), 8226);
	g_signal_connect (G_OBJECT (appGUI->nte->note_name_entry), "changed",
	                  G_CALLBACK (notes_add_entry_changed_cb), appGUI);

	g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Note name"));
	label = gtk_label_new (tmpbuf);
	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

	frame = gtk_frame_new (NULL);
	gtk_grid_attach (GTK_GRID (table), frame, 1, 0, 1, 1);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

	appGUI->nte->category_combobox = gtk_combo_box_text_new ();
	gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->category_combobox);
        gtk_widget_set_margin_left(appGUI->nte->category_combobox, 16);
        gtk_widget_set_margin_right(appGUI->nte->category_combobox, 4);
        gtk_widget_set_margin_top(appGUI->nte->category_combobox, 4);
        gtk_widget_set_margin_bottom(appGUI->nte->category_combobox, 4);
	gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->nte->category_combobox), NULL, _("None"));

	g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Category"));
	label = gtk_label_new (tmpbuf);
	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

	frame = gtk_frame_new (NULL);
	gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

	appGUI->nte->remember_cursor_checkbutton = gtk_check_button_new_with_mnemonic (_("Remember cursor position"));
	gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->remember_cursor_checkbutton);
	gtk_widget_set_can_focus (appGUI->nte->remember_cursor_checkbutton, FALSE);
        gtk_widget_set_margin_left(appGUI->nte->remember_cursor_checkbutton, 16);
        gtk_widget_set_margin_right(appGUI->nte->remember_cursor_checkbutton, 4);
        gtk_widget_set_margin_top(appGUI->nte->remember_cursor_checkbutton, 4);
        gtk_widget_set_margin_bottom(appGUI->nte->remember_cursor_checkbutton, 4);

	g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Options"));
	label = gtk_label_new (tmpbuf);
	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

	hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
	gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, TRUE, 4);

	hbuttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
	gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox, FALSE, FALSE, 0);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
	gtk_box_set_spacing (GTK_BOX (hbuttonbox), 4);

	cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
	gtk_widget_set_can_focus (cancel_button, FALSE);
	gtk_container_add (GTK_CONTAINER (hbuttonbox), cancel_button);
	g_signal_connect (G_OBJECT (cancel_button), "clicked",
	                  G_CALLBACK (button_notes_edit_close_cb), appGUI);

	appGUI->nte->add_entry_ok_button = gtk_button_new_with_mnemonic (_("_OK"));
	gtk_widget_set_can_focus (appGUI->nte->add_entry_ok_button, FALSE);
	gtk_container_add (GTK_CONTAINER (hbuttonbox), appGUI->nte->add_entry_ok_button);
	g_signal_connect (G_OBJECT (appGUI->nte->add_entry_ok_button), "clicked",
	                  G_CALLBACK (notes_edit_action_cb), appGUI);

	iter = utl_gui_get_first_selection_iter(appGUI->nte->notes_list_selection, &model);
	gtk_tree_model_get(model, &iter,
                N_COLUMN_NAME, &name,
                N_COLUMN_CATEGORY, &category,
                N_COLUMN_REMEMBER_EDITOR_LINE, &remember_cursor,
                -1);

	gtk_entry_set_text(GTK_ENTRY(appGUI->nte->note_name_entry), name);
        
        utl_gui_create_category_combobox(GTK_COMBO_BOX(appGUI->nte->category_combobox),
            appGUI->opt->notes_category_store, TRUE);
            
	gtk_combo_box_set_active(GTK_COMBO_BOX(appGUI->nte->category_combobox), utl_gui_list_store_get_text_index(appGUI->opt->notes_category_store, category));

	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(appGUI->nte->remember_cursor_checkbutton), remember_cursor);

	g_free(category);
	g_free(name);
	gtk_widget_show_all(appGUI->nte->edit_entry_window);
}
/*------------------------------------------------------------------------------*/
void
notes_remove(GtkTreeRowReference *ref, GUI *appGUI) {
    GtkTreePath *path;
    GtkTreeIter iter, filter_iter, sort_iter;
    gchar *filename;
    GtkTreeModel *model;

    model = gtk_tree_row_reference_get_model(ref);
    path = gtk_tree_row_reference_get_path(ref);
    if (path != NULL) {
        if (gtk_tree_model_get_iter(model, &sort_iter, path)) {
            gtk_tree_model_get(model, &sort_iter, N_COLUMN_FILENAME, &filename, -1);
            g_unlink(notes_get_full_filename(filename, appGUI));
            g_free(filename);
            gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(model), &filter_iter, &sort_iter);
            gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model))), &iter, &filter_iter);
            gtk_list_store_remove(appGUI->nte->notes_list_store, &iter);
        }
        gtk_tree_path_free(path);
    }
}
/*------------------------------------------------------------------------------*/

void
notes_remove_dialog_show (GUI *appGUI) {
    gint response;
    gchar tmpbuf[BUFFER_SIZE];


    g_snprintf(tmpbuf, BUFFER_SIZE, "%s\n%s\n\n%s", _("Selected note will be removed."),
            _("No further data recovery will be possible."), _("Are you sure?"));

    response = utl_gui_create_dialog(GTK_MESSAGE_QUESTION, tmpbuf, GTK_WINDOW(appGUI->main_window));

    if (response == GTK_RESPONSE_YES) {
        utl_gui_foreach_selected(appGUI->nte->notes_list_selection, GTK_TREE_MODEL(appGUI->nte->notes_list_store),
                (GFunc) notes_remove, appGUI);
        update_notes_items(appGUI);
        check_notes_type(appGUI);

        if (config.save_data_after_modification) {
            write_notes_entries(appGUI);
        }
    }
}

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

void
notes_add_close_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) {

    GUI *appGUI = (GUI *)user_data;

#ifdef HAVE_LIBGRINGOTTS
    appGUI->nte->password_entry = NULL;
    appGUI->nte->spassword_entry = NULL;
#endif  /* HAVE_LIBGRINGOTTS */

    gtk_widget_destroy(appGUI->nte->add_entry_window);
}

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

void
button_notes_add_close_cb (GtkWidget *widget, gpointer data) {

    notes_add_close_cb (widget, NULL, data);
}

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

gint 
notes_add_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data) {

    GUI *appGUI = (GUI *)data;

    if (event->keyval == GDK_KEY_Escape) {
            notes_add_close_cb (NULL, NULL, appGUI);
            return TRUE;
    }
    return FALSE;
}

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

void
notes_add_entry_action_cb (GtkWidget *widget, gpointer data) {

gchar *name;
gchar *current_filename;
gchar *category, *create_date_str;
guint32 current_date;
GtkTreeIter iter;
gint current_time;
gboolean remember_cursor;

#ifdef HAVE_LIBGRINGOTTS
gchar *pass = NULL, *spass = NULL;
GRG_CTX context;
GRG_KEY keyholder;
#endif /* HAVE_LIBGRINGOTTS */

    GUI *appGUI = (GUI *)data;

#ifdef HAVE_LIBGRINGOTTS
	if (appGUI->nte->encrypted == TRUE) {
		pass = g_strdup(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->password_entry)));
		spass = g_strdup(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->spassword_entry)));

		if (g_utf8_collate (pass, spass) != 0) {
			utl_gui_create_dialog(GTK_MESSAGE_ERROR, _("Passwords do not match!"), GTK_WINDOW(appGUI->main_window));
			gtk_widget_grab_focus (appGUI->nte->password_entry);
			g_free(pass);
			g_free(spass);
			return;
		}
	}
#endif /* HAVE_LIBGRINGOTTS */

    name = g_strdup(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->note_name_entry)));
    category = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(appGUI->nte->category_combobox));
	remember_cursor = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(appGUI->nte->remember_cursor_checkbutton));

    notes_add_close_cb (NULL, NULL, appGUI);

    current_date = utl_date_get_current_julian ();
    current_time = utl_time_get_current_seconds ();
    current_filename = g_strdup (notes_get_new_filename (appGUI));

#ifdef HAVE_LIBGRINGOTTS
	if (appGUI->nte->encrypted == TRUE) {

		context = grg_context_initialize_defaults ((unsigned char*) "OSM");
		keyholder = grg_key_gen ((unsigned char*) pass, -1);

		grg_ctx_set_crypt_algo (context, get_enc_algorithm_value());
		grg_ctx_set_hash_algo (context, get_enc_hashing_value());
		grg_ctx_set_comp_algo (context, get_comp_algorithm_value());
		grg_ctx_set_comp_ratio (context, get_comp_ratio_value());

		grg_encrypt_file (context, keyholder,
		                  (unsigned char*) notes_get_full_filename (current_filename, appGUI),
		                  (guchar *)"", 0);

		grg_key_free (context, keyholder);
		grg_context_free (context);

	} else {

		g_file_set_contents (notes_get_full_filename(current_filename, appGUI), 
							 "", 0, NULL);
	}
#endif /* HAVE_LIBGRINGOTTS */
        create_date_str = g_strdup(get_date_time_str (current_date, current_time));

        gtk_list_store_append(appGUI->nte->notes_list_store, &iter);
        gtk_list_store_set(appGUI->nte->notes_list_store, &iter, 
                           N_COLUMN_NAME, name, 
                           N_COLUMN_CATEGORY, category, 
                           N_COLUMN_LAST_CHANGES_DATE, create_date_str,
                           N_COLUMN_LAST_CHANGES_DATE_JULIAN, current_date,
                           N_COLUMN_LAST_CHANGES_TIME, current_time,
                           N_COLUMN_CREATE_DATE, create_date_str,
                           N_COLUMN_CREATE_DATE_JULIAN, current_date,
                           N_COLUMN_CREATE_TIME, current_time,
                           N_COLUMN_REMEMBER_EDITOR_LINE, remember_cursor,
                           N_COLUMN_EDITOR_LINE, 0,
                           N_COLUMN_FILENAME, current_filename,
                           N_COLUMN_FONTNAME, DEFAULT_NOTE_FONT,
                           -1);
        g_free (category);
        g_free (create_date_str);

        update_notes_items(appGUI);
		check_notes_type (appGUI);

        if (config.save_data_after_modification) {
            write_notes_entries (appGUI);
        }

    g_free(current_filename);
    g_free(name);

#ifdef HAVE_LIBGRINGOTTS
	if (appGUI->nte->encrypted == TRUE) {
		g_free(pass);
		g_free(spass);
	}
#endif /* HAVE_LIBGRINGOTTS */

}

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

gint 
notes_add_ok_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data) {

    GUI *appGUI = (GUI *)data;

    if (event->keyval == GDK_KEY_Return && notes_get_active_state (appGUI) == TRUE) {
            notes_add_entry_action_cb (NULL, appGUI);
            return TRUE;
    }
    return FALSE;
}

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

void
note_type_cb (GtkWidget *widget, gpointer user_data) {

	GUI *appGUI = (GUI *) user_data;

	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (appGUI->nte->note_normal_radiobutton)) == TRUE) {
		appGUI->nte->encrypted = FALSE;
	} else {
		appGUI->nte->encrypted = TRUE;
	}

	gtk_widget_set_sensitive (appGUI->nte->password_entry, appGUI->nte->encrypted);
	gtk_widget_set_sensitive (appGUI->nte->spassword_entry, appGUI->nte->encrypted);
    gtk_widget_set_sensitive(appGUI->nte->add_entry_ok_button, notes_get_active_state (appGUI));
}

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

void
notes_add_entry (GUI *appGUI) {

GtkWidget *vbox1;
GtkWidget *hseparator;
GtkWidget *hbuttonbox;
GtkWidget *cancel_button;
GtkWidget *label;
GtkWidget *frame;
GtkWidget *table;

#ifdef HAVE_LIBGRINGOTTS
GtkWidget *hbox1;
GtkWidget *note_encrypted_radiobutton;
GSList *note_normal_radiobutton_group = NULL;
#endif  /* HAVE_LIBGRINGOTTS */

gchar tmpbuf[BUFFER_SIZE];
gboolean has_next;
gchar *category;
GtkTreeIter iter;

	appGUI->nte->encrypted = FALSE;     /* default mode */

    appGUI->nte->add_entry_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width (GTK_CONTAINER (appGUI->nte->add_entry_window), 4);
    gtk_window_set_title (GTK_WINDOW (appGUI->nte->add_entry_window), _("Add note"));
    gtk_window_set_default_size (GTK_WINDOW(appGUI->nte->add_entry_window), 450, -1);
	if (config.fullscreen == FALSE) {
        gtk_window_set_transient_for(GTK_WINDOW(appGUI->nte->add_entry_window), GTK_WINDOW(appGUI->main_window));
	}
    gtk_window_set_position(GTK_WINDOW(appGUI->nte->add_entry_window), GTK_WIN_POS_CENTER_ON_PARENT);
    gtk_window_set_modal(GTK_WINDOW(appGUI->nte->add_entry_window), TRUE);
    g_signal_connect (G_OBJECT (appGUI->nte->add_entry_window), "delete_event",
                      G_CALLBACK(notes_add_close_cb), appGUI);
    g_signal_connect (G_OBJECT (appGUI->nte->add_entry_window), "key_press_event",
                      G_CALLBACK (notes_add_key_press_cb), appGUI);

    vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_widget_show (vbox1);
    gtk_container_add (GTK_CONTAINER (appGUI->nte->add_entry_window), vbox1);

    table = gtk_grid_new ();
    gtk_widget_show (table);
    gtk_box_pack_start (GTK_BOX (vbox1), table, FALSE, TRUE, 0);

    frame = gtk_frame_new (NULL);
    gtk_widget_show (frame);
    gtk_widget_set_hexpand(frame, TRUE);
    gtk_widget_set_vexpand(frame, TRUE);
    gtk_grid_attach (GTK_GRID (table), frame, 0, 0, 1, 1);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

    appGUI->nte->note_name_entry = gtk_entry_new ();
    gtk_widget_show (appGUI->nte->note_name_entry);
    gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->note_name_entry);
    gtk_widget_set_margin_left(appGUI->nte->note_name_entry, 16);
    gtk_widget_set_margin_right(appGUI->nte->note_name_entry, 4);
    gtk_widget_set_margin_top(appGUI->nte->note_name_entry, 4);
    gtk_widget_set_margin_bottom(appGUI->nte->note_name_entry, 4);
    gtk_entry_set_invisible_char (GTK_ENTRY (appGUI->nte->note_name_entry), 8226);
    g_signal_connect (G_OBJECT (appGUI->nte->note_name_entry), "changed",
                      G_CALLBACK (notes_add_entry_changed_cb), appGUI);

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Note name"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

    frame = gtk_frame_new (NULL);
    gtk_widget_show (frame);
    gtk_grid_attach (GTK_GRID (table), frame, 1, 0, 1, 1);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

    appGUI->nte->category_combobox = gtk_combo_box_text_new ();
    gtk_widget_show (appGUI->nte->category_combobox);
    gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->category_combobox);
    gtk_widget_set_margin_left(appGUI->nte->category_combobox, 16);
    gtk_widget_set_margin_right(appGUI->nte->category_combobox, 4);
    gtk_widget_set_margin_top(appGUI->nte->category_combobox, 4);
    gtk_widget_set_margin_bottom(appGUI->nte->category_combobox, 4);
    gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->nte->category_combobox), NULL, _("None"));

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter);
    while (has_next) {
        gtk_tree_model_get(GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter, 0, &category, -1);
        gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->nte->category_combobox), NULL, category);
        g_free(category);
        has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter);
    }

    gtk_combo_box_set_active (GTK_COMBO_BOX(appGUI->nte->category_combobox), 
                              gtk_combo_box_get_active (GTK_COMBO_BOX (appGUI->nte->cf_combobox)));

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Category"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

#ifdef HAVE_LIBGRINGOTTS

	frame = gtk_frame_new (NULL);
	gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

	hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
	gtk_widget_show (hbox1);
	gtk_container_add (GTK_CONTAINER (frame), hbox1);
        gtk_widget_set_margin_left(hbox1, 16);
        gtk_widget_set_margin_right(hbox1, 4);
        gtk_widget_set_margin_top(hbox1, 4);
        gtk_widget_set_margin_bottom(hbox1, 4);

	appGUI->nte->note_normal_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Plain"));
	gtk_widget_show (appGUI->nte->note_normal_radiobutton);
    g_signal_connect (appGUI->nte->note_normal_radiobutton, "toggled", 
					  G_CALLBACK (note_type_cb), appGUI);
    gtk_widget_set_can_focus(appGUI->nte->note_normal_radiobutton, FALSE);
	gtk_box_pack_start (GTK_BOX (hbox1), appGUI->nte->note_normal_radiobutton, TRUE, TRUE, 0);
	gtk_radio_button_set_group (GTK_RADIO_BUTTON (appGUI->nte->note_normal_radiobutton), note_normal_radiobutton_group);
	note_normal_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (appGUI->nte->note_normal_radiobutton));

	note_encrypted_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Encrypted"));
	gtk_widget_show (note_encrypted_radiobutton);
    gtk_widget_set_can_focus(note_encrypted_radiobutton, FALSE);
	gtk_box_pack_start (GTK_BOX (hbox1), note_encrypted_radiobutton, TRUE, TRUE, 0);
	gtk_radio_button_set_group (GTK_RADIO_BUTTON (note_encrypted_radiobutton), note_normal_radiobutton_group);

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Note type"));
	label = gtk_label_new (tmpbuf);
	gtk_widget_show (label);
	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

    frame = gtk_frame_new (NULL);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

    appGUI->nte->password_entry = gtk_entry_new ();
    gtk_widget_show (appGUI->nte->password_entry);
    gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->password_entry);
    gtk_widget_set_margin_left(appGUI->nte->password_entry, 16);
    gtk_widget_set_margin_right(appGUI->nte->password_entry, 4);
    gtk_widget_set_margin_top(appGUI->nte->password_entry, 4);
    gtk_widget_set_margin_bottom(appGUI->nte->password_entry, 4);
    gtk_entry_set_invisible_char (GTK_ENTRY (appGUI->nte->password_entry), 8226);
    gtk_entry_set_visibility (GTK_ENTRY (appGUI->nte->password_entry), FALSE);
    g_signal_connect (G_OBJECT (appGUI->nte->password_entry), "changed",
                      G_CALLBACK (notes_add_entry_changed_cb), appGUI);
	gtk_widget_set_sensitive (appGUI->nte->password_entry, FALSE);

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Enter password"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

    frame = gtk_frame_new (NULL);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

    appGUI->nte->spassword_entry = gtk_entry_new ();
    gtk_widget_show (appGUI->nte->spassword_entry);
    gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->spassword_entry);
    gtk_widget_set_margin_left(appGUI->nte->spassword_entry, 16);
    gtk_widget_set_margin_right(appGUI->nte->spassword_entry, 4);
    gtk_widget_set_margin_top(appGUI->nte->spassword_entry, 4);
    gtk_widget_set_margin_bottom(appGUI->nte->spassword_entry, 4);
    gtk_entry_set_invisible_char (GTK_ENTRY (appGUI->nte->spassword_entry), 8226);
    gtk_entry_set_visibility (GTK_ENTRY (appGUI->nte->spassword_entry), FALSE);
    g_signal_connect (G_OBJECT (appGUI->nte->spassword_entry), "changed",
                      G_CALLBACK (notes_add_entry_changed_cb), appGUI);
    g_signal_connect (G_OBJECT (appGUI->nte->spassword_entry), "key_press_event",
                      G_CALLBACK (notes_add_ok_key_press_cb), appGUI);
	gtk_widget_set_sensitive (appGUI->nte->spassword_entry, FALSE);

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Re-enter password"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

#endif  /* HAVE_LIBGRINGOTTS */

    frame = gtk_frame_new (NULL);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

    appGUI->nte->remember_cursor_checkbutton = gtk_check_button_new_with_mnemonic (_("Remember cursor position"));
    gtk_widget_set_can_focus(appGUI->nte->remember_cursor_checkbutton, FALSE);
    gtk_widget_show (appGUI->nte->remember_cursor_checkbutton);
    gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->remember_cursor_checkbutton);
    gtk_widget_set_margin_left(appGUI->nte->remember_cursor_checkbutton, 16);
    gtk_widget_set_margin_right(appGUI->nte->remember_cursor_checkbutton, 4);
    gtk_widget_set_margin_top(appGUI->nte->remember_cursor_checkbutton, 4);
    gtk_widget_set_margin_bottom(appGUI->nte->remember_cursor_checkbutton, 4);

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Options"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, TRUE, 4);

    hbuttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hbuttonbox);
    gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox, FALSE, FALSE, 0);
    gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
    gtk_box_set_spacing (GTK_BOX (hbuttonbox), 4);

	cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
    gtk_widget_set_can_focus(cancel_button, FALSE);
    gtk_widget_show (cancel_button);
    gtk_container_add (GTK_CONTAINER (hbuttonbox), cancel_button);
    g_signal_connect (G_OBJECT (cancel_button), "clicked",
                        G_CALLBACK (button_notes_add_close_cb), appGUI);
    
    appGUI->nte->add_entry_ok_button = gtk_button_new_with_mnemonic (_("_OK"));
    gtk_widget_set_can_focus(appGUI->nte->add_entry_ok_button, FALSE);
    gtk_widget_show (appGUI->nte->add_entry_ok_button);
    gtk_container_add (GTK_CONTAINER (hbuttonbox), appGUI->nte->add_entry_ok_button);
    g_signal_connect (G_OBJECT (appGUI->nte->add_entry_ok_button), "clicked",
                        G_CALLBACK (notes_add_entry_action_cb), appGUI);
    gtk_widget_set_sensitive(appGUI->nte->add_entry_ok_button, FALSE);

    gtk_widget_show (appGUI->nte->add_entry_window);

}

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

void
notes_enter_password_close_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) {

    GUI *appGUI = (GUI *)user_data;

    appGUI->nte->password_entry = NULL;
    appGUI->nte->spassword_entry = NULL;

    gtk_widget_destroy(appGUI->nte->enter_password_window);
}

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

void
button_enter_password_close_cb (GtkWidget *widget, gpointer data) {

    notes_enter_password_close_cb (widget, NULL, data);
}

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

void
notes_enter_editor_action (GUI *appGUI) {

GtkTextBuffer *buffer;
gchar *txtnote;
gchar *current_filename;
GtkTreeIter iter;
GtkTreeModel *model;

    iter = utl_gui_get_first_selection_iter(appGUI->nte->notes_list_selection, &model);
    gtk_tree_model_get(model, &iter, N_COLUMN_FILENAME, &current_filename, -1);

    appGUI->nte->filename = g_strdup(current_filename);

    g_file_get_contents(notes_get_full_filename(current_filename, appGUI), &txtnote, NULL, NULL);

    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->nte->editor_textview));
    utl_gui_text_buffer_set_text_with_tags(buffer, (const gchar *) txtnote, TRUE);
    notes_show_selector_editor(EDITOR, appGUI);
    appGUI->nte->buffer_check_modify_enable = TRUE;

    g_free(txtnote);
    g_free(current_filename);
}

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

#ifdef HAVE_LIBGRINGOTTS

void
notes_enter_password_action_cb (GtkWidget *widget, gpointer data) {

gchar *pass, *current_filename;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTextBuffer *buffer;
unsigned char *txtnote;
long txtlen;
gint ret;

    GUI *appGUI = (GUI *) data;

    pass = g_strdup(gtk_entry_get_text(GTK_ENTRY(appGUI->nte->password_entry)));

    notes_enter_password_close_cb(widget, NULL, data);

    iter = utl_gui_get_first_selection_iter(appGUI->nte->notes_list_selection, &model);

    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, N_COLUMN_FILENAME, &current_filename, -1);

    appGUI->nte->filename = g_strdup(notes_get_full_filename(current_filename, appGUI));
    appGUI->nte->context = grg_context_initialize_defaults((unsigned char*) "OSM");
    appGUI->nte->keyholder = grg_key_gen((unsigned char*) pass, -1);

    grg_ctx_set_crypt_algo(appGUI->nte->context, get_enc_algorithm_value());
    grg_ctx_set_hash_algo(appGUI->nte->context, get_enc_hashing_value());
    grg_ctx_set_comp_algo(appGUI->nte->context, get_comp_algorithm_value());
    grg_ctx_set_comp_ratio(appGUI->nte->context, get_comp_ratio_value());

    ret = grg_decrypt_file(appGUI->nte->context, appGUI->nte->keyholder,
            (unsigned char *) appGUI->nte->filename, &txtnote, &txtlen);

    if (ret != GRG_OK) {
        utl_gui_create_dialog(GTK_MESSAGE_ERROR, _("Incorrect password!"), GTK_WINDOW(appGUI->main_window));
        g_free(pass);
        grg_key_free(appGUI->nte->context, appGUI->nte->keyholder);
        appGUI->nte->keyholder = NULL;
        grg_context_free(appGUI->nte->context);
        appGUI->nte->context = NULL;
        g_free(appGUI->nte->filename);
        appGUI->nte->filename = NULL;
        return;
    } else {
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->nte->editor_textview));
        utl_gui_text_buffer_set_text_with_tags(buffer, (const gchar *) txtnote, TRUE);
        notes_show_selector_editor(EDITOR, appGUI);
        appGUI->nte->buffer_check_modify_enable = TRUE;
    }

    if(txtnote) {
        grg_free(appGUI->nte->context, txtnote, txtlen);
    }

    g_free(current_filename);
    g_free(pass);
}


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

gint 
notes_enter_password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data) {

    GUI *appGUI = (GUI *)data;

    if (event->keyval == GDK_KEY_Escape) {
            notes_enter_password_close_cb (NULL, NULL, appGUI);
            return TRUE;
    } else if (event->keyval == GDK_KEY_Return) {
            notes_enter_password_action_cb (NULL, appGUI);
            return TRUE;
    }
    return FALSE;
}

#endif /* HAVE_LIBGRINGOTTS */

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

void
notes_enter_password (GUI *appGUI) {

gchar tmpbuf[BUFFER_SIZE];

GtkTreeIter iter;
GtkTreeModel *model;
gchar *current_filename;

#ifdef HAVE_LIBGRINGOTTS
	GtkWidget *frame;
	GtkWidget *ok_button;
	GtkWidget *cancel_button;
	GtkWidget *label;
	GtkWidget *vbox1;
	GtkWidget *hseparator;
	GtkWidget *hbuttonbox;
#endif /* HAVE_LIBGRINGOTTS */

        iter = utl_gui_get_first_selection_iter(appGUI->nte->notes_list_selection, &model);
        gtk_tree_model_get (model, &iter, N_COLUMN_FILENAME, &current_filename, -1);

#ifndef HAVE_LIBGRINGOTTS

		if (check_if_encrypted (current_filename, appGUI) == TRUE) {

			g_snprintf (tmpbuf, BUFFER_SIZE, "%s\n\n(%s)", _("Cannot open the note."), _("encryption support is disabled"));
			utl_gui_create_dialog (GTK_MESSAGE_ERROR, tmpbuf, GTK_WINDOW(appGUI->main_window));
			g_free (current_filename);
			return;

		} else {
			appGUI->nte->encrypted = FALSE;
            appGUI->nte->changed = FALSE;
			notes_enter_editor_action (appGUI);
		}

#else

		if (check_if_encrypted (current_filename, appGUI) == TRUE) {

			appGUI->nte->encrypted = TRUE;

			appGUI->nte->enter_password_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
			gtk_container_set_border_width (GTK_CONTAINER (appGUI->nte->enter_password_window), 4);
			gtk_window_set_title (GTK_WINDOW (appGUI->nte->enter_password_window), _("Authorization"));
			gtk_window_set_default_size (GTK_WINDOW(appGUI->nte->enter_password_window), 350, -1);
			if (config.fullscreen == FALSE) {
				gtk_window_set_transient_for(GTK_WINDOW(appGUI->nte->enter_password_window), GTK_WINDOW(appGUI->main_window));
			}
			gtk_window_set_position(GTK_WINDOW(appGUI->nte->enter_password_window), GTK_WIN_POS_CENTER_ON_PARENT);
			gtk_window_set_modal(GTK_WINDOW(appGUI->nte->enter_password_window), TRUE);
			g_signal_connect (G_OBJECT (appGUI->nte->enter_password_window), "delete_event",
							  G_CALLBACK(notes_enter_password_close_cb), appGUI);
			g_signal_connect (G_OBJECT (appGUI->nte->enter_password_window), "key_press_event",
							  G_CALLBACK (notes_enter_password_key_press_cb), appGUI);

			vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
			gtk_widget_show (vbox1);
			gtk_container_add (GTK_CONTAINER (appGUI->nte->enter_password_window), vbox1);

			frame = gtk_frame_new (NULL);
			gtk_widget_show (frame);
			gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0);
			gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);

			appGUI->nte->password_entry = gtk_entry_new ();
			gtk_widget_show (appGUI->nte->password_entry);
			gtk_container_add (GTK_CONTAINER (frame), appGUI->nte->password_entry);
                        gtk_widget_set_margin_left(appGUI->nte->password_entry, 16);
                        gtk_widget_set_margin_right(appGUI->nte->password_entry, 4);
                        gtk_widget_set_margin_top(appGUI->nte->password_entry, 4);
                        gtk_widget_set_margin_bottom(appGUI->nte->password_entry, 4);
			gtk_entry_set_invisible_char (GTK_ENTRY (appGUI->nte->password_entry), 8226);
			gtk_entry_set_visibility (GTK_ENTRY (appGUI->nte->password_entry), FALSE);

			g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Enter password"));
			label = gtk_label_new (tmpbuf);
			gtk_widget_show (label);
			gtk_frame_set_label_widget (GTK_FRAME (frame), label);
			gtk_label_set_use_markup (GTK_LABEL (label), TRUE);

			hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
			gtk_widget_show (hseparator);
			gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, TRUE, 4);

			hbuttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
			gtk_widget_show (hbuttonbox);
			gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox, FALSE, FALSE, 0);
			gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
			gtk_box_set_spacing (GTK_BOX (hbuttonbox), 4);

			cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
			gtk_widget_set_can_focus(cancel_button, FALSE);
			gtk_widget_show (cancel_button);
			gtk_container_add (GTK_CONTAINER (hbuttonbox), cancel_button);
			g_signal_connect (G_OBJECT (cancel_button), "clicked",
								G_CALLBACK (button_enter_password_close_cb), appGUI);
			
			ok_button = gtk_button_new_with_mnemonic (_("_OK"));
			gtk_widget_set_can_focus(ok_button, FALSE);
			gtk_widget_show (ok_button);
			gtk_container_add (GTK_CONTAINER (hbuttonbox), ok_button);
			g_signal_connect (G_OBJECT (ok_button), "clicked",
								G_CALLBACK (notes_enter_password_action_cb), appGUI);

			gtk_widget_show (appGUI->nte->enter_password_window);

		} else {
			appGUI->nte->encrypted = FALSE;
            appGUI->nte->changed = FALSE;
			notes_enter_editor_action (appGUI);
		}

#endif /* HAVE_LIBGRINGOTTS */

		g_free (current_filename);
}

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

void
read_notes_entries (GUI *appGUI) {

xmlDocPtr doc;
xmlChar *key;
xmlNodePtr node, cnode, category_node, main_node;
GtkTreeIter iter;
gchar *name, *category, *create_date_str, *fontname;
gchar *notes_dir, *str, *dir, *fullpath;
gint last_changes_time, create_time, editor_line;
guint32 last_changes_date_julian, create_date_julian;
gboolean remember_editor_line, editor_readonly;

    notes_dir = g_strdup(prefs_get_data_filename(NOTES_DIRNAME, appGUI));
    if (g_file_test (notes_dir, G_FILE_TEST_IS_DIR | G_FILE_TEST_EXISTS) == FALSE) {
        g_mkdir (notes_dir, 0755);
    }
    g_free(notes_dir);

    if (g_file_test (prefs_get_data_filename(NOTES_ENTRIES_FILENAME, appGUI), G_FILE_TEST_IS_REGULAR) == FALSE) 
        return;

    if((doc = xmlParseFile(prefs_get_data_filename(NOTES_ENTRIES_FILENAME, appGUI)))) {

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

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

        main_node = node->xmlChildrenNode;

        while (main_node != NULL) {

            if(!xmlStrcmp(main_node->name, (xmlChar *) NOTES_CATEGORY_ENTRIES_NAME)) {

                /* read note */
                category_node = main_node->xmlChildrenNode;

                while (category_node != NULL) {

                    if ((!xmlStrcmp(category_node->name, (const xmlChar *) "name"))) {
                        key = xmlNodeListGetString(doc, category_node->xmlChildrenNode, 1);
                        if (key != NULL) {
                            gtk_list_store_append(appGUI->opt->notes_category_store, &iter);
                            gtk_list_store_set(appGUI->opt->notes_category_store, &iter, 0, (gchar *) key, -1);
                        }
                        xmlFree(key);
                    }

                    category_node = category_node->next;
                }
            }

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

            if(!xmlStrcmp(main_node->name, (xmlChar *) NOTES_ENTRIES_NAME)) {

                /* read note */
                node = main_node->xmlChildrenNode;

                while (node != NULL) {

                    if(!xmlStrcmp(node->name, (xmlChar *) "entry")) {

                        cnode = node->xmlChildrenNode;

						remember_editor_line = FALSE;
						editor_readonly = FALSE;
                        editor_line = 0;
						fontname = NULL;

                        while (cnode != NULL) {

							utl_xml_get_str ("name", &name, cnode);
							utl_xml_get_str ("category", &category, cnode);
							utl_xml_get_uint ("last_changes_date", &last_changes_date_julian, cnode);
							utl_xml_get_int ("last_changes_time", &last_changes_time, cnode);
							utl_xml_get_uint ("create_date", &create_date_julian, cnode);
							utl_xml_get_int ("create_time", &create_time, cnode);
							utl_xml_get_int ("remember_editor_line", &remember_editor_line, cnode);
							utl_xml_get_int ("editor_line", &editor_line, cnode);
							utl_xml_get_int ("read_only", &editor_readonly, cnode);
							utl_xml_get_str ("fontname", &fontname, cnode);

                            if ((!xmlStrcmp(cnode->name, (const xmlChar *) "filename"))) {
                                key = xmlNodeListGetString(doc, cnode->xmlChildrenNode, 1);
                                if (key != NULL) {

									str = g_path_get_basename ((gchar *) key);
									dir = g_path_get_dirname ((gchar *) key);

									if (str && dir) {

										if (dir[0] == '.') {
											fullpath = g_strdup (notes_get_full_filename (str, appGUI));
										} else {
											fullpath = (gchar *) key;
										}

										gtk_list_store_append (appGUI->nte->notes_list_store, &iter);

										create_date_str = g_strdup(get_date_time_str (create_date_julian, create_time));

										if (fontname == NULL) {
											fontname = g_strdup(DEFAULT_NOTE_FONT);
										}

										gtk_list_store_set (appGUI->nte->notes_list_store, &iter, 
															N_COLUMN_NAME, name, 
															N_COLUMN_CATEGORY, category, 
															N_COLUMN_LAST_CHANGES_DATE, get_date_time_str (last_changes_date_julian, last_changes_time),
															N_COLUMN_LAST_CHANGES_DATE_JULIAN, last_changes_date_julian,
															N_COLUMN_LAST_CHANGES_TIME, last_changes_time,
															N_COLUMN_CREATE_DATE, create_date_str,
															N_COLUMN_CREATE_DATE_JULIAN, create_date_julian,
															N_COLUMN_CREATE_TIME, create_time,
															N_COLUMN_REMEMBER_EDITOR_LINE, remember_editor_line,
															N_COLUMN_FONTNAME, fontname,
															N_COLUMN_EDITOR_LINE, editor_line,
															N_COLUMN_EDITOR_READONLY, editor_readonly, -1);

										g_free (create_date_str);

										if (dir[0] == '.') {
											gtk_list_store_set (appGUI->nte->notes_list_store, &iter, 
																N_COLUMN_FILENAME, (gchar *)key, -1);
											g_free (fullpath);
										} else {
											gtk_list_store_set (appGUI->nte->notes_list_store, &iter, 
																N_COLUMN_FILENAME, str, -1);
										}

										g_free (str);
										g_free (dir);
										g_free (name);
										g_free (fontname);
										g_free (category);

										fontname = NULL;
									}
                                    xmlFree (key);
                                }
                            }

                            cnode = cnode->next;
                        }

                    }

                    node = node->next;
                }

            }

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

            main_node = main_node->next;
        }

        xmlFree(node);
        xmlFreeDoc(doc);

        notes_cleanup_files (appGUI);
		check_notes_type (appGUI);
    }

}

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

void
write_notes_entries (GUI *appGUI) {

xmlDocPtr doc;
xmlNodePtr main_node, node, note_node;
xmlAttrPtr attr;
GtkTreeIter iter;
gchar *category, *name, *note_filename, *note_fontname;
gint last_changes_time, create_time, editor_line;
guint32 last_changes_date_julian, create_date_julian;
gboolean remember_editor_line, editor_readonly, has_next;
xmlChar *escaped;

    if ((appGUI->save_status & WRT_NOTES) != 0) return;

    appGUI->save_status |= WRT_NOTES;

    doc = xmlNewDoc((const xmlChar *) "1.0");
    attr = xmlNewDocProp (doc, (const xmlChar *) "encoding", (const xmlChar *) "utf-8");

    main_node = xmlNewNode(NULL, (const xmlChar *) NOTES_NAME);
    xmlDocSetRootElement(doc, main_node);

    node = xmlNewChild(main_node, NULL, (const xmlChar *) NOTES_CATEGORY_ENTRIES_NAME, (xmlChar *) NULL);

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter);
    while (has_next) {

        gtk_tree_model_get(GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter, 0, &category, -1);
		escaped = xmlEncodeEntitiesReentrant(doc, (const xmlChar *) category);
        xmlNewChild(node, NULL, (const xmlChar *) "name", (xmlChar *) escaped);
        g_free(category);
        xmlFree (escaped);
        has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->opt->notes_category_store), &iter);
    }

    node = xmlNewChild(main_node, NULL, (const xmlChar *) NOTES_ENTRIES_NAME, (xmlChar *) NULL);

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (appGUI->nte->notes_list_store), &iter);
    	while (has_next) {

		gtk_tree_model_get (GTK_TREE_MODEL (appGUI->nte->notes_list_store), &iter,
		                    N_COLUMN_NAME, &name,
		                    N_COLUMN_CATEGORY, &category,
		                    N_COLUMN_LAST_CHANGES_DATE_JULIAN, &last_changes_date_julian,
		                    N_COLUMN_LAST_CHANGES_TIME, &last_changes_time,
		                    N_COLUMN_CREATE_DATE_JULIAN, &create_date_julian,
		                    N_COLUMN_CREATE_TIME, &create_time,
		                    N_COLUMN_REMEMBER_EDITOR_LINE, &remember_editor_line,
		                    N_COLUMN_EDITOR_LINE, &editor_line,
		                    N_COLUMN_EDITOR_READONLY, &editor_readonly,
		                    N_COLUMN_FONTNAME, &note_fontname,
		                    N_COLUMN_FILENAME, &note_filename, -1);

		note_node = xmlNewChild (node, NULL, (const xmlChar *) "entry", (xmlChar *) NULL);

		utl_xml_put_str ("name", name, note_node);
		g_free (name);
		utl_xml_put_str ("category", category, note_node);
		g_free (category);
		utl_xml_put_uint ("last_changes_date", last_changes_date_julian, note_node);
		utl_xml_put_int ("last_changes_time", last_changes_time, note_node);
		utl_xml_put_uint ("create_date", create_date_julian, note_node);
		utl_xml_put_int ("create_time", create_time, note_node);
		utl_xml_put_int ("remember_editor_line", remember_editor_line, note_node);
		utl_xml_put_int ("editor_line", editor_line, note_node);
		utl_xml_put_int ("read_only", editor_readonly, note_node);
		utl_xml_put_str ("fontname", note_fontname, note_node);
		g_free (note_fontname);
		utl_xml_put_str ("filename", note_filename, note_node);
		g_free (note_filename);
                has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (appGUI->nte->notes_list_store), &iter);
	}

	utl_xml_write_doc (prefs_get_data_filename (NOTES_ENTRIES_FILENAME, appGUI), doc);
	xmlFreeProp (attr);
	xmlFreeDoc (doc);

	appGUI->save_status &= ~WRT_NOTES;
}

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

gchar *
notes_get_new_filename (GUI *appGUI) {

guint i;
static gchar fullpath[PATH_MAX];

    for(i=0; i < 99999999; i++) {
        g_snprintf(fullpath, PATH_MAX-1, "%s%c%08d.osm", 
                   prefs_get_data_filename(NOTES_DIRNAME, appGUI), G_DIR_SEPARATOR, i);
        if (g_file_test (fullpath, G_FILE_TEST_EXISTS) == FALSE) break;
    }

	g_snprintf(fullpath, PATH_MAX-1, "%08d.osm", i);

    return fullpath;
}

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

void
notes_cleanup_files (GUI *appGUI) {

gchar fullpath[PATH_MAX];
GDir *dpath;
gboolean found;
const gchar *item_name;
gchar *note_filename;
GtkTreeIter iter;

    g_snprintf(fullpath, PATH_MAX-1, "%s", prefs_get_data_filename(NOTES_DIRNAME, appGUI));
    dpath = g_dir_open (fullpath, 0, NULL);

    if (dpath != NULL) {

        while ((item_name = g_dir_read_name (dpath)) != NULL) {
            gboolean has_next;

            found = FALSE;

            g_snprintf(fullpath, PATH_MAX-1, "%s%c%s", 
                       prefs_get_data_filename(NOTES_DIRNAME, appGUI), G_DIR_SEPARATOR, item_name);

            has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->nte->notes_list_store), &iter);
            while (has_next) {

                gtk_tree_model_get(GTK_TREE_MODEL(appGUI->nte->notes_list_store), &iter, 
                                   N_COLUMN_FILENAME, &note_filename, -1);
                
                if (!strncmp(notes_get_full_filename(note_filename, appGUI), fullpath, PATH_MAX)) {
                    found = TRUE;
                    g_free(note_filename);
                    break;
                }

                g_free(note_filename);
                has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->nte->notes_list_store), &iter);
            }

            if (found == FALSE) {
                g_unlink (fullpath);
            }

        }

        g_dir_close (dpath);
    }

}

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

gchar *
notes_get_full_filename (gchar *filename, GUI *appGUI) {

static gchar fullname[PATH_MAX];
gchar *str;

    g_snprintf (fullname, PATH_MAX-1, "%s%c%s", 
				prefs_get_data_filename(NOTES_DIRNAME, appGUI), G_DIR_SEPARATOR, filename);

	if (g_file_test (fullname, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) == FALSE) {

		str = g_path_get_basename (fullname);

		if (str) {
			g_snprintf (fullname, PATH_MAX-1, "%s%c%s", 
						prefs_get_data_filename(NOTES_DIRNAME, appGUI), G_DIR_SEPARATOR, str);
			g_free (str);
		}
	}

	return fullname;
}

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

#endif  /* NOTES_ENABLED */

