/*
 * mape - C4 Landscape.txt editor
 *
 * Copyright (c) 2005-2009 Armin Burgmeier
 *
 * Portions might be copyrighted by other authors who have contributed
 * to OpenClonk.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * See isc_license.txt for full license and disclaimer.
 *
 * "Clonk" is a registered trademark of Matthes Bender.
 * See clonk_trademark_license.txt for full license.
 */

#include <stdlib.h>
#include <gtksourceview/gtksourcebuffer.h>

#include "mape/cpp-handles/version-handle.h"
#include "mape/fileicon.h"
#include "mape/configfile.h"
#include "mape/preferencesdialog.h"
#include "mape/header.h"
#include "mape/statusbar.h"
#include "mape/diskview.h"
#include "mape/mattexview.h"
#include "mape/editview.h"
#include "mape/preview.h"
#include "mape/window.h"

static gboolean mape_window_file_load(MapeWindow* wnd,
                                      const gchar* filename)
{
	GError* error = NULL;
	GtkWidget* error_dialog;
	gchar* title;
	gboolean result;

	result = mape_edit_view_open(wnd->edit_view, filename, &error);
		
	if(result == FALSE)
	{
		error_dialog = gtk_message_dialog_new(
			GTK_WINDOW(wnd->window),
			GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
			GTK_MESSAGE_ERROR,
			GTK_BUTTONS_OK,
			"%s",
			error->message
		);

		gtk_dialog_run(GTK_DIALOG(error_dialog) );

		gtk_widget_destroy(error_dialog);
		g_error_free(error);

		return FALSE;
	}
	else
	{
		title = g_strdup_printf("%s - Mape", filename);
		gtk_window_set_title(GTK_WINDOW(wnd->window), title);
		g_free(title);

		return TRUE;
	}
}

static gboolean mape_window_file_save(MapeWindow* wnd,
                                      const gchar* filename)
{
	GError* error = NULL;
	GtkWidget* error_dialog;
	gchar* title;
	gboolean result;

	result = mape_edit_view_save(wnd->edit_view, filename, &error);
		
	if(result == FALSE)
	{
		error_dialog = gtk_message_dialog_new(
			GTK_WINDOW(wnd->window),
			GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
			GTK_MESSAGE_ERROR,
			GTK_BUTTONS_OK,
			"%s",
			error->message
		);
			
		gtk_dialog_run(GTK_DIALOG(error_dialog) );
			
		gtk_widget_destroy(error_dialog);
		g_error_free(error);
		
		return FALSE;
	}
	else
	{
		title = g_strdup_printf("%s - Mape", wnd->edit_view->file_path);
		gtk_window_set_title(GTK_WINDOW(wnd->window), title);
		g_free(title);
		
		return TRUE;
	}
}

static GtkWidget* mape_window_create_file_chooser(MapeWindow* wnd,
                                                  GtkFileChooserAction action)
{
	GtkWidget* dialog;
	GtkFileFilter* filter_all;
	GtkFileFilter* filter_landscape;
	
	filter_all = gtk_file_filter_new();
	gtk_file_filter_set_name(filter_all, "All files");
	gtk_file_filter_add_pattern(filter_all, "*");
	
	filter_landscape = gtk_file_filter_new();
	gtk_file_filter_set_name(filter_landscape, "Landscape.txt files");
	gtk_file_filter_add_pattern(filter_landscape, "[Ll]andscape.txt");

	dialog = gtk_file_chooser_dialog_new(
		action == GTK_FILE_CHOOSER_ACTION_OPEN ?
			"Open landscape file..." : "Save landscape file...",
		GTK_WINDOW(wnd->window),
		action,
		GTK_STOCK_CANCEL,
		GTK_RESPONSE_CANCEL,
		action == GTK_FILE_CHOOSER_ACTION_OPEN ?
			GTK_STOCK_OPEN : GTK_STOCK_SAVE,
		GTK_RESPONSE_OK,
		NULL
	);
	
	gtk_file_chooser_add_filter(
		GTK_FILE_CHOOSER(dialog),
		filter_landscape
	);
	
	gtk_file_chooser_add_filter(
		GTK_FILE_CHOOSER(dialog),
		filter_all
	);
	
	gtk_file_chooser_set_do_overwrite_confirmation(
		GTK_FILE_CHOOSER(dialog),
		TRUE
	);

	return dialog;
}

static void mape_window_cb_file_save_as(GtkWidget* widget,
                                        gpointer user_data)
{
	MapeWindow* wnd;
	gint response;
	gchar* filename;
	GtkWidget* save_dialog;

	wnd = (MapeWindow*)user_data;
	save_dialog = mape_window_create_file_chooser(
		wnd,
		GTK_FILE_CHOOSER_ACTION_SAVE
	);
	
	if(wnd->edit_view->file_path != NULL)
	{
		gtk_file_chooser_set_filename(
			GTK_FILE_CHOOSER(save_dialog),
			wnd->edit_view->file_path
		);
	}
	else if(wnd->last_path != NULL)
	{
		gtk_file_chooser_set_current_folder(
			GTK_FILE_CHOOSER(save_dialog),
			wnd->last_path
		);
	}
	
	response = gtk_dialog_run(GTK_DIALOG(save_dialog) );
	if(response == GTK_RESPONSE_OK)
	{
		filename = gtk_file_chooser_get_filename(
			GTK_FILE_CHOOSER(save_dialog)
		);
		
		g_free(wnd->last_path);
		wnd->last_path = gtk_file_chooser_get_current_folder(
			GTK_FILE_CHOOSER(save_dialog)
		);

		mape_window_file_save(wnd, filename);

		g_free(filename);
	}

	gtk_widget_destroy(save_dialog);
}

static void mape_window_cb_file_save(GtkWidget* widget,
                                     gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;
	
	if(wnd->edit_view->file_path == NULL)
	{
		mape_window_cb_file_save_as(widget, user_data);
	}
	else
	{
		mape_window_file_save(wnd, wnd->edit_view->file_path);
	}
}

static gboolean mape_window_confirm_close(MapeWindow* wnd)
{
	GtkWidget* confirm_dialog;
	gint response;

	/* No need to confirm if the document has not been modified */
	if(mape_edit_view_get_modified(wnd->edit_view) == FALSE)
		return TRUE;

	confirm_dialog = gtk_message_dialog_new(
		GTK_WINDOW(wnd->window),
		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
		GTK_MESSAGE_WARNING,
		GTK_BUTTONS_NONE,
		"Save the changes to document before closing?"
	);
	
	gtk_message_dialog_format_secondary_text(
		GTK_MESSAGE_DIALOG(confirm_dialog),
		"Unsaved changes will be permanently lost."
	);
	
	gtk_dialog_add_buttons(
		GTK_DIALOG(confirm_dialog),
		"Close _without saving",
		GTK_RESPONSE_REJECT,
		GTK_STOCK_CANCEL,
		GTK_RESPONSE_CANCEL,
		GTK_STOCK_SAVE,
		GTK_RESPONSE_ACCEPT,
		NULL
	);

	response = gtk_dialog_run(GTK_DIALOG(confirm_dialog) );
	gtk_widget_destroy(confirm_dialog);
	
	switch(response)
	{
	case GTK_RESPONSE_DELETE_EVENT:
	case GTK_RESPONSE_CANCEL:
		return FALSE;
		break;
	case GTK_RESPONSE_REJECT:
		/* Document may be closed */
		return TRUE;
	case GTK_RESPONSE_ACCEPT:
		/* Save before closing */
		mape_window_cb_file_save(wnd->window, wnd);
		return TRUE;
	default:
		g_assert_not_reached();
		return FALSE;
	}
}

static void mape_window_cb_realize(GtkWidget* widget,
                                   gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;

	gtk_paned_set_position(GTK_PANED(wnd->mid_paned), 200);
}

static void mape_window_cb_file_new(GtkWidget* widget,
                                    gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;
	
	if(mape_window_confirm_close(wnd) == TRUE)
	{
		mape_edit_view_clear(wnd->edit_view);
		gtk_window_set_title(GTK_WINDOW(wnd->window), "Mape");
	}
}

static void mape_window_cb_file_open(GtkWidget* widget,
                                     gpointer user_data)
{
	MapeWindow* wnd;
	gint response;
	GtkWidget* open_dialog;
	gchar* filename;

	wnd = (MapeWindow*)user_data;
	if(mape_window_confirm_close(wnd) == FALSE)
		return;

	open_dialog = mape_window_create_file_chooser(
		wnd,
		GTK_FILE_CHOOSER_ACTION_OPEN
	);

	if(wnd->last_path != NULL)
	{
		gtk_file_chooser_set_current_folder(
			GTK_FILE_CHOOSER(open_dialog),
			wnd->last_path
		);
	}

	response = gtk_dialog_run(GTK_DIALOG(open_dialog) );
	if(response == GTK_RESPONSE_OK)
	{
		filename = gtk_file_chooser_get_filename(
			GTK_FILE_CHOOSER(open_dialog)
		);
		
		g_free(wnd->last_path);
		wnd->last_path = gtk_file_chooser_get_current_folder(
			GTK_FILE_CHOOSER(open_dialog)
		);

		mape_window_file_load(wnd, filename);

		g_free(filename);
	}

	gtk_widget_destroy(open_dialog);
}

static void mape_window_cb_file_quit(GtkWidget* widget,
                                     gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;

	if(mape_window_confirm_close(wnd) == TRUE)
		gtk_widget_destroy(wnd->window);
}

static gboolean mape_window_cb_delete_event(GtkWidget* widget,
                                            GdkEvent* event,
                                            gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;

	if(mape_window_confirm_close(wnd) == TRUE)
		return FALSE;
	else
		return TRUE;
}

static void mape_window_cb_edit_undo(GtkAction* action,
                                     gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;

	mape_edit_view_undo(wnd->edit_view);
}

static void mape_window_cb_edit_redo(GtkAction* action,
                                     gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;
	
	mape_edit_view_redo(wnd->edit_view);
}

static void mape_window_cb_edit_can_undo(GObject* object,
                                         GParamSpec* pspec,
                                         gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;
	
	gtk_action_set_sensitive(
		wnd->header->edit_undo,
		gtk_source_buffer_can_undo(GTK_SOURCE_BUFFER(object))
	);
}

static void mape_window_cb_edit_can_redo(GObject* object,
                                         GParamSpec* pspec,
                                         gpointer user_data)
{
	MapeWindow* wnd;
	wnd = (MapeWindow*)user_data;
	
	gtk_action_set_sensitive(
		wnd->header->edit_redo,
		gtk_source_buffer_can_redo(GTK_SOURCE_BUFFER(object))
	);
}

static void mape_window_cb_edit_preferences(GtkAction* action,
                                            gpointer user_data)
{
	MapeWindow* wnd;
	MapePreferencesDialog* dialog;
	gint result;

	wnd = (MapeWindow*)user_data;
	
	dialog = mape_preferences_dialog_new(
		GTK_WINDOW(wnd->window),
		&wnd->preferences
	);

	result = gtk_dialog_run(GTK_DIALOG(dialog->dialog) );
	if(result == GTK_RESPONSE_OK)
	{
		wnd->preferences = mape_preferences_dialog_get(dialog);
		mape_preferences_to_config(&wnd->preferences, wnd->config);

		mape_edit_view_apply_preferences(
			wnd->edit_view,
			&wnd->preferences
		);
		mape_pre_view_apply_preferences(wnd->pre_view, &wnd->preferences);
	}

	mape_preferences_dialog_destroy(dialog);
}

static void mape_window_cb_help_about(GtkAction* action,
                                      gpointer user_data)
{
	MapeWindow* wnd;
	GtkWidget* about_dialog;

	const gchar* authors[] = {
		"Developers:",
		"  Armin Burgmeier <armin@arbur.net>",
		"",
		"Contributors:",
		"  Tyron Madlener <tm@tyron.at>",
		"  Günther Brammer <gbrammer@gmx.de>",
		NULL
	};

	const gchar* artists[] = {
		"Stefan \"KaZoiTeZ\" Ryll",
		NULL
	};

	wnd = (MapeWindow*)user_data;
	about_dialog = gtk_about_dialog_new();

	gtk_about_dialog_set_program_name(
		GTK_ABOUT_DIALOG(about_dialog),
		"Mape"
	);

	gtk_about_dialog_set_version(
		GTK_ABOUT_DIALOG(about_dialog),
		c4_version_get()
	);

	gtk_about_dialog_set_copyright(
		GTK_ABOUT_DIALOG(about_dialog),
		"Copyright \xc2\xa9 2005-2013 Armin Burgmeier"
	);

	gtk_about_dialog_set_comments(
		GTK_ABOUT_DIALOG(about_dialog),
		"A Clonk Landscape.txt editor"
	);

	gtk_about_dialog_set_authors(
		GTK_ABOUT_DIALOG(about_dialog),
		authors
	);

	gtk_about_dialog_set_artists(
		GTK_ABOUT_DIALOG(about_dialog),
		artists
	);

	gtk_about_dialog_set_license(
		GTK_ABOUT_DIALOG(about_dialog),
		"Permission to use, copy, modify, and/or distribute this "
		"software for any purpose with or without fee is hereby "
		"granted, provided that the above copyright notice and this "
		"permission notice appear in all copies.\n\n"

		"THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS "
		"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL "
		"IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO "
		"EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, "
		"INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES "
		"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, "
		"WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER "
		"TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE "
		"USE OR PERFORMANCE OF THIS SOFTWARE."
	);

	gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(about_dialog), TRUE);

	gtk_dialog_run(GTK_DIALOG(about_dialog) );
	gtk_widget_destroy(about_dialog);
}

MapeWindow* mape_window_new(int argc,
                            char* argv[],
                            GError** error)
{
	MapeWindow* wnd;
	MapeConfigFileEntry* entry;
	gchar* config_path;
	gchar* material_path;
	gchar* current_dir;
	gchar* landscape_path;
	gchar* basename;
	int i;

	wnd = malloc(sizeof(MapeWindow) );

	/* Load preferences */
	config_path = g_build_filename(g_get_home_dir(), ".mape", NULL);
	wnd->config = mape_config_file_new(config_path);
	g_free(config_path);

	current_dir = g_get_current_dir();
	landscape_path = NULL;

	for(i = 1; i < argc; ++ i)
	{
		basename = g_path_get_basename(argv[i]);
		if(g_strcasecmp(basename, "Material.ocg") == 0)
		{
			if(!g_path_is_absolute(argv[i]))
			{
				material_path = g_build_filename(
					current_dir,
					argv[i],
					NULL
				);
			}
			else
			{
				material_path = g_strdup(argv[i]);
			}

			mape_config_file_set_entry(
				wnd->config,
				"material_path",
				material_path
			);

			g_free(material_path);
		}
		else
		{
			g_free(landscape_path);

			if(!g_path_is_absolute(argv[i]))
			{
				landscape_path = g_build_filename(
					current_dir,
					argv[i],
					NULL
				);
			}
			else
			{
				landscape_path = g_strdup(argv[i]);
			}
		}

		g_free(basename);
	}

	g_free(current_dir);
	
	mape_preferences_from_config(&wnd->preferences, wnd->config);

	wnd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	wnd->icon_set = mape_file_icon_set_new(wnd->window);
	wnd->last_path = NULL;

	wnd->header = mape_header_new();
	wnd->statusbar = mape_statusbar_new();

	wnd->mat_tex_view = mape_mat_tex_view_new(wnd->icon_set, error);
	if(wnd->mat_tex_view == NULL)
		goto mat_tex_error;

	wnd->pre_view = mape_pre_view_new(wnd->mat_tex_view, error);
	if(wnd->pre_view == NULL)
		goto pre_view_error;

	wnd->edit_view = mape_edit_view_new(
		wnd->pre_view,
		wnd->statusbar,
		error
	);
	if(wnd->edit_view == NULL)
		goto edit_view_error;
	
	wnd->disk_view = mape_disk_view_new(
		wnd->icon_set,
		wnd->mat_tex_view,
		wnd->edit_view,
		wnd->config,
		error
	);

	if(wnd->disk_view == NULL)
		goto disk_view_error;

	wnd->menubar = wnd->header->menubar;
	gtk_widget_show(wnd->menubar);

	wnd->toolbar = wnd->header->toolbar;
	gtk_toolbar_set_style(GTK_TOOLBAR(wnd->toolbar), GTK_TOOLBAR_ICONS);
	gtk_widget_show(wnd->toolbar);
	
	wnd->mid_paned = gtk_hpaned_new();
	gtk_paned_pack1(
		GTK_PANED(wnd->mid_paned),
		wnd->disk_view->window,
		TRUE,
		FALSE
	);

	gtk_paned_pack2(
		GTK_PANED(wnd->mid_paned),
		wnd->edit_view->window,
		TRUE,
		FALSE
	);

	gtk_widget_show(wnd->mid_paned);
	
	wnd->bottom_hbox = gtk_hbox_new(FALSE, 5);
	gtk_box_pack_start(
		GTK_BOX(wnd->bottom_hbox),
		wnd->mat_tex_view->notebook,
		TRUE,
		TRUE,
		0
	);
	
	gtk_box_pack_start(
		GTK_BOX(wnd->bottom_hbox),
		wnd->pre_view->frame,
		FALSE,
		FALSE,
		0
	);
	gtk_widget_show(wnd->bottom_hbox);

	wnd->topbox = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(
		GTK_BOX(wnd->topbox),
		wnd->menubar,
		FALSE,
		TRUE,
		0
	);

	gtk_box_pack_start(
		GTK_BOX(wnd->topbox),
		wnd->toolbar,
		FALSE,
		TRUE,
		0
	);

	gtk_box_pack_start(
		GTK_BOX(wnd->topbox),
		wnd->mid_paned,
		TRUE,
		TRUE,
		0
	);

	gtk_box_pack_start(
		GTK_BOX(wnd->topbox),
		wnd->bottom_hbox,
		FALSE,
		TRUE,
		0
	);
	
	gtk_box_pack_start(
		GTK_BOX(wnd->topbox),
		wnd->statusbar->bar,
		FALSE,
		TRUE,
		0
	);

	gtk_widget_show(wnd->topbox);

	gtk_container_add(
		GTK_CONTAINER(wnd->window),
		wnd->topbox
	);

	gtk_window_add_accel_group(
		GTK_WINDOW(wnd->window),
		wnd->header->accel_group
	);
	
	g_signal_connect(
		G_OBJECT(wnd->window),
		"realize",
		G_CALLBACK(mape_window_cb_realize),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->window),
		"delete-event",
		G_CALLBACK(mape_window_cb_delete_event),
		wnd
	);
	
	gtk_widget_grab_focus(wnd->edit_view->view);
	
	g_signal_connect(
		G_OBJECT(wnd->header->file_new),
		"activate",
		G_CALLBACK(mape_window_cb_file_new),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->file_open),
		"activate",
		G_CALLBACK(mape_window_cb_file_open),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->file_save),
		"activate",
		G_CALLBACK(mape_window_cb_file_save),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->file_save_as),
		"activate",
		G_CALLBACK(mape_window_cb_file_save_as),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->file_quit),
		"activate",
		G_CALLBACK(mape_window_cb_file_quit),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->edit_undo),
		"activate",
		G_CALLBACK(mape_window_cb_edit_undo),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->edit_redo),
		"activate",
		G_CALLBACK(mape_window_cb_edit_redo),
		wnd
	);

	g_signal_connect(
		G_OBJECT(
			gtk_text_view_get_buffer(
				GTK_TEXT_VIEW(wnd->edit_view->view)
			)
		),
		"notify::can-undo",
		G_CALLBACK(mape_window_cb_edit_can_undo),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(
			gtk_text_view_get_buffer(
				GTK_TEXT_VIEW(wnd->edit_view->view)
			)
		),
		"notify::can-redo",
		G_CALLBACK(mape_window_cb_edit_can_redo),
		wnd
	);

	g_signal_connect(
		G_OBJECT(wnd->header->edit_preferences),
		"activate",
		G_CALLBACK(mape_window_cb_edit_preferences),
		wnd
	);
	
	g_signal_connect(
		G_OBJECT(wnd->header->help_about),
		"activate",
		G_CALLBACK(mape_window_cb_help_about),
		wnd
	);
	
	gtk_action_set_sensitive(wnd->header->edit_undo, FALSE);
	gtk_action_set_sensitive(wnd->header->edit_redo, FALSE);

	mape_edit_view_apply_preferences(wnd->edit_view, &wnd->preferences);
	mape_pre_view_apply_preferences(wnd->pre_view, &wnd->preferences);

	/* Load initial path in disk view, if any. Note this needs to go
	 * after applying preferences in edit_view, so that the map size is
	 * correct in case the newly loaded Material.ocg triggers a map update. */
	entry = mape_config_file_get_entry_by_key(
		wnd->config,
		"material_path"
	);

	if(entry != NULL)
	{
		mape_disk_view_extend_to_path(
			wnd->disk_view,
			mape_config_file_entry_get_value(entry),
			NULL
		);
	}

	gtk_window_set_title(GTK_WINDOW(wnd->window), "Mape");
	gtk_window_set_default_size(GTK_WINDOW(wnd->window), 640, 480);

	/* Load initial landscape */
	if(landscape_path != NULL)
	{
		mape_window_file_load(wnd, landscape_path);
		g_free(landscape_path);
	}

	gtk_widget_show(wnd->window);

	return wnd;

disk_view_error:
	mape_edit_view_destroy(wnd->edit_view);
	
edit_view_error:
	mape_pre_view_destroy(wnd->pre_view);

pre_view_error:
	mape_mat_tex_view_destroy(wnd->mat_tex_view);

mat_tex_error:
	g_free(landscape_path);

	mape_header_destroy(wnd->header);
	mape_statusbar_destroy(wnd->statusbar);

	mape_file_icon_set_destroy(wnd->icon_set);
	gtk_widget_destroy(wnd->window);
	mape_config_file_destroy(wnd->config);
	free(wnd);

	return NULL;
}

void mape_window_destroy(MapeWindow* wnd)
{
	mape_pre_view_destroy(wnd->pre_view);
	mape_edit_view_destroy(wnd->edit_view);
	mape_disk_view_destroy(wnd->disk_view);
	mape_mat_tex_view_destroy(wnd->mat_tex_view);
	mape_header_destroy(wnd->header);
	mape_file_icon_set_destroy(wnd->icon_set);

	mape_config_file_serialise(wnd->config, NULL);
	mape_config_file_destroy(wnd->config);
	g_free(wnd->last_path);
	free(wnd);
}
