/* interface.c - general GUI procedures */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gtk/gtk.h>
#include "main.h"


void clean_up(opt_s *o) {
	int i ;

	/* removing temporary files */
	for(i = 0 ; i < 3 ; i++) remove(o->panels[i].tmpfil) ;

	/* saving configuration */
	write_rcfile(o) ;

	/* freeing program entries */
	free_entries_all(o) ;

	/* freeing colors */
	free(o->colors) ;

	/* printout of the memory summary */
	memory_summary() ;

	fprintf(stderr, "Koniec\n") ;
	exit(EXIT_SUCCESS) ;
}


/* end of the program */
void arka_end(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o = (opt_s *) dane ;

	/* check if output changed and ask for saving if yes */
	if(o->panels[1].changed) 
		if(!demand("Output not saved.\nReally quit?")) return ;

	gtk_main_quit() ;

	clean_up(o) ;
	return ;
}


/* end of the program: translate functions */
void main_window_destroy(GtkWidget *kontrolka, gpointer dane) {
	opt_s *o = (opt_s *) dane ;

	if(o->panels[1].changed && demand("Output not saved.\nSave?")) {
		file_save_lowlevel(o, 1, o->panels[1].filenam) ;
	}

	clean_up(dane) ;
}


/* end of a gtk_main_quit dialog */
void zakoncz_dialog(GtkWidget *kontrolka, gpointer dane) {
	GtkWidget *okno = (GtkWidget *) dane ;

	gtk_widget_destroy(okno) ;
	gtk_main_quit() ;
}


/* --- some shortcuts for creating widgets and putting them into the provided box -- */


/* creates horizontal separator and puts it into the parent box */
GtkWidget *create_separator(GtkWidget *parentbox) {
	GtkWidget *res ;
	res = gtk_hseparator_new() ;
	gtk_box_pack_start(GTK_BOX(parentbox), res, FALSE, FALSE, 0) ;
	gtk_widget_show(res) ;
	return res ;
}


/* creates a label widget and puts it in the parent box */
GtkWidget *create_label(GtkWidget *parentbox, char* label) {
	GtkWidget *res ;
	res = gtk_label_new(label) ;
	gtk_box_pack_start(GTK_BOX(parentbox), res, FALSE, FALSE, 0) ;
	gtk_widget_show(res) ;
	return res ;
}


/* fed up with the gtk mess. creates a hbox and puts it into the parent box  */
GtkWidget *create_hbox(GtkWidget *parentbox) {
	GtkWidget *hpole ;
	hpole = gtk_hbox_new(FALSE, 5) ;
	gtk_box_pack_start(GTK_BOX(parentbox), hpole, FALSE, FALSE, 0) ;
	gtk_widget_show(hpole) ;
	return hpole ;
}


/* creates a hbox with a combo list and a label in it. returns the combo list */
GtkWidget *create_combo(GtkWidget* parentbox, char *label, char *items[], int n) {
	GtkWidget *res, *hpole, *lab ;
	GList *lista = NULL ;
	int i ;

	hpole = gtk_hbox_new(FALSE, 5) ;
	gtk_box_pack_start(GTK_BOX(parentbox), hpole, FALSE, FALSE, 0) ;
	res = gtk_combo_new() ;
	gtk_box_pack_start(GTK_BOX(hpole), res, TRUE, TRUE, 5) ;

	/* creating item list */
	for(i = 0 ; i < n ; i++) {
		lista = g_list_append(lista, items[i]) ;
	}

	gtk_combo_set_popdown_strings(GTK_COMBO(res), lista) ;
	gtk_combo_set_value_in_list(GTK_COMBO(res), TRUE, FALSE) ;

	if(label) {
		lab = gtk_label_new(label) ;
		gtk_box_pack_start(GTK_BOX(hpole), lab, FALSE, FALSE, 5) ;
	}

	return res ;
}


/* creates a gtk list from a char array of items */
GtkWidget *create_list(GtkWidget* parentbox, char *label, char *items[], int n) {
	GtkWidget *res, *hpole, *item, *lab ;
	GList *lista = NULL ;
	int i ;

	hpole = gtk_hbox_new(FALSE, 5) ;
	gtk_box_pack_start(GTK_BOX(parentbox), hpole, TRUE, TRUE, 0) ;

	/* creating item list */
	for(i = 0 ; i < n ; i++) {
		item = gtk_list_item_new_with_label(items[i]) ;
		lista = g_list_append(lista, item) ;
	}

	/* creating list */
	res = gtk_list_new() ;
	gtk_list_append_items(GTK_LIST(res), lista) ;
	gtk_list_set_selection_mode(GTK_LIST(res), GTK_SELECTION_BROWSE) ;
	gtk_box_pack_start(GTK_BOX(hpole), res, FALSE, FALSE, 5) ;

	/* label, if not NULL */
	if(label) {
		lab = gtk_label_new(label) ;
		gtk_box_pack_start(GTK_BOX(hpole), lab, FALSE, FALSE, 5) ;
	}

	gtk_widget_show_all(hpole) ;
	lista = NULL ;
	return res ;
}


/* makes a button, puts it in a box, connects a function with respective data */
GtkWidget *create_button(GtkWidget *box, gpointer func, char* label, gpointer data) {
	GtkWidget *res ;

	res = gtk_button_new_with_label(label) ;
	gtk_box_pack_start(GTK_BOX(box), res, FALSE, FALSE, 5) ;

	if(func) {
		gtk_signal_connect(GTK_OBJECT(res), "clicked", GTK_SIGNAL_FUNC(func), data) ;
	}

  GTK_WIDGET_SET_FLAGS(res, GTK_CAN_DEFAULT) ;
	return res ;
}


/* creates a scrollable text box and puts it into the parentbox */
GtkWidget* create_text(GtkWidget *parentbox, char* text, int editable) {
	GtkWidget *res, *scrol ;
	int i = 0 ;

	res = gtk_text_new(NULL, NULL) ;

	gtk_text_set_word_wrap(GTK_TEXT(res), FALSE) ;
	gtk_text_set_line_wrap(GTK_TEXT(res), FALSE) ;
	gtk_text_set_editable(GTK_TEXT(res), editable) ;

	if(text) gtk_editable_insert_text(GTK_EDITABLE(res), text, strlen(text), &i) ;

	scrol = gtk_scrolled_window_new(NULL, NULL) ;
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrol), 
		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC) ;
	gtk_container_add(GTK_CONTAINER(scrol), res) ;

	gtk_box_pack_start(GTK_BOX(parentbox), scrol, TRUE, TRUE, 0) ;
	gtk_widget_show_all(parentbox) ;

	return res ;
}



/* recycling code. creates an option widget with label and returns this widget
 * which is in control of the options value. */
GtkWidget* create_option_widget(GtkWidget *parentbox, int type, char* description) {

	GtkWidget *hbox, *label, *res ;
	GtkAdjustment *adj ;

	hbox = gtk_hbox_new(FALSE, 5) ;
	gtk_box_pack_start(GTK_BOX(parentbox), hbox, FALSE, FALSE, 5) ;

	switch(type){
		case BOOLEAN:
			/* just a simple check button */
			res = gtk_check_button_new() ;
			break ;

		case INT:
		case DOUBLE:
			adj = (GtkAdjustment *) gtk_adjustment_new(0, INT_MIN, INT_MAX, 1, 10, 10) ;

			if(type == INT) res = gtk_spin_button_new(adj, 1, 0) ;
			else res = gtk_spin_button_new(adj, 1, 2) ;

			gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(res), FALSE) ;
			break ;
		case FILENAME:
		case STRING:
		default:
			res = gtk_entry_new() ;
			break;
	}

	gtk_box_pack_start(GTK_BOX(hbox), res, TRUE, TRUE, 5) ;
	
	if(description) {
		label = gtk_label_new(description) ;
		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5) ;
	}

	gtk_widget_show_all(hbox) ;
	return res ;
}


/* shows the menu that was pressed. debugging purposes only */
void pokaz(gpointer dane, guint signal, GtkWidget *kontrolka) {
	char tmp[100] ;
	opt_s *o ;
	o = (opt_s*) dane ;
	sprintf(tmp, "Fabryka: %s is %d",
		gtk_item_factory_path_from_widget(kontrolka), signal) ;
	komunikat(tmp) ;
}


/* clears the selected window */
void clear_window(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;
	okno_s *okno ;

	o = (opt_s *) dane ;

	okno = &o->panels[signal] ;

	gtk_editable_delete_text(GTK_EDITABLE(okno->tekst), 0, -1) ;
	okno->changed = FALSE ;
}


/* launches an external editor */
void external_editor(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;
	okno_s *okno ;
	char *cmd ;

	o = (opt_s *) dane ;

	okno = &o->panels[signal] ;

	window_tofile(okno, o) ; /* save window contents */
	cmd = my_strsubst(o->external_editor, "%input", okno->tmpfil) ;
	/* execute external editor */

	if(system(cmd))
		komunikat("There was a problem running command:\n%s", o->external_editor); 

	clear_window(dane, signal, kontrolka) ; /* clear window */
	file_to_window(o, okno, 0) ; /* load edited file again into the window */
}


/* switches window showing on and off */
void toggle_windows(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;
	okno_s *okno ;
	GtkRequisition req = { -1 , 0 } ;

	o = (opt_s *) dane ;
	okno = &o->panels[signal] ;

	if(okno->on) {
		gtk_widget_hide(okno->ramka) ;
		gtk_widget_size_request(okno->ramka, &req) ;
		okno->on = FALSE ;
	} else {
		gtk_widget_show(okno->ramka) ;
		okno->on = TRUE ;
	}
	gtk_paned_set_position(GTK_PANED(okno->parent), -1) ;
}


/* plops the contents from one window to the other one */
void plop_contents(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;
	okno_s *okno1, *okno2 ;
	char *tmp ;
	int i = 0 ;

	o = (opt_s *) dane ;

	okno1 = &o->panels[signal >> 8] ;
	okno2 = &o->panels[signal - 256 * (signal >> 8)] ;

	say(0, "%s => %s", okno1->title, okno2->title) ;

	tmp = gtk_editable_get_chars(GTK_EDITABLE(okno1->tekst), 0, -1) ;
	gtk_editable_delete_text(GTK_EDITABLE(okno2->tekst), 0, -1) ;
	gtk_editable_insert_text(GTK_EDITABLE(okno2->tekst), tmp, strlen(tmp), &i) ;
	free(tmp) ;
	
}



/* toggles the input window editable / not editable */
void toggle_editable(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;

	o = (opt_s *) dane ;
	o->editable = (!o->editable) ;
	gtk_text_set_editable(GTK_TEXT(o->panels[0].tekst), o->editable) ;
}


/* toggles the input window editable / not editable */
void toggle_tooltips(gpointer dane, guint signal, GtkWidget *kontrolka) {
	opt_s *o ;

	o = (opt_s *) dane ;
	o->show_tooltips = (!o->show_tooltips) ;
	if(o->show_tooltips) gtk_tooltips_enable(o->tips) ;
	else gtk_tooltips_disable(o->tips) ;
}


/* sets the selected font; dialog window is passed in the o->tmp structure */
void set_font(GtkWidget *okno, opt_s *o) {
	char *czcionka ;
	GtkWidget *wybcz ;
	GtkFontSelectionDialog *wybcz_d ;

	wybcz_d = (GtkFontSelectionDialog *) o->tmp ;
	wybcz = (GtkWidget *) o->tmp ;
	czcionka = gtk_font_selection_dialog_get_font_name(wybcz_d) ;

	if(czcionka != NULL) {
		printf("czcionka %s\n", czcionka) ;
		o->czcionka = gdk_font_load(czcionka) ;
	} else {
		printf("null font loaded \n") ;
	}

	gtk_widget_destroy(wybcz) ;
}


/* select font dialog */
void select_font(opt_s *o) {

	GtkWidget *wybcz ;
	GtkFontSelectionDialog *wybcz_d ;

	wybcz = gtk_font_selection_dialog_new("Choose a font for the main window") ;
	wybcz_d = GTK_FONT_SELECTION_DIALOG(wybcz) ;

	o->tmp = wybcz ;

	gtk_signal_connect(GTK_OBJECT(wybcz_d->ok_button),
		"clicked", GTK_SIGNAL_FUNC(set_font), o) ;
	gtk_signal_connect(GTK_OBJECT(wybcz_d->cancel_button),
		"clicked", GTK_SIGNAL_FUNC(close_dialog), GTK_OBJECT(wybcz_d)) ;
	gtk_signal_connect(GTK_OBJECT(wybcz_d), "destroy", 
		GTK_SIGNAL_FUNC(zakoncz_dialog), wybcz_d) ;
	gtk_widget_show(wybcz) ;

	gtk_main() ;
}


/* called when OK is pressed in the font selection dialog */
void get_font_name_ok(GtkWidget *okno, gpointer dane) {
	GtkFontSelectionDialog *wybcz_d ;
	data_s *d ;
	char *czcionka ;

	d = (data_s *) dane ;
	wybcz_d = (GtkFontSelectionDialog*) d->data1 ;

	czcionka = gtk_font_selection_dialog_get_font_name(wybcz_d) ;
	d->data = my_strdup(czcionka) ;
	gtk_widget_destroy(GTK_WIDGET(wybcz_d)) ;
}


/* starts the font selection dialog and returns the font */
char *get_font_name(opt_s *o, char *name) {
	GtkWidget *wybcz ;
	GtkFontSelectionDialog *wybcz_d ;
	data_s d ;
	char *res ;
	say(0, "get_font_name") ;

	wybcz = gtk_font_selection_dialog_new("Choose a font for the main window") ;
	wybcz_d = GTK_FONT_SELECTION_DIALOG(wybcz) ;
	if(name) gtk_font_selection_dialog_set_font_name(wybcz_d, name) ;
	gtk_widget_show(wybcz) ;

	d.data = NULL ;
	d.data1 = wybcz_d ;

	gtk_signal_connect(GTK_OBJECT(wybcz_d->ok_button),
		"clicked", GTK_SIGNAL_FUNC(get_font_name_ok), &d) ;
	gtk_signal_connect(GTK_OBJECT(wybcz_d->cancel_button),
		"clicked", GTK_SIGNAL_FUNC(zakoncz_dialog), wybcz) ;
	gtk_signal_connect(GTK_OBJECT(wybcz), "destroy", 
		GTK_SIGNAL_FUNC(zakoncz_dialog), wybcz) ;

	gtk_widget_show(wybcz) ;

	gtk_main() ;
	res = (char *) d.data ;

	return res ;
}


/* sets new style recursively for a widget and all further winoows */
void set_style_recursive(GtkWidget *okno, gpointer dane) {
	GtkStyle *styl ;

	styl = (GtkStyle *) dane ;
	gtk_widget_set_style(okno, styl) ;
	if(GTK_IS_CONTAINER(okno)) {
		gtk_container_foreach(GTK_CONTAINER(okno), set_style_recursive, styl) ;
	}

}


/* redraws text in a text window using the new font set */
void redraw_text(opt_s *o) {
	gchar *tmp ;
	tmp = gtk_editable_get_chars(GTK_EDITABLE(o->panels[0].tekst), 0, -1);
	gtk_editable_delete_text(GTK_EDITABLE(o->panels[0].tekst), 0, -1);
	gtk_text_insert(GTK_TEXT(o->panels[0].tekst), o->czcionka, NULL, NULL,
		tmp, strlen(tmp)) ;
}


/* changes fonts */
void change_font(opt_s *o) {
	select_font(o) ;
	redraw_text(o) ;
}


/* given a filename and it's position, it appends the apriopriate entry to the
 * "File" menu */
int append_single_entry(opt_s *o, char *filen, int i) {
	GtkItemFactoryEntry separator = {"/File/sep2",	NULL,	NULL,	0, "<Separator>"} ;
	GtkItemFactoryEntry element = {NULL, NULL,	file_open_from_list,	0} ;
	char *menun, *a, tmp1[10] ;

	if(! (filen)) return EXIT_FAILURE ;

	if(i == 0) gtk_item_factory_create_items(o->fabryka, 1, &separator, o) ;
	if(i == -1) i = g_list_length(o->file_history) - 1 ;

	if(! (menun = strrchr(filen, '/')) ) menun = filen ;
	else menun++ ;

	a = malloc(strlen(menun) + 30) ;
	sprintf(a, "/File/_%i %s", i+1, menun) ;
	sprintf(tmp1, "<control>%i", i+1) ;
	element.path = a ;
	element.accelerator = tmp1 ;
	element.callback_action = i ;

	gtk_item_factory_create_items(o->fabryka, 1, &element, o) ;
	free(a) ;

	return EXIT_SUCCESS ;
}


/* appends the file entries from config file */ 
int append_entries(opt_s *o) {
	char *filen ;
	int i ;

	if(o->file_history == NULL) return EXIT_FAILURE ;

	for(i = 0 ; i < g_list_length(o->file_history) ; i++ ) {
		filen = g_list_nth_data(o->file_history, i) ;
		append_single_entry(o, filen, i) ;
	}

	return EXIT_SUCCESS ;
}


/* here, the main menu and main window is created */
void inicjuj_menu(opt_s *o) {
	int nel ;

	static GtkItemFactoryEntry elementy[] = {
		{"/_File",	NULL, 0, 0, "<Branch>"},
		{"/File/tearoff1",	NULL,	NULL, 0, "<Tearoff>"},
		/* {"/File/_New",	"<control>N",	NULL,	0}, */
		{"/File/_Open input file", "<control>O",	file_open,	0},
		{"/File/Quick _save output", "<control>S",	file_save,	1},
		{"/File/S_ave.../Save _input as", NULL,	file_save_as,	0},
		{"/File/S_ave.../Save _output as", NULL,	file_save_as,	1},
		{"/File/S_ave.../Save _error as", NULL,	file_save_as,	2},
		{"/File/sep1",	NULL,	NULL,	0, "<Separator>"},
		{"/File/_Quit",	"<control>Q",	arka_end,	0},

		{"/_Edit",	NULL, 0, 0, "<Branch>"},
		{"/Edit/tearoff1",	NULL,	NULL, 0, "<Tearoff>"},
		{"/Edit/_Search", NULL, search, 0},
		{"/Edit/Search & _replace", NULL, search, 1},
		{"/Edit/_Clear.../Clear _input",	NULL,	clear_window,	0},
		{"/Edit/_Clear.../Clear _output",	"<control>C",	clear_window,	1},
		{"/Edit/_Clear.../Clear _error",	NULL,	clear_window,	2},
		{"/Edit/_External editor.../Edit _input", NULL,	external_editor,	0},
		{"/Edit/_External editor.../Edit _output", NULL,	external_editor,	1},
		{"/Edit/_External editor.../Edit _error", NULL,	external_editor,	2},
		{"/Edit/_Output => input", NULL,	plop_contents,	(1<<8)},
		{"/Edit/_Sequence editor", NULL,	seqed_start,	0},

		{"/_Options", NULL,	0,	0, "<Branch>"},
		{"/Options/tearoff1",	NULL,	0, 0, "<Tearoff>"},
		{"/Options/_Editable",	NULL,	toggle_editable,	0, "<CheckItem>"},
		{"/Options/_Hide tooltips",	NULL,	toggle_tooltips,	0, "<CheckItem>"},
		{"/Options/_Font",	NULL,	change_font,	0},
		{"/Options/_Preferences...",	NULL,	options_preferences_set,	0},

		{"/_Tools", NULL,	0,	0, "<Branch>"},
		{"/Tools/tearoff1",	NULL,	NULL, 0, "<Tearoff>"},
		{"/Tools/_GC graph",	NULL,	graph_gc,	0},
		{"/Tools/Graph _3D", NULL, NULL, 0, "<Branch>"},
		{"/Tools/Graph 3D/_From input", NULL, graph3d_create_from_input, 0},
		{"/Tools/Graph 3D/_From file", NULL, graph3d_create_from_file, 0},
		{"/Tools/_Command...",	NULL,	command,	0},
		{"/Tools/_Sequence editor", NULL,	seqed_start,	0},

		{"/_Programs", NULL,	0,	0, "<Branch>"},
		{"/Programs/tearoff1",	NULL,	NULL, 0, "<Tearoff>"},

		{"/_Windows", NULL,	0,	0, "<Branch>"},
		{"/Windows/tearoff1",	NULL,	0, 0, "<Tearoff>"},
		{"/Windows/_Input",	NULL,	toggle_windows,	0, "<CheckItem>"},
		{"/Windows/_Output",	NULL,	toggle_windows,	1, "<CheckItem>"},
		{"/Windows/_Error",	NULL,	toggle_windows,	2, "<CheckItem>"} } ,

	helps[] = {
		{"/_Help",	NULL, 0, 0, "<LastBranch>"},
		/* {"/Help/_Topics", NULL,	help_about,	0} ,*/
		{"/Help/_Readme", NULL,	help_text,	0} ,
		{"/Help/_License", NULL,	help_text,	1} ,
		{"/Help/_About",	NULL,	help_about,	0}
	} ;

	nel = sizeof(elementy) / sizeof(GtkItemFactoryEntry) ;
	o->shortcuts = gtk_accel_group_new() ;
	gtk_accel_group_attach(o->shortcuts, GTK_OBJECT(o->okno)) ;

	o->fabryka = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<bla>", o->shortcuts) ;
	gtk_item_factory_create_items(o->fabryka, nel, elementy, o) ;

	append_entries(o) ;
	programs_append(o) ;

	nel = sizeof(helps) / sizeof(GtkItemFactoryEntry) ;
	gtk_item_factory_create_items(o->fabryka, nel, helps, o) ;

	gtk_box_pack_start(GTK_BOX(o->ypole), 
		gtk_item_factory_get_widget(o->fabryka,"<bla>"), FALSE, FALSE, 0) ;
}


/* changes the "changed" flag in okno_s struct when text is modified */
void tekst_changed(GtkEditable *kontrolka, gpointer data) {
	okno_s *o ;
	o = (okno_s *) data ;
	o->changed = TRUE ;
}


/* function that handles inserting of the text */
void insert_text(GtkEditable *w, const gchar *text, gint l, gint *p, gpointer data) {

	gtk_signal_handler_block_by_func(GTK_OBJECT(w), GTK_SIGNAL_FUNC(insert_text), data) ;
	gtk_editable_insert_text(w, text, l, p) ;
	gtk_signal_handler_unblock_by_func(GTK_OBJECT(w), GTK_SIGNAL_FUNC(insert_text), data) ;
	gtk_signal_emit_stop_by_name(GTK_OBJECT(w), "insert_text") ;
}


/* initiates the color map */
int allocate_colors(opt_s *o) {
	int i, n ;

	n = WHITE + 1 ;

	say(0, "Allocating colors") ;
	o->ncolors = n ;
	o->colors = malloc(n * sizeof(*o->colors)) ;
	gdk_color_parse("black", &o->colors[BLACK]) ;
	gdk_color_parse("red", &o->colors[RED]) ; 
	gdk_color_parse("green", &o->colors[GREEN]) ;
	gdk_color_parse("blue", &o->colors[BLUE]) ;
	gdk_color_parse("violet", &o->colors[VIOLET]) ;
	gdk_color_parse("yellow", &o->colors[YELLOW]) ;
	gdk_color_parse("magenta", &o->colors[MAGENTA]) ;
	gdk_color_parse("cyan", &o->colors[CYAN]) ; 
	gdk_color_parse("white", &o->colors[WHITE]) ; 

	for(i = 0; i < n; i++) {
		if(!gdk_colormap_alloc_color(gdk_colormap_get_system(), &o->colors[i], FALSE, TRUE)) 
			printf("Color %i could not be allocated\n", i) ;
	}

	return EXIT_SUCCESS ;
}

/* makes a table containing a text widget with scroll bars and adds it to the
 * specified GtkWidget called kontrolka */
void make_ramka(GtkWidget *kontrolka, okno_s *o) {

	o->tekst = gtk_text_new(NULL, NULL) ;
	gtk_text_set_word_wrap(GTK_TEXT(o->tekst), FALSE) ;
	gtk_text_set_line_wrap(GTK_TEXT(o->tekst), FALSE) ;

	gtk_widget_show(o->tekst) ;
	gtk_text_set_editable(GTK_TEXT(o->tekst), FALSE) ;

	/* handlers for "change text" and "insert text" */
	gtk_signal_connect(GTK_OBJECT(o->tekst), "changed", 
		GTK_SIGNAL_FUNC(tekst_changed), o) ;
	gtk_signal_connect(GTK_OBJECT(o->tekst), "insert_text", 
		GTK_SIGNAL_FUNC(insert_text), o) ;

	o->tabela = gtk_scrolled_window_new(NULL, NULL) ;
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(o->tabela), 
		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC) ;
	gtk_container_add(GTK_CONTAINER(o->tabela), o->tekst) ;
	gtk_widget_show(o->tabela) ;

	gtk_container_add(GTK_CONTAINER(kontrolka), o->tabela) ;

	o->on = TRUE ;
}


/* initiates the main window and calls the inicjuj_menu function */
void inicjuj_main_window(opt_s *o) {
	int i ;
	char tmp[100] ;
	GtkWidget *w, *panel1, *panel2 ;

	/* creating main window */
	o->okno = gtk_window_new(GTK_WINDOW_TOPLEVEL) ;
	gtk_widget_show(o->okno) ;
	gtk_widget_set_usize(o->okno,
		gdk_screen_width() * 0.8, gdk_screen_height() * 0.8) ;
	sprintf(tmp, "Arka v. %s", VERSION) ;
	gtk_window_set_title(GTK_WINDOW(o->okno), tmp) ;
	gtk_signal_connect(GTK_OBJECT(o->okno), "destroy", 
		GTK_SIGNAL_FUNC(main_window_destroy), o) ;

	/* vertical container */
	o->ypole = gtk_vbox_new(FALSE, 1) ;
	gtk_container_add(GTK_CONTAINER(o->okno), o->ypole) ;
	gtk_widget_show(o->ypole) ;

	inicjuj_menu(o) ;

	/* initiating three main windows */
	strcpy(o->panels[0].title, "Input") ;
	strcpy(o->panels[1].title, "Output") ;
	strcpy(o->panels[2].title, "Errors") ;

	for(i = 0 ; i < 3 ; i++) {
		o->panels[i].ramka = gtk_frame_new(o->panels[i].title) ;
		make_ramka(o->panels[i].ramka, &o->panels[i]) ;
	}

	/* text windows are stored in panels so we can resize them */
	panel1 = gtk_vpaned_new() ;
	panel2 = gtk_vpaned_new() ;

	gtk_paned_pack1(GTK_PANED(panel2), o->panels[0].ramka, TRUE, TRUE) ;
	gtk_paned_pack2(GTK_PANED(panel2), o->panels[1].ramka, TRUE, TRUE) ;
	gtk_paned_pack1(GTK_PANED(panel1), panel2, TRUE, TRUE) ;
	gtk_paned_pack2(GTK_PANED(panel1), o->panels[2].ramka, TRUE, TRUE) ;

	o->panels[0].parent = panel2 ;
	o->panels[1].parent = panel2 ;
	o->panels[2].parent = panel1 ;
	
	gtk_box_pack_start(GTK_BOX(o->ypole), panel1, TRUE, TRUE, 0) ;

	gtk_tooltips_set_tip(GTK_TOOLTIPS(o->tips), o->panels[0].tekst,
		"This is the data input window. " 
		"Use the FILE/Open menu entry to load data into that window", "Just try it") ;
	gtk_tooltips_set_tip(GTK_TOOLTIPS(o->tips), o->panels[1].tekst,
		"This is the output window. "
		"The output of any external programs (from the PROGRAMS menu)"
		"you will run.", "Just try it") ;
	gtk_tooltips_set_tip(GTK_TOOLTIPS(o->tips), o->panels[2].tekst,
		"This is the error window. "
		"You will find here any error messages issued by the programs run."
		"In other words, it corresponds to the stderr", "Just try it") ;

	w = gtk_item_factory_get_widget(o->fabryka, "/Options/Hide tooltips") ;
	i = o->show_tooltips ;
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), !o->show_tooltips) ;
	o->show_tooltips = i ;
	if(o->show_tooltips) gtk_tooltips_enable(o->tips) ;
	else gtk_tooltips_disable(o->tips) ;

	/* status bar */
	o->status = gtk_statusbar_new () ;
	i = gtk_statusbar_get_context_id(GTK_STATUSBAR(o->status), "dupa") ;
	gtk_statusbar_push(GTK_STATUSBAR(o->status), i, "Welcome!") ;
	gtk_box_pack_start(GTK_BOX(o->ypole), o->status, FALSE, FALSE, 0) ;

	gtk_window_set_position(GTK_WINDOW(o->okno), GTK_WIN_POS_CENTER) ;
	gtk_widget_show_all(o->okno) ;
}

