
/*
 * 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 "contacts_items.h"
#include "i18n.h"
#include "contacts.h"
#include "tasks.h"
#include "calendar.h"
#include "calendar_notes.h"
#include "calendar_widget.h"
#include "calendar_utils.h"
#include "utils.h"
#include "utils_date.h"
#include "utils_gui.h"
#include "options_prefs.h"
#include "stock_icons.h"

#ifdef CONTACTS_ENABLED

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

void
contacts_fill_ids (GUI *appGUI) {

GtkTreeIter iter;
gint i = 0;
gboolean has_next;

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
    while (has_next) {
        gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, COLUMN_ID, ++i, -1);
        has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
    }

}

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

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

    GUI *appGUI = (GUI *)user_data;

    gtk_window_get_size (GTK_WINDOW(appGUI->cnt->contacts_add_window),
                        &config.contacts_addedit_win_w, &config.contacts_addedit_win_h);
    gdk_window_get_root_origin (gtk_widget_get_window(appGUI->cnt->contacts_add_window),
                        &config.contacts_addedit_win_x, &config.contacts_addedit_win_y);
    gtk_widget_destroy(appGUI->cnt->contacts_add_window);
}

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

void
contacts_item_entered_cb (GtkWidget *widget, gpointer data) {

GtkTextBuffer *text_buffer;
GtkTextIter iter_a, iter_b;
GtkTreePath *sort_path, *filter_path, *path;
GtkTreeIter iter;
gint i;
gboolean free_str;
const gchar *text;

    GUI *appGUI = (GUI *)data;

    if (appGUI->cnt->contacts_edit_state == TRUE) {

        gtk_tree_view_get_cursor (GTK_TREE_VIEW (appGUI->cnt->contacts_list), &sort_path, NULL);

        if (sort_path != NULL) {

            filter_path = gtk_tree_model_sort_convert_path_to_child_path (GTK_TREE_MODEL_SORT(appGUI->cnt->contacts_sort), sort_path);

            if (filter_path != NULL) {

                path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter), filter_path);

                if (path != NULL) {
                    gtk_tree_model_get_iter(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter, path);
                    gtk_list_store_remove(appGUI->cnt->contacts_list_store, &iter);
                    gtk_tree_path_free(path);
                }

                gtk_tree_path_free(filter_path);
            }

            gtk_tree_path_free(sort_path);
        }
    }

    gtk_list_store_append(appGUI->cnt->contacts_list_store, &iter);

    for(i=0; i<CONTACTS_NUM_COLUMNS; i++) {

        if (i != COLUMN_ID) {
            text = NULL;
            free_str = FALSE;

            if (i == COLUMN_BIRTH_DAY_DATE) {
                if (appGUI->cnt->birthday_date) {
                    gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, i, appGUI->cnt->birthday_date, -1);
                }
            } else  if (i == COLUMN_NAME_DAY_DATE) {
                if (appGUI->cnt->nameday_date) {
                    gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, i, appGUI->cnt->nameday_date, -1);
                }
            } else {

                if (i == COLUMN_GROUP) {
                    text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(appGUI->cnt->combobox_group));
                    free_str = TRUE;
                } else if (i == COLUMN_INFO) {
                    text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->cnt->add_info_textview));
                    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(text_buffer), &iter_a, 0);
                    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(text_buffer), &iter_b, -1);
                    text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(text_buffer), &iter_a, &iter_b, TRUE);
                    free_str = TRUE;
                } else {
                    text = gtk_entry_get_text (GTK_ENTRY(appGUI->cnt->contact_entries[i]));
                }

                if (text != NULL) {
                    if (strlen(text)) {
                        gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, i, text, -1);
                        if (free_str == TRUE) {
                            g_free((gchar *)text);
                        }
                    }
                }
            }
        }
    }

    appGUI->cnt->write_flag = TRUE;
    contacts_add_edit_window_close_cb (NULL, NULL, appGUI);
   
    pango_font_description_free(appGUI->cnt->fd_ai_font);

    contacts_select_iter_position(&iter, appGUI);

    gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));

    set_export_active(appGUI);
    gui_systray_tooltip_update(appGUI);
    contacts_fill_ids (appGUI);
    cal_refresh_marks (appGUI);
    update_aux_calendars (appGUI);

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

/*------------------------------------------------------------------------------*/
void
contacts_remove(GtkTreeRowReference *ref, GUI *appGUI) {
    GtkTreePath *path;
    GtkTreeIter iter, filter_iter, sort_iter;
    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_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->cnt->contacts_list_store, &iter);
        }
        gtk_tree_path_free(path);
    } 
}

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

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

    g_snprintf(tmpbuf, BUFFER_SIZE, "%s\n\n%s", _("Selected contact will be removed."), _("Are you sure?"));

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

    if (response == GTK_RESPONSE_YES) {
        contacts_selection_activate (FALSE, appGUI);
        utl_gui_foreach_selected(appGUI->cnt->contacts_list_selection, GTK_TREE_MODEL(appGUI->cnt->contacts_list_store),
                (GFunc)contacts_remove, appGUI);
        contacts_selection_activate (TRUE, appGUI);
        contacts_select_first_position_in_list(appGUI);
        g_signal_emit_by_name(G_OBJECT(appGUI->cal->calendar), "day-selected");
        set_export_active(appGUI);
        gui_systray_tooltip_update(appGUI);

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

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

void
button_contacts_add_edit_window_close_cb (GtkWidget *widget, gpointer user_data) {

    GUI *appGUI = (GUI *)user_data;

    contacts_add_edit_window_close_cb (widget, NULL, appGUI);
    pango_font_description_free(appGUI->cnt->fd_ai_font);
}

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

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

    GUI *appGUI = (GUI *)data;

    switch(event->keyval) {

        case GDK_KEY_Escape:
            contacts_add_edit_window_close_cb (NULL, NULL, appGUI);
            return TRUE;
    }

    if(strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contact_entries[COLUMN_FIRST_NAME]))) || 
       strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contact_entries[COLUMN_LAST_NAME])))) {
        appGUI->cnt->contacts_accept_state = TRUE;
    } else {
        appGUI->cnt->contacts_accept_state = FALSE;
    }

    gtk_widget_set_sensitive(appGUI->cnt->contacts_ok_button, appGUI->cnt->contacts_accept_state);

    return FALSE;
}

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

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

const gchar *text;

    MESSAGE *msg = (MESSAGE *)data;
    gint i = (size_t) msg->data;

    if (event->keyval == GDK_KEY_Return) {

        text = gtk_entry_get_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[i]));

        if(strlen(text) && i != COLUMN_HOME_PHONE_4 && i != COLUMN_WORK_PHONE_4 &&
           i != COLUMN_CELL_PHONE_4 && i != COLUMN_EMAIL_4 && i != COLUMN_WWW_4) {
            gtk_widget_show (msg->appGUI->cnt->contact_entries[i+1]);
            gtk_widget_grab_focus (msg->appGUI->cnt->contact_entries[i+1]);
        }

        return TRUE;
    }

    return FALSE;
}

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

gboolean
group_combo_box_focus_cb (GtkWidget *widget, GtkDirectionType *arg1, gpointer user_data) {
    return TRUE;
}

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

void
group_combobox_changed_cb (GtkComboBox *widget, gpointer user_data) {

    GUI *appGUI = (GUI *)user_data;

    gtk_widget_grab_focus (appGUI->cnt->contact_entries[COLUMN_FIRST_NAME]);
}

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

void
select_date_close_cb (GtkWidget *widget, gpointer data) {

    GUI *appGUI = (GUI *)data;

    gtk_widget_destroy(appGUI->cnt->select_date_window);
}

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

void
select_date_selected_cb (GuiCalendar *s_calendar, gpointer user_data) {

guint day, month, year;
gchar *temp;
guint32 julian_day;

    MESSAGE *msg = (MESSAGE *)user_data;

    gui_calendar_get_date (s_calendar, &year, &month, &day);
    gtk_widget_destroy(msg->appGUI->cnt->select_date_window);

    julian_day = utl_date_dmy_to_julian (day, month + 1, year);

    if (GPOINTER_TO_INT(msg->data) == COLUMN_BIRTH_DAY_DATE) {
        temp = julian_to_str (julian_day, DATE_FULL, config.override_locale_settings);
        gtk_entry_set_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE]), temp);
        msg->appGUI->cnt->birthday_date = julian_day;
    } else if (GPOINTER_TO_INT(msg->data) == COLUMN_NAME_DAY_DATE) {
        temp = julian_to_str (julian_day, DATE_NAME_DAY, config.override_locale_settings);
        gtk_entry_set_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE]), temp);
        msg->appGUI->cnt->nameday_date = julian_day;
    }
}

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

void
select_date_ok_cb (GtkWidget *widget, gpointer data) {

    MESSAGE *msg = (MESSAGE *)data;

    select_date_selected_cb (GUI_CALENDAR (msg->appGUI->cnt->select_date_calendar), msg);
}

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

void
select_date_nodate_cb (GuiCalendar *s_calendar, gpointer user_data) {

    MESSAGE *msg = (MESSAGE *)user_data;

    gtk_widget_destroy(msg->appGUI->cnt->select_date_window);

    if (GPOINTER_TO_INT(msg->data) == COLUMN_BIRTH_DAY_DATE) {
        gtk_entry_set_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE]), "");
        msg->appGUI->cnt->birthday_date = 0;
    } else if (GPOINTER_TO_INT(msg->data) == COLUMN_NAME_DAY_DATE) {
        gtk_entry_set_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE]), "");
        msg->appGUI->cnt->nameday_date = 0;
    }

}

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

void
next_field_button_clicked_cb (GtkWidget *widget, gpointer user_data) {

const gchar *text;

    MESSAGE *msg = (MESSAGE *)user_data;
    gint i = (size_t) msg->data;

    text = gtk_entry_get_text (GTK_ENTRY(msg->appGUI->cnt->contact_entries[i]));

    if(strlen(text) && i != COLUMN_HOME_PHONE_4 && i != COLUMN_WORK_PHONE_4 &&
       i != COLUMN_CELL_PHONE_4 && i != COLUMN_EMAIL_4 && i != COLUMN_WWW_4) {
        gtk_widget_hide (msg->appGUI->cnt->next_field_button[i]);

        gtk_widget_show (msg->appGUI->cnt->contact_entries[i+1]);

        if (msg->appGUI->cnt->next_field_button[i+1] != NULL) {
            gtk_widget_show (msg->appGUI->cnt->next_field_button[i+1]);
        }

        gtk_widget_grab_focus (msg->appGUI->cnt->contact_entries[i+1]);
    }
}

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

void
date_select_cb (GtkWidget *widget, gpointer user_data) {

GDate *cdate = NULL;
GtkWidget *vbox1;
GtkWidget *hbox1;
GtkWidget *nodate_button;
GtkWidget *close_button;
GtkWidget *ok_button;
static MESSAGE msg_selected;


    MESSAGE *msg = (MESSAGE *)user_data;

    msg->appGUI->cnt->select_date_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(msg->appGUI->cnt->select_date_window), GTK_WIN_POS_MOUSE);
    gtk_window_set_modal(GTK_WINDOW(msg->appGUI->cnt->select_date_window), TRUE);
    if (config.fullscreen == FALSE) {
        gtk_window_set_transient_for(GTK_WINDOW(msg->appGUI->cnt->select_date_window), GTK_WINDOW(msg->appGUI->cnt->contacts_add_window));
    }
    gtk_window_set_decorated(GTK_WINDOW(msg->appGUI->cnt->select_date_window), FALSE);

    vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_widget_show (vbox1);
    gtk_container_add (GTK_CONTAINER (msg->appGUI->cnt->select_date_window), vbox1);

    msg->appGUI->cnt->select_date_calendar = gui_calendar_new();
    gui_calendar_set_cursor_type (GUI_CALENDAR(msg->appGUI->cnt->select_date_calendar), CURSOR_BLOCK);
	gui_set_calendar_defaults(msg->appGUI->cnt->select_date_calendar);
    gtk_widget_show(msg->appGUI->cnt->select_date_calendar);
    msg_selected.data = msg->data;
    msg_selected.appGUI = msg->appGUI;
    g_signal_connect (G_OBJECT (msg->appGUI->cnt->select_date_calendar), "day_selected_double_click",
                      G_CALLBACK (select_date_selected_cb), &msg_selected);
    gtk_widget_set_margin_left(msg->appGUI->cnt->select_date_calendar, 4);
    gtk_widget_set_margin_right(msg->appGUI->cnt->select_date_calendar, 4);
    gtk_widget_set_margin_top(msg->appGUI->cnt->select_date_calendar, 4);
    gtk_widget_set_margin_bottom(msg->appGUI->cnt->select_date_calendar, 4);
    gtk_box_pack_start (GTK_BOX (vbox1), msg->appGUI->cnt->select_date_calendar, TRUE, TRUE, 0);
    gui_calendar_set_display_options (GUI_CALENDAR (msg->appGUI->cnt->select_date_calendar), 
                                      (config.display_options & !GUI_CALENDAR_NO_MONTH_CHANGE) | 
                                      GUI_CALENDAR_SHOW_HEADING | GUI_CALENDAR_SHOW_DAY_NAMES | 
                                      (config.display_options & GUI_CALENDAR_WEEK_START_MONDAY));

    hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
    gtk_widget_set_margin_left(hbox1, 4);
    gtk_widget_set_margin_right(hbox1, 4);
    gtk_widget_set_margin_top(hbox1, 4);
    gtk_widget_set_margin_bottom(hbox1, 4);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);

    nodate_button = gtk_button_new_with_mnemonic (_("No date"));
    gtk_widget_show (nodate_button);
    gtk_box_pack_start (GTK_BOX (hbox1), nodate_button, FALSE, FALSE, 4);
    g_signal_connect (G_OBJECT (nodate_button), "clicked",
                        G_CALLBACK (select_date_nodate_cb), &msg_selected);

    ok_button = gtk_button_new_from_icon_name ("gtk-ok", GTK_ICON_SIZE_BUTTON);
    gtk_widget_set_can_focus(ok_button, FALSE);
    gtk_button_set_relief (GTK_BUTTON(ok_button), GTK_RELIEF_NONE);
    gtk_widget_show (ok_button);
    gtk_box_pack_end (GTK_BOX (hbox1), ok_button, FALSE, FALSE, 0);
    g_signal_connect (G_OBJECT (ok_button), "clicked",
                        G_CALLBACK (select_date_ok_cb), &msg_selected);

    close_button = gtk_button_new_from_icon_name("gtk-cancel", GTK_ICON_SIZE_BUTTON);
    gtk_widget_set_can_focus(close_button, FALSE);
    gtk_button_set_relief (GTK_BUTTON(close_button), GTK_RELIEF_NONE);
    gtk_widget_show (close_button);
    gtk_box_pack_end (GTK_BOX (hbox1), close_button, FALSE, FALSE, 0);
    g_signal_connect (G_OBJECT (close_button), "clicked",
                        G_CALLBACK (select_date_close_cb), msg->appGUI);

    gtk_widget_show (msg->appGUI->cnt->select_date_window);

    if (GPOINTER_TO_INT(msg->data) == COLUMN_BIRTH_DAY_DATE) {
        if (g_date_valid_julian(msg->appGUI->cnt->birthday_date)) {
            cdate = g_date_new_julian(msg->appGUI->cnt->birthday_date);
        }
    } else if (GPOINTER_TO_INT(msg->data) == COLUMN_NAME_DAY_DATE) {
        if (g_date_valid_julian(msg->appGUI->cnt->nameday_date)) {
            cdate = g_date_new_julian(msg->appGUI->cnt->nameday_date);
        }
    }
    if (cdate != NULL) {
        gui_calendar_select_month(GUI_CALENDAR(msg->appGUI->cnt->select_date_calendar),
                g_date_get_month(cdate) - 1, g_date_get_year(cdate));
        gui_calendar_select_day(GUI_CALENDAR(msg->appGUI->cnt->select_date_calendar),
                g_date_get_day(cdate));
        g_date_free(cdate);
    }
}

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

void
photo_file_select_cb (GtkWidget *widget, gpointer user_data) {

GtkWidget *dialog;

        GUI *appGUI = (GUI *)user_data;

        dialog = utl_gui_create_open_file_dialog(_("Select photo"),
                                             GTK_WINDOW (appGUI->cnt->contacts_add_window));

        if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
            gtk_entry_set_text (GTK_ENTRY(appGUI->cnt->contact_entries[COLUMN_PHOTO]), gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
        }

        gtk_widget_destroy(dialog);
}

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

void
photo_clear_cb (GtkWidget *widget, gpointer user_data) {
    GUI *appGUI = (GUI *)user_data;
    
    gtk_entry_set_text (GTK_ENTRY(appGUI->cnt->contact_entries[COLUMN_PHOTO]), "");
}
/*------------------------------------------------------------------------------*/
static void
show_hide_field_group(gint start_index, gint end_index, GUI *appGUI) {
    gint i;

    for (i = start_index; i < end_index; i++) {
        const gchar *text;
        gtk_widget_hide(appGUI->cnt->contact_entries[i]);
        text = gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contact_entries[i]));
        if (!strlen(text)) break;
        gtk_widget_show(appGUI->cnt->contact_entries[i]);
        gtk_widget_hide(appGUI->cnt->next_field_button[i - 1]);
    }
}

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

static void
show_hide_multiple_fields(GUI *appGUI) {
    show_hide_field_group(COLUMN_HOME_PHONE_2, COLUMN_HOME_PHONE_4 + 1, appGUI);
    show_hide_field_group(COLUMN_WORK_PHONE_2, COLUMN_WORK_PHONE_4 + 1, appGUI);
    show_hide_field_group(COLUMN_CELL_PHONE_2, COLUMN_CELL_PHONE_4 + 1, appGUI);
    show_hide_field_group(COLUMN_EMAIL_2, COLUMN_EMAIL_4 + 1, appGUI);
    show_hide_field_group(COLUMN_WWW_2, COLUMN_WWW_4 + 1, appGUI);
}

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

void
contacts_add_edit_dialog_show (gboolean contacts_edit_mode, GUI *appGUI) {

GtkWidget       *vbox1;
GtkWidget       *vbox2;
GtkWidget       *hseparator;
GtkWidget       *hbuttonbox;
GtkWidget       *table;
GtkWidget       *cancel_button;
GtkWidget       *contacts_add_scrolledwindow;
GtkWidget       *viewport;
GtkWidget       *label;
GtkWidget       *scrolledwindow;
GtkWidget       *photo_clear_button;
GtkTreeIter     iter;
GtkTreeModel    *model;
GtkTextIter     titer;
GtkTextBuffer   *text_buffer;
gchar           *text;
gint            pos, i;
guint32         date;
gchar tmpbuf[BUFFER_SIZE];
static MESSAGE msg_date[2]; /* birthday, name day */
static MESSAGE msg_index[CONTACTS_NUM_COLUMNS];

gchar *contact_replace_tags[] = {
    N_("Address"), N_("Postcode"), N_("City"), N_("State"), N_("Country")
};

    appGUI->cnt->contacts_add_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width (GTK_CONTAINER (appGUI->cnt->contacts_add_window), 6);

    if(contacts_edit_mode == TRUE) {
        gtk_window_set_title (GTK_WINDOW (appGUI->cnt->contacts_add_window), _("Edit contact"));
    } else {
        gtk_window_set_title (GTK_WINDOW (appGUI->cnt->contacts_add_window), _("Add contact"));
    }

    appGUI->cnt->birthday_date = appGUI->cnt->nameday_date = 0;

    if (config.fullscreen == FALSE) {
        gtk_window_set_transient_for(GTK_WINDOW(appGUI->cnt->contacts_add_window), 
                                     GTK_WINDOW(appGUI->main_window));
    }
    gtk_window_set_modal(GTK_WINDOW(appGUI->cnt->contacts_add_window), TRUE);
    gtk_window_set_default_size (GTK_WINDOW(appGUI->cnt->contacts_add_window), 
                                 config.contacts_addedit_win_w, config.contacts_addedit_win_h);
    gtk_window_move (GTK_WINDOW (appGUI->cnt->contacts_add_window), 
                     config.contacts_addedit_win_x, config.contacts_addedit_win_y);

    g_signal_connect (G_OBJECT (appGUI->cnt->contacts_add_window), "key_release_event",
                      G_CALLBACK (contacts_add_edit_key_release_cb), appGUI);

    g_signal_connect (G_OBJECT (appGUI->cnt->contacts_add_window), "delete_event",
                      G_CALLBACK(contacts_add_edit_window_close_cb), appGUI);

    vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_widget_show (vbox1);
    gtk_container_add (GTK_CONTAINER (appGUI->cnt->contacts_add_window), vbox1);

    vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_widget_show (vbox2);
    gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);

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

    contacts_add_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (contacts_add_scrolledwindow);
    gtk_box_pack_start (GTK_BOX (vbox2), contacts_add_scrolledwindow, TRUE, TRUE, 0);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contacts_add_scrolledwindow), 
                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

    viewport = gtk_viewport_new (NULL, NULL);
    gtk_widget_show (viewport);
    gtk_container_add (GTK_CONTAINER (contacts_add_scrolledwindow), viewport);
    gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_ETCHED_IN);

    table = gtk_grid_new ();       /* FIXME: don't use hardcoded values */
    gtk_widget_show (table);
    gtk_container_add (GTK_CONTAINER (viewport), table);
    gtk_container_set_border_width (GTK_CONTAINER (table), 4);
    gtk_grid_set_row_spacing (GTK_GRID (table), 8);
    gtk_grid_set_column_spacing (GTK_GRID (table), 4);

    /*** PERSONAL ***/

    pos = 0;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Personal"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_valign(label, GTK_ALIGN_START);
    gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", _("Group"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_widget_set_margin_left(label, 4);
    gtk_widget_set_margin_right(label, 4);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
    gtk_widget_set_halign(label, GTK_ALIGN_START);

    appGUI->cnt->combobox_group = gtk_combo_box_text_new ();
    gtk_widget_show (appGUI->cnt->combobox_group);
    g_signal_connect(G_OBJECT(appGUI->cnt->combobox_group), "focus",
                     G_CALLBACK(group_combo_box_focus_cb), NULL);

    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->combobox_group, 2, pos, 3, 1);

    utl_gui_create_category_combobox (GTK_COMBO_BOX(appGUI->cnt->combobox_group), 
                                      appGUI->opt->contacts_group_store, TRUE);

    gtk_combo_box_set_active(GTK_COMBO_BOX(appGUI->cnt->combobox_group), 0);

    pos++;

    for(i=COLUMN_FIRST_NAME; i<COLUMN_BIRTH_DAY_DATE; i++) {

        g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[i*2]));
        label = gtk_label_new (tmpbuf);
        gtk_widget_show (label);
        gtk_widget_set_margin_left(label, 4);
        gtk_widget_set_margin_right(label, 4);
        gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
        gtk_widget_set_halign(label, GTK_ALIGN_START);

        appGUI->cnt->contact_entries[i] = gtk_entry_new ();

        if (i == COLUMN_FIRST_NAME) {
            appGUI->cnt->next_field_button[i] = gtk_button_new_from_icon_name ("go-down", GTK_ICON_SIZE_BUTTON);
            gtk_widget_show (appGUI->cnt->next_field_button[i]);
            gtk_widget_set_can_focus(appGUI->cnt->next_field_button[i], FALSE);
        }

        gtk_widget_show (appGUI->cnt->contact_entries[i]);
        gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
        gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 3, 1);
        pos++;
    }

    /* BIRTHDAY DATE */

    g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[COLUMN_BIRTH_DAY_DATE*2]));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_widget_set_margin_left(label, 4);
    gtk_widget_set_margin_right(label, 4);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
    gtk_widget_set_halign(label, GTK_ALIGN_START);

    appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE] = gtk_entry_new ();
    gtk_widget_set_can_focus(appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE], FALSE);
    gtk_editable_set_editable (GTK_EDITABLE(appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE]), FALSE);
    gtk_widget_show (appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE]);
    gtk_widget_set_hexpand(appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE], TRUE);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[COLUMN_BIRTH_DAY_DATE], 2, pos, 2, 1);

    appGUI->cnt->birth_day_date_button = gtk_button_new_from_icon_name (OSMO_STOCK_BUTTON_SELECT_DATE, GTK_ICON_SIZE_BUTTON);
    gtk_widget_set_can_focus(appGUI->cnt->birth_day_date_button, FALSE);
    gtk_widget_show (appGUI->cnt->birth_day_date_button);
    msg_date[0].data = GINT_TO_POINTER(COLUMN_BIRTH_DAY_DATE);
    msg_date[0].appGUI = appGUI;
    g_signal_connect (G_OBJECT (appGUI->cnt->birth_day_date_button), "clicked",
                      G_CALLBACK (date_select_cb), &msg_date[0]);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->birth_day_date_button, 4, pos, 1, 1);

    pos++;

    /* NAMEDAY DATE */

    g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[COLUMN_NAME_DAY_DATE*2]));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_widget_set_margin_left(label, 4);
    gtk_widget_set_margin_right(label, 4);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
    gtk_widget_set_halign(label, GTK_ALIGN_START);

    appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE] = gtk_entry_new ();
    gtk_widget_set_can_focus(appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE], FALSE);
    gtk_editable_set_editable (GTK_EDITABLE(appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE]), FALSE);
    gtk_widget_show (appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE]);
    gtk_widget_set_hexpand(appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE], TRUE);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[COLUMN_NAME_DAY_DATE], 2, pos, 2, 1);

    appGUI->cnt->name_day_date_button = gtk_button_new_from_icon_name (OSMO_STOCK_BUTTON_SELECT_DATE, GTK_ICON_SIZE_BUTTON);
    gtk_widget_set_can_focus(appGUI->cnt->name_day_date_button, FALSE);
    gtk_widget_show (appGUI->cnt->name_day_date_button);
    msg_date[1].data = GINT_TO_POINTER(COLUMN_NAME_DAY_DATE);
    msg_date[1].appGUI = appGUI;
    g_signal_connect (G_OBJECT (appGUI->cnt->name_day_date_button), "clicked",
                      G_CALLBACK (date_select_cb), &msg_date[1]);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->name_day_date_button, 4, pos, 1, 1);

    pos++;

    /* PHOTO */

    g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[COLUMN_PHOTO*2]));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_widget_set_margin_left(label, 4);
    gtk_widget_set_margin_right(label, 4);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
    gtk_widget_set_halign(label, GTK_ALIGN_START);

    appGUI->cnt->contact_entries[COLUMN_PHOTO] = gtk_entry_new ();
    gtk_widget_set_can_focus(appGUI->cnt->contact_entries[COLUMN_PHOTO], FALSE);
    gtk_editable_set_editable (GTK_EDITABLE(appGUI->cnt->contact_entries[COLUMN_PHOTO]), FALSE);
    gtk_widget_show (appGUI->cnt->contact_entries[COLUMN_PHOTO]);
    gtk_widget_set_hexpand(appGUI->cnt->contact_entries[COLUMN_PHOTO], TRUE);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[COLUMN_PHOTO], 2, pos, 1, 1);

    appGUI->cnt->photo_browse_button = gtk_button_new_from_icon_name ("folder", GTK_ICON_SIZE_BUTTON);
    gtk_widget_set_can_focus(appGUI->cnt->photo_browse_button, FALSE);
    gtk_widget_show (appGUI->cnt->photo_browse_button);
    g_signal_connect (G_OBJECT (appGUI->cnt->photo_browse_button), "clicked",
                      G_CALLBACK (photo_file_select_cb), appGUI);
    gtk_grid_attach (GTK_GRID (table), appGUI->cnt->photo_browse_button, 3, pos, 1, 1);
    
    photo_clear_button = gtk_button_new_from_icon_name ("edit-clear", GTK_ICON_SIZE_BUTTON);
    gtk_widget_show (photo_clear_button);
    g_signal_connect (G_OBJECT (photo_clear_button), "clicked",
                      G_CALLBACK (photo_clear_cb), appGUI);
    gtk_grid_attach (GTK_GRID (table), photo_clear_button, 4, pos, 1, 1);
    pos++;

    /*** HOME ***/

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_grid_attach (GTK_GRID (table), hseparator, 0, pos, 5, 1);
    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Home"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    for(i=COLUMN_HOME_ADDRESS; i<COLUMN_WORK_ORGANIZATION; i++) {

        g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(contact_replace_tags[i-COLUMN_HOME_ADDRESS]));
        label = gtk_label_new (tmpbuf);
        gtk_widget_show (label);
        gtk_widget_set_margin_left(label, 4);
        gtk_widget_set_margin_right(label, 4);
        gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
        gtk_widget_set_halign(label, GTK_ALIGN_START);

        appGUI->cnt->contact_entries[i] = gtk_entry_new ();
        gtk_widget_show (appGUI->cnt->contact_entries[i]);
        gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
        gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 3, 1);
        pos++;
    }

    /*** WORK ***/

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_grid_attach (GTK_GRID (table), hseparator, 0, pos, 5, 1);
    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Work"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    for(i=COLUMN_WORK_ORGANIZATION; i<COLUMN_HOME_PHONE_1; i++) {

        if (i >= COLUMN_WORK_ADDRESS && i <= COLUMN_WORK_COUNTRY) {
            g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(contact_replace_tags[i-COLUMN_WORK_ADDRESS]));
        } else {
            g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[i*2]));
        }
        label = gtk_label_new (tmpbuf);
        gtk_widget_show (label);
        gtk_widget_set_margin_left(label, 4);
        gtk_widget_set_margin_right(label, 4);
        gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
        gtk_widget_set_halign(label, GTK_ALIGN_START);

        appGUI->cnt->contact_entries[i] = gtk_entry_new ();
        gtk_widget_show (appGUI->cnt->contact_entries[i]);
        gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
        gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 3, 1);
        pos++;
    }

    /*** PHONES ***/

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_grid_attach (GTK_GRID (table), hseparator, 0, pos, 5, 1);
    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Phones"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    for(i=COLUMN_HOME_PHONE_1; i<COLUMN_EMAIL_1; i++) {

        g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[i*2]));
        label = gtk_label_new (tmpbuf);
        gtk_widget_set_margin_left(label, 4);
        gtk_widget_set_margin_right(label, 4);
        gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
        gtk_widget_set_halign(label, GTK_ALIGN_START);

        appGUI->cnt->contact_entries[i] = gtk_entry_new ();
        gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
        gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 2, 1);
        msg_index[i].appGUI = appGUI;
        msg_index[i].data = GINT_TO_POINTER(i);
        g_signal_connect (G_OBJECT (appGUI->cnt->contact_entries[i]), "key_press_event",
                          G_CALLBACK (show_hide_fields_key_press_cb), &msg_index[i]);

        if (i != COLUMN_HOME_PHONE_4 && i != COLUMN_WORK_PHONE_4 && i != COLUMN_CELL_PHONE_4) {

            appGUI->cnt->next_field_button[i] = gtk_button_new_from_icon_name ("go-down", GTK_ICON_SIZE_BUTTON);
            gtk_widget_hide (appGUI->cnt->next_field_button[i]);
            gtk_widget_set_can_focus(appGUI->cnt->next_field_button[i], FALSE);

            g_signal_connect (G_OBJECT (appGUI->cnt->next_field_button[i]), "clicked",
                              G_CALLBACK (next_field_button_clicked_cb), &msg_index[i]);
            gtk_grid_attach (GTK_GRID (table), appGUI->cnt->next_field_button[i], 4, pos, 1, 1);
        } else {
            appGUI->cnt->next_field_button[i] = NULL;
        }

        if(i == COLUMN_HOME_PHONE_1 || i == COLUMN_WORK_PHONE_1 || i == COLUMN_CELL_PHONE_1) {
            gtk_widget_show (label);
            gtk_widget_show (appGUI->cnt->contact_entries[i]);
            gtk_widget_show (appGUI->cnt->next_field_button[i]);
        }

        pos++;
    }

    /*** INTERNET ***/

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_grid_attach (GTK_GRID (table), hseparator, 0, pos, 5, 1);
    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Internet"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    for(i=COLUMN_EMAIL_1; i<COLUMN_PHOTO; i++) {

        g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[i*2]));
        label = gtk_label_new (tmpbuf);
        gtk_widget_show (label);
        gtk_widget_set_margin_left(label, 4);
        gtk_widget_set_margin_right(label, 4);
        gtk_grid_attach (GTK_GRID (table), label, 0, pos, 2, 1);
        gtk_widget_set_halign(label, GTK_ALIGN_START);

        appGUI->cnt->contact_entries[i] = gtk_entry_new ();
        gtk_widget_show (appGUI->cnt->contact_entries[i]);
        msg_index[i].appGUI = appGUI;
        msg_index[i].data = GINT_TO_POINTER(i);
        g_signal_connect (G_OBJECT (appGUI->cnt->contact_entries[i]), "key_press_event",
                          G_CALLBACK (show_hide_fields_key_press_cb), &msg_index[i]);

        if (i == COLUMN_EMAIL_1 || i == COLUMN_EMAIL_2 || i == COLUMN_EMAIL_3 || 
            i == COLUMN_WWW_1 || i == COLUMN_WWW_2 || i == COLUMN_WWW_3) {

            appGUI->cnt->next_field_button[i] = gtk_button_new_from_icon_name ("go-down", GTK_ICON_SIZE_BUTTON);
            gtk_widget_hide (appGUI->cnt->next_field_button[i]);
            gtk_widget_set_can_focus(appGUI->cnt->next_field_button[i], FALSE);

            g_signal_connect (G_OBJECT (appGUI->cnt->next_field_button[i]), "clicked",
                              G_CALLBACK (next_field_button_clicked_cb), &msg_index[i]);
            gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
            gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 2, 1);
            gtk_grid_attach (GTK_GRID (table), appGUI->cnt->next_field_button[i], 4, pos, 1, 1);
        } else if (i == COLUMN_EMAIL_4 || i == COLUMN_WWW_4) {
            appGUI->cnt->next_field_button[i] = NULL;
            gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
            gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 2, 1);
        } else {
            appGUI->cnt->next_field_button[i] = NULL;
            gtk_widget_set_hexpand(appGUI->cnt->contact_entries[i], TRUE);
            gtk_grid_attach (GTK_GRID (table), appGUI->cnt->contact_entries[i], 2, pos, 3, 1);
        }


        if(i == COLUMN_EMAIL_1 || i == COLUMN_WWW_1) {
            gtk_widget_show (appGUI->cnt->next_field_button[i]);
        }

        if((i > COLUMN_EMAIL_1  && i < COLUMN_WWW_1) || (i > COLUMN_WWW_1  && i < COLUMN_IM_GG)) {
            gtk_widget_hide (label);
            gtk_widget_hide (appGUI->cnt->contact_entries[i]);
        }

        pos++;
    }

    /*** Additional info ***/

    hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_widget_show (hseparator);
    gtk_grid_attach (GTK_GRID (table), hseparator, 0, pos, 5, 1);
    pos++;

    g_snprintf(tmpbuf, BUFFER_SIZE, "<b><big>%s</big></b>", _("Additional info"));
    label = gtk_label_new (tmpbuf);
    gtk_widget_show (label);
    gtk_grid_attach (GTK_GRID (table), label, 0, pos, 5, 1);
    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_margin_left (label, 5);
    gtk_widget_set_margin_right (label, 5);

    pos++;

    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (scrolledwindow);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN);
    gtk_widget_set_hexpand(scrolledwindow, TRUE);
    gtk_widget_set_vexpand(scrolledwindow, TRUE);
    gtk_widget_set_size_request (scrolledwindow, -1, 350);
    gtk_grid_attach (GTK_GRID (table), scrolledwindow, 0, pos, 5, 1);

    appGUI->cnt->add_info_textview = gtk_text_view_new ();
    gtk_container_add (GTK_CONTAINER (scrolledwindow), appGUI->cnt->add_info_textview);
    /*gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (appGUI->cnt->add_info_textview), GTK_WRAP_WORD);*/
    gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW(appGUI->cnt->add_info_textview), 4);
    gtk_text_view_set_left_margin (GTK_TEXT_VIEW(appGUI->cnt->add_info_textview), 4);
    gtk_text_view_set_right_margin (GTK_TEXT_VIEW(appGUI->cnt->add_info_textview), 4);
    gtk_widget_show (appGUI->cnt->add_info_textview);

    /*appGUI->cnt->fd_ai_font = pango_font_description_from_string(config.contact_item_font);*/
    appGUI->cnt->fd_ai_font = pango_font_description_from_string("Monospace");
    gtk_widget_override_font (GTK_WIDGET(appGUI->cnt->add_info_textview), appGUI->cnt->fd_ai_font);

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

    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_container_set_border_width (GTK_CONTAINER (hbuttonbox), 2);
    gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
    gtk_box_set_spacing (GTK_BOX (hbuttonbox), 16);

    cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
    gtk_widget_show (cancel_button);
    gtk_container_add (GTK_CONTAINER (hbuttonbox), cancel_button);
    g_signal_connect(cancel_button, "clicked", 
                     G_CALLBACK(button_contacts_add_edit_window_close_cb), appGUI);

    appGUI->cnt->contacts_ok_button = gtk_button_new_with_mnemonic (_("_OK"));
    gtk_widget_show (appGUI->cnt->contacts_ok_button);
    gtk_container_add (GTK_CONTAINER (hbuttonbox), appGUI->cnt->contacts_ok_button);
    g_signal_connect(appGUI->cnt->contacts_ok_button, "clicked",
                     G_CALLBACK(contacts_item_entered_cb), appGUI);

    appGUI->cnt->contacts_edit_state = contacts_edit_mode;
    appGUI->cnt->contacts_accept_state = FALSE;

    if (contacts_edit_mode == TRUE) {
        appGUI->cnt->contacts_accept_state = TRUE;

        iter = utl_gui_get_first_selection_iter(appGUI->cnt->contacts_list_selection, &model);

        for(i=0; i < CONTACTS_NUM_COLUMNS; i++) {

            if (i != COLUMN_ID) {

                if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
                    gtk_tree_model_get (model, &iter, i, &date, -1);
                    if (date == 0) {
                        text = NULL;
                    } else {
                        if (i == COLUMN_BIRTH_DAY_DATE) {
                            appGUI->cnt->birthday_date = date;
                            text = g_strdup((const gchar *)julian_to_str(date, DATE_FULL, config.override_locale_settings));
                        } else {
                            appGUI->cnt->nameday_date = date;
                            text = g_strdup((const gchar *)julian_to_str(date, DATE_NAME_DAY, config.override_locale_settings));
                        }
                    }
                } else {
                    gtk_tree_model_get (model, &iter, i, &text, -1);
                }

                if (text != NULL) {
                    if (i == COLUMN_GROUP) {
                        gtk_combo_box_set_active (GTK_COMBO_BOX(appGUI->cnt->combobox_group),
                                                  utl_gui_list_store_get_text_index (appGUI->opt->contacts_group_store, text));
                    } else if (i == COLUMN_INFO) {
                        text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(appGUI->cnt->add_info_textview));
                        utl_gui_clear_text_buffer (text_buffer, &titer);
                        gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(text_buffer), &titer, 0);
                        gtk_text_buffer_insert (text_buffer, &titer, text, -1);
                        gtk_text_view_set_buffer (GTK_TEXT_VIEW(appGUI->cnt->add_info_textview), text_buffer);
                    } else {
                        gtk_entry_set_text (GTK_ENTRY(appGUI->cnt->contact_entries[i]), text);
                        if (appGUI->cnt->next_field_button[i] != NULL) {
                            gtk_widget_show (appGUI->cnt->next_field_button[i]);
                        }
                    }
                    g_free(text);
                }
            }
        }

        show_hide_multiple_fields(appGUI);
    }

    gtk_widget_set_sensitive(appGUI->cnt->contacts_ok_button, appGUI->cnt->contacts_accept_state);

    g_signal_connect(G_OBJECT(appGUI->cnt->combobox_group), "changed",
                     G_CALLBACK(group_combobox_changed_cb), appGUI);

    gtk_widget_show(appGUI->cnt->contacts_add_window);
    gtk_widget_grab_focus (appGUI->cnt->contact_entries[COLUMN_FIRST_NAME]);
}

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

void
read_contacts_entries (GUI *appGUI) {

xmlDocPtr doc;
xmlChar *key;
xmlNodePtr node, cnode, main_node;
xmlNodePtr group_node;
GtkTreeIter iter;
gint j;
gchar tmpbuf[BUFFER_SIZE];

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

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

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

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

        main_node = node->xmlChildrenNode;

        while (main_node != NULL) {

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

                group_node = main_node->xmlChildrenNode;

                while (group_node != NULL) {

                    if ((!xmlStrcmp(group_node->name, (const xmlChar *) "name"))) {
                        key = xmlNodeGetContent (group_node->xmlChildrenNode);
                        if (key != NULL) {
                            if GTK_IS_LIST_STORE(appGUI->opt->contacts_group_store) {
                                gtk_list_store_append(appGUI->opt->contacts_group_store, &iter);
                                gtk_list_store_set(appGUI->opt->contacts_group_store, &iter, 0, (gchar *) key, -1);
                            }
                            xmlFree (key);
                        }
                    }

                    group_node = group_node->next;
                }
            }

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

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

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

                while (node != NULL) {

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

                        cnode = node->xmlChildrenNode;

                        gtk_list_store_append(appGUI->cnt->contacts_list_store, &iter);
                        g_snprintf(tmpbuf, BUFFER_SIZE, "(%s)", _("None"));
                        gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, COLUMN_GROUP, tmpbuf, -1);
                        gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, COLUMN_FIRST_NAME, tmpbuf, -1);
                        gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, COLUMN_LAST_NAME, tmpbuf, -1);

                        while (cnode != NULL) {

                            for (j = COLUMN_GROUP; j < CONTACTS_NUM_COLUMNS; j++) {
                                if (j != COLUMN_ID) {
                                    if (j == COLUMN_BIRTH_DAY_DATE || j == COLUMN_NAME_DAY_DATE) {
                                        guint32 date = 0;
                                        utl_xml_get_uint(appGUI->cnt->contact_fields_tags_name[j * 2 + 1], &date, cnode);
                                        if (date) {
                                            gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, j, date, -1);
                                        }
                                    } else {
                                        gchar *value = NULL;
                                        utl_xml_get_str(appGUI->cnt->contact_fields_tags_name[j * 2 + 1], &value, cnode);
                                        if (value) {
                                            gtk_list_store_set(appGUI->cnt->contacts_list_store, &iter, j, value, -1);
                                        }
                                    }
                                }
                            }
                            cnode = cnode->next;
                        }

                    }

                    node = node->next;
                }

            }

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

            main_node = main_node->next;
        }

        xmlFree(node);
        xmlFreeDoc(doc);

        appGUI->cnt->write_flag = TRUE;

        contacts_fill_ids (appGUI);

    } else {

        appGUI->cnt->write_flag = FALSE;

        /* FIXME: add translation here */
        g_snprintf(tmpbuf, BUFFER_SIZE, "Contacts file is malformed. Please edit\n<b>%s</b>\nfile manually to fix its structure and restart the Osmo.", 
                 prefs_get_data_filename(CONTACTS_ENTRIES_FILENAME, appGUI));
        utl_gui_create_dialog (GTK_MESSAGE_ERROR, tmpbuf, NULL);
    }

}

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

void
write_contacts_entries (GUI *appGUI) {
gboolean has_next;
xmlDocPtr doc;
xmlNodePtr main_node, node, note_node;
xmlAttrPtr attr;
GtkTreeIter iter;
gchar *item;

    if (((appGUI->save_status & WRT_CONTACTS) != 0) || appGUI->cnt->write_flag == FALSE) return;

    appGUI->save_status |= WRT_CONTACTS;

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

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

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

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->opt->contacts_group_store), &iter);
    while (has_next) {
        gtk_tree_model_get (GTK_TREE_MODEL(appGUI->opt->contacts_group_store), &iter, 0, &item, -1);
        utl_xml_put_str ("name", item, node);
        g_free (item);
        has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->opt->contacts_group_store), &iter);
    }

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

    has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
    while (has_next) {
        gint i;

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

        for (i = COLUMN_GROUP; i < CONTACTS_NUM_COLUMNS; i++) {

            if (i != COLUMN_ID) {

                if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
                    guint32 date;

                    gtk_tree_model_get(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter, i, &date, -1);
                    if (date) {
                        utl_xml_put_uint(appGUI->cnt->contact_fields_tags_name[i * 2 + 1], date, note_node);
                    }
                } else {
                    gtk_tree_model_get (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter, i, &item, -1);

                    if (item) {
                        if (strlen(item)) {
                            utl_xml_put_str (appGUI->cnt->contact_fields_tags_name[i*2+1], item, note_node);
                        }
                    }

                    g_free (item);
                }
            }
        }
        has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
    }

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

    appGUI->save_status &= ~WRT_CONTACTS;
}

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

#endif  /* CONTACTS_ENABLED */

