(no subject)



Added check for valid project directory (prev caused dump).
Added project directory selection dialog.
/* $Header: /cvs/gnome/gIDE/src/gI_project.c,v 1.17 2000/11/04 15:13:21 dirkvan Exp $ */
/* gIDE
 * Copyright (C) 1998-2000 Steffen Kern
 *
 * 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "gide.h"
#include <dirent.h>
#include <sys/stat.h>

#include "gI_file.h"
#include "gI_compile_sets.h"
#include "gI_compile.h"
#include "gI_common.h"
#include "gI_window.h"
#include "gI_menus.h"
#include "gI_project.h"
#include "gI_project_window.h"

/* local prototypes */
static void project_open_file_in_editor(GtkWidget* widget, gchar* file);
static void project_add_new_file_to(GtkWidget* widget, gpointer);
static void close_project_files(gI_project* project);
/*static void project_open_file(GtkWidget* widget, gpointer data);*/
static gboolean is_compile_window_visible(GideDocument* doc);
static void project_add_to_current(gI_project* parent_project,
	gI_project* project);
static gI_project* project_create(void);
static void project_destroy(gI_project* project);
static void project_open(void);
static void project_delete(void);
static void project_fill_prj_list(void);
static void project_delete_clicked(GnomeDialog* dlg, int button,
	gpointer data);
static void project_open_clicked(GnomeDialog* dlg, int button,
	gpointer data);
static gchar* project_get_includes(gI_project* project);
static gchar* project_get_libdirs(gI_project* project);
static gchar* project_get_libs(gI_project* project);
static gchar* project_get_makefile_name(gI_project* project);
static gchar* project_get_options(gI_project* project);
static void project_add_to_compile_window(GideDocument* document, gchar* buf);
static void project_objects_add(gI_project* project, gchar* exec_file);
static void project_compile_source(gI_project* project, gchar* c_filename,
	GideDocument* document);
static void project_link(gI_project* project, gchar* c_filename,
	GideDocument* document);

/* Additions for project dialog */
void project_open_dialog(GtkWidget* widget, gpointer data);
void project_set_dir(GtkFileSelection *selector, gpointer user_data);


/* globals */
static GtkWidget*						project_open_window = NULL;
static GtkWidget*						project_delete_window = NULL;
static GtkWidget*						cb_open;
static GtkWidget*						cb_close;
static GtkWidget*						prj_list;
static GtkWidget*						e_prjdir;
static GtkWidget*                       prj_open;
/*
static GtkWidget*						cb_select;
*/
static GtkWidget*						cb_delete;
static glong							prj_selected = -1;
static gI_project*						current_project = NULL;
static GtkWidget*						root_tree = NULL;
static gchar*							objects = NULL;

/*
 * Create a new project structure
 */
static gI_project*
project_create(
	void
)
{
	glong								i;
	glong								j;
	gI_project*							project;

	project = g_malloc0(sizeof(gI_project));

	for(i = 0; i < MAX_PROJECT_TARGETS; i++)
	{
		project->targets[i] = g_malloc0(sizeof(gI_target));
	}

	project->filename = NULL;
	project->name = NULL;
	project->version = NULL;
	project->changelog = NULL;
	project->prjroot = NULL;
	project->prjfdir = NULL;
	for(j = 0; j < MAX_PROJECT_TARGETS; j++)
	{
		for(i = 0; i < MAX_PROJECT_FILES; i++)
		{
			project->targets[j]->sources[i] = NULL;
			project->targets[j]->build[i] = 0;
		}
		project->targets[j]->name = NULL;
		project->targets[j]->sources_no = 0;
	}
	project->libs_no = 0;
	for(i = 0; i < MAX_PROJECT_FILES; i++)
	{
		project->libs[i] = NULL;
	}
	project->cpar = NULL;
	project->cinc = NULL;
	project->lpar = NULL;
	project->llib = NULL;

	project->mtarget = NULL;

	return project;
}

/*
 * Destructor function to destroy project & deallocate mem etc.
 */
static void
project_destroy(
	gI_project*							project
)
{
	glong								i;
	glong								j;

	g_assert(project);

	if(project->filename)
	{
		g_free(project->filename);
	}
	if(project->name)
	{
		g_free(project->name);
	}
	if(project->version)
	{
		g_free(project->version);
	}
	if(project->changelog)
	{
		g_free(project->changelog);
	}
	if(project->prjroot)
	{
		g_free(project->prjroot);
	}
	if(project->prjfdir)
	{
		g_free(project->prjfdir);
	}

	for(j = 0; j < MAX_PROJECT_TARGETS; j++)
	{
		for(i = 0; i < project->targets[j]->sources_no; i++)
		{
			/* presumably, sources_no works */
			g_assert(project->targets[j]->sources[i]);
			g_free(project->targets[j]->sources[i]);
		}
		if(project->targets[j]->name)
		{
			g_free(project->targets[j]->name);
		}
		g_free(project->targets[j]);
	}

	for(j = 0; j < MAX_PROJECT_FILES && j < project->libs_no; j++)
	{
		/* presumably, libs_no works */
		g_assert(project->libs[j]);
		g_free(project->libs[j]);
	}

	if(project->cpar)
	{
		g_free(project->cpar);
	}
	if(project->cinc)
	{
		g_free(project->cinc);
	}
	if(project->lpar)
	{
		g_free(project->lpar);
	}
	if(project->llib)
	{
		g_free(project->llib);
	}

	gI_todo_list_destroy(project->todoList);

	if(project->mtarget)
	{
		g_free(project->mtarget);
	}

	g_free(project);
}


/*
 * Open and parse a project
 */
static void
project_open(
	void
)
{
	gchar*								selected_project;
	FILE*								prjfile;
	gchar*								prjwp;
	gchar								buf[MAXLEN];
	gchar								key[64];
	gchar								arg[256];
	gI_project*							project;
	glong								i;
	glong								j = 0;
	gchar*								ptr;
	GList*								selection;

	selection = GTK_CLIST(prj_list)->selection;
	if(!selection)
	{
		return;
	}

	prj_selected = (gint)selection->data;

	gtk_clist_get_text(GTK_CLIST(prj_list), prj_selected, 0, &selected_project);

	prjwp = g_strdup_printf("%s/%s.prj", prj_path, selected_project);
	prjfile = fopen(prjwp, "r");
	if(!prjfile)
	{
		gI_error_dialog(_("Unable to open project file"));
		g_free(prjwp);
		return;
	}

	project = project_create();

	project->filename = prjwp;

	if(GTK_TOGGLE_BUTTON(cb_close)->active)
	{
		gI_file_close_all(NULL, NULL);
	}

	while(fgets(buf, sizeof(buf), prjfile))
	{
		g_strchug(buf);
		if(buf[0] == ';' || buf[0] == '#' || buf[0] == '\0')
		{
			continue;
		}

		if(sscanf(buf, "%s %s\n", key, arg) != 2)
		{
			g_print("Unknown line in project file!\n");
			g_print(buf);
			continue;
		}

		if(!strcmp(key, "PROJECT:"))
		{
			project->name = g_strdup(arg);
		}
		else if(!strcmp(key, "VERSION:"))
		{
			project->version = g_strdup(arg);
		}
		else if(!strcmp(key, "CHANGELOG:"))
		{
			ptr = SK_GetBetween(buf, '!', '!');
			project->changelog = g_strdup(ptr);
		}
		else if(!strcmp(key, "MTARGET:"))
		{
			ptr = SK_GetBetween(buf, '!', '!');
			project->mtarget = g_strdup(ptr);
		}
		else if(!strcmp(key, "PRJROOT:"))
		{
			ptr = SK_GetBetween(buf, '!', '!');
			project->prjroot = g_strdup(ptr);
		}
		else if(!strcmp(key, "PRJFDIR:"))
		{
			ptr = SK_GetBetween(buf, '!', '!');
			project->prjfdir = g_strdup(ptr);
		}
		else if(!strcmp(key, "$TARGETS:"))
		{
			project->targets_no = atoi(arg);
			for(i = 0; i < project->targets_no; i++)
			{
				fgets(buf, sizeof(buf), prjfile);
				ptr = strchr(buf, '\n');
				if(ptr)
				{
					*ptr = '\0';
				}
				project->targets[i]->name = g_strdup(buf);
			}
			fgets(buf, sizeof(buf), prjfile);
			g_strchug(buf);
			ptr = strchr(buf, '\n');
			if(ptr)
			{
				*ptr = '\0';
			}
			if(strcmp(buf, "$END TARGETS"))
			{
				g_warning("Unfinished $TARGETS statement in project file\n");
			}
		}
		else if(!strcmp(key, "$SOURCES:"))
		{
			project->targets[j]->sources_no = atoi(arg);
			fgets(buf, sizeof(buf), prjfile);
			j = atoi(buf);

			for(i = 0; i < project->targets[j]->sources_no; i++)
			{
				fgets(buf, sizeof(buf), prjfile);
				ptr = strchr(buf, '\n');
				if(ptr)
				{
					*ptr = '\0';
				}
				if(GTK_TOGGLE_BUTTON(cb_open)->active)
				{
					project_open_file_in_editor(NULL, buf);
				}
				project->targets[j]->sources[i] = g_strdup(buf);

				fgets(buf, sizeof(buf), prjfile);
				project->targets[j]->build[i] = atoi(buf);
			}
			fgets(buf, sizeof(buf), prjfile);
			g_strchug(buf);
			ptr = strchr(buf, '\n');
			if(ptr)
			{
				*ptr = '\0';
			}
			if(strcmp(buf, "$END SOURCES"))
			{
				g_warning("Unfinished $SOURCES statement in project file\n");
			}
		}
		else if(!strcmp(key, "$LIBS:"))
		{
			project->libs_no = atoi(arg);

			for(i = 0; i < project->libs_no; i++)
			{
				fgets(buf, sizeof(buf), prjfile);
				if(feof(prjfile))
				{
					g_error("Unfinished statement in project file\n");
				}

				if(!strcmp(buf, "$END LIBS"))
				{
					/* something is going wrong */
					g_warning("Can't find end of libs statement\n");
					break;
				}

				ptr = strchr(buf, '\n');
				if(ptr)
				{
					*ptr = '\0';
				}
				project->libs[i] = g_strdup(buf);
			}
			fgets(buf, sizeof(buf), prjfile);
			g_strchug(buf);
			ptr = strchr(buf, '\n');
			if(ptr)
			{
				*ptr = '\0';
			}
			if(strcmp(buf, "$END LIBS"))
			{
				g_error("Unfinished $LIBS statement in project file\n");
			}
		}
		else if(!strcmp(key, "CPAR:"))
		{
			strcpy(arg, SK_GetBetween(buf,  '!', '!'));
			project->cpar = g_strdup(arg);
		}
		else if(!strcmp(key, "CINC:"))
		{
			strcpy(arg, SK_GetBetween(buf, '!', '!'));
			project->cinc = g_strdup(arg);
		}
		else if(!strcmp(key, "LPAR:"))
		{
			strcpy(arg, SK_GetBetween(buf, '!', '!' ));
			project->lpar = g_strdup(arg);
		}
		else if(!strcmp(key, "LLIB:"))
		{
			strcpy(arg, SK_GetBetween(buf, '!', '!'));
			project->llib = g_strdup(arg);
		}
		else if(!strcmp(key, "$Begin_Todo"))
		{
			project->todoList = gI_todo_list_read_from_file(prjfile,
				"$End_Todo List");
		}
		else
		{
			g_print("Unknown line in project file!\n");
			g_print(buf);
		}
	}

	if(!project->todoList)
	{
		g_print("No todo list found");
		project->todoList = gI_todo_list_create();
	}

	project_add_to_current(gI_project_get_current(), project);

	current_project = project;

	if(cfg->prjftree)
	{
		gtk_widget_show(main_window->tree_box);
		gI_project_files_tree(main_window->tree_viewport, project);
	}

	prj_selected = -1;
}


/*
 * Delete a project
 */
static void
project_delete(
	void
)
{
	gchar*								selected_project;
	gchar*								prjwp;
	FILE*								prjfile;
	gchar								buf[MAXLEN];
	gchar								key[64];
	gchar								arg[64];
	gchar*								ptr;
	glong								i;

	if(prj_selected == -1)
	{
		return;
	}

	gtk_clist_get_text(GTK_CLIST(prj_list), prj_selected, 0,
		&selected_project);
	prjwp = g_strdup_printf("%s/%s.prj", prj_path, selected_project);

	if(GTK_TOGGLE_BUTTON(cb_delete)->active)
	{
		/* delete all source files as well */
		prjfile = fopen(prjwp, "r");
		if(!prjfile)
		{
			gI_error_dialog(_("Unable to open project file"));
			g_free(prjwp);
			return;
		}

		/* we read only the sources */
		while(fgets(buf, MAXLEN, prjfile))
		{
			if(sscanf(buf, "%s %s", key, arg) != 2)
			{
				continue;
			}

			if(strcmp(key, "$SOURCES:"))
			{
				continue;
			}

			fgets(buf, sizeof(buf), prjfile);

			for(i = 0; i < atoi(arg); i++)
			{
				fgets(buf, sizeof(buf), prjfile);
				ptr = strchr(buf, '\n');
				if(ptr)
				{
					*ptr = '\0';
				}
				remove(buf);
			}
		}
	}

	remove(prjwp);

	g_free(prjwp);

	gtk_clist_remove(GTK_CLIST(prj_list), prj_selected);
	prj_selected = -1;
}


/*
 * Callback when user clicks on project in project list
 */
static void
prj_list_select(
	GtkWidget*							widget,
	gint								row,
	gint								column,
	GdkEventButton*						bevent
)
{
	if(!bevent)
	{
		return;
	}

	if(bevent->type == GDK_2BUTTON_PRESS || bevent->type == GDK_3BUTTON_PRESS)
	{
		prj_selected = row;
		project_open();
		prj_selected = -1;

		/* close dialog box manually */
		gnome_dialog_close(GNOME_DIALOG(project_open_window));
		project_open_window = NULL;
		gI_project_update_menu(main_window);
	}
	else
	{
		if(!GTK_CLIST(widget)->selection)
		{
			prj_selected = -1;
		}
		else
		{
			prj_selected = row;
		}
	}
}


/*
 * Callback when user inputs a new path
 */
static void
prjdir_activated(
	GtkWidget*							widget,
	gpointer							data
)
{
	gchar*								path;
	struct stat                         st;

	path = gtk_entry_get_text(GTK_ENTRY(e_prjdir));
	if(!path || isempty(path))
	{
		g_warning("Invalid Path.\n");
		return;
	}

	stat(path, &st);
	if(S_ISDIR(st.st_mode))
	{
		gtk_clist_clear(GTK_CLIST(prj_list));
		strcpy(prj_path, path);
		project_fill_prj_list();
	}
	else
	{
		g_warning("Invalid Path.\n");
		return;
	}
}


/*
 * Add project to project list.  Currently, just replace it - fixme when needed
 */
static void
project_add_to_current(
	gI_project*							parent_project,
	gI_project*							project
)
{
	g_assert(project);

	if(parent_project)
	{
		project_destroy(parent_project);
	}

	current_project = project;
}


static void
close_project_files(
	gI_project*							project
)
{
	glong								i;
	glong								j;
	gchar								source[MAXLEN];

	for(i = 0; i < project->targets_no; i++)
	{
		for(j = 0; j < project->targets[i]->sources_no; j++)
		{
			if(isempty(project->prjroot))
			{
				g_snprintf(source, sizeof(source),
					project->targets[i]->sources[j]);
			}
			else
			{
				g_snprintf(source, sizeof(source), "%s/%s", project->prjroot,
					project->targets[i]->sources[j]);
			}

			if(check_file_open(source) && goto_file(source))
			{
				file_close(NULL, main_window);
			}
		}
	}
}


static void
project_file_selected(
	GtkWidget*							widget,
	GdkEventButton*						event,
	gchar*								file
)
{
	if(event->button == 3)
	{
		GnomeUIInfo popupmenu[] = {
			GNOMEUIINFO_ITEM_NONE(_("Open file in editor"),
				_("Open file in editor"), project_open_file_in_editor),
			GNOMEUIINFO_ITEM_NONE(_("Add new file to project"),
				_("Add new file to project"), project_add_new_file_to),
			GNOMEUIINFO_ITEM_NONE(_("Remove file from project"),
				_("Remove file from project"), gI_project_window_remove_file),
			GNOMEUIINFO_END
		};

		gnome_popup_menu_do_popup_modal(gnome_popup_menu_new(popupmenu),
			NULL, NULL, (GdkEventButton*)event, file);
	}
	else if(event->button == 1 && GTK_IS_TREE_ITEM(widget) &&
		(event->type == GDK_2BUTTON_PRESS))
	{
		project_open_file_in_editor(NULL, file);
	}
}


static void
project_open_file_in_editor(
	GtkWidget*							widget,
	gchar*								file
)
{
	gchar*								prjfile;
	gI_project*							project = gI_project_get_current();

	if(!project)
	{
		return;
	}

	if(!isempty(project->prjroot))
	{
		prjfile = g_strdup_printf("%s/%s", project->prjroot, file);
	}
	else
	{
		prjfile = g_strdup(file);
	}

	if(!check_file_open(prjfile))
	{
		file_open_by_name(main_window, prjfile);
	}
	else
	{
		goto_file(prjfile);
	}
	g_free(prjfile);
}


static void
project_add_new_file_to(
	GtkWidget*							widget,
	gpointer							p
)
{
	gI_ok_dialog(_("Not supported yet. Sorry..."));
}


static gboolean
is_compile_window_visible(
	GideDocument*						doc
)
{
	gI_compile_window*		compile_window;

	compile_window = gI_document_get_compile_window(doc);

	if(!doc || !compile_window ||
		!compile_window->window ||
		!compile_window->list ||
		!GTK_WIDGET_VISIBLE(compile_window->window))
	{
		return FALSE;
	}
	return TRUE;
}


/*
 * Get compiler options (cflags + includes)
 * note: need to include compiler sets
 * note: overlaps project_get_includes
 */
static gchar*
project_get_options(
	gI_project*							project
)
{
	gchar**								paths;
	gchar*								tmpstr;
	gchar*								options;

	if(!isempty(project->cinc))
	{
		paths = g_strsplit(project->cinc, ":", 0);
		tmpstr = g_strjoinv(" -I", paths);
		g_strfreev(paths);
		options = g_strconcat(project->cpar, " -I", tmpstr, NULL);
		g_free(tmpstr);
	}
	else
	{
		if(!isempty(project->cpar))
		{
			options = g_strdup(project->cpar);
		}
		else
		{
			options = g_strdup("");
		}
	}

	return options;
}


/*
 * Add a string to the compile window
 */
static void
project_add_to_compile_window(
	GideDocument*						document,
	gchar*								buf
)
{
	gchar*								p;
	gchar*								item[1];
	gI_compile_window*		compile_window;

	if(isempty(buf))
	{
		return;
	}

	compile_window = gI_document_get_compile_window(document);

	/*
	 * a line splitter is needed here, but how long is one line???
	 */

	/*
	 * MAX_LINE_LENGTH is defined in gI_compile.h, currently it's set to 100.
	 * Maybe we should set dynamically depending on the current window width.
	 */

	if(strlen(buf) > MAX_LINE_LENGTH)
	{
		p = &buf[0];
		while(strlen(p) > MAX_LINE_LENGTH)
		{
			gchar*						e = &p[MAX_LINE_LENGTH];
			gchar						tmp[MAX_LINE_LENGTH + 1];

			while(*e != ' ')
			{
				e--;
			}

			strncpy(tmp, p, e - p);
			tmp[e - p] = '\0';

			item[0] = tmp;
			gtk_clist_append(GTK_CLIST(compile_window->list), item);

			p = e + 1;
		}

		if(strlen(p) > 0)
		{
			item[0] = p;
			gtk_clist_append(GTK_CLIST(compile_window->list), item);
		}
	}
	else
	{
		item[0] = buf;
		gtk_clist_append(GTK_CLIST(compile_window->list), item);
	}
}


/*
 * Add the object file to the objects array
 */
static void
project_objects_add(
	gI_project*							project,
	gchar*								exec_file
)
{
	gchar*								tmpstr;

	if(isempty(project->prjroot))
	{
		if(objects)
		{
			tmpstr = g_strdup_printf("%s %s.o", objects, exec_file);
			g_free(objects);
			objects = tmpstr;
		}
		else
		{
			objects = g_strdup_printf("%s.o", exec_file);
		}
	}
	else
	{
		if(objects)
		{
			tmpstr = g_strdup_printf("%s %s/%s.o", objects,
				project->prjroot, exec_file);
			g_free(objects);
			objects = tmpstr;
		}
		else
		{
			objects = g_strdup_printf("%s/%s.o", project->prjroot,
				exec_file);
		}
	}
}


/*
 * Compile a source file to an object file
 */
static void
project_compile_source(
	gI_project*							project,
	gchar*								c_filename,
	GideDocument*						document
)
{
	gchar*								exec_file;
	gchar*								ptr;
	gboolean							cset_found = FALSE;
	gchar*								filename;
	gchar*								options = NULL;
	gchar*								exec_string;
	gchar*								tmpstr;
	gchar*								path = NULL;
	gchar								buf[STRLEN];
	gchar*								item[1];
	FILE*								file;
	gI_comp_set*						cset = NULL;

	/* compile source files to objects */
	if(c_filename == NULL || isempty(c_filename))
	{
		return;
	}

	exec_file = g_strdup(c_filename);

	ptr = match_cset_fpat((cset = get_comp_set_from_filename(c_filename)),
		exec_file);
	if(!ptr)
	{
		cset_found = FALSE;

		if(!(ptr = strstr(exec_file, ".c")))
		{
			gchar*						str;
			str = g_strdup_printf(_("Don't know how to compile %s"),
				exec_file);
			gI_error_dialog(str);
			g_free(str);
			g_free(exec_file);
			return;
		}
	}
	else
	{
		cset_found = TRUE;
	}

	/* only files, no targets */
	if(c_filename[0] == '%')
	{
		g_free(exec_file);
		return;
	}

	/* tmp filename */
	filename = g_strdup_printf("%s/gide_bldprj.%d.%d",
		cfg->tmpdir, (int)time(0), (int)getpid());

	/* we change c_filename here!! */
	if(ptr)
	{
		*ptr = '\0';
	}

	if(isempty(project->prjroot))
	{
		gchar*							object;

		object = g_strdup_printf("%s.o", exec_file);

		if(get_last_mod(object) >= get_last_mod(c_filename))
		{
			if(objects)
			{
				tmpstr = g_strdup_printf("%s %s", objects, object);
				g_free(objects);
				objects = tmpstr;
				g_free(object);
			}
			else
			{
				objects = object;
			}
			g_free(exec_file);
			g_free(filename);
			return;
		}
		g_free(object);
	}
	else
	{
		gchar*							object;
		gchar*							source;

		object = g_strdup_printf("%s/%s.o", project->prjroot, exec_file);
		source = g_strdup_printf("%s/%s", project->prjroot, c_filename);

		if(get_last_mod(object) >= get_last_mod(source))
		{
			if(objects)
			{
				tmpstr = g_strdup_printf("%s %s", objects, object);
				g_free(objects);
				objects = tmpstr;
				g_free(object);
			}
			else
			{
				objects = object;
			}
			g_free(source);
			g_free(exec_file);
			g_free(filename);
			return;
		}
		g_free(object);
		g_free(source);
	}

	/* probably a bug: should use filename, not c_filename. but it works... */
	/* change to working dir */
	path = get_path(c_filename);
	chdir(path);
	g_free(path);

	options = project_get_options(project);

	/* real exec */
	if(isempty(project->prjroot))
	{
		exec_string = g_strdup_printf(
			"%s -c \"(%s %s -c %s -o %s.o 1>%s 2>&1 ; touch %s.done) &\"",
			cfg->bash, cset_found ? cset->compiler : cfg->cc, options,
			c_filename, exec_file, filename, filename);
	}
	else
	{
		exec_string = g_strdup_printf(
			"%s -c \"(%s %s -c %s/%s -o %s/%s.o 1>%s 2>&1 ;"
			" touch %s.done) &\"", cfg->bash,
			cset_found ? cset->compiler : cfg->cc, options,
			project->prjroot, c_filename, project->prjroot, exec_file,
			filename, filename);
	}
	g_free(options);
	options = NULL;
	system(exec_string);

	if(!is_compile_window_visible(document))
	{
		g_free(exec_file);
		g_free(exec_string);
		g_free(filename);
		return;
	}

	/* Add the output of the compile to the compile window */
	ptr = strstr(exec_string, "1>");
	if(ptr)
	{
		*ptr = '\0';
	}
	ptr = strchr(exec_string, '(');
	ptr++;
	item[0] = ptr;
	gtk_clist_append(GTK_CLIST(gI_document_get_compile_window(document)->list), item);
	g_free(exec_string);
	tmpstr = g_strdup_printf("%s.done", filename);
	/* process gtk messages while the compile is busy */
	while(!file_exist(tmpstr))
	{
		while(gtk_events_pending())
		{
			gtk_main_iteration();
		}
	}

	/* remove .done file */
	remove(tmpstr);
	g_free(tmpstr);

	file = fopen(filename, "r");
	while(fgets(buf, sizeof(buf), file))
	{
		if(!is_compile_window_visible(document))
		{
			fclose(file);
			g_free(exec_file);
			g_free(filename);
			return;
		}
		project_add_to_compile_window(document, buf);
	}
	fclose(file);

	/* remove the tmp file */
	remove(filename);
	g_free(filename);

	project_objects_add(project, exec_file);

	g_free(exec_file);

	if(!is_compile_window_visible(document))
	{
		return;
	}

	/* correct the scrolling */
	gtk_clist_moveto(GTK_CLIST(gI_document_get_compile_window(document)->list),
		GTK_CLIST(gI_document_get_compile_window(document)->list)->rows - 1, 0, 1.0, 0.0);
}


/*
 * Link the project objects together
 * note: does not use compile sets
 */
static void
project_link(
	gI_project*							project,
	gchar*								c_filename,
	GideDocument*						document
)
{
	gchar*								options;
	gchar*								exec_string;
	gchar*								tmpstr;
	gchar*								filename;
	gchar*								ptr = NULL;
	gchar*								item[1];
	FILE*								file;
	gchar								buf[STRLEN];
	gchar*								libdirs;
	gchar*								libs;

	if(project->lpar)
	{
		options = g_strdup(project->lpar);
	}
	else
	{
		options = g_strdup("");
	}

	if(isempty(project->prjroot))
	{
		exec_string = g_strdup_printf("%s -c \"(%s %s -o %s ",
			cfg->bash, cfg->cc, options, project->mtarget);
	}
	else
	{
		gchar*							path;

		path = get_path(project->mtarget);
		if(path[0] == '\0')
		{
			exec_string = g_strdup_printf("%s -c \"(%s %s -o %s/%s ",
				cfg->bash, cfg->cc, options, project->prjroot,
				project->mtarget);
		}
		else
		{
			exec_string = g_strdup_printf("%s -c \"(%s %s -o %s ",
				cfg->bash, cfg->cc, options, project->mtarget);
		}

		g_free(path);
	}

	tmpstr = g_strconcat(exec_string, objects, NULL);
	g_free(exec_string);
	exec_string = tmpstr;

	libdirs = project_get_libdirs(project);
	libs = project_get_libs(project);
	tmpstr = g_strconcat(options, " ", libdirs, " ", libs, NULL);
	g_free(options);
	options = tmpstr;
	g_free(libdirs);
	g_free(libs);

	/* tmp filename */
	filename = g_strdup_printf("%s/gide_bldprj.%d.%d",
		cfg->tmpdir, (int)time(0), (int)getpid());

	tmpstr = g_strdup_printf("%s %s 1>%s 2>&1 ; touch %s.done) &\"",
		exec_string, options, filename, filename);
	g_free(exec_string);
	exec_string = tmpstr;
	g_free(options);

	system(exec_string);

	if(!is_compile_window_visible(document))
	{
		g_free(exec_string);
		g_free(filename);
		return;
	}

	/**/
	ptr = strstr(exec_string, "1>");
	if(ptr)
	{
		*ptr = '\0';
	}
	ptr = strchr(exec_string, '(');
	ptr++;
	item[0] = ptr;
	gtk_clist_append(GTK_CLIST(gI_document_get_compile_window(document)->list), item);
	g_free(exec_string);
	tmpstr = g_strdup_printf("%s.done", filename);
	while(!file_exist(tmpstr))
	{
		while(gtk_events_pending())
		{
			/* process gtk stuff */
			gtk_main_iteration();
		}
	}

	/* remove .done file */
	remove(tmpstr);
	g_free(tmpstr);

	file = fopen(filename, "r");
	while(fgets(buf, sizeof(buf), file))
	{
		if(!is_compile_window_visible(document))
		{
			g_free(filename);
			return;
		}

		project_add_to_compile_window(document, buf);
	}

	if(!is_compile_window_visible(document))
	{
		g_free(filename);
		return;
	}

	strcpy(buf, "Done.");
	project_add_to_compile_window(document, buf);

	/* remove temp file */
	remove(filename);
	g_free(filename);

	if(!is_compile_window_visible(document))
	{
		return;
	}

	/* correct the scrolling */
	gtk_clist_moveto(GTK_CLIST(gI_document_get_compile_window(document)->list),
		GTK_CLIST(gI_document_get_compile_window(document)->list)->rows - 1, 0, 1.0, 0.0);
}


/*
 * Fill the prj_list listbox with a list of current projects
 */
static void
project_fill_prj_list(
	void
)
{
	DIR*								dir;
	struct dirent*						dirent;
	gchar								tmpstr[STRLEN];
	gchar*								ptr;
	gchar*								insrow[1];

	dir = opendir(prj_path);
	while((dirent = readdir(dir)))
	{
		if(strstr(dirent->d_name, ".prj"))
		{
			strncpy(tmpstr, dirent->d_name, STRLEN);
			ptr = strstr(tmpstr, ".prj");
			if(ptr)
			{
				if(strncmp(ptr, ".prj", 4))
				{
					continue;
				}
				*ptr = '\0';
			}
			insrow[0] = tmpstr;
			gtk_clist_append(GTK_CLIST(prj_list), insrow);
		}
	}
	closedir(dir);
}


/*
 * Button callback for project delete
 */
static void
project_delete_clicked(
	GnomeDialog*						dlg,
	int									button,
	gpointer							data
)
{
	switch(button)
	{
	case 0:
		project_delete();
		/* FALL THROUGH */
	case 1:
		gnome_dialog_close(dlg);
		project_delete_window = NULL;
		gI_project_update_menu(main_window);
		break;
	}
}


/*
 * Button callback for project open
 */
static void
project_open_clicked(
	GnomeDialog*						dlg,
	int									button,
	gpointer							data
)
{
	switch(button)
	{
	case 0:
		project_open();
		/* FALL THROUGH */
	case 1:
		gnome_dialog_close(dlg);
		project_open_window = NULL;
		gI_project_update_menu(main_window);
		break;
	}
}


/*
 * Public functions
 */

/*
 * Returns a pointer to the current project
 */
gI_project*
gI_project_get_current(
	void
)
{
	return current_project;
}


/*
 * Create a new project
 */
void
gI_project_new(
	GtkWidget*							widget,
	gpointer							data
)
{
	gI_project*							project;

	project = project_create();

	project->todoList = gI_todo_list_create();

	project_add_to_current(gI_project_get_current(), project);

	gI_project_window_create(project, GI_PW_NEW);
}


/*
 * Open an existing project
 */
void
gI_project_open(
	GtkWidget*							widget,
	gpointer							data
)
{
	GtkBox*								vbox;
	GtkWidget*							hbox;
	GtkWidget*							frame;
	GtkWidget*							frame_vbox;
	GtkWidget*							scrolled;
	GtkWidget*                          button_open;

	if(project_open_window)
	{
		return;
	}

	project_open_window = gnome_dialog_new(_("Open project"),
		_("Open"), GNOME_STOCK_BUTTON_CLOSE, NULL);
	gnome_dialog_set_parent(GNOME_DIALOG(project_open_window),
		GTK_WINDOW(main_window));

	vbox = GTK_BOX(GNOME_DIALOG(project_open_window)->vbox);

	frame = gtk_frame_new(_("Existing projects"));
	gtk_box_pack_start(vbox, frame, TRUE, TRUE, 5);

	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_container_add(GTK_CONTAINER(frame), scrolled);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
		GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);

	prj_list = gtk_clist_new(1);
	gtk_container_add(GTK_CONTAINER(scrolled), prj_list);
	gtk_widget_set_usize(scrolled, 150, 75);
	gtk_signal_connect(GTK_OBJECT(prj_list), "select_row",
		GTK_SIGNAL_FUNC(prj_list_select), NULL);
	gtk_signal_connect(GTK_OBJECT(prj_list),"unselect_row",
		GTK_SIGNAL_FUNC(prj_list_select), NULL);

	gtk_box_pack_start(vbox, gtk_hseparator_new(), FALSE, TRUE, 5);

	frame = gtk_frame_new(_("Options"));
	gtk_box_pack_start(vbox, frame, FALSE, TRUE, 5);

	frame_vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(frame), frame_vbox);

	cb_open = gtk_check_button_new_with_label(_("Open all project files"));
	gtk_box_pack_start(GTK_BOX(frame_vbox), cb_open, FALSE, TRUE, 0);

	cb_close = gtk_check_button_new_with_label(_("Close all other files"));
	gtk_box_pack_start(GTK_BOX(frame_vbox), cb_close, FALSE, TRUE, 0);

	hbox = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(frame_vbox), hbox, FALSE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(_("Directory:")), FALSE,
		TRUE, 5);

	e_prjdir = gtk_entry_new_with_max_length(255);
	gtk_box_pack_start(GTK_BOX(hbox), e_prjdir, TRUE, TRUE, 1);
	gtk_signal_connect(GTK_OBJECT(e_prjdir), "activate",
		GTK_SIGNAL_FUNC(prjdir_activated), NULL);

	button_open = gtk_button_new_with_label (_("..."));
	gtk_widget_ref (button_open);
	gtk_object_set_data_full (GTK_OBJECT (project_open_window), "button_open", button_open,
                            (GtkDestroyNotify) gtk_widget_unref);
	gtk_widget_show (button_open);
	gtk_box_pack_start (GTK_BOX (hbox), button_open, FALSE, FALSE, 0);
	gtk_widget_set_usize (button_open, -2, 19);

	gtk_signal_connect(GTK_OBJECT(button_open), "clicked",
		GTK_SIGNAL_FUNC(project_open_dialog), NULL);

	project_fill_prj_list();

	gtk_entry_set_text(GTK_ENTRY(e_prjdir), prj_path);

	gtk_widget_show_all(GTK_WIDGET(vbox));

	gnome_dialog_set_default(GNOME_DIALOG(project_open_window), 0);

	gtk_signal_connect(GTK_OBJECT(project_open_window), "clicked",
		GTK_SIGNAL_FUNC(project_open_clicked), NULL);
	gtk_widget_show(project_open_window);
}


/*
 * Open dialog handler
 */
void project_set_dir(GtkFileSelection *selector, gpointer user_data)
{
	gtk_entry_set_text(GTK_ENTRY(e_prjdir), gtk_file_selection_get_filename(GTK_FILE_SELECTION(prj_open)));
	prjdir_activated(NULL, NULL);
}

/*
 * Show open dialog
 */
void
project_open_dialog(
	GtkWidget*                          widget,
	gpointer                            data)
{
	prj_open = gtk_file_selection_new("Select directory.");
     
	gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(prj_open)->ok_button),
	"clicked", GTK_SIGNAL_FUNC (project_set_dir), NULL);
                             
	gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(prj_open)->ok_button),
	"clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) prj_open);

	gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(prj_open)->cancel_button),
	"clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) prj_open);
     
	gtk_widget_show (prj_open);
}


/*
 * Delete a project
 */
void
gI_project_delete(
	GtkWidget*							widget,
	gpointer							data
)
{
	GtkBox*								vbox;
	GtkWidget*							frame;
	GtkWidget*							frame_vbox;

	if(project_delete_window)
	{
		return;
	}

	project_delete_window = gnome_dialog_new(_("Delete project"),
		_("Delete"), GNOME_STOCK_BUTTON_CANCEL, NULL);
	gnome_dialog_set_parent(GNOME_DIALOG(project_delete_window),
		GTK_WINDOW(main_window));

	vbox = GTK_BOX(GNOME_DIALOG(project_delete_window)->vbox);

	frame = gtk_frame_new(_("Existing projects"));
	gtk_box_pack_start(vbox, frame, TRUE, TRUE, 5);

	prj_list = gtk_clist_new(1);
	gtk_container_add(GTK_CONTAINER(frame), prj_list);
	gtk_widget_set_usize(prj_list, 150, 75);
	gtk_signal_connect(GTK_OBJECT(prj_list), "select_row",
		GTK_SIGNAL_FUNC(prj_list_select), NULL);
	gtk_signal_connect(GTK_OBJECT(prj_list), "unselect_row",
		GTK_SIGNAL_FUNC(prj_list_select), NULL);

	gtk_box_pack_start(vbox, gtk_hseparator_new(), FALSE, TRUE, 5);

	frame = gtk_frame_new(_("Options"));
	gtk_box_pack_start(vbox, frame, FALSE, TRUE, 5);

	frame_vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(frame), frame_vbox);

	cb_delete = gtk_check_button_new_with_label(_("Delete all project files"));
	gtk_box_pack_start(GTK_BOX(frame_vbox), cb_delete, FALSE, TRUE, 0);

	project_fill_prj_list();

	gtk_widget_show_all(GTK_WIDGET(vbox));

	gnome_dialog_set_default(GNOME_DIALOG(project_delete_window), 0);

	gtk_signal_connect(GTK_OBJECT(project_delete_window), "clicked",
		GTK_SIGNAL_FUNC(project_delete_clicked), NULL);
	gtk_widget_show(project_delete_window);

	gI_project_update_menu(main_window);
}


/*
 * Close the current project
 */
void
gI_project_close(
	GtkWidget*							widget,
	gpointer							data
)
{
	gI_project*							project;

	project = gI_project_get_current();
	if(!project)
	{
		return;
	}

	if(root_tree)
	{
		gtk_widget_destroy(root_tree);
		root_tree = NULL;
	}

	gtk_widget_hide(main_window->tree_box);

	gtk_widget_queue_resize(GTK_WIDGET(main_window));

	close_project_files(project);

	project_destroy(project);

	gtk_paned_set_position(GTK_PANED(main_window->hpane), 0);

	project = NULL;
	current_project = NULL;

	gI_project_update_menu(main_window);
}


/*
 * Edit the current project
 */
void
gI_project_edit(
	GtkWidget*							widget,
	gpointer							data
)
{
	gI_project*							project;

	project = gI_project_get_current();

	if(!project)
	{
		return;
	}

	gI_project_window_create(project, GI_PW_EDIT);
}


/*
 * Extract the include paths from a project (in -I... format)
 * note: should add paths from compile set
 */
static gchar*
project_get_includes(
	gI_project*							project
)
{
	gchar**								paths;
	gchar*								tmpstr;
	gchar*								includes;

	if(!isempty(project->cinc))
	{
		paths = g_strsplit(project->cinc, ":", 0);
		tmpstr = g_strjoinv(" -I", paths);
		g_strfreev(paths);
		includes = g_strconcat("-I", tmpstr, NULL);
		g_free(tmpstr);
	}
	else
	{
		includes = g_strdup("");
	}

	return includes;
}

/*
 * Extract the library paths from a project (in -L... format)
 * note: should add paths from compile set
 */
static gchar*
project_get_libdirs(
	gI_project*							project
)
{
	gchar**								paths;
	gchar*								tmpstr;
	gchar*								libdirs;

	if(!isempty(project->llib))
	{
		paths = g_strsplit(project->llib, ":", 0);
		tmpstr = g_strjoinv(" -L", paths);
		g_strfreev(paths);
		libdirs = g_strconcat("-L", tmpstr, NULL);
		g_free(tmpstr);
	}
	else
	{
		libdirs = g_strdup("");
	}

	return libdirs;
}


/*
 * Extract the libraries from a project (in -l... format)
 * note: should add libraries from compile set
 */
static gchar*
project_get_libs(
	gI_project*							project
)
{
	gchar*								libs;
	gchar*								tmpstr;
	gint								i;

	libs = g_strdup("");
	if(project->libs_no > 0)
	{
		for(i = 0; i < project->libs_no; i++)
		{
			tmpstr = g_strdup_printf("%s -l%s", libs, project->libs[i]);
			g_free(libs);
			libs = tmpstr;
		}
	}

	return libs;
}


/*
 * Extract the makefile name from a project (including full path)
 */
static gchar*
project_get_makefile_name(
	gI_project*							project
)
{
	gchar*								mf;

	if(!isempty(project->version))
	{
		mf = g_strconcat(project->prjroot, "/Makefile", ".", project->name,
			"-", project->version, NULL);
	}
	else
	{
		mf = g_strconcat(project->prjroot, "/Makefile", ".", project->name,
			NULL);
	}

	return mf;
}

/*
 * Create a makefile for the current project
 */
void
gI_project_create_makefile(
	GtkWidget*							widget,
	gpointer							data
)
{
	FILE*								makefile;
	gI_project*							project;
	glong								i;
	glong								j;
	gchar*								tmpstr;
	gchar*								ptr;
	gchar*								libdirs;
	gchar*								libs;
	gchar*								includes;
	gchar*								mf;

	project = gI_project_get_current();

	if(project == NULL)
	{
		gI_error_dialog(_("Can't create a makefile for an empty project"));
		return;
	}

	if(isempty(project->name))
	{
		gI_error_dialog(_("Project doesn't have a name"));
		return;
	}

	mf = project_get_makefile_name(project);

	if(file_exist(mf))
	{
		if(gI_ask_dialog(_("The makefile already exists.\nDo you want to "
			"overwrite it?")) != 0)
		{
			g_free(mf);
			return;
		}
	}

	makefile = fopen(mf, "w");
	if(!makefile)
	{
		g_free(mf);
		gI_error_dialog(_("Unable to create or write to the makefile"));
		return;
	}
	g_free(mf);

	includes = project_get_includes(project);

	libdirs = project_get_libdirs(project);

	libs = project_get_libs(project);

	fprintf(makefile, "# Makefile for project '%s' generated by gIDE %s\n",
		project->name, VERSION);

	fprintf(makefile, "CC=%s\n", cfg->cc);
	fprintf(makefile, "LD=%s\n", cfg->cc);
	fprintf(makefile, "RM=%s\n", "rm");
	fprintf(makefile, "INSTALL=%s\n\n", "install");

	fprintf(makefile, "INCLUDES=%s\n", includes);
	fprintf(makefile, "LIB_DIRS=%s\n", libdirs);
	fprintf(makefile, "LIBS=%s\n", libs);
	fprintf(makefile, "LDFLAGS=%s\n", project->lpar);
	fprintf(makefile, "CFLAGS=%s\n\n", project->cpar);

	g_free(includes);
	g_free(libdirs);
	g_free(libs);

	fprintf(makefile, "COMPILE=$(CC) $(INCLUDES) $(CFLAGS) -c $<\n");
	fprintf(makefile, "LINK=$(LD) $(LDFLAGS) -o $(MTARGET) $(OBJECTS) "
		"$(LIB_DIRS) $(LIBS)\n\n");

/***
	fprintf(makefile, "all:");
	for(i = 0; i < project->targets_no; i++)
	{
		fprintf(makefile, " %s", project->targets[i]->name);
	}
	fprintf(makefile, "\n");
***/

/***
	for(i = 0; i < project->targets_no; i++)
	{
		fprintf(makefile, "%s:", project->targets[i]->name);
		for(j = 0; j < project->targets[i]->sources_no; j++)
		{
			fprintf(makefile, " %s", project->targets[i]->sources[j]);
		}
		fprintf(makefile, "\n\n");
	}
***/

	fprintf(makefile, "MTARGET=%s\n", project->mtarget);

	fprintf(makefile, "OBJECTS=");
	for(i = 0; i < project->targets_no; i++)
	{
		for(j = 0; j < project->targets[i]->sources_no; j++)
		{
			if(!project->targets[i]->build[j])
			{
				continue;
			}

			tmpstr = strdup(project->targets[i]->sources[j]);
			if((ptr = strstr(tmpstr, ".c")))
			{
				*ptr = '\0';
				fprintf(makefile, " %s.o", g_basename(tmpstr));
			}
			g_free(tmpstr);
		}
	}
	fprintf(makefile, "\n\n");

	fprintf(makefile, "all: %s\n\n", project->mtarget);

	fprintf(makefile, "%s: $(OBJECTS)\n", project->mtarget);
	fprintf(makefile, "\t$(LINK)\n\n");

	for(i = 0; i < project->targets_no; i++)
	{
		for(j = 0; j < project->targets[i]->sources_no; j++)
		{
			if(!project->targets[i]->build[j])
			{
				continue;
			}

			tmpstr = g_strdup(project->targets[i]->sources[j]);
			if((ptr = strstr(tmpstr, ".c")))
			{
				*ptr = '\0';
				fprintf(makefile, "%s.o:", g_basename(tmpstr));
				fprintf(makefile, " %s\n",
					g_basename(project->targets[i]->sources[j]));
				fprintf(makefile, "\t$(COMPILE)\n\n");
			}
			g_free(tmpstr);
		}
	}
	fprintf(makefile, "\n\n");

	fprintf(makefile, "install:\n\t$(INSTALL) -m 755 %s /usr/local/bin\n\n",
		project->mtarget);

	fprintf(makefile, "clean:\n\t$(RM) -f *~ core *.o %s\n", project->mtarget);
	fprintf(makefile, "\n\n");

	fclose(makefile);

	gI_ok_dialog(_("Makefile created successfully"));
}


/*
 * Create a tree view for the project files
 */
void
gI_project_files_tree(
	GtkWidget*							container,
	gI_project*							project
)
{
	GtkWidget*							root_item;
	GtkWidget*							sub_tree;
	GtkWidget*							sub_item;
	GList*								con_list;
	glong								i;
	glong								j;

	if(container == NULL)
	{
		return;
	}

	if(root_tree != NULL)
	{
		con_list = gtk_container_children(GTK_CONTAINER(container));
		if(con_list)
		{
			gtk_container_remove(GTK_CONTAINER(container), root_tree);
		}
	}

	gtk_paned_set_position(GTK_PANED(main_window->hpane), -1);

	root_tree = gtk_tree_new();
	gtk_container_add(GTK_CONTAINER(container), root_tree);
	gtk_widget_show(root_tree);

	root_item = gtk_tree_item_new_with_label(project->name);
	gtk_tree_append(GTK_TREE(root_tree), root_item);

	for(j = 0; j < project->targets_no; j++)
	{
		sub_tree = gtk_tree_new();
		gtk_tree_item_set_subtree(GTK_TREE_ITEM(root_item), sub_tree);
		gtk_widget_show(sub_tree);

		for(i = 0; i < project->targets[j]->sources_no; i++)
		{
			sub_item = gtk_tree_item_new_with_label(
				project->targets[j]->sources[i]);
			gtk_signal_connect(GTK_OBJECT(sub_item), "button_press_event",
				GTK_SIGNAL_FUNC(project_file_selected),
				project->targets[j]->sources[i]);
			gtk_tree_append(GTK_TREE(sub_tree), sub_item);
			gtk_widget_show(sub_item);
		}
	}
	gtk_tree_item_expand(GTK_TREE_ITEM(root_item));
	gtk_widget_show(root_item);
}


/*
 * Build the currently open project
 */
void
gI_project_build(
	GtkWidget*							widget,
	gpointer							data
)
{
	glong								i;
	glong								j;
	GideDocument*						current;
	gI_project*							project;
	static gboolean						build_is_running = FALSE;

	if(build_is_running)
	{
		gI_error_dialog(_("There's already a build running"));
		return;
	}

	build_is_running = TRUE;
	gI_menus_set_sensitive(main_window, "/Project/Build Project", FALSE);

	/* in fact, we don't need the curren document here, but w/ it, we can use
	   the old functions */
	current = gI_window_get_current_doc(main_window);
	if(!current)
	{
		current = GIDE_DOCUMENT(gI_document_new());
	}

	project = gI_project_get_current();
	if(project != NULL)
	{
		if(gI_document_get_compile_window(current) == NULL)
		{
			gI_compile_window*	compile_window;

			compile_window = gI_compile_window_new(
				_("Compile Window"));
			gI_document_set_compile_window(current, compile_window);
			gtk_signal_connect(GTK_OBJECT(compile_window->window),
				"destroy", GTK_SIGNAL_FUNC(gI_compile_window_destroy),
				current);
			gtk_signal_connect(
				GTK_OBJECT(compile_window->close_button), "clicked",
				GTK_SIGNAL_FUNC(gI_compile_window_destroy), current);
			gtk_widget_show(compile_window->window);
		}

		/* init. */
		if(objects != NULL)
		{
			g_free(objects);
			objects = NULL;
		}

		show_compiling(current);

		/* compile all project files */
		for(i = 0; i < project->targets_no; i++)
		{
			for(j = 0; j < project->targets[i]->sources_no; j++)
			{
				/* build the source? */
				if(project->targets[i]->build[j])
				{
					project_compile_source(project,
						project->targets[i]->sources[j], current);
				}
			}
		}
		project_link(project, project->mtarget, current);

		if(objects != NULL)
		{
			g_free(objects);
			objects = NULL;
		}

		if(!is_compile_window_visible(current))
		{
			build_is_running = FALSE;
			gI_menus_set_sensitive(main_window, "/Project/Build Project", TRUE);
			return;
		}

		gtk_widget_destroy(gI_document_get_compile_window(current)->comp_dialog);
		gI_document_get_compile_window(current)->comp_dialog = NULL;
	}

	build_is_running = FALSE;
	gI_menus_set_sensitive(main_window, "/Project/Build Project", TRUE);
}


/*
 * Update the menu sensitivity
 */
void
gI_project_update_menu(
	GideWindow*							window
)
{
	if(gI_project_get_current() != NULL)
	{
		gI_menus_set_sensitive(window, "/Project/Open Project", FALSE);
		gI_menus_set_sensitive(window, "/Project/Close Project", TRUE);
		gI_menus_set_sensitive(window, "/Project/Build Project", TRUE);
		gI_menus_set_sensitive(window, "/Project/Create Makefile", TRUE);
	}
	else
	{
		if(project_open_window)
		{
			gI_menus_set_sensitive(window, "/Project/Open Project", FALSE);
		}
		else
		{
			gI_menus_set_sensitive(window, "/Project/Open Project", TRUE);
		}
		gI_menus_set_sensitive(window, "/Project/Close Project", FALSE);
		gI_menus_set_sensitive(window, "/Project/Build Project", FALSE);
		gI_menus_set_sensitive(window, "/Project/Create Makefile", FALSE);
	}
	gI_menus_set_sensitive(window, "/Project/Delete Project",
		project_delete_window == NULL);

	gI_project_window_update_menu(window);
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]