/*
   Kickshaw - A Menu Editor for Openbox

   Copyright (c) 2010–2024        Marcus Schätzle

   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 Kickshaw. If not, see http://www.gnu.org/licenses/.
*/

#ifndef __declarations_definitions_and_enumerations_h
#define __declarations_definitions_and_enumerations_h

// The following pragmas also work with Clang.
#if !(GLIB_CHECK_VERSION(2,44,0))
#pragma GCC error "The minimum version of GLib needed to compile Kickshaw is 2.44."
#endif
#if !(GTK_CHECK_VERSION(3,18,0))
#pragma GCC error "The minimum version of GTK needed to compile Kickshaw is 3.18."
#endif

#define G_DISABLE_ASSERT // Leave this uncommented when compiling after testing

#include <glib/gi18n.h>
#include <libintl.h>
#include <stdbool.h>


/*

	Function prototypes

*/


// adding_and_deleting.c

void action_option_insert (const gchar *origin);
void add_new (const gchar *new_menu_element_plus_opt_suppl);
void generate_items_for_action_option_combo_box (const gchar *preset_choice);
void hide_action_option_grid (const gchar *origin);
void one_of_the_enter_values_buttons_pressed (const gchar *origin);
void remove_all_children (void);
void remove_menu_id (const gchar *menu_id);
void remove_rows (const gchar *origin);
void show_or_hide_startupnotify_options (void);
void single_field_entry (void);

// auxiliary.c

#if !__GLIBC__
gint8 strverscmp_nonglibc (const gchar *version1, const gchar *version2);
#endif
void add_elements_to_ptr_array (GPtrArray *array, ...) G_GNUC_NULL_TERMINATED;
gboolean add_icon_occurrence_to_list (G_GNUC_UNUSED GtkTreeModel *foreach_model, 
                                                    GtkTreePath  *foreach_path,
                                                    GtkTreeIter  *foreach_iter,
                                      G_GNUC_UNUSED gpointer      user_data);
gboolean check_expansion_statuses_of_nodes (GtkTreeModel *foreach_or_filter_model, 
                                            GtkTreePath  *foreach_or_filter_path, 
                                            GtkTreeIter  *foreach_or_filter_iter, 
                                            gpointer      expansion_statuses_of_nodes_ptr);
void check_for_existing_options (      GtkTreeIter  *parent, 
                                 const guint8        number_of_opts, 
                                 const gchar       **options_array, 
                                       gboolean     *opts_exist);
guint8 check_if_invisible_ancestor_exists (GtkTreeModel *local_model, 
                                           GtkTreePath  *local_path);
gboolean check_if_invisible_descendant_exists (              GtkTreeModel *filter_model,
                                               G_GNUC_UNUSED GtkTreePath  *filter_path,
                                                             GtkTreeIter  *filter_iter, 
                                                             gboolean     *at_least_one_descendant_is_invisible);
gboolean check_if_regex_is_valid (GtkWidget *regex_checkbox, 
                                  GtkWidget *entry_field);
GtkWidget *create_dialog (      GtkWidget **dialog, 
                          const gchar      *dialog_title, 
                          const gchar      *icon_name, 
                          const gchar      *label_txt, 
                          const gchar      *button_txt_1, 
                          const gchar      *button_txt_2, 
                          const gchar      *button_txt_3, 
                          const gboolean    show_immediately);
void create_file_dialog (      GtkWidget **dialog, 
                         const gboolean    open);
void create_invalid_icon_imgs (void);
void delete_autosave (void);
void delete_undo_stack_items (void);
void determine_theme_type (void);
void expand_row_from_iter (GtkTreeIter *local_iter);
gchar *extract_substring_via_regex (const gchar *string, 
                                    const gchar *regex_str);
void find_in_columns_management (const gboolean    origin_is_fr, 
                                       GtkWidget **in_columns, 
                                       GtkWidget  *in_all_columns, 
                                       gulong     *handler_ids, 
                                 const gchar      *column_check_button_clicked);
void free_elements_of_static_string_array (      gchar    **string_array, 
                                                 gint8      number_of_fields, 
                                           const gboolean   set_to_NULL);
gchar *get_font_name (void);
guint get_font_size (void);
gchar *get_modification_time_for_icon (const gchar *icon_path);
gchar *get_txt_from_resources (      GResource *resources, 
                               const gchar     *path);
void get_toplevel_iter_from_path (GtkTreeIter *local_iter, 
                                  GtkTreePath *local_path);
const gchar *installed_or_local (void);
GtkWidget *new_label_with_formattings (const gchar    *label_txt, 
                                       const gboolean  wrap);
void repopulate_txt_fields_array (void);
gboolean rm_rf (GFile         *file, 
                GCancellable  *cancellable, 
                GError       **error);
void set_header_bar_for_dialog (      GtkWidget *dialog, 
                                const gchar     *dialog_title_txt);
void set_settings (gint field, ...); // No G_GNUC_NULL_TERMINATED here, as the sentinel is -1, not NULL.
void show_message_dialog (const gchar *dialog_title, 
                          const gchar *icon_name, 
                          const gchar *label_txt, 
                          const gchar *button_txt);
gboolean streq_any (const gchar *string, ...) G_GNUC_NULL_TERMINATED;
void visually_indicate_request_for_user_intervention (GtkWidget      *widget, 
                                                      GtkCssProvider *css_provider);

// check_for_external_changes_timeout.c

gboolean check_for_external_file_and_settings_changes (G_GNUC_UNUSED gpointer identifier);
void stop_timeout (void);

// context_menu.c

void create_context_menu (GdkEventButton *event);

// drag_and_drop.c

void drag_drop_handler (G_GNUC_UNUSED GtkWidget      *widget, 
                        G_GNUC_UNUSED GdkDragContext *drag_context, 
                                      gint            x, 
                                      gint            y,
                        G_GNUC_UNUSED guint           time,
                        G_GNUC_UNUSED gpointer        user_data);
void drag_leave_handler (G_GNUC_UNUSED GtkWidget      *widget,
                         G_GNUC_UNUSED GdkDragContext *drag_context, 
                         G_GNUC_UNUSED guint           time,
                         G_GNUC_UNUSED gpointer        user_data);
gboolean drag_motion_handler (G_GNUC_UNUSED GtkWidget      *widget,
                                            GdkDragContext *drag_context, 
                                            gint            x, 
                                            gint            y, 
                                            guint           time, 
                              G_GNUC_UNUSED gpointer        user_data);

// editing.c

void boolean_toggled (void);
void build_entry_liststore (gpointer treestore_pos_ptr);
void cell_edited (G_GNUC_UNUSED       GtkCellRendererText *renderer, 
                                const gchar               *path, 
                                const gchar               *new_text, 
                                      gpointer             column_number_pointer);
void change_row (gpointer changed_entry_field_ptr);
gchar *choose_icon (void);
gboolean entry_completion_func (                    GtkEntryCompletion *entry_completion, 
                                G_GNUC_UNUSED const gchar              *key, 
                                                    GtkTreeIter        *match_iter, 
                                G_GNUC_UNUSED       gpointer            user_data);
gboolean focus_no_longer_on_entry_field (G_GNUC_UNUSED gpointer user_data);
void icon_choosing_by_button_or_context_menu (void);
void move_selection (gpointer direction_pointer);
void remove_icons_from_menus_or_items (gpointer push_on_undo_stack);
gboolean set_icon (      GtkTreeIter *icon_iter, 
                   const gchar       *icon_path, 
                   const gboolean     display_err_msg, 
                   const gboolean     during_undo_redo);
void sort_execute_or_startupnotify_options_after_insertion (      GtkTreeSelection *selection, 
                                                                  GtkTreeIter      *parent, 
                                                            const gchar            *execute_or_startupnotify, 
                                                            const gchar            *option);
gboolean sort_loop_after_sorting_activation (GtkTreeModel  *foreach_model, 
                                             GtkTreePath   *foreach_path,
                                             GtkTreeIter   *foreach_iter, 
                                             G_GNUC_UNUSED  gpointer user_data);
void visualize_menus_items_and_separators (gpointer recursively_pointer);

// find.c

gchar *compute_final_search_string (const gchar *string);
GList *create_list_of_rows_with_found_occurrences (void);
void find_buttons_management (const gchar *column_check_button_clicked);
void jump_to_previous_or_next_occurrence (gpointer direction_pointer);
void run_search (void);
void set_forward_and_back_buttons_of_find_grid (void);
void show_or_hide_find_grid (void);

// find_and_replace.c

void show_find_and_replace_dialog (void);

// kickshaw.c

void activate_change_done (void);
void change_view_and_options_GMenu (GSimpleAction *simple_action, 
                                    GVariant      *parameter, 
                                    gpointer       key_str_pointer);
void clear_global_data (void);
gboolean close_window (GtkWidget   *window, 
                       GdkEventKey *event_key, 
                       gpointer     keys);
gboolean continue_despite_unsaved_changes (void);
PangoTabArray *create_and_set_tab_array (void);
void get_latest_version_str_from_server_callback (              GObject      *source_object, 
                                                                GAsyncResult *result, 
                                                  G_GNUC_UNUSED gpointer      user_data);
gboolean selection_block_unblock (G_GNUC_UNUSED GtkTreeSelection *selection, 
                                  G_GNUC_UNUSED GtkTreeModel     *model,
                                  G_GNUC_UNUSED GtkTreePath      *path, 
                                  G_GNUC_UNUSED gboolean          path_currently_selected, 
                                                gpointer          block_state);
void set_filename_and_window_title (gchar *new_filename);
void set_status_of_expand_and_collapse_buttons_and_menu_items (void);
void show_errmsg (const gchar *errmsg_raw_txt);
void show_msg_in_statusbar (const gchar *message);

// load_menu.c

gboolean get_menu_elements_from_file (gchar *new_filename);
void open_menu (void);

// save_menu.c

void save_menu (gchar *save_as_filename);
void save_menu_as (void);

// selecting.c

void row_selected (void);
void set_entry_fields (void);

// undo_redo_autosave.c

void push_new_item_on_undo_stack (const gboolean after_save);
void undo_redo_restore (const gchar *action);
void write_autosave (GFile *compressed_undo_file);


/*

	Enumerations

*/


// possible edits done to the menu during loading process
enum { ICON_INFO_CORRECTED, INVALID_OPTION_VALUE_CORRECTED, INVISIBLE_ELEMENT_VISUALIZED_OR_REMOVED, DEPRECATED_EXE_CMD_CVTD, 
       NUMBER_OF_LOADING_PROCESS_EDIT_TYPES };
// action option combo
enum { ACTION_OPTION_COMBO_ITEM, NUMBER_OF_ACTION_OPTION_COMBO_ELEMENTS };
// new action option grid/table widgets
enum { INSIDE_MENU_LABEL, INSIDE_MENU_CHECK_BUTTON, INCLUDING_ACTION_LABEL, INCLUDING_ACTION_CHECK_BUTTON, 
       NEW_ACTION_OPTION_COMBO_BOX, ACTION_OPTION_DONE, ACTION_OPTION_CANCEL, NUMBER_OF_NEW_ACTION_OPTION_WIDGETS };
// actions
enum { EXECUTE, EXIT, RECONFIGURE, RESTART, SESSIONLOGOUT, NUMBER_OF_ACTIONS };
// add buttons
enum { MENU, PIPE_MENU, ITEM, SEPARATOR, ACTION_OR_OPTION, NUMBER_OF_ADD_BUTTONS };
// ancestor visibility
enum { NONE_OR_VISIBLE_ANCESTOR, INVISIBLE_ANCESTOR, INVISIBLE_ORPHANED_ANCESTOR };
// columns
enum { COL_MENU_ELEMENT, COL_TYPE, COL_VALUE, COL_MENU_ID, COL_EXECUTE, COL_ELEMENT_VISIBILITY, NUMBER_OF_COLUMNS };
// visibility states
enum { VISIBLE, INVISIBLE_MENU, INVISIBLE_ITEM, INVISIBLE_ORPHANED_MENU, 
       INVISIBLE_DSCT_OF_INVISIBLE_MENU, INVISIBLE_DSCT_OF_INVISIBILE_ORPHANED_MENU, NUMBER_OF_VISIBILITY_STATES };
// entry fields
enum { MENU_ELEMENT_OR_VALUE_ENTRY, ICON_PATH_ENTRY, MENU_ID_ENTRY, EXECUTE_ENTRY, NUMBER_OF_ENTRY_FIELDS };
// execute options
enum { PROMPT, COMMAND, STARTUPNOTIFY, SN_OR_PROMPT = 2, NUMBER_OF_EXECUTE_OPTS };
// find buttons
enum { CLOSE, BACK, FORWARD, NUMBER_OF_FIND_ENTRY_BUTTONS };
// special options for find
enum { MATCH_CASE, REGULAR_EXPRESSION, WHOLE_WORD, NUMBER_OF_SPECIAL_OPTIONS };
// find and replace entry fields
enum { REPLACE_ENTRY, WITH_ENTRY, NUMBER_OF_FR_ENTRY_FIELDS };
// invalid icon images
enum { INVALID_PATH_ICON, INVALID_FILE_ICON, NUMBER_OF_INVALID_ICON_IMGS };
// invalid icon image statuses
enum { NONE_OR_NORMAL, INVALID_PATH, INVALID_FILE };
// popup menus
enum { FILE_MENU, EDIT_MENU, SEARCH_MENU, VIEW_MENU, OPTIONS_MENU, HELP_MENU, NUMBER_OF_MENUS };
// popup menu items file
enum { M_NEW, M_OPEN, M_SAVE, M_SAVE_AS, M_QUIT, NUMBER_OF_FILE_MENU_ITEMS };
// popup menu items edit
enum { M_UNDO, M_REDO, M_MOVE_TOP, M_MOVE_UP, M_MOVE_DOWN, M_MOVE_BOTTOM, 
       M_REMOVE, M_REMOVE_ALL_CHILDREN, M_VISUALIZE, M_VISUALIZE_RECURSIVELY, NUMBER_OF_EDIT_MENU_ITEMS };
// popup menu items find (& replace)
enum { M_FIND, M_FIND_AND_REPLACE, NUMBER_OF_SEARCH_MENU_ITEMS };
// popup menu items view
enum { M_EXPAND_ALL_NODES, M_COLLAPSE_ALL_NODES, M_SHOW_MENU_ID_COL, M_SHOW_EXECUTE_COL, M_SHOW_ELEMENT_VIS_COL, 
       M_SHOW_ICONS, M_HIGHLIGHT_SEPARATORS, M_SHOW_TREE_LINES, M_SHOW_GRID, NUMBER_OF_VIEW_MENU_ITEMS };
// popup menu element visibity submenu items
enum { M_SHOW_ELEMENT_VISIBILITY_COL_ACTVTD, M_SHOW_ELEMENT_VISIBILITY_COL_KEEP_HIGHL, NUMBER_OF_VIEW_MENU_VISIBILITY_ITEMS };
// popup menu grid submenu items
enum { M_NO_GRID_LINES, M_SHOW_GRID_HOR, M_SHOW_GRID_VER, M_BOTH, NUMBER_OF_VIEW_MENU_GRID_ITEMS };
// popup menu items options
enum { M_CREATE_BACKUP_BEFORE_OVERWRITING_MENU, M_USE_TABS_FOR_INDENTATIONS, M_KEEP_ROOT_MENU_SEPARATE, 
       M_SORT_EXECUTE_AND_STARTUPN_OPTIONS, M_NOTIFY_ABOUT_EXECUTE_OPT_CONVERSIONS, M_USE_HEADER_BAR, M_SHOW_MENU_BUTTON, 
       NUMBER_OF_OPTIONS_MENU_ITEMS };
// popup menu items help
enum { M_HINTS, M_SHORTCUTS, M_REPORT_ISSUE, M_ABOUT, NUMBER_OF_HELP_MENU_ITEMS };
// move row
enum { MOVE_TOP, MOVE_UP, MOVE_DOWN, MOVE_BOTTOM, NUMBER_OF_MOVEMENT_BUTTONS };
// startupnotify options
enum { ENABLED, NAME, WM_CLASS, ICON, NUMBER_OF_STARTUPNOTIFY_OPTS };
// toolbar buttons
enum { TB_BUTTON_NEW, TB_BUTTON_OPEN, TB_BUTTON_SAVE, TB_BUTTON_SAVE_AS, TB_BUTTON_UNDO, TB_BUTTON_REDO, 
       TB_BUTTON_FIND, TB_BUTTON_EXPAND_ALL_NODES, TB_BUTTON_COLLAPSE_ALL_NODES, NUMBER_OF_TB_BUTTONS };
// treestore elements
enum { TS_ICON_IMG, TS_ICON_IMG_STATUS, TS_ICON_MODIFICATION_TIME, TS_ICON_PATH, TS_MENU_ELEMENT, 
       TS_TYPE, TS_VALUE, TS_MENU_ID, TS_EXECUTE, TS_ELEMENT_VISIBILITY, NUMBER_OF_TS_ELEMENTS };
// text fields
enum { ICON_PATH_TXT, MENU_ELEMENT_TXT, TYPE_TXT, VALUE_TXT, MENU_ID_TXT, 
       EXECUTE_TXT, ELEMENT_VISIBILITY_TXT, NUMBER_OF_TXT_FIELDS };
// renderer for treeview
enum { TXT_RENDERER, EXCL_TXT_RENDERER, PIXBUF_RENDERER, BOOL_RENDERER, NUMBER_OF_RENDERERS };
// hint texts
enum { MENU_FILE_HINTS, WORKING_WITH_KS_HINTS, MISCELLANEOUS_HINTS, NUMBER_OF_HINT_TXTS };
// for create_file_dialog ()
enum { SAVE_FILE, OPEN_FILE };
// for write_settings ()
enum { WRITE_CURRENT_STATES, CHANGE_STATES_TO_DEFAULT };
// for the buttons inside the "new xy" mask
enum { CANCEL_NEW_XY, RESET_NEW_XY, OK_NEW_XY };
// for push_new_item_on_undo_stack ()
enum { NOT_AFTER_SAVE, AFTER_SAVE };
// for create_dialog ()
enum { DONT_SHOW_IMMEDIATELY, SHOW_IMMEDIATELY };
// for iterations through the tree
enum { CONTINUE_ITERATING, STOP_ITERATING };


/*

	Macros

*/


#define KICKSHAW_VERSION "1.1.77"
#define RELEASED_IN "2024"

#define TREEVIEW_COLUMN_OFFSET NUMBER_OF_TS_ELEMENTS - NUMBER_OF_COLUMNS
#define FREE_AND_REASSIGN(string, new_value) { g_free (string); string = new_value; }
#define NOT_NULL_AND_NOT_EMPTY(string) (string && *string)
#define STREQ(string1, string2) (g_strcmp0 ((string1), (string2)) == 0)
#define FOREACH_IN_ARRAY(array, counter) for (counter = 0; counter < sizeof (array) / sizeof *(array); ++counter)
#define FOREACH_IN_LIST(list, counter) for (counter = list; counter != NULL; counter = counter->next)

#if !(GLIB_CHECK_VERSION(2,70,0))
G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontDescription, pango_font_description_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoTabArray, pango_tab_array_free)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC(cairo_pattern_t, cairo_pattern_destroy)
#if !(GTK_CHECK_VERSION(3,24,0))
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GResource, g_resource_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTreePath, gtk_tree_path_free)
#endif


/*

	Structs

*/


/* bool should be used instead of gboolean here.
   gboolean is a typedef for int, so when TRUE is assigned to a gboolean bit field 
   this can result in a compiler warning like the following: 
   overflow in conversion from ‘int’ to ‘signed char:1’ changes value from ‘1’ to ‘-1’ */
typedef struct {
    bool at_least_one_is_expanded        : 1;
    bool at_least_one_imd_ch_is_expanded : 1;
    bool at_least_one_is_collapsed       : 1;
} b_ExpansionStatuses;

typedef struct {
    bool create_backup                 : 1;
    bool tabs_for_indentations         : 1;
    bool separate_root_menu            : 1;
    bool autosort_options              : 1;
    bool always_notify_about_opts_conv : 1;
    bool use_header_bar                : 1;
    bool show_menu_button              : 1;
} b_KickshawSettings;

typedef struct {
    const gchar *locale;

    GtkApplication *app;

    GtkWidget *window;
    GtkWidget *header_bar;
    GtkWidget *sub_box;

    GtkWidget *basename_label;
    GtkWidget *subtitle_label;

    GtkWidget *hints_window;

    GMenu *popup_menu;
    GMenuItem *MBut_menu_items[NUMBER_OF_MENUS];

    GSimpleAction *file_actions[NUMBER_OF_FILE_MENU_ITEMS];
    GSimpleAction *edit_actions[NUMBER_OF_EDIT_MENU_ITEMS];
    GSimpleAction *view_actions[NUMBER_OF_VIEW_MENU_ITEMS];
    GSimpleAction *view_action_visibility, *view_action_highlighting;
    GSimpleAction *options_actions[NUMBER_OF_OPTIONS_MENU_ITEMS];

    const gchar *grid_submenu_item_txts[NUMBER_OF_VIEW_MENU_GRID_ITEMS];
    const gchar *grid_states[NUMBER_OF_VIEW_MENU_GRID_ITEMS];

    const gchar *edit_simple_action_txts[NUMBER_OF_EDIT_MENU_ITEMS];

    GMenuItem *MBut_options_menu_items[NUMBER_OF_OPTIONS_MENU_ITEMS];

    GtkWidget *MBar_menus[NUMBER_OF_MENUS];
    GtkWidget *MBar_menu_items[NUMBER_OF_MENUS];
    GtkWidget *MBar_file_menu_items[NUMBER_OF_EDIT_MENU_ITEMS];
    GtkWidget *MBar_edit_menu_items[NUMBER_OF_EDIT_MENU_ITEMS];
    GtkWidget *MBar_view_menu_items[NUMBER_OF_VIEW_MENU_ITEMS];
    GtkWidget *MBar_options_menu_items[NUMBER_OF_OPTIONS_MENU_ITEMS];
    GtkWidget *MBar_view_menu_visibility_items[NUMBER_OF_VIEW_MENU_VISIBILITY_ITEMS];
    GtkWidget *MBar_view_menu_grid_items[NUMBER_OF_VIEW_MENU_GRID_ITEMS];

    GtkWidget *tb_buttons[NUMBER_OF_TB_BUTTONS];
    GtkWidget *tb_button_quit;

    GtkWidget *button_grid;
    GtkWidget *add_image;
    GtkWidget *bt_bar_label;
    GtkWidget *bt_add[NUMBER_OF_ADD_BUTTONS];
    GtkWidget *bt_add_action_option_label;
    GtkWidget *bt_remove;
    GtkWidget *bt_movements[NUMBER_OF_MOVEMENT_BUTTONS];

    GtkWidget *enter_values_box, *enter_values_label;

    GtkWidget *action_option_grid, *new_action_option_grid_or_table;
    GtkWidget *new_action_option_widgets[NUMBER_OF_NEW_ACTION_OPTION_WIDGETS];
    GtkListStore *action_option_combo_box_liststore;
    GtkTreeModel *action_option_combo_box_model;
    GtkWidget *mandatory;
    GString *mandatory_label_txt;
    GtkWidget *options_grid, *suboptions_grid;
    const gchar *options_label_txts[NUMBER_OF_EXECUTE_OPTS];
    GtkWidget *options_labels[NUMBER_OF_EXECUTE_OPTS], *options_fields[NUMBER_OF_EXECUTE_OPTS];
    GtkCssProvider *execute_options_css_providers[NUMBER_OF_EXECUTE_OPTS - 1]; // Only "command" and "prompt".
    GtkWidget *suboptions_labels[NUMBER_OF_STARTUPNOTIFY_OPTS], *suboptions_fields[NUMBER_OF_STARTUPNOTIFY_OPTS];
    GtkCssProvider *suboptions_fields_css_providers[NUMBER_OF_STARTUPNOTIFY_OPTS - 1]; // Only "name", "wmclass" and "icon".

    const gchar *actions[NUMBER_OF_ACTIONS];
    const gchar *execute_options[NUMBER_OF_EXECUTE_OPTS];
    const gchar *execute_displayed_txts[NUMBER_OF_EXECUTE_OPTS];

    const gchar *startupnotify_options[NUMBER_OF_STARTUPNOTIFY_OPTS];
    const gchar *startupnotify_displayed_txts[NUMBER_OF_STARTUPNOTIFY_OPTS];

    GtkWidget *separator, *enter_values_buttons_grid;

    GtkWidget *find_grid;
    GtkWidget *find_entry_buttons[NUMBER_OF_FIND_ENTRY_BUTTONS];
    GtkWidget *find_entry;
    GtkCssProvider *find_entry_css_provider;
    GtkWidget *find_in_columns[NUMBER_OF_COLUMNS - 1], *find_in_all_columns;
    GtkCssProvider *find_in_columns_css_providers[NUMBER_OF_COLUMNS - 1], *find_in_all_columns_css_provider;
    GtkWidget *special_options[NUMBER_OF_SPECIAL_OPTIONS];
    GString *search_term;
    GList *rows_with_found_occurrences;

    GtkWidget *fr_dialog;
    GtkWidget *fr_entry_fields[NUMBER_OF_FR_ENTRY_FIELDS];
    GtkWidget *fr_in_columns[NUMBER_OF_COLUMNS - 1];
    GtkWidget *fr_in_all_columns;
    GtkWidget *fr_special_options[NUMBER_OF_SPECIAL_OPTIONS];
    GtkWidget *fr_replacements_done_label;
    GtkCssProvider *fr_in_columns_css_providers[NUMBER_OF_COLUMNS - 1], *fr_in_all_columns_css_provider;

    GtkWidget *text_views[NUMBER_OF_HINT_TXTS];

    GtkWidget *treeview;
    GtkTreeStore *treestore;
    GtkTreeModel *ts_model;
    GtkTreeIter iter;
    const gchar *column_header_txts[NUMBER_OF_COLUMNS];
    GtkTreeViewColumn *columns[NUMBER_OF_COLUMNS];
    GtkCellRenderer *renderers[NUMBER_OF_RENDERERS];

    gchar *txt_fields[NUMBER_OF_TXT_FIELDS];

    GtkTargetEntry enable_list[3];

    GtkWidget *entry_grid;
    GtkWidget *entry_labels[NUMBER_OF_ENTRY_FIELDS], *entry_fields[NUMBER_OF_ENTRY_FIELDS];
    GString *label_field_txt, *menu_ID_field_txt, *execute_field_txt, *prompt_field_txt, *command_field_txt, *mandatory_empty_string_txt;
    GtkWidget *double_menu_id_label;
    GString *double_menu_id_label_txt;
    GtkCssProvider *menu_element_or_value_entry_css_provider, *icon_path_entry_css_provider, 
                   *menu_id_css_provider, *execute_entry_css_provider;
    GtkWidget *icon_chooser, *remove_icon;

    GtkListStore *liststore;
    GtkTreeModel *ls_model;

    GtkWidget *about;
    gchar *version_info;
    gboolean stopped_trying_to_connect_to_server;

    gchar *settings_file_actions;
    GPtrArray *settings_menu_items;

    GSList *source_paths;

    GSList *enter_values_user_settings;

    GtkWidget *statusbar;
    gboolean statusbar_msg_shown;

    GtkCssProvider *cm_css_provider;

    gboolean dark_theme;
    gboolean bg_image_or_gradient;
    gchar *red_hue, *blue_hue;

    gchar *icon_theme_name;
    gchar *font_desc;
    guint font_size;

    GdkPixbuf *invalid_icon_imgs[NUMBER_OF_INVALID_ICON_IMGS];

    const gchar *home_dir;
    gchar *filename;

    gchar *tmp_path;
    GFile *symlink_tmp_folder;

    gboolean restored_autosave_that_hasnt_been_saved_yet;

    GSList *menu_ids;
    GSList *rows_with_icons;

    gint number_of_undo_stack_items;
    gint pos_inside_undo_stack;
    gint last_save_pos;

    /* Only boolean values will be stored here, but using gint8 saves some space when used for an array.
       Using a bit field for this is unwieldy because the array has to be iterated at several places. */
    gint8 loading_process_edit_types[NUMBER_OF_LOADING_PROCESS_EDIT_TYPES];

    b_KickshawSettings settings;

    gboolean change_done;

    guint timeout_id;

    gulong handler_id_row_selected, 
           handler_id_action_option_combo_box, handler_id_action_option_button_clicked, 
           handler_id_show_or_hide_startupnotify_options, 
           handler_id_use_header_bar, 
           handler_id_show_menu_button, 
           handler_id_find_in_columns[NUMBER_OF_COLUMNS - 1], 
           handler_id_fr_in_columns[NUMBER_OF_COLUMNS - 1], 
           handler_id_entry_fields[NUMBER_OF_ENTRY_FIELDS], 
           handler_id_entry_field_changed, 
           handler_id_double_menu_id, 
           handler_id_including_action_check_button;
} ks_data;

#endif
