// main.c

#include <gtk/gtk.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <string.h>
#include <locale.h>
#include "compare.h" // Подключаем заголовочный файл compare.h

// Структура для хранения информации о выбранных ячейках
typedef struct {
    int row;
    int column;
} CellPosition;

// Функция хеширования для структуры CellPosition
guint cell_position_hash(gconstpointer key) {
    const CellPosition *cell = key;
    return g_int_hash(&cell->row) ^ g_int_hash(&cell->column);
}

// Функция сравнения для структуры CellPosition
gboolean cell_position_equal(gconstpointer a, gconstpointer b) {
    const CellPosition *cell_a = a;
    const CellPosition *cell_b = b;
    return cell_a->row == cell_b->row && cell_a->column == cell_b->column;
}

// Структура для передачи виджетов между функциями
typedef struct {
    GtkWidget *tree_view;
    GtkListStore *store;
    GtkWidget *text_view;
    GHashTable *selected_cells; // Хэш-таблица для хранения выбранных ячеек
    gboolean selecting;
    int start_row, start_column;
    int end_row, end_column;
    int current_row; // Текущая выбранная строка
} AppWidgets;

// Функция для проверки допустимости вводимых символов
gboolean is_valid_input(const gchar *input) {
    // Допустимые символы: расширенная латиница, МФА, '-', '(', ')', '/'
    // Устанавливаем локаль
    setlocale(LC_CTYPE, "");

    // Преобразуем строку в последовательность Unicode символов
    gunichar *winput = g_utf8_to_ucs4(input, -1, NULL, NULL, NULL);
    if (!winput) {
        return FALSE;
    }

    for (int i = 0; winput[i] != 0; i++) {
        gunichar wc = winput[i];

        if (wc == '-' || wc == '(' || wc == ')' || wc == '/') {
            continue;
        } else if ((wc >= 0x0041 && wc <= 0x005A) || // A-Z
                   (wc >= 0x0061 && wc <= 0x007A) || // a-z
                   (wc >= 0x00C0 && wc <= 0x02AF) || // Расширенная латиница и МФА
                   (wc >= 0x1D00 && wc <= 0x1D7F) || // Фонетические расширения
                   (wc >= 0x1D80 && wc <= 0x1DBF) || // Фонетические расширения дополнение
                   (wc >= 0x1E00 && wc <= 0x1EFF) || // Дополнительная расширенная латиница
                   (wc >= 0x0250 && wc <= 0x02AF)    // IPA Extensions
                   ) {
            continue;
        } else {
            g_free(winput);
            return FALSE;
        }
    }

    g_free(winput);
    return TRUE;
}

// Обработчик нажатия кнопки "Стереть"
void on_clear_clicked(GtkButton *button, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    // Очистить выбранные ячейки
    GHashTableIter iter;
    gpointer key, value;

    g_hash_table_iter_init(&iter, widgets->selected_cells);
    while (g_hash_table_iter_next(&iter, &key, &value)) {
        CellPosition *cell = (CellPosition *)key;
        GtkTreeIter tree_iter;
        GtkTreePath *path = gtk_tree_path_new_from_indices(cell->row, -1);
        if (gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->store), &tree_iter, path)) {
            gtk_list_store_set(widgets->store, &tree_iter, cell->column, "", -1);
        }
        gtk_tree_path_free(path);
    }

    // Очистить список выбранных ячеек
    g_hash_table_remove_all(widgets->selected_cells);

    // Обновить отображение
    gtk_widget_queue_draw(widgets->tree_view);

    // Очистить текстовое поле вывода
    GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
    gtk_text_buffer_set_text(buffer, "", -1);
}

// Обработчик нажатия кнопки "Сравнить"
void on_compare_clicked(GtkButton *button, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    if (widgets->current_row < 0) {
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
        gtk_text_buffer_set_text(buffer, "Ошибка: Не выбрана строка для сравнения.", -1);
        return;
    }

    // Получаем названия языков из первой строки (зеленая строка)
    GtkTreeIter iter;
    GtkTreePath *path = gtk_tree_path_new_from_indices(0, -1); // Первая строка
    if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->store), &iter, path)) {
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
        gtk_text_buffer_set_text(buffer, "Ошибка: Не удалось получить названия языков.", -1);
        gtk_tree_path_free(path);
        return;
    }

    gchar *language1 = NULL;
    gchar *language2 = NULL;

    // Предполагаем, что названия языков находятся в столбцах 1 и 2
    gtk_tree_model_get(GTK_TREE_MODEL(widgets->store), &iter,
                       1, &language1,
                       2, &language2,
                       -1);

    gtk_tree_path_free(path);

    if (!language1 || !language2) {
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
        gtk_text_buffer_set_text(buffer, "Ошибка: Названия языков отсутствуют.", -1);
        g_free(language1);
        g_free(language2);
        return;
    }

    // Получаем слова из выбранной строки
    GtkTreeIter word_iter;
    GtkTreePath *word_path = gtk_tree_path_new_from_indices(widgets->current_row, -1);
    if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->store), &word_iter, word_path)) {
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
        gtk_text_buffer_set_text(buffer, "Ошибка: Не удалось получить данные строки.", -1);
        gtk_tree_path_free(word_path);
        return;
    }

    gchar *word1 = NULL;
    gchar *word2 = NULL;

    gtk_tree_model_get(GTK_TREE_MODEL(widgets->store), &word_iter,
                       1, &word1,
                       2, &word2,
                       -1);

    gtk_tree_path_free(word_path);

    if (!word1 || !word2) {
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
        gtk_text_buffer_set_text(buffer, "Ошибка: Слова отсутствуют в выбранной строке.", -1);
        g_free(word1);
        g_free(word2);
        return;
    }

    // Сравниваем слова и получаем звуковые соответствия
    GArray *correspondences = find_sound_correspondences(word1, word2);

    // Формируем вывод
    gchar *result_text = format_correspondences(correspondences, language1, language2);

    GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));
    gtk_text_buffer_set_text(buffer, result_text, -1);

    // Освобождаем память
    g_free(language1);
    g_free(language2);
    g_free(word1);
    g_free(word2);
    g_free(result_text);
}

// Обработчик нажатия кнопки "Сравнить выделенное"
void on_compare_selected_clicked(GtkButton *button, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    // Проверить, что все выбранные ячейки находятся в одной строке
    GHashTableIter iter_hash;
    gpointer key, value;
    int row = -1;
    gboolean same_row = TRUE;

    g_hash_table_iter_init(&iter_hash, widgets->selected_cells);
    while (g_hash_table_iter_next(&iter_hash, &key, &value)) {
        CellPosition *cell = (CellPosition *)key;
        if (row == -1) {
            row = cell->row;
        } else if (cell->row != row) {
            same_row = FALSE;
            break;
        }
    }

    GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->text_view));

    if (same_row && row != -1 && g_hash_table_size(widgets->selected_cells) > 0) {
        // Получаем названия языков из первой строки (зеленая строка)
        GtkTreeIter iter;
        GtkTreePath *path = gtk_tree_path_new_from_indices(0, -1); // Первая строка
        if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->store), &iter, path)) {
            gtk_text_buffer_set_text(buffer, "Ошибка: Не удалось получить названия языков.", -1);
            gtk_tree_path_free(path);
            return;
        }

        gchar *language1 = NULL;
        gchar *language2 = NULL;

        // Предполагаем, что названия языков находятся в столбцах 1 и 2
        gtk_tree_model_get(GTK_TREE_MODEL(widgets->store), &iter,
                           1, &language1,
                           2, &language2,
                           -1);

        gtk_tree_path_free(path);

        if (!language1 || !language2) {
            gtk_text_buffer_set_text(buffer, "Ошибка: Названия языков отсутствуют.", -1);
            g_free(language1);
            g_free(language2);
            return;
        }

        // Получаем слова из выбранной строки
        GtkTreeIter word_iter;
        GtkTreePath *word_path = gtk_tree_path_new_from_indices(row, -1);
        if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->store), &word_iter, word_path)) {
            gtk_text_buffer_set_text(buffer, "Ошибка: Не удалось получить данные строки.", -1);
            gtk_tree_path_free(word_path);
            return;
        }

        gchar *word1 = NULL;
        gchar *word2 = NULL;

        gtk_tree_model_get(GTK_TREE_MODEL(widgets->store), &word_iter,
                           1, &word1,
                           2, &word2,
                           -1);

        gtk_tree_path_free(word_path);

        if (!word1 || !word2) {
            gtk_text_buffer_set_text(buffer, "Ошибка: Слова отсутствуют в выбранной строке.", -1);
            g_free(word1);
            g_free(word2);
            return;
        }

        // Сравниваем слова и получаем звуковые соответствия
        GArray *correspondences = find_sound_correspondences(word1, word2);

        // Формируем вывод
        gchar *result_text = format_correspondences(correspondences, language1, language2);

        gtk_text_buffer_set_text(buffer, result_text, -1);

        // Освобождаем память
        g_free(language1);
        g_free(language2);
        g_free(word1);
        g_free(word2);
        g_free(result_text);

    } else {
        gtk_text_buffer_set_text(buffer, "Ошибка: Выберите ячейки только одной строки.", -1);
    }
}

// Обработчик редактирования ячейки
void on_cell_edited(GtkCellRendererText *renderer, gchar *path_str, gchar *new_text, gpointer user_data) {
    GtkListStore *store = GTK_LIST_STORE(user_data);
    GtkTreeIter iter;

    // Проверяем допустимость вводимых символов
    if (!is_valid_input(new_text)) {
        // Недопустимые символы
        GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
                                                   "Ввод содержит недопустимые символы.");
        gtk_dialog_run(GTK_DIALOG(dialog));
        gtk_widget_destroy(dialog);
        return;
    }

    GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
    gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path);

    // Получить номер столбца из данных рендерера
    gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer), "column-number"));

    gtk_list_store_set(store, &iter, column, new_text, -1);

    gtk_tree_path_free(path);
}

// Функция для получения позиции ячейки из координат указателя мыши
gboolean get_cell_at_pos(GtkTreeView *tree_view, gint x, gint y, gint *row_out, gint *col_out) {
    GtkTreePath *path;
    GtkTreeViewColumn *col;
    if (gtk_tree_view_get_path_at_pos(tree_view, x, y, &path, &col, NULL, NULL)) {
        gint *indices = gtk_tree_path_get_indices(path);
        if (!indices) {
            gtk_tree_path_free(path);
            return FALSE;
        }
        *row_out = indices[0];

        GList *columns = gtk_tree_view_get_columns(tree_view);
        *col_out = g_list_index(columns, col);
        g_list_free(columns);

        gtk_tree_path_free(path);
        return TRUE;
    }
    return FALSE;
}

// Обработчик нажатия кнопки мыши
gboolean on_tree_view_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    if (event->button == 1) { // Левая кнопка мыши
        gint x = (gint)event->x;
        gint y = (gint)event->y;
        gint row, column;
        if (get_cell_at_pos(GTK_TREE_VIEW(widget), x, y, &row, &column)) {
            // Проверяем, что не нажата ячейка в столбце нумерации строк
            if (column == 0) {
                return FALSE;
            }

            // Обновляем текущую выбранную строку
            widgets->current_row = row;

            GdkModifierType state = event->state;

            if (state & GDK_SHIFT_MASK) {
                // Shift нажат
                // Проверяем, что новая ячейка в той же строке
                if (g_hash_table_size(widgets->selected_cells) > 0) {
                    GHashTableIter iter;
                    gpointer key, value;
                    gboolean same_row = TRUE;
                    int selected_row = -1;

                    g_hash_table_iter_init(&iter, widgets->selected_cells);
                    while (g_hash_table_iter_next(&iter, &key, &value)) {
                        CellPosition *cell = (CellPosition *)key;
                        if (selected_row == -1) {
                            selected_row = cell->row;
                        } else if (cell->row != selected_row) {
                            same_row = FALSE;
                            break;
                        }
                    }

                    if (same_row && row == selected_row) {
                        // Добавляем ячейку к выбору
                        CellPosition *cell = g_malloc(sizeof(CellPosition));
                        cell->row = row;
                        cell->column = column;
                        g_hash_table_insert(widgets->selected_cells, cell, cell);
                    } else {
                        // Игнорируем, если строки разные
                        return FALSE;
                    }
                } else {
                    // Если выбор пуст, просто добавляем ячейку
                    CellPosition *cell = g_malloc(sizeof(CellPosition));
                    cell->row = row;
                    cell->column = column;
                    g_hash_table_insert(widgets->selected_cells, cell, cell);
                }
            } else {
                // Shift не нажат, начинаем новое выделение

                // Очистить предыдущий выбор
                g_hash_table_remove_all(widgets->selected_cells);

                widgets->selecting = TRUE;
                widgets->start_row = row;
                widgets->start_column = column;
                widgets->end_row = row;
                widgets->end_column = column;

                // Добавить ячейку в выбранные
                CellPosition *cell = g_malloc(sizeof(CellPosition));
                cell->row = row;
                cell->column = column;
                g_hash_table_insert(widgets->selected_cells, cell, cell);
            }

            gtk_widget_queue_draw(widget);
        }
    }

    return FALSE; // Продолжить обработку события
}

// Обработчик движения мыши
gboolean on_tree_view_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    if (widgets->selecting) {
        gint x = (gint)event->x;
        gint y = (gint)event->y;
        gint row, column;
        if (get_cell_at_pos(GTK_TREE_VIEW(widget), x, y, &row, &column)) {
            // Проверяем, что не захватываем столбец нумерации строк
            if (column == 0) {
                return FALSE;
            }

            widgets->end_row = row;
            widgets->end_column = column;

            // Очистить предыдущий выбор
            g_hash_table_remove_all(widgets->selected_cells);

            // Добавить ячейки в диапазоне в выбранные
            int min_row = MIN(widgets->start_row, widgets->end_row);
            int max_row = MAX(widgets->start_row, widgets->end_row);
            int min_col = MIN(widgets->start_column, widgets->end_column);
            int max_col = MAX(widgets->start_column, widgets->end_column);

            for (int r = min_row; r <= max_row; r++) {
                for (int c = min_col; c <= max_col; c++) {
                    CellPosition *cell = g_malloc(sizeof(CellPosition));
                    cell->row = r;
                    cell->column = c;
                    g_hash_table_insert(widgets->selected_cells, cell, cell);
                }
            }

            gtk_widget_queue_draw(widget);
        }
    }

    return FALSE; // Продолжить обработку события
}

// Обработчик отпускания кнопки мыши
gboolean on_tree_view_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    if (event->button == 1 && widgets->selecting) { // Левая кнопка мыши
        widgets->selecting = FALSE;
        gtk_widget_queue_draw(widget);
    }

    return FALSE; // Продолжить обработку события
}

void on_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
                       GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;

    gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer), "column-number"));
    GtkTreePath *path = gtk_tree_model_get_path(model, iter);
    gint *indices = gtk_tree_path_get_indices(path);
    gint row = indices[0];
    gtk_tree_path_free(path);

    // Do not interfere if the cell is being edited
    GValue editing = G_VALUE_INIT;
    g_object_get_property(G_OBJECT(renderer), "editing", &editing);
    gboolean is_editing = g_value_get_boolean(&editing);
    g_value_unset(&editing);

    if (is_editing) {
        // Do not override properties while editing
        return;
    }

    // Reset previous properties (do not reset pad properties)
    g_object_set(renderer,
                 "cell-background-set", FALSE,
                 "cell-background", NULL,
                 NULL);

    // Check if the cell is selected
    CellPosition temp_cell = { row, column };
    if (g_hash_table_contains(widgets->selected_cells, &temp_cell)) {
        // Set background color for selection
        g_object_set(renderer,
                     "cell-background", "#008080", // Dark teal color
                     "cell-background-set", TRUE,
                     NULL);
    } else if (row == 0) {
        // Set background color for the first row
        g_object_set(renderer,
                     "cell-background", "#006400", // Dark green color
                     "cell-background-set", TRUE,
                     NULL);
    } else {
        // Normal cell
        g_object_set(renderer,
                     "cell-background-set", FALSE,
                     NULL);
    }
}

// Обработчик для ячеек нумерации строк
void on_row_number_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
                                  GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) {
    // Устанавливаем фон для ячеек нумерации строк
    g_object_set(renderer,
                 "cell-background", "#444444", // Цвет #444444
                 "cell-background-set", TRUE,
                 NULL);
}

// Создание новой функции для установки ширины колонок
void set_initial_column_widths(GtkTreeView *tree_view, GtkWidget *window) {
    gint window_width;
    gtk_window_get_size(GTK_WINDOW(window), &window_width, NULL);
    gint column_width = window_width / 16;

    GList *columns = gtk_tree_view_get_columns(tree_view);
    for (GList *l = columns; l != NULL; l = l->next) {
        GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(l->data);
        gtk_tree_view_column_set_min_width(col, column_width);
        gtk_tree_view_column_set_fixed_width(col, column_width);
        gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
    }
    g_list_free(columns);
}

// Сигнал изменения размера окна
void on_window_size_allocate(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) {
    AppWidgets *widgets = (AppWidgets *)user_data;
    set_initial_column_widths(GTK_TREE_VIEW(widgets->tree_view), widget);
}

int main(int argc, char *argv[]) {
    // Инициализация GTK
    gtk_init(&argc, &argv);

    // Создание главного окна
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Таблица");
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);

    // Обработка события закрытия окна
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    // Создание модели данных с 30 строковыми столбцами (+1 для нумерации строк)
    GType types[31];
    types[0] = G_TYPE_STRING; // Для нумерации строк
    for (int i = 1; i < 31; i++) {
        types[i] = G_TYPE_STRING;
    }
    GtkListStore *store = gtk_list_store_newv(31, types);

    // Создание представления таблицы
    GtkWidget *tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));

    // Отключаем стандартное выделение строк
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
    gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE);

    // Инициализация структуры для хранения виджетов
    AppWidgets *widgets = g_malloc(sizeof(AppWidgets));
    widgets->tree_view = tree_view;
    widgets->store = store;
    widgets->current_row = -1; // Инициализируем текущую строку

    // Добавление столбца для нумерации строк
    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
    GtkTreeViewColumn *number_column = gtk_tree_view_column_new_with_attributes("#", renderer, "text", 0, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), number_column);
    gtk_tree_view_column_set_resizable(number_column, FALSE);
    gtk_tree_view_column_set_sizing(number_column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_fixed_width(number_column, 30);

    // Устанавливаем функцию отображения данных для столбца нумерации строк
    gtk_tree_view_column_set_cell_data_func(number_column, renderer, on_row_number_cell_data_func, NULL, NULL);

    // Добавление остальных столбцов в таблицу
    for (int i = 1; i < 31; i++) {
        GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
        g_object_set(renderer, "editable", TRUE, NULL);

        // Сохранение номера столбца в данных рендерера
        g_object_set_data(G_OBJECT(renderer), "column-number", GINT_TO_POINTER(i));

        // Привязка обработчика редактирования ячейки
        g_signal_connect(renderer, "edited", G_CALLBACK(on_cell_edited), store);

        gchar *col_title = g_strdup_printf("%d", i);
        GtkTreeViewColumn *column = gtk_tree_view_column_new();
        gtk_tree_view_column_set_title(column, col_title);
        gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);

        gtk_tree_view_column_pack_start(column, renderer, TRUE);

        // Устанавливаем функцию для отображения данных и выделения
        gtk_tree_view_column_set_cell_data_func(column, renderer, on_cell_data_func, widgets, NULL);

        // Разрешаем растягивать столбцы
        gtk_tree_view_column_set_resizable(column, TRUE);

        // Устанавливаем политику размера столбца для автоматического расширения при вводе текста
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);

        g_free(col_title);
    }

    // Заполнение таблицы данными и номерами строк
    GtkTreeIter iter;
    for (int i = 0; i < 300; i++) {
        gtk_list_store_append(store, &iter);
        // Устанавливаем номер строки
        gchar *number = g_strdup_printf("%d", i + 1);
        gtk_list_store_set(store, &iter, 0, number, -1);
        g_free(number);

        for (int j = 1; j < 31; j++) {
            gtk_list_store_set(store, &iter, j, "", -1);
        }
    }

    // Создание области с прокруткой для таблицы
    GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_container_add(GTK_CONTAINER(scrolled_window), tree_view);

    // Создание кнопок
    GtkWidget *clear_button = gtk_button_new_with_label("Стереть");
    GtkWidget *compare_selected_button = gtk_button_new_with_label("Сравнить выделенное");
    GtkWidget *compare_button = gtk_button_new_with_label("Сравнить");

    // Создание контейнера для кнопок
    GtkWidget *button_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
    gtk_box_pack_start(GTK_BOX(button_box), clear_button, FALSE, FALSE, 5);
    gtk_box_pack_start(GTK_BOX(button_box), compare_selected_button, TRUE, TRUE, 5);
    gtk_box_pack_end(GTK_BOX(button_box), compare_button, FALSE, FALSE, 5);

    // Создание текстового поля вывода
    GtkWidget *text_view = gtk_text_view_new();
    gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(text_view), FALSE);

    // Создание области с прокруткой для текстового поля
    GtkWidget *text_view_scrolled = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(text_view_scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_container_add(GTK_CONTAINER(text_view_scrolled), text_view);
    gtk_widget_set_size_request(text_view_scrolled, -1, 100); // Устанавливаем высоту

    // Создание основного контейнера
    GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
    gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(main_vbox), button_box, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(main_vbox), text_view_scrolled, FALSE, FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), main_vbox);

    // Дополнительная инициализация структуры виджетов
    widgets->text_view = text_view;
    widgets->selected_cells = g_hash_table_new_full(cell_position_hash, cell_position_equal, g_free, NULL);
    widgets->selecting = FALSE;

    // Привязка обработчиков к кнопкам
    g_signal_connect(clear_button, "clicked", G_CALLBACK(on_clear_clicked), widgets);
    g_signal_connect(compare_button, "clicked", G_CALLBACK(on_compare_clicked), widgets);
    g_signal_connect(compare_selected_button, "clicked", G_CALLBACK(on_compare_selected_clicked), widgets);

    // Привязка обработчиков событий мыши к tree_view
    gtk_widget_add_events(tree_view, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
    g_signal_connect(tree_view, "button-press-event", G_CALLBACK(on_tree_view_button_press_event), widgets);
    g_signal_connect(tree_view, "button-release-event", G_CALLBACK(on_tree_view_button_release_event), widgets);
    g_signal_connect(tree_view, "motion-notify-event", G_CALLBACK(on_tree_view_motion_notify_event), widgets);

    // Устанавливаем начальные ширины колонок
    set_initial_column_widths(GTK_TREE_VIEW(tree_view), window);

    // Привязка сигнала изменения размера окна
    g_signal_connect(window, "size-allocate", G_CALLBACK(on_window_size_allocate), widgets);

    // Отображение всех виджетов
    gtk_widget_show_all(window);

    // Запуск главного цикла GTK
    gtk_main();

    // Освобождение памяти
    g_hash_table_destroy(widgets->selected_cells);
    g_free(widgets);

    return 0;
}

// compare.h

#ifndef COMPARE_H
#define COMPARE_H

#include <glib.h>

// Структура для хранения звуковых соответствий
typedef struct {
    gchar *sound1;
    gchar *sound2;
} SoundCorrespondence;

// Функции для сравнения слов и формирования результата
GArray* find_sound_correspondences(const gchar *word1, const gchar *word2);
gchar* format_correspondences(GArray *correspondences, const gchar *language1, const gchar *language2);

#endif // COMPARE_H

// compare.c

#include <stdio.h>
#include <string.h>
#include <glib.h>
#include "compare.h"

// Удалённое повторное определение структуры

// Массив звуковых соответствий из вашего первого сообщения
const SoundCorrespondence correspondences[] = {
    {"p", "b"}, {"p", "f"}, {"b", "f"},
    {"t", "d"}, {"t", "θ"}, {"t", "ð"},
    {"k", "g"}, {"k", "h"}, {"k", "x"},
    {"s", "z"}, {"s", "ʃ"}, {"s", "ʒ"},
    {"m", "n"}, {"m", "ŋ"}, {"n", "ŋ"},
    {"r", "l"},
    {"w", "v"}, {"w", "β"},
    {"j", "ʝ"}, {"j", "dʒ"},
    {"e", "i"}, {"e", "ɛ"},
    {"o", "u"}, {"o", "ɔ"},
    {"æ", "a"}, {"æ", "ɑ"},
    {"θ", "f"}, {"θ", "h"},
    {"d", "ð"}, {"d", "z"},
    {"k", "tʃ"}, {"k", "ʃ"},
    {"g", "ʒ"}, {"g", "dʒ"},
    {"p", "pf"}, {"p", "f"},
    {"t", "ts"}, {"t", "s"},
    {"b", "v"}, {"b", "w"},
    {"h", "ʔ"},
    {"l", "ɾ"}, {"l", "r"}
};

// Количество звуковых соответствий
const int num_correspondences = sizeof(correspondences) / sizeof(SoundCorrespondence);

// Функция для разбивки слова на звуки (предполагается посимвольная разбивка)
GArray* split_word_into_sounds(const gchar *word) {
    GArray *sounds = g_array_new(FALSE, FALSE, sizeof(gchar *));
    const gchar *p = word;

    while (*p) {
        gunichar c = g_utf8_get_char(p);
        int char_len = g_unichar_to_utf8(c, NULL);
        gchar *sound = g_utf8_substring(p, 0, 1);
        g_array_append_val(sounds, sound);
        p = g_utf8_next_char(p);
    }

    return sounds;
}

// Функция для освобождения памяти массива звуков
void free_sounds_array(GArray *sounds) {
    for (guint i = 0; i < sounds->len; i++) {
        gchar *sound = g_array_index(sounds, gchar *, i);
        g_free(sound);
    }
    g_array_free(sounds, TRUE);
}

// Функция для поиска звуковых соответствий между двумя словами
GArray* find_sound_correspondences(const gchar *word1, const gchar *word2) {
    GArray *result = g_array_new(FALSE, FALSE, sizeof(SoundCorrespondence));

    GArray *sounds1 = split_word_into_sounds(word1);
    GArray *sounds2 = split_word_into_sounds(word2);

    guint len = MIN(sounds1->len, sounds2->len);

    for (guint i = 0; i < len; i++) {
        gchar *sound1 = g_array_index(sounds1, gchar *, i);
        gchar *sound2 = g_array_index(sounds2, gchar *, i);

        // Если звуки идентичны
        if (g_strcmp0(sound1, sound2) == 0) {
            // Добавляем в результат как одинаковый звук
            SoundCorrespondence sc = { g_strdup(sound1), g_strdup(sound2) };
            g_array_append_val(result, sc);
        } else {
            // Проверяем, есть ли данная пара в списке соответствий
            for (int j = 0; j < num_correspondences; j++) {
                if ((g_strcmp0(sound1, correspondences[j].sound1) == 0 && g_strcmp0(sound2, correspondences[j].sound2) == 0) ||
                    (g_strcmp0(sound1, correspondences[j].sound2) == 0 && g_strcmp0(sound2, correspondences[j].sound1) == 0)) {
                    SoundCorrespondence sc = { g_strdup(sound1), g_strdup(sound2) };
                    g_array_append_val(result, sc);
                    break;
                }
            }
        }
    }

    free_sounds_array(sounds1);
    free_sounds_array(sounds2);

    return result;
}

// Функция для формирования строки с результатами
gchar* format_correspondences(GArray *correspondences, const gchar *language1, const gchar *language2) {
    GString *result = g_string_new("");

    if (correspondences->len == 0) {
        g_string_append(result, "Звуковые соответствия не обнаружены.");
    } else {
        for (guint i = 0; i < correspondences->len; i++) {
            SoundCorrespondence sc = g_array_index(correspondences, SoundCorrespondence, i);
            if (g_strcmp0(sc.sound1, sc.sound2) == 0) {
                // Идентичные звуки
                gchar *line = g_strdup_printf("В %s и %s одинаковый звук: /%s/.\n", language1, language2, sc.sound1);
                g_string_append(result, line);
                g_free(line);
            } else {
                // Различные звуки с соответствием
                gchar *line = g_strdup_printf("Вероятные звуковые соответствия в %s и %s: /%s/ и /%s/.\n", language1, language2, sc.sound1, sc.sound2);
                g_string_append(result, line);
                g_free(line);
            }
            g_free(sc.sound1);
            g_free(sc.sound2);
        }
    }

    g_array_free(correspondences, TRUE);

    gchar *final_result = result->str;
    g_string_free(result, FALSE);
    return final_result;
}

Проанализируй этот код и внеси в него следующие исправления:
1. Исправь баг, когда при попытке ввода текста в ячейку появляется поле ввода на месте кнопки "Сравнить", а в ячейку код не вводится.
2. Задай каждой ячейке(включая ячейки нумерации строк и колонок)  обводку шириной в 2 пикселя.
3. Задай следующие цвета ячейкам: #0d450d для цвета первой(зеленой) строки, #4a6466 для выделения, #707070 для обводки ячееу нумерации, #314344 - для обводки выделения снаружи и выделенных ячеек, #115e11 для обводки первой (зеленой) строки, #444444 для обводки обычных, не выделенных ячеек