/* ui.c
 * This file is part of Amsam photo cropping program
 * Copyright 2021, 2023, 2024, 2025, 2026 Nandakumar Edamana
 * Distributed under GNU General Public License, version 3
 */ 

#include <assert.h>
#include <stdarg.h>
#include <stdbool.h>

#include "ui.h"


#include "warpcore.c"

CommandLineOptions clopts;

double ZOOMSTEP = 0.1;

SimpleHelpItem helpitems[1] = { (SimpleHelpItem) { "TODO", "TODO" } };

Ratio ratios[8] = { (Ratio) { 1, 1, "1:1", "Square", NULL }, (Ratio) { 5, 4, "5:4", NULL, NULL }, (Ratio) { 4, 3, "4:3", "Fullscreen", NULL }, (Ratio) { 3, 2, "3:2", NULL, NULL }, (Ratio) { 1618, 1000, "1.618", "Golden ratio", NULL }, (Ratio) { 16, 9, "16:9", "HD", NULL }, (Ratio) { 185, 100, "1.85", "Flat", NULL }, (Ratio) { 239, 100, "2.39", "Scope", NULL } };

void myapp_construct(myapp *this, const char *infile_path)
{
	this->curratioh = 1;
	this->curratiow = 1;
	ImageDocument *_tmp_1 = (ImageDocument *) malloc(sizeof(ImageDocument));
	if (_tmp_1 == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	image_document_construct(_tmp_1, DEFWIDTH_DOC, DEFHEIGHT_DOC, default_drawparams(), true);
	ProxyDocument *_tmp_2 = (ProxyDocument *) malloc(sizeof(ProxyDocument));
	if (_tmp_2 == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	proxy_document_construct(_tmp_2, _tmp_1);
	this->proxydoc = _tmp_2;
	this->wnd = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
	this->accgrp = (GtkAccelGroup *) gtk_accel_group_new();
	GtkBox *bx = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
	gtk_container_set_border_width((GtkContainer *) bx, (unsigned int) 4);
	this->box_main = bx;
	this->mbr = (GtkMenuBar *) gtk_menu_bar_new();
	this->mni_file = (GtkMenuItem *) gtk_menu_item_new();
	this->mnu_file = (GtkMenu *) gtk_menu_new();
	this->mni_file_open = (GtkMenuItem *) gtk_menu_item_new();
	this->mni_file_export = (GtkMenuItem *) gtk_menu_item_new();
	this->mnisep_file_1 = (GtkSeparatorMenuItem *) gtk_separator_menu_item_new();
	this->mni_file_quit = (GtkMenuItem *) gtk_menu_item_new();
	this->mni_help = (GtkMenuItem *) gtk_menu_item_new();
	this->mnu_help = (GtkMenu *) gtk_menu_new();
	this->mni_help_topics = (GtkMenuItem *) gtk_menu_item_new();
	this->mni_help_about = (GtkMenuItem *) gtk_menu_item_new();
	GtkBox *_ngg_tmp_23_bx = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
	gtk_container_set_border_width((GtkContainer *) _ngg_tmp_23_bx, (unsigned int) 4);
	this->hbx_toolbar = _ngg_tmp_23_bx;
	GtkBox *_ngg_tmp_25_bx = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
	gtk_container_set_border_width((GtkContainer *) _ngg_tmp_25_bx, (unsigned int) 4);
	this->box_ratios = _ngg_tmp_25_bx;
	this->btn_ratio_original = (GtkRadioButton *) gtk_radio_button_new(NULL);
	this->lbl_curdims = (GtkLabel *) gtk_label_new(NULL);
	GtkBox *_ngg_tmp_27_bx = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
	gtk_container_set_border_width((GtkContainer *) _ngg_tmp_27_bx, (unsigned int) 4);
	this->hbx_export = _ngg_tmp_27_bx;
	this->btn_export_doc = (GtkButton *) gtk_button_new();
	this->grd_viewport = (GtkGrid *) gtk_grid_new();
	this->da = (GtkDrawingArea *) gtk_drawing_area_new();
	this->btn_ratio_custdim = (GtkRadioButton *) gtk_radio_button_new(NULL);
	this->btn_ratio_custrat = (GtkRadioButton *) gtk_radio_button_new(NULL);
	this->spn_custw = (GtkSpinButton *) gtk_spin_button_new(NULL, 0.1, 2u);
	this->spn_custh = (GtkSpinButton *) gtk_spin_button_new(NULL, 0.1, 2u);
	this->spn_custrat = (GtkSpinButton *) gtk_spin_button_new(NULL, 0.1, 2u);
	this->updating_lst_layers = false;
	this->layerstack_version = 0;
	this->test_vara_logo_exit = false;
	this->test_vara_logo_size = 0;
	this->disable_brush_preview = false;
	this->was_autoscroll = false;
	this->surf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, DEFWIDTH_DOC, DEFHEIGHT_DOC);

	DrawingParams dpbak = this->proxydoc->prevdoc->drawparams;

	this->ivw_ballpoint = brushpreview_widget_new(prebrush_ballpoint());
	this->ivw_charcoal = brushpreview_widget_new(prebrush_charcoal());
	this->ivw_crayon = brushpreview_widget_new(prebrush_crayon());
	this->ivw_pencil = brushpreview_widget_new(prebrush_pencil());
	this->ivw_round = brushpreview_widget_new(prebrush_round());
	this->ivw_round_pressure_size = brushpreview_widget_new(prebrush_round_pressure_size());
	this->ivw_soft_round = brushpreview_widget_new(prebrush_soft_round());

	gtk_window_set_title(this->wnd, PROGRAM_NAME);
	g_signal_connect((GtkWidget *) (this->wnd), "delete-event", G_CALLBACK(on_wnd_deleteevent), this);
	gtk_widget_set_visible((GtkWidget *) (this->wnd), false);
	g_signal_connect((GtkWidget *) (this->wnd), "destroy", G_CALLBACK(gtk_main_quit), NULL);
	gtk_window_add_accel_group(this->wnd, this->accgrp);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->wnd)), GTK_WIDGET((GtkWidget *) (this->box_main)));
	gtk_box_set_spacing(this->box_main, 0);
	gtk_container_set_border_width((GtkContainer *) (this->box_main), (unsigned int) 0);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_main)), GTK_WIDGET((GtkWidget *) (this->mbr)));
	gtk_menu_shell_append((GtkMenuShell *) (this->mbr), (GtkWidget *) (this->mni_file));
	gtk_menu_item_set_label(this->mni_file, "_File");
	gtk_menu_item_set_use_underline(this->mni_file, true);
	gtk_menu_item_set_submenu(this->mni_file, (GtkWidget *) (this->mnu_file));
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_file), (GtkWidget *) (this->mni_file_open));
	gtk_menu_item_set_label(this->mni_file_open, "_Open...");
	gtk_menu_item_set_use_underline(this->mni_file_open, true);
	g_signal_connect((GtkWidget *) (this->mni_file_open), "activate", G_CALLBACK(myapp_on_mni_file_open_activate), this);
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_file), (GtkWidget *) (this->mni_file_export));
	gtk_menu_item_set_label(this->mni_file_export, "_Export...");
	gtk_menu_item_set_use_underline(this->mni_file_export, true);
	g_signal_connect((GtkWidget *) (this->mni_file_export), "activate", G_CALLBACK(myapp_on_btn_export_doc_clicked), this);
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_file), (GtkWidget *) (this->mnisep_file_1));
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_file), (GtkWidget *) (this->mni_file_quit));
	gtk_menu_item_set_label(this->mni_file_quit, "_Quit");
	gtk_menu_item_set_use_underline(this->mni_file_quit, true);
	g_signal_connect((GtkWidget *) (this->mni_file_quit), "activate", G_CALLBACK(myapp_on_mni_file_quit_activate), this);
	gtk_menu_shell_append((GtkMenuShell *) (this->mbr), (GtkWidget *) (this->mni_help));
	gtk_menu_item_set_label(this->mni_help, "_Help");
	gtk_menu_item_set_use_underline(this->mni_help, true);
	gtk_menu_item_set_submenu(this->mni_help, (GtkWidget *) (this->mnu_help));
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_help), (GtkWidget *) (this->mni_help_topics));
	gtk_menu_item_set_label(this->mni_help_topics, "_Topics");
	gtk_menu_item_set_use_underline(this->mni_help_topics, true);
	gtk_widget_set_visible((GtkWidget *) (this->mni_help_topics), false);
	gtk_menu_shell_append((GtkMenuShell *) (this->mnu_help), (GtkWidget *) (this->mni_help_about));
	gtk_menu_item_set_label(this->mni_help_about, "_About Amsam...");
	gtk_menu_item_set_use_underline(this->mni_help_about, true);
	g_signal_connect((GtkWidget *) (this->mni_help_about), "activate", G_CALLBACK(myapp_on_mni_help_about_activate), this);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_main)), GTK_WIDGET((GtkWidget *) (this->hbx_toolbar)));
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->hbx_toolbar)), GTK_WIDGET((GtkWidget *) (this->box_ratios)));
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->btn_ratio_original)));
	gtk_button_set_label((GtkButton *) (this->btn_ratio_original), "Original");
	gtk_toggle_button_set_mode((GtkToggleButton *) (this->btn_ratio_original), false);
	gtk_widget_set_tooltip_text((GtkWidget *) (this->btn_ratio_original), "Original ratio of the image");
	g_signal_connect((GtkWidget *) (this->btn_ratio_original), "toggled", G_CALLBACK(myapp_on_btn_tool_x_toggled), this);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->hbx_toolbar)), GTK_WIDGET((GtkWidget *) (this->lbl_curdims)));
	gtk_widget_set_hexpand((GtkWidget *) (this->lbl_curdims), true);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->hbx_toolbar)), GTK_WIDGET((GtkWidget *) (this->hbx_export)));
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->hbx_export)), GTK_WIDGET((GtkWidget *) (this->btn_export_doc)));
	gtk_button_set_label(this->btn_export_doc, "Export");
	g_signal_connect((GtkWidget *) (this->btn_export_doc), "clicked", G_CALLBACK(myapp_on_btn_export_doc_clicked), this);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_main)), GTK_WIDGET((GtkWidget *) (this->grd_viewport)));
	gtk_grid_attach(this->grd_viewport, (GtkWidget *) (this->da), 0, 0, 1, 1);
	g_signal_connect((GtkWidget *) (this->da), "size-allocate", G_CALLBACK(myapp_on_da_sizeallocate), this);
	gtk_widget_set_hexpand((GtkWidget *) (this->da), true);
	gtk_widget_set_vexpand((GtkWidget *) (this->da), true);
	gtk_widget_show((GtkWidget *) (this->da));
	gtk_widget_show((GtkWidget *) (this->grd_viewport));
	gtk_widget_show((GtkWidget *) (this->btn_export_doc));
	gtk_widget_show((GtkWidget *) (this->hbx_export));
	gtk_widget_show((GtkWidget *) (this->lbl_curdims));
	gtk_widget_show((GtkWidget *) (this->btn_ratio_original));
	gtk_widget_show((GtkWidget *) (this->box_ratios));
	gtk_widget_show((GtkWidget *) (this->hbx_toolbar));
	gtk_widget_show((GtkWidget *) (this->mni_help_about));
	gtk_widget_show((GtkWidget *) (this->mnu_help));
	gtk_widget_show((GtkWidget *) (this->mni_help));
	gtk_widget_show((GtkWidget *) (this->mni_file_quit));
	gtk_widget_show((GtkWidget *) (this->mnisep_file_1));
	gtk_widget_show((GtkWidget *) (this->mni_file_export));
	gtk_widget_show((GtkWidget *) (this->mni_file_open));
	gtk_widget_show((GtkWidget *) (this->mnu_file));
	gtk_widget_show((GtkWidget *) (this->mni_file));
	gtk_widget_show((GtkWidget *) (this->mbr));
	gtk_widget_show((GtkWidget *) (this->box_main));

	unsigned int accelkey = 0u;
	GdkModifierType accelmods = (GdkModifierType) 0;
	gtk_accelerator_parse("<Ctrl>o", &accelkey, &accelmods);

	gtk_widget_add_accelerator((GtkWidget *) (this->mni_file_open), "activate", this->accgrp, accelkey, accelmods, GTK_ACCEL_VISIBLE);
	unsigned int _ngg_tmp_29_accelkey = 0u;
	GdkModifierType _ngg_tmp_31_accelmods = (GdkModifierType) 0;
	gtk_accelerator_parse("<Ctrl>e", &_ngg_tmp_29_accelkey, &_ngg_tmp_31_accelmods);

	gtk_widget_add_accelerator((GtkWidget *) (this->mni_file_export), "activate", this->accgrp, _ngg_tmp_29_accelkey, _ngg_tmp_31_accelmods, GTK_ACCEL_VISIBLE);
	unsigned int _ngg_tmp_33_accelkey = 0u;
	GdkModifierType _ngg_tmp_35_accelmods = (GdkModifierType) 0;
	gtk_accelerator_parse("<Ctrl>q", &_ngg_tmp_33_accelkey, &_ngg_tmp_35_accelmods);

	gtk_widget_add_accelerator((GtkWidget *) (this->mni_file_quit), "activate", this->accgrp, _ngg_tmp_33_accelkey, _ngg_tmp_35_accelmods, GTK_ACCEL_VISIBLE);

	GtkMenu *mnu_help_topics = (GtkMenu *) gtk_menu_new();
	gtk_menu_item_set_submenu(this->mni_help_topics, (GtkWidget *) mnu_help_topics);
	for (size_t _ngg_tmp_5 = 0u; _ngg_tmp_5 < sizeof(helpitems) / sizeof(helpitems[0]); _ngg_tmp_5 += 1u) {
		SimpleHelpItem helpitem;
		helpitem = helpitems[_ngg_tmp_5];
		HelpMenuItem *mni = (HelpMenuItem *) malloc(sizeof(HelpMenuItem));
		if (mni == NULL) {
			perror(NULL);
			exit(EXIT_FAILURE);
		}

		help_menu_item_construct(mni, helpitem.title, helpitem.message);
		GtkMenuItem *_tmp_3 = help_menu_item_get_native_widget(mni);
		gtk_menu_shell_append((GtkMenuShell *) mnu_help_topics, (GtkWidget *) _tmp_3);
	}

	gtk_widget_show_all((GtkWidget *) mnu_help_topics);

	for (size_t i = 0u; i < sizeof(ratios) / sizeof(ratios[0]); i += 1u) {
		Ratio ratio;
		ratio = ratios[i];
		GtkRadioButton *btn_ratio = (GtkRadioButton *) gtk_radio_button_new(NULL);
		gtk_button_set_label((GtkButton *) btn_ratio, ratio.label);
		gtk_toggle_button_set_mode((GtkToggleButton *) btn_ratio, false);
		gtk_widget_set_tooltip_text((GtkWidget *) btn_ratio, ratio.tooltip);
		g_signal_connect((GtkWidget *) btn_ratio, "toggled", G_CALLBACK(myapp_on_btn_tool_x_toggled), this);
		gtk_widget_show((GtkWidget *) btn_ratio);

		gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) btn_ratio));
		gtk_radio_button_join_group(btn_ratio, this->btn_ratio_original);

		ratios[i].button = btn_ratio;
	}

	gtk_button_set_label((GtkButton *) (this->btn_ratio_custdim), "Custom W×H");
	gtk_toggle_button_set_mode((GtkToggleButton *) (this->btn_ratio_custdim), false);
	g_signal_connect((GtkWidget *) (this->btn_ratio_custdim), "toggled", G_CALLBACK(myapp_on_btn_tool_x_toggled), this);
	gtk_widget_show((GtkWidget *) (this->btn_ratio_custdim));

	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->btn_ratio_custdim)));
	gtk_radio_button_join_group(this->btn_ratio_custdim, this->btn_ratio_original);

	gtk_button_set_label((GtkButton *) (this->btn_ratio_custrat), "Custom Ratio");
	gtk_toggle_button_set_mode((GtkToggleButton *) (this->btn_ratio_custrat), false);
	g_signal_connect((GtkWidget *) (this->btn_ratio_custrat), "toggled", G_CALLBACK(myapp_on_btn_tool_x_toggled), this);
	gtk_widget_show((GtkWidget *) (this->btn_ratio_custrat));

	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->btn_ratio_custrat)));
	gtk_radio_button_join_group(this->btn_ratio_custrat, this->btn_ratio_original);

	int MAXCUSTDIM = 64000;
	gtk_spin_button_set_digits(this->spn_custw, (unsigned int) 0);
	g_signal_connect((GtkWidget *) (this->spn_custw), "value-changed", G_CALLBACK(myapp_on_spn_custdim_changed), this);
	gtk_widget_set_visible((GtkWidget *) (this->spn_custw), false);
	gtk_spin_button_set_range(this->spn_custw, 1, MAXCUSTDIM);
	gtk_spin_button_set_increments(this->spn_custw, 1, 4);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->spn_custw)));

	gtk_spin_button_set_digits(this->spn_custh, (unsigned int) 0);
	gtk_widget_set_visible((GtkWidget *) (this->spn_custh), false);
	gtk_spin_button_set_range(this->spn_custh, 1, MAXCUSTDIM);
	gtk_spin_button_set_increments(this->spn_custh, 1, 4);
	g_signal_connect((GtkWidget *) (this->spn_custh), "value-changed", G_CALLBACK(myapp_on_spn_custdim_changed), this);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->spn_custh)));

	gtk_spin_button_set_digits(this->spn_custrat, (unsigned int) 4);
	gtk_widget_set_visible((GtkWidget *) (this->spn_custrat), false);
	gtk_spin_button_set_range(this->spn_custrat, 0.0001, MAXCUSTDIM);
	gtk_spin_button_set_value(this->spn_custrat, 1.77);
	gtk_spin_button_set_increments(this->spn_custrat, 0.1, 1);
	g_signal_connect((GtkWidget *) (this->spn_custrat), "value-changed", G_CALLBACK(myapp_on_spn_custrat_changed), this);
	gtk_container_add(GTK_CONTAINER((GtkWidget *) (this->box_ratios)), GTK_WIDGET((GtkWidget *) (this->spn_custrat)));

	myapp_reserve_cairo_surface(this, DEFWIDTH_CAIRO, DEFHEIGHT_CAIRO);

	int _tmp_3 = imax2(DEFWIDTH_DOC, MINWIDTH_MWND);
	int _tmp_4 = imax2(DEFHEIGHT_DOC, MINHEIGHT_MWND);
	gtk_widget_set_size_request((GtkWidget *) (this->wnd), _tmp_3, _tmp_4);
	gtk_window_set_default_size(this->wnd, DEFWIDTH_MWND, DEFHEIGHT_MWND);

	gtk_widget_show((GtkWidget *) (this->wnd));

	gtk_widget_add_events((GtkWidget *) (this->da), (((GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK) | GDK_POINTER_MOTION_MASK) | GDK_SCROLL_MASK) | GDK_TOUCH_MASK);

	gdk_window_set_event_compression(gtk_widget_get_window((GtkWidget *) (this->da)), false);

	g_signal_connect((GtkWidget *) (this->da), "draw", G_CALLBACK(on_da_paint), this);

	ProxyDocument *initdoc = NULL;

	if (infile_path) {
		const char *pathnn;
		pathnn = (const char *) infile_path;
		initdoc = read_proxy_document_from_file(pathnn);
		if (!initdoc) {
			myapp_handle_fileio_err(this, VARA_FILE_IO_ERROR_OTHER, false);
		}
	}

	if (!initdoc) {
		ImageDocument *_tmp_3 = (ImageDocument *) malloc(sizeof(ImageDocument));
		if (_tmp_3 == NULL) {
			perror(NULL);
			exit(EXIT_FAILURE);
		}

		image_document_construct(_tmp_3, this->proxydoc->prevdoc->width, this->proxydoc->prevdoc->height, dpbak, true);
		ProxyDocument *_tmp_4 = (ProxyDocument *) malloc(sizeof(ProxyDocument));
		if (_tmp_4 == NULL) {
			perror(NULL);
			exit(EXIT_FAILURE);
		}

		proxy_document_construct(_tmp_4, _tmp_3);
		initdoc = _tmp_4;
	}

	assert(initdoc);
	myapp_set_document(this, initdoc);
}

_Bool myapp_can_zoom_in(myapp *this)
{
	return true;
}

_Bool myapp_can_zoom_out(myapp *this)
{
	return this->proxydoc->prevdoc->vpzoom >= 2 * ZOOMSTEP;
}

_Bool myapp_prompt_close_document(myapp *this)
{
	return true;
}

void myapp_reflect_brush_status(myapp *this)
{
}

void myapp_reflect_document_state(myapp *this)
{
	myapp_reflect_tool_status(this);

	myapp_reflect_brush_status(this);

	myapp_reflect_layer_status(this);
}

void myapp_reflect_layer_status(myapp *this)
{
}

void myapp_reflect_tool_status(myapp *this)
{
}

void myapp_set_document(myapp *this, ProxyDocument *newdoc)
{
	if (layer_owning_vector_get_count(newdoc->prevdoc->layers) < 1) {
		fprintf(stderr, "bug: ImageDocument passed to set-document has zero layers");
		return;
	}

	ProxyDocument *_ngg_tmp_8 = newdoc;
	if (this->proxydoc) {
		proxy_document_destruct(this->proxydoc);
		free(this->proxydoc);
	}

	this->proxydoc = _ngg_tmp_8;
	myapp_after_set_document(this);
}

void myapp_after_set_document(myapp *this)
{
	if (!image_document_has_fglayer(this->proxydoc->prevdoc)) {
		image_document_create_layer(this->proxydoc->prevdoc, "Foreground", LINEAR_PIXEL_TRANSP);
	}

	int vpw = imax2(gtk_widget_get_allocated_width((GtkWidget *) (this->da)), 1);
	int vph = imax2(gtk_widget_get_allocated_height((GtkWidget *) (this->da)), 1);
	image_document_viewport_set_size(this->proxydoc->prevdoc, vpw, vph);

	image_document_viewport_zoom_to_fit(this->proxydoc->prevdoc);

	this->layerstack_version = -1;

	myapp_reflect_document_state(this);

	if (gtk_toggle_button_get_active((GtkToggleButton *) (this->btn_ratio_original))) {
		myapp_drawframe_noskip(this);
	} else {
		gtk_toggle_button_set_active((GtkToggleButton *) (this->btn_ratio_original), true);
	}
}

void myapp_apply_custdim(myapp *this)
{
	double w = gtk_spin_button_get_value(this->spn_custw);
	double h = gtk_spin_button_get_value(this->spn_custh);
	myapp_pick_ratio(this, (int) w, (int) h);
}

void myapp_on_spn_custdim_changed(GtkSpinButton *widget, void *user_data)
{
	myapp_apply_custdim((myapp *) user_data);
}

void myapp_apply_custrat(myapp *this)
{
	int h = this->proxydoc->prevdoc->height;
	int w = (int) (h * gtk_spin_button_get_value(this->spn_custrat));
	myapp_pick_ratio(this, w, h);
}

void myapp_on_spn_custrat_changed(GtkSpinButton *widget, void *user_data)
{
	myapp_apply_custrat((myapp *) user_data);
}

void myapp_on_btn_layer_delete_clicked(GtkToolButton *widget, void *user_data)
{
	image_document_delete_layer(((myapp *) user_data)->proxydoc->prevdoc);
	myapp_reflect_layer_status((myapp *) user_data);
	myapp_drawframe_noskip((myapp *) user_data);
}

void myapp_on_btn_layer_move_down_clicked(GtkToolButton *widget, void *user_data)
{
	image_document_move_layer_down(((myapp *) user_data)->proxydoc->prevdoc);
	myapp_reflect_layer_status((myapp *) user_data);
	myapp_drawframe_noskip((myapp *) user_data);
}

void myapp_on_btn_layer_move_up_clicked(GtkToolButton *widget, void *user_data)
{
	image_document_move_layer_up(((myapp *) user_data)->proxydoc->prevdoc);
	myapp_reflect_layer_status((myapp *) user_data);
	myapp_drawframe_noskip((myapp *) user_data);
}

void myapp_on_btn_layer_new_clicked(GtkToolButton *widget, void *user_data)
{
	InputDialog *ndlg = (InputDialog *) malloc(sizeof(InputDialog));
	if (ndlg == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	input_dialog_construct(ndlg, ((myapp *) user_data)->wnd, "New Layer", "Name: ");
	InputDialogResponse *resp = input_dialog_run(ndlg);

	if (resp->ok) {
		assert(resp->name);
		image_document_create_layer_and_switch(((myapp *) user_data)->proxydoc->prevdoc, resp->name, LINEAR_PIXEL_TRANSP);
		myapp_reflect_layer_status((myapp *) user_data);
	}

	if (ndlg) {
		input_dialog_destruct(ndlg);
		free(ndlg);
	}

	if (resp) {
		input_dialog_response_destruct(resp);
		free(resp);
	}
}

void myapp_on_btn_layer_rename_clicked(GtkToolButton *widget, void *user_data)
{
	InputDialog *ndlg = (InputDialog *) malloc(sizeof(InputDialog));
	if (ndlg == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	input_dialog_construct(ndlg, ((myapp *) user_data)->wnd, "Rename Layer", "Name: ");
	InputDialogResponse *resp = input_dialog_run(ndlg);

	if (resp->ok) {
		assert(resp->name);
		image_document_rename_layer(((myapp *) user_data)->proxydoc->prevdoc, resp->name);
		myapp_reflect_layer_status((myapp *) user_data);
	}

	if (ndlg) {
		input_dialog_destruct(ndlg);
		free(ndlg);
	}

	if (resp) {
		input_dialog_response_destruct(resp);
		free(resp);
	}
}

void myapp_on_btn_tool_x_toggled(GtkCheckButton *widget, void *user_data)
{
	if (!gtk_toggle_button_get_active((GtkToggleButton *) widget)) {
		return;
	}

	_Bool dimvisib = false;
	_Bool ratvisib = dimvisib;

	if (widget == (GtkCheckButton *) (((myapp *) user_data)->btn_ratio_original)) {
		myapp_pick_ratio((myapp *) user_data, ((myapp *) user_data)->proxydoc->prevdoc->width, ((myapp *) user_data)->proxydoc->prevdoc->height);
	} else if (widget == (GtkCheckButton *) (((myapp *) user_data)->btn_ratio_custdim)) {
		dimvisib = true;
		myapp_apply_custdim((myapp *) user_data);
	} else if (widget == (GtkCheckButton *) (((myapp *) user_data)->btn_ratio_custrat)) {
		ratvisib = true;
		myapp_apply_custrat((myapp *) user_data);
	} else {
		for (size_t _ngg_tmp_6 = 0u; _ngg_tmp_6 < sizeof(ratios) / sizeof(ratios[0]); _ngg_tmp_6 += 1u) {
			Ratio ratio;
			ratio = ratios[_ngg_tmp_6];
			if (widget == (GtkCheckButton *) (ratio.button)) {
				myapp_pick_ratio((myapp *) user_data, ratio.width, ratio.height);
				break;
			}
		}
	}

	gtk_widget_set_visible((GtkWidget *) (((myapp *) user_data)->spn_custw), dimvisib);
	gtk_widget_set_visible((GtkWidget *) (((myapp *) user_data)->spn_custh), dimvisib);
	gtk_widget_set_visible((GtkWidget *) (((myapp *) user_data)->spn_custrat), ratvisib);
}

void myapp_on_mni_file_open_activate(GtkMenuItem *widget, void *user_data)
{
	if (!myapp_prompt_close_document((myapp *) user_data)) {
		return;
	}

	char *fnam = myapp_prompt_for_open_filename((myapp *) user_data);
	if (fnam) {
		char *fnamnn;
		fnamnn = (char *) fnam;
		ProxyDocument *opdoc = read_proxy_document_from_file(fnamnn);
		if (opdoc) {
			ProxyDocument *opdocnn;
			opdocnn = (ProxyDocument *) opdoc;
			myapp_set_document((myapp *) user_data, opdocnn);
		} else {
			myapp_handle_fileio_err((myapp *) user_data, VARA_FILE_IO_ERROR_OTHER, false);
		}
	}

	if (fnam) {
		free(fnam);
	}
}

void myapp_on_mni_file_quit_activate(GtkMenuItem *widget, void *user_data)
{
	gtk_window_close(((myapp *) user_data)->wnd);
}

void myapp_on_chk_pressure_toggled(GtkCheckButton *widget, void *user_data)
{
	((myapp *) user_data)->proxydoc->prevdoc->drawparams.brushparams.pressure_size = gtk_toggle_button_get_active((GtkToggleButton *) widget);
	myapp_repreview_brush((myapp *) user_data);
}

void myapp_on_btn_xlayer_toggled(GtkCheckButton *widget, void *user_data)
{
	if (!((myapp *) user_data)->proxydoc->prevdoc) {
		return;
	}

	if (intvector_get_count(((myapp *) user_data)->proxydoc->prevdoc->layerstack) <= 2) {
		return;
	}

	myapp_reflect_layer_status((myapp *) user_data);
}

void myapp_on_btn_clear_layer_clicked(GtkButton *widget, void *user_data)
{
	image_document_clear_layer(((myapp *) user_data)->proxydoc->prevdoc);
	myapp_drawframe_noskip((myapp *) user_data);
}

void myapp_handle_fileio_err(myapp *this, VaraFileIOError err, _Bool saving)
{
	switch (err) {
	case VARA_FILE_IO_ERROR_SUCCESS:
	{
		break;
	}

	default: {
		const char *_tmp_1 = saving? "Error saving file; please try another location and manually adding the file extension (if not done already).": "Error opening file.";
		GtkDialog *dlg = (GtkDialog *) gtk_message_dialog_new(this->wnd, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _tmp_1);

		int res = gtk_dialog_run(dlg);
		gtk_widget_destroy((GtkWidget *) dlg);
		(void) res;
		break;
	}
	}
}

_ngg_tuple_myapp__get_outrect myapp_get_outrect(myapp *this, RawJpegDocument *rawdoc)
{
	int outw = rawdoc->width;
	int outh = rawdoc->height;
	int offx = 0;
	int offy = 0;

	double docratio = rawdoc->width / (double) (rawdoc->height);
	double newratio = this->curratiow / (double) (this->curratioh);

	if (newratio > docratio) {
		outh = (int) ((outw * this->curratioh) / (double) (this->curratiow));
		offy = (rawdoc->height - outh) / 2;
	} else {
		outw = (int) (outh * newratio);
		offx = (rawdoc->width - outw) / 2;
	}

	return (_ngg_tuple_myapp__get_outrect) { offx, offy, outw, outh };
}

_ngg_tuple_myapp__get_outdims myapp_get_outdims(myapp *this, RawJpegDocument *rawdoc)
{
	_ngg_tuple_myapp__get_outrect _ngg_tmp_0 = myapp_get_outrect(this, rawdoc);
	int outh = _ngg_tmp_0.m3;
	int outw = _ngg_tmp_0.m2;
	return (_ngg_tuple_myapp__get_outdims) { outw, outh };
}

void myapp_on_btn_export_doc_clicked(GtkButton *widget, void *user_data)
{
	if (((myapp *) user_data)->proxydoc->rawdoc) {
		RawJpegDocument *rawdocnn;
		rawdocnn = (RawJpegDocument *) (((myapp *) user_data)->proxydoc->rawdoc);
		char *fnam = myapp_prompt_for_export_filename((myapp *) user_data);
		if (fnam) {
			char *fnamnn;
			fnamnn = (char *) fnam;
			char *fnamext = append_jpg_if_needed_and_possible(fnamnn);

			VaraFileIOError err = VARA_FILE_IO_ERROR_SUCCESS;

			FILE *fp = fopen(fnamnn, "wb");
			if (fp) {
				FILE *fpnn;
				fpnn = (FILE *) fp;
				_ngg_tuple_myapp__get_outrect _ngg_tmp_1 = myapp_get_outrect((myapp *) user_data, rawdocnn);
				int outh = _ngg_tmp_1.m3;
				int outw = _ngg_tmp_1.m2;
				int offy = _ngg_tmp_1.m1;
				int offx = _ngg_tmp_1.m0;
				err = write_raw_jpeg_document_to_fp(rawdocnn, offx, offy, outw, outh, fpnn, fnamext);
			} else {
				err = VARA_FILE_IO_ERROR_OTHER;
			}

			myapp_handle_fileio_err((myapp *) user_data, err, true);
			if (fnamext) {
				free(fnamext);
			}
		}

		if (fnam) {
			free(fnam);
		}
	} else {
		GtkDialog *dlg = (GtkDialog *) gtk_message_dialog_new(((myapp *) user_data)->wnd, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Nothing to export! Please open an image first.");

		int res = gtk_dialog_run(dlg);
		gtk_widget_destroy((GtkWidget *) dlg);
		(void) res;
	}
}

void myapp_on_btn_export_layer_clicked(GtkButton *widget, void *user_data)
{
	char *fnam = myapp_prompt_for_export_filename((myapp *) user_data);
	if (fnam) {
		char *fnamnn;
		fnamnn = (char *) fnam;
		char *fnamext = append_png_if_needed_and_possible(fnamnn);
		myapp_handle_fileio_err((myapp *) user_data, image_document_export_layer(((myapp *) user_data)->proxydoc->prevdoc, fnamext, false), true);
		if (fnamext) {
			free(fnamext);
		}
	}

	if (fnam) {
		free(fnam);
	}
}

char * myapp_prompt_for_export_filename(myapp *this)
{
	GtkFileChooserNative *_ngg_tmp_37_dlg = gtk_file_chooser_native_new("Save File", this->wnd, GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", "_Cancel");
	gtk_file_chooser_set_do_overwrite_confirmation((GtkFileChooser *) _ngg_tmp_37_dlg, true);

	GtkNativeDialog *dlg = (GtkNativeDialog *) _ngg_tmp_37_dlg;

	GtkFileFilter *filter = gtk_file_filter_new();
	gtk_file_filter_add_mime_type(filter, "image/jpeg");
	gtk_file_filter_set_name(filter, "*.jpg");
	gtk_file_chooser_add_filter((GtkFileChooser *) dlg, filter);

	int res = gtk_native_dialog_run(dlg);

	char *fnam = NULL;

	if (res == GTK_RESPONSE_ACCEPT) {
		fnam = gtk_file_chooser_get_filename((GtkFileChooser *) dlg);
	}

	g_object_unref((GObject *) dlg);

	return fnam;
}

char * myapp_prompt_for_open_filename(myapp *this)
{
	GtkFileChooserNative *_ngg_tmp_39_dlg = gtk_file_chooser_native_new("Open File", this->wnd, GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel");
	gtk_file_chooser_set_do_overwrite_confirmation((GtkFileChooser *) _ngg_tmp_39_dlg, true);

	GtkNativeDialog *dlg = (GtkNativeDialog *) _ngg_tmp_39_dlg;

	GtkFileFilter *filter_jpeg = gtk_file_filter_new();
	gtk_file_filter_add_mime_type(filter_jpeg, "image/jpeg");
	gtk_file_filter_set_name(filter_jpeg, "*.jpg");
	gtk_file_chooser_add_filter((GtkFileChooser *) dlg, filter_jpeg);

	int res = gtk_native_dialog_run(dlg);

	char *fnam = NULL;

	if (res == GTK_RESPONSE_ACCEPT) {
		fnam = gtk_file_chooser_get_filename((GtkFileChooser *) dlg);
	}

	g_object_unref((GObject *) dlg);

	return fnam;
}

void myapp_on_da_sizeallocate(GtkDrawingArea *widget, GdkRectangle *nggevent_allocation, void *user_data)
{
	if (!gtk_widget_get_mapped((GtkWidget *) widget)) {
		return;
	}

	myapp_reserve_cairo_surface((myapp *) user_data, nggevent_allocation->width, nggevent_allocation->height);

	image_document_viewport_set_size(((myapp *) user_data)->proxydoc->prevdoc, nggevent_allocation->width, nggevent_allocation->height);

	image_document_viewport_zoom_to_fit(((myapp *) user_data)->proxydoc->prevdoc);

	myapp_drawframe_noskip((myapp *) user_data);
}

void myapp_pick_ratio(myapp *this, int w, int h)
{
	this->curratiow = w;

	this->curratioh = h;

	if (h == 0) {
		fprintf(stderr, "amsam bug: pick-ratio called with h = 0\n");
		return;
	}

	Layer *fglayer = image_document_get_fglayer_must(this->proxydoc->prevdoc);

	layer_set_alpha(fglayer, 0.9);

	image_document_switch_layer_fg(this->proxydoc->prevdoc);

	image_document_clear_layer(this->proxydoc->prevdoc);

	double docratio = this->proxydoc->prevdoc->width / (double) (this->proxydoc->prevdoc->height);
	double newratio = w / (double) h;

	VaraRect reg1 = vara_rect_default();
	VaraRect reg2 = reg1;

	if (newratio > docratio) {
		int hnew = (this->proxydoc->prevdoc->width * h) / w;
		int hdiff = this->proxydoc->prevdoc->height - hnew;
		int hbar = (int) (hdiff / 2);
		reg1 = (VaraRect) { 0, 0, this->proxydoc->prevdoc->width, hbar };
		reg2 = (VaraRect) { 0, this->proxydoc->prevdoc->height - hbar, this->proxydoc->prevdoc->width, hbar };
	} else {
		double wnew = this->proxydoc->prevdoc->height * newratio;
		double wdiff = this->proxydoc->prevdoc->width - wnew;
		int wbar = (int) (wdiff / 2);
		reg1 = (VaraRect) { 0, 0, wbar, this->proxydoc->prevdoc->height };
		reg2 = (VaraRect) { this->proxydoc->prevdoc->width - wbar, 0, wbar, this->proxydoc->prevdoc->height };
	}

	image_fill_region(fglayer->img, LINEAR_PIXEL_BLACK, reg1);
	image_fill_region(fglayer->img, LINEAR_PIXEL_BLACK, reg2);

	image_document_mark_all_dirty(this->proxydoc->prevdoc);

	myapp_drawframe_noskip(this);

	if (this->proxydoc->rawdoc) {
		RawJpegDocument *rawdoc;
		rawdoc = (RawJpegDocument *) (this->proxydoc->rawdoc);
		_ngg_tuple_myapp__get_outdims _ngg_tmp_2 = myapp_get_outdims(this, rawdoc);
		int outh = _ngg_tmp_2.m1;
		int outw = _ngg_tmp_2.m0;
		size_t _tmp_catpos = 0u;
		char *_tmp_1 = (char *) calloc((size_t) (16u + 4u + 16u + 1u), sizeof(char));
		if (_tmp_1 == NULL) {
			perror(NULL);
			exit(EXIT_FAILURE);
		}

		char *_tmp_catstr = (char *) _tmp_1;
		snprintf(_tmp_catstr + _tmp_catpos, 16u, "%d", outw);
		_tmp_catpos = strlen(_tmp_catstr);
		memcpy(_tmp_catstr + _tmp_catpos, " × ", 4u);
		_tmp_catpos += 4u;
		snprintf(_tmp_catstr + _tmp_catpos, 16u, "%d", outh);
		_tmp_catpos = strlen(_tmp_catstr);
		_tmp_catstr[_tmp_catpos] = '\0';
		char *_ngg_tmp_3 = _tmp_catstr;
		gtk_label_set_label(this->lbl_curdims, _ngg_tmp_3);
		if (_ngg_tmp_3) {
			free(_ngg_tmp_3);
		}
	} else {
		gtk_label_set_label(this->lbl_curdims, "");
	}
}

void myapp_reserve_cairo_surface(myapp *this, int w, int h)
{
	assert(w > 0);

	assert(h > 0);
	if (this->surf && (cairo_image_surface_get_width(this->surf) >= w && cairo_image_surface_get_height(this->surf) >= h)) {
		return;
	}

	cairo_surface_t *_ngg_tmp_9 = gdk_window_create_similar_image_surface(gtk_widget_get_window((GtkWidget *) (this->da)), CAIRO_FORMAT_RGB24, w, h, 0);
	if (this->surf) {
		cairo_surface_destroy(this->surf);
	}

	this->surf = _ngg_tmp_9;
}

VaraRect myapp_copy_preview_to_cairo_surface(myapp *this)
{
	assert(this->proxydoc->prevdoc);

	VaraRect dirtyrect = image_document_update_preview(this->proxydoc->prevdoc);

	assert(this->proxydoc->prevdoc->preview);
	copy_image_region_to_cairo_surface(this->proxydoc->prevdoc->preview, this->surf, dirtyrect);

	return dirtyrect;
}

void myapp_clear_cairo_surface(myapp *this)
{
	assert(this->surf);

	int stride = cairo_image_surface_get_stride(this->surf);
	unsigned char *ibuf = cairo_image_surface_get_data(this->surf);

	size_t rowpos = 0u;
	for (int y = 0; y < cairo_image_surface_get_height(this->surf); y += 1) {
		size_t pixpos = rowpos;
		for (int x = 0; x < cairo_image_surface_get_width(this->surf); x += 1) {
			nan_copy_pixel_to_rgb24(srgbpixel2linear(PIXEL_VPBG), ibuf + pixpos);

			pixpos = pixpos + 4;
		}

		rowpos = rowpos + stride;
	}

	cairo_surface_mark_dirty(this->surf);
}

void myapp_drawframe(myapp *this)
{
	myapp_drawframe_noskip(this);
}

void myapp_drawframe_noskip(myapp *this)
{
	if (this->proxydoc->prevdoc && this->proxydoc->prevdoc->preview) {
		VaraRect dirtyrect = myapp_copy_preview_to_cairo_surface(this);

		if (!region_is_zero(dirtyrect)) {
			gtk_widget_queue_draw_area((GtkWidget *) (this->da), dirtyrect.x, dirtyrect.y, dirtyrect.w, dirtyrect.h);
		}
	} else {
		myapp_clear_cairo_surface(this);
		gtk_widget_queue_draw((GtkWidget *) (this->da));
	}
}

void myapp_on_mni_help_about_activate(GtkMenuItem *widget, void *user_data)
{
	GtkAboutDialog *dlg = (GtkAboutDialog *) gtk_about_dialog_new();
	gtk_about_dialog_set_program_name(dlg, PROGRAM_NAME);
	gtk_about_dialog_set_comments(dlg, "Preview aspect ratios and crop.");
	gtk_about_dialog_set_logo_icon_name(dlg, "amsam"); // FLATPAK_DELETE
	// FLATPAK_UNCOMMENT gtk_about_dialog_set_logo_icon_name(dlg, "in.co.nandakumar.amsam");
	const char *authors[2] = { "Nandakumar Edamana", NULL };
	gtk_about_dialog_set_authors(dlg, authors);

	gtk_about_dialog_set_copyright(dlg, "Copyright (C) 2021, 2023, 2024, 2025, 2026 Nandakumar Edamana <contact@nandakumar.co.in>");
	gtk_about_dialog_set_license_type(dlg, GTK_LICENSE_GPL_3_0_ONLY);
	gtk_about_dialog_set_version(dlg, VERSION);
	gtk_about_dialog_set_website(dlg, "https://nandakumar.co.in/software/amsam/");
	gtk_window_set_transient_for((GtkWindow *) dlg, ((myapp *) user_data)->wnd);
	int res = gtk_dialog_run((GtkDialog *) dlg);
	gtk_widget_destroy((GtkWidget *) dlg);
	(void) res;
}

void myapp_repreview_brush(myapp *this)
{
	if (this->disable_brush_preview) {
		return;
	}

	DrawingParams dp = this->proxydoc->prevdoc->drawparams;
	dp.active_tool = TOOL_BRUSH;
	dp.erase = false;
}

void myapp_destruct(myapp *this)
{
	if (this->ivw_ballpoint) {
		this->ivw_ballpoint->_ngg_vtab_image_view.destruct(this->ivw_ballpoint);
		free(this->ivw_ballpoint);
	}

	if (this->ivw_charcoal) {
		this->ivw_charcoal->_ngg_vtab_image_view.destruct(this->ivw_charcoal);
		free(this->ivw_charcoal);
	}

	if (this->ivw_crayon) {
		this->ivw_crayon->_ngg_vtab_image_view.destruct(this->ivw_crayon);
		free(this->ivw_crayon);
	}

	if (this->ivw_pencil) {
		this->ivw_pencil->_ngg_vtab_image_view.destruct(this->ivw_pencil);
		free(this->ivw_pencil);
	}

	if (this->ivw_round) {
		this->ivw_round->_ngg_vtab_image_view.destruct(this->ivw_round);
		free(this->ivw_round);
	}

	if (this->ivw_round_pressure_size) {
		this->ivw_round_pressure_size->_ngg_vtab_image_view.destruct(this->ivw_round_pressure_size);
		free(this->ivw_round_pressure_size);
	}

	if (this->ivw_soft_round) {
		this->ivw_soft_round->_ngg_vtab_image_view.destruct(this->ivw_soft_round);
		free(this->ivw_soft_round);
	}

	if (this->proxydoc) {
		proxy_document_destruct(this->proxydoc);
		free(this->proxydoc);
	}

	if (this->surf) {
		cairo_surface_destroy(this->surf);
	}
}

void on_da_paint(GtkWidget *w, cairo_t *cr, myapp *app)
{
	cairo_set_source_surface(cr, app->surf, 0, 0);

	cairo_paint(cr);
}

_Bool on_wnd_deleteevent(GtkWidget *wgt, GdkEvent *event, myapp *app)
{
	if (!myapp_prompt_close_document(app)) {
		return true;
	}

	gtk_main_quit();

	return false;
}

void draw_brush_preview(Image *img, DrawingParams dpcopy, _Bool dot_only)
{
	Pixel PIXEL_LIGHT_GRAY = (Pixel) { { 0.8, 0.8, 0.8, 1 } };

	image_fill(img, srgbpixel2linear(PIXEL_LIGHT_GRAY));

	image_fill_region(img, LINEAR_PIXEL_WHITE, (VaraRect) { 1, 1, img->width - 2, img->height - 2 });

	dpcopy.fgcolor = LINEAR_PIXEL_BLACK;
	dpcopy.oldpressure = 1;

	double radius = dpcopy.brushparams.siz / 2.0;
	double ymid = img->height / 2.0;

	if (dot_only) {
		double xmid = img->width / 2.0;

		dpcopy.pressure = 1;
		image_line(img, xmid, ymid, xmid, ymid, dpcopy);
	} else {
		int padding = 5;

		dpcopy.pressure = 0;
		image_line(img, padding + radius, ymid, (img->width - radius) - padding, ymid, dpcopy);
	}
}

ImageView * brushpreview_widget_new(BrushParams brushparams)
{
	ImageView *iv = (ImageView *) malloc(sizeof(ImageView));
	if (iv == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	image_view_construct(iv);
	Image *img = (Image *) malloc(sizeof(Image));
	if (img == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	image_construct(img, 36, 24, 255);

	DrawingParams dp = default_drawparams();
	dp.brushparams = brushparams;
	dp.active_tool = TOOL_BRUSH;
	draw_brush_preview(img, dp, false);

	image_view_set_image(iv, img);

	return iv;
}

_Bool probably_inside_container()
{
	const char *containerenvs[4] = { "container", "FLATPAK_ID", "SNAP", "APPIMAGE" };

	for (size_t _ngg_tmp_7 = 0u; _ngg_tmp_7 < sizeof(containerenvs) / sizeof(containerenvs[0]); _ngg_tmp_7 += 1u) {
		const char *id;
		id = containerenvs[_ngg_tmp_7];
		if (getenv(id)) {
			return true;
		}
	}

	return false;
}

char * append_ext_if_needed_and_possible(const char *fnam, const char *ext)
{
	char *_tmp_2 = (char *) calloc((size_t) (strlen(fnam) + 1u), sizeof(char));
	if (_tmp_2 == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	char *_tmp_1 = (char *) _tmp_2;
	memcpy(_tmp_1, fnam, strlen(fnam) + 1u);
	return _tmp_1;
}

char * append_png_if_needed_and_possible(const char *fnam)
{
	return append_ext_if_needed_and_possible(fnam, "png");
}

char * append_jpg_if_needed_and_possible(const char *fnam)
{
	return append_ext_if_needed_and_possible(fnam, "jpg");
}

void set_tool_icon(GtkButton *btn, Image *img)
{
	ImageView *iv = (ImageView *) malloc(sizeof(ImageView));
	if (iv == NULL) {
		perror(NULL);
		exit(EXIT_FAILURE);
	}

	image_view_construct(iv);
	image_view_set_image(iv, img);

	gtk_button_set_image(btn, image_view_get_native_widget(iv));
	gtk_button_set_label(btn, NULL);
	gtk_button_set_relief(btn, GTK_RELIEF_NONE);
}

ProxyDocument * read_proxy_document_from_file(const char *path)
{
	return read_proxy_document_from_jpeg(path);
}

CommandLineOptions command_line_options_default()
{
	CommandLineOptions s;
	s.static_cursor = false;
	return s;
}

SimpleHelpItem simple_help_item_default()
{
	SimpleHelpItem s;
	s.title = "";
	s.message = "";
	return s;
}

_ngg_tuple_myapp__get_outdims _ngg_tuple_myapp__get_outdims_default()
{
	_ngg_tuple_myapp__get_outdims s;
	s.m0 = 0;
	s.m1 = 0;
	return s;
}

_ngg_tuple_myapp__get_outrect _ngg_tuple_myapp__get_outrect_default()
{
	_ngg_tuple_myapp__get_outrect s;
	s.m0 = 0;
	s.m1 = 0;
	s.m2 = 0;
	s.m3 = 0;
	return s;
}
