Oh, if you are touching it: being able to handle Zip files would be
great. :)  Zip files are the common method to transfer an entire
manufacturing batch.
Yeah that would be great as well, but one step at a time. I am relatively new to the Gtk based development (I am rather familiar with Qt), so it takes some time to figure out things properly. BTW I have not really found ZIP file support in glib. If this is true what library would be the preferred formanaging ZIP files?

I think when opening an already opened layer file a dialog should be
shown with the following options:
- Reload the affected layer(s)
- Open as a new layer
- Skip
Sounds good to me.

I have attached a patch for the following changes:
- merge open menus
- the reload popup mentioned above
- and the drop file support

Any review comment will be highly appericiated! If necessary I can create separate patches for the features above to ease the review.

Best regards,
Miklos Marton

diff --git a/src/callbacks.c b/src/callbacks.c
index 51ea349..0a6f4e5 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -56,6 +56,7 @@
 #include "attribute.h"
 #include "render.h"
 #include "table.h"
+#include "project.h"
 #include "selection.h"
 
 #include "draw-gdk.h"
@@ -162,13 +163,8 @@ callbacks_new_project_activate (GtkMenuItem *menuitem, gpointer user_data)
   * project file.
   *
   */
-void
-callbacks_open_project_activate               (GtkMenuItem     *menuitem,
-                                        gpointer         user_data)
+void open_project(char *project_filename)
 {
-	gchar *filename=NULL;
-	GtkFileFilter * filter;
-
 	if (mainProject->last_loaded >= 0) {
 		if (!interface_get_alert_dialog_response (
 			_("Do you want to close any open layers and load "
@@ -179,66 +175,99 @@ callbacks_open_project_activate               (GtkMenuItem     *menuitem,
 			FALSE, NULL, GTK_STOCK_CLOSE, GTK_STOCK_CANCEL))
 			return;
 	}
-	
-	screen.win.gerber = 
-	gtk_file_chooser_dialog_new (_("Open project file..."),
-				     NULL,
-				     GTK_FILE_CHOOSER_ACTION_OPEN,
-				     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-				     GTK_STOCK_OPEN,   GTK_RESPONSE_ACCEPT,
-				     NULL);
-	gtk_file_chooser_set_current_folder ((GtkFileChooser *) screen.win.gerber,
-		mainProject->path);
 
-	filter = gtk_file_filter_new();
-	gtk_file_filter_set_name(filter, _(gerbv_project_file_name));
-	gtk_file_filter_add_pattern(filter, gerbv_project_file_pat);
-	gtk_file_chooser_add_filter ((GtkFileChooser *) screen.win.gerber,
-	        filter);
+	/* update the last folder */
+	g_free (mainProject->path);
+	mainProject->path = project_filename;
 
-	filter = gtk_file_filter_new();
-	gtk_file_filter_set_name(filter, _("All"));
-	gtk_file_filter_add_pattern(filter, "*");
-	gtk_file_chooser_add_filter ((GtkFileChooser *) screen.win.gerber,
-	        filter);
+	gerbv_unload_all_layers (mainProject);
+	main_open_project_from_filename (mainProject, project_filename);
+}
 
-	gtk_widget_show (screen.win.gerber);
-	if (gtk_dialog_run ((GtkDialog*)screen.win.gerber) == GTK_RESPONSE_ACCEPT) {
-		filename =
-		    gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (screen.win.gerber));
-		/* update the last folder */
-		g_free (mainProject->path);
-		mainProject->path = gtk_file_chooser_get_current_folder ((GtkFileChooser *) screen.win.gerber);
+
+/* --------------------------------------------------------- */
+/**
+  * File -> open action requested
+  * or file drop event happened.
+  * Open a layer (or layers) or one gerbv project from the files.
+  * This function will show a question if the layer to be opened
+  * is already open.
+  */
+void open_files(GSList *filenames)
+{
+	char *project_filename = NULL;
+	GSList *filename = NULL;
+	gint fileIndex = 0;
+	gboolean already_loaded = FALSE;
+
+	if (filenames == NULL)
+		return;
+
+	/* Check if there is a gerbv project in the list */
+	/* If there is least open only that and ignore the rest */
+	for (filename=filenames; filename; filename=filename->next) {
+		gboolean is_project = FALSE;
+		if (project_is_gerbv_p(filename->data, &is_project) == 0 && is_project == TRUE) {
+			project_filename = filename->data;
+			break;
+		}
 	}
-	gtk_widget_destroy (screen.win.gerber);
 
-	if (filename) {
-		gerbv_unload_all_layers (mainProject);
-		main_open_project_from_filename (mainProject, filename);
+	if (project_filename != NULL) {
+		open_project(project_filename);
+	} else {
+		/* Now try to open all gerbers specified */
+		for (filename=filenames; filename; filename=filename->next) {
+			/* First check if the same file already loaded */
+			already_loaded = FALSE;
+
+			for (fileIndex = 0; fileIndex <= mainProject->last_loaded; ++fileIndex) {
+				if ((strlen(filename->data) == strlen(mainProject->file[fileIndex]->fullPathname)) &&
+					 g_ascii_strncasecmp (mainProject->file[fileIndex]->fullPathname, filename->data, strlen(filename->data)) == 0) {
+					already_loaded = TRUE;
+					break;
+				}
+			}
+
+			if (already_loaded) {
+				gint answer = interface_reopen_question ((char*)filename->data);
+				if (answer == GTK_RESPONSE_YES) {
+					/* Reload was selected -> reload all loaded layers */
+					for (fileIndex = 0; fileIndex <= mainProject->last_loaded; ++fileIndex) {
+						if ((strlen(filename->data) == strlen(mainProject->file[fileIndex]->fullPathname)) &&
+							 g_ascii_strncasecmp (mainProject->file[fileIndex]->fullPathname, filename->data, strlen(filename->data)) == 0) {
+							gerbv_revert_file(mainProject, fileIndex);
+						}
+					}
+				} else if (answer == GTK_RESPONSE_APPLY) {
+					/* Open as a new layer was selected */
+					gerbv_open_layer_from_filename (mainProject, filename->data);
+				}
+			} else {
+				gerbv_open_layer_from_filename (mainProject, filename->data);
+			}
+		}
 	}
+	g_slist_free(filenames);
+
 	gerbv_render_zoom_to_fit_display (mainProject, &screenRenderInfo);
 	render_refresh_rendered_image_on_screen();
 	callbacks_update_layer_tree();
-
-	return;
 }
 
-
 /* --------------------------------------------------------- */
 /**
-  * The file -> open layer menu item was selected.  Open a
-  * layer (or layers) from a file.
+  * The file -> open action was selected.  Open a
+  * layer (or layers) or a project file.
   *
   */
 void
-callbacks_open_layer_activate                 (GtkMenuItem     *menuitem,
+callbacks_open_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
 	GSList *filenames=NULL;
-	GSList *filename=NULL;
-
 	screen.win.gerber = 
-	gtk_file_chooser_dialog_new (_("Open Gerber, drill, or pick & place file(s)..."),
+	gtk_file_chooser_dialog_new (_("Open gerbv project, Gerber, drill, or pick & place file(s)..."),
 				     NULL,
 				     GTK_FILE_CHOOSER_ACTION_OPEN,
 				     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
@@ -258,17 +287,7 @@ callbacks_open_layer_activate                 (GtkMenuItem     *menuitem,
 	}
 	gtk_widget_destroy (screen.win.gerber);
 
-	/* Now try to open all gerbers specified */
-	for (filename=filenames; filename; filename=filename->next) {
-		gerbv_open_layer_from_filename (mainProject, filename->data);
-	}
-	g_slist_free(filenames);
-	
-	gerbv_render_zoom_to_fit_display (mainProject, &screenRenderInfo);
-	render_refresh_rendered_image_on_screen();
-	callbacks_update_layer_tree();
-
-	return;
+	open_files(filenames);
 }
 
 /* --------------------------------------------------------- */
@@ -1833,7 +1852,7 @@ callbacks_get_col_num_from_tree_view_col (GtkTreeViewColumn *col)
 /* --------------------------------------------------------- */
 void
 callbacks_add_layer_button_clicked  (GtkButton *button, gpointer   user_data) {
-	callbacks_open_layer_activate (NULL, NULL);
+	callbacks_open_activate (NULL, NULL);
 }
 
 /* --------------------------------------------------------- */
@@ -2366,6 +2385,38 @@ callbacks_change_layer_format_clicked  (GtkButton *button, gpointer   user_data)
 
 /* --------------------------------------------------------------------------- */
 gboolean
+callbacks_file_drop_event (GtkWidget          *widget,
+						  GdkDragContext     *dc,
+						  gint                x,
+						  gint                y,
+						  GtkSelectionData   *data,
+						  guint               info,
+						  guint               time,
+						  gpointer p)
+{
+	const gchar *urilist = NULL;
+	gchar **uris;
+	gchar **uri;
+	GSList *filenames = NULL;
+
+	urilist = (const gchar *)gtk_selection_data_get_data (data);
+	if (!urilist)
+		return FALSE;
+
+	uris = g_strsplit (urilist, "\r\n", -1);
+
+	for (uri = uris; *uri; uri++) {
+		if (g_strrstr(*uri, "file://") == *uri) {
+			filenames = g_slist_append(filenames, *uri + 7);
+		}
+	}
+	open_files(filenames);
+	g_strfreev (uris);
+	return TRUE;
+}
+
+/* --------------------------------------------------------------------------- */
+gboolean
 callbacks_layer_tree_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
 	/* if space is pressed while a color picker icon is in focus,
 	show the color picker dialog. */
diff --git a/src/callbacks.h b/src/callbacks.h
index 7043acd..9c44bd7 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -52,13 +52,14 @@ callbacks_new_project_activate                (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
 
 void
-callbacks_open_project_activate               (GtkMenuItem     *menuitem,
-                                        gpointer         user_data);
+open_project               (char *project_filename);
 
 void
-callbacks_open_layer_activate                 (GtkMenuItem     *menuitem,
+callbacks_open_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
 
+void open_files(GSList *filenames);
+
 void
 callbacks_revert_activate                     (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
@@ -222,6 +223,16 @@ gboolean
 callbacks_layer_tree_button_press (GtkWidget *widget, GdkEventButton *event,
                                    gpointer user_data);
 
+gboolean
+callbacks_file_drop_event (GtkWidget          *widget,
+						  GdkDragContext     *dc,
+						  gint                x,
+						  gint                y,
+						  GtkSelectionData   *data,
+						  guint               info,
+						  guint               time,
+						  gpointer p);
+
 void callbacks_add_layer_button_clicked  (GtkButton *button, gpointer   user_data);
 
 void callbacks_remove_layer_button_clicked  (GtkButton *button, gpointer   user_data);
diff --git a/src/gerbv.c b/src/gerbv.c
index cd8b8fb..bc52330 100644
--- a/src/gerbv.c
+++ b/src/gerbv.c
@@ -390,13 +390,13 @@ gerbv_add_parsed_image_to_project (gerbv_project_t *gerbvProject, gerbv_image_t
      * a new memory before we define anything more.
      */
     if (reload) {
-	gerbv_destroy_image(gerbvProject->file[idx]->image);
-	gerbvProject->file[idx]->image = parsed_image;
-	return 0;
+		gerbv_destroy_image(gerbvProject->file[idx]->image);
+		gerbvProject->file[idx]->image = parsed_image;
+		return 0;
     } else {
-	/* Load new file. */
-	gerbvProject->file[idx] = (gerbv_fileinfo_t *) g_new0 (gerbv_fileinfo_t, 1);
-	gerbvProject->file[idx]->image = parsed_image;
+		/* Load new file. */
+		gerbvProject->file[idx] = (gerbv_fileinfo_t *) g_new0 (gerbv_fileinfo_t, 1);
+		gerbvProject->file[idx]->image = parsed_image;
     }
     
     /*
@@ -454,20 +454,20 @@ gerbv_open_image(gerbv_project_t *gerbvProject, char *filename, int idx, int rel
     /* if we don't have enough spots, then grow the file list by 2 to account for the possible 
        loading of two images for PNP files */
     if ((idx+1) >= gerbvProject->max_files) {
-	gerbvProject->file = g_renew (gerbv_fileinfo_t *,
-			gerbvProject->file, gerbvProject->max_files + 2);
+		gerbvProject->file = g_renew (gerbv_fileinfo_t *,
+				gerbvProject->file, gerbvProject->max_files + 2);
 
-	gerbvProject->file[gerbvProject->max_files] = NULL;
-	gerbvProject->file[gerbvProject->max_files+1] = NULL;
-	gerbvProject->max_files += 2;
+		gerbvProject->file[gerbvProject->max_files] = NULL;
+		gerbvProject->file[gerbvProject->max_files+1] = NULL;
+		gerbvProject->max_files += 2;
     }
     
     dprintf("In open_image, about to try opening filename = %s\n", filename);
     
     fd = gerb_fopen(filename);
     if (fd == NULL) {
-	GERB_MESSAGE(_("Trying to open %s: %s"), filename, strerror(errno));
-	return -1;
+		GERB_MESSAGE(_("Trying to open %s: %s"), filename, strerror(errno));
+		return -1;
     }
 
     /* Store filename info fd for further use */
diff --git a/src/interface.c b/src/interface.c
index 935eb9b..3cdf16a 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -139,8 +139,7 @@ interface_create_gui (int req_width, int req_height)
 	GtkWidget *menuitem_file;
 	GtkWidget *menuitem_file_menu;
 	GtkWidget *new_project;
-	GtkWidget *open_project;
-	GtkWidget *open_layer;
+	GtkWidget *open;
 	GtkWidget *revert;
 	GtkWidget *save;
 	GtkWidget *save_as;
@@ -307,6 +306,11 @@ interface_create_gui (int req_width, int req_height)
 	GtkWidget *tempImage;
 
 	gchar str_coord[MAX_COORDLEN];
+
+	static GtkTargetEntry dragTargetentries[] =
+	{
+		{ "text/uri-list", 0, 1 },
+	};
 	
 	pointerpixbuf = gdk_pixbuf_new_from_inline(-1, pointer, FALSE, NULL);
 	movepixbuf = gdk_pixbuf_new_from_inline(-1, move, FALSE, NULL);
@@ -325,6 +329,14 @@ interface_create_gui (int req_width, int req_height)
 	menubar1 = gtk_menu_bar_new ();
 	gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);
 
+	gtk_drag_dest_set (mainWindow,
+					   GTK_DEST_DEFAULT_ALL,
+					   dragTargetentries,
+					   1,
+					   GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK);
+	gtk_signal_connect(GTK_OBJECT(mainWindow), "drag-data-received",
+		GTK_SIGNAL_FUNC(callbacks_file_drop_event), NULL);
+
 	/* --- File menu --- */
 	menuitem_file = gtk_menu_item_new_with_mnemonic (_("_File"));
 	gtk_container_add (GTK_CONTAINER (menubar1), menuitem_file);
@@ -336,10 +348,10 @@ interface_create_gui (int req_width, int req_height)
 	
 	/* File menu items dealing individual layers. */
 
-	open_layer = gtk_menu_item_new_with_mnemonic (_("Open _layer(s)..."));
-	SET_ACCELS (open_layer, ACCEL_FILE_OPEN_LAYER);
-	gtk_container_add (GTK_CONTAINER (menuitem_file_menu), open_layer);
-	gtk_tooltips_set_tip (tooltips, open_layer, _("Open Gerber, drill, or pick and place file(s)"), NULL);
+	open = gtk_menu_item_new_with_mnemonic (_("Open"));
+	SET_ACCELS (open, ACCEL_FILE_OPEN_LAYER);
+	gtk_container_add (GTK_CONTAINER (menuitem_file_menu), open);
+	gtk_tooltips_set_tip (tooltips, open, _("Open gerbv project, Gerber, drill, or pick and place file(s)"), NULL);
 
 	save_layer = gtk_menu_item_new_with_mnemonic (_("_Save active layer"));
 	screen.win.curFileMenuItem[0] = save_layer;
@@ -423,12 +435,6 @@ interface_create_gui (int req_width, int req_height)
 	tempImage = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (new_project), tempImage);
 
-	open_project = gtk_image_menu_item_new_with_mnemonic (_("_Open project..."));
-	gtk_container_add (GTK_CONTAINER (menuitem_file_menu), open_project);
-	gtk_tooltips_set_tip (tooltips, open_project, _("Open an existing Gerbv project"), NULL);
-	tempImage = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
-	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (open_project), tempImage);
-
 	save = gtk_image_menu_item_new_with_mnemonic (_("Save project"));
 	screen.win.curFileMenuItem[4] = save;
 	gtk_tooltips_set_tip (tooltips, save, _("Save the current project"), NULL);
@@ -1170,11 +1176,8 @@ interface_create_gui (int req_width, int req_height)
 	g_signal_connect ((gpointer) new_project, "activate",
 	                  G_CALLBACK (callbacks_new_project_activate),
 	                  NULL);
-	g_signal_connect ((gpointer) open_project, "activate",
-	                  G_CALLBACK (callbacks_open_project_activate),
-	                  NULL);
-	g_signal_connect ((gpointer) open_layer, "activate",
-	                  G_CALLBACK (callbacks_open_layer_activate),
+	g_signal_connect ((gpointer) open, "activate",
+					  G_CALLBACK (callbacks_open_activate),
 	                  NULL);
 	g_signal_connect ((gpointer) revert, "activate",
 	                  G_CALLBACK (callbacks_revert_activate),
@@ -1380,7 +1383,7 @@ interface_create_gui (int req_width, int req_height)
 	                  G_CALLBACK (callbacks_save_project_activate),
 	                  NULL);
 	g_signal_connect ((gpointer) toolbutton_open, "clicked",
-	                  G_CALLBACK (callbacks_open_project_activate),
+					  G_CALLBACK (callbacks_open_activate),
 	                  NULL);
 	g_signal_connect ((gpointer) toolbutton_revert, "clicked",
 	                  G_CALLBACK (callbacks_revert_activate),
@@ -1784,6 +1787,80 @@ interface_get_alert_dialog_response (const gchar *primaryText,
 
 /* ----------------------------------------------------  */
 /**
+  * This dialog box shows a textmessage with three buttons in the case
+  * if the file to be open was already loaded:
+  * "Reload" (the already loaded file)
+  * "Open as new layer"
+  * "Skip loading"
+  */
+int
+interface_reopen_question(const gchar *filename)
+{
+  GtkWidget *dialog1;
+  GtkWidget *dialog_vbox1;
+  GtkWidget *hbox1;
+  GtkWidget *image1;
+  GtkWidget *label1;
+  GtkWidget *dialog_action_area1;
+  GtkWidget *reloadButton, *openAsNewButton, *skipButton;
+  gint ret = 0;
+  GString *title = g_string_new(NULL);
+  g_string_printf (title, _("The %s layer file is already loaded"), filename);
+
+  dialog1 = gtk_dialog_new ();
+  gtk_container_set_border_width (GTK_CONTAINER (dialog1), 6);
+  gtk_window_set_resizable (GTK_WINDOW (dialog1), FALSE);
+  gtk_window_set_type_hint (GTK_WINDOW (dialog1), GDK_WINDOW_TYPE_HINT_DIALOG);
+  gtk_dialog_set_has_separator (GTK_DIALOG (dialog1), FALSE);
+
+  dialog_vbox1 = GTK_DIALOG (dialog1)->vbox;
+
+  hbox1 = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox1), hbox1, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox1), 6);
+
+  image1 = gtk_image_new_from_icon_name (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
+  gtk_box_pack_start (GTK_BOX (hbox1), image1, TRUE, TRUE, 0);
+  gtk_misc_set_alignment (GTK_MISC (image1), 0.5, 0);
+
+  gchar *labelMessage = g_strconcat ("<span weight=\"bold\" size=\"larger\">", title->str,
+		"</span>\n<span/>\n", NULL);
+  label1 = gtk_label_new (labelMessage);
+  g_free (labelMessage);
+
+  GtkWidget *vbox9 = gtk_vbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox9), label1, FALSE, FALSE, 0);
+  gtk_label_set_use_markup (GTK_LABEL (label1), TRUE);
+  gtk_label_set_line_wrap (GTK_LABEL (label1), TRUE);
+  gtk_box_pack_start (GTK_BOX (hbox1), vbox9, FALSE, FALSE, 0);
+
+  GtkWidget *hbox2 = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (vbox9), hbox2, FALSE, FALSE, 12);
+
+  dialog_action_area1 = GTK_DIALOG (dialog1)->action_area;
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+
+  reloadButton = gtk_button_new_with_mnemonic (_("Reload"));
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog1), reloadButton, GTK_RESPONSE_YES);
+  GTK_WIDGET_SET_FLAGS (reloadButton, GTK_CAN_DEFAULT);
+
+  openAsNewButton = gtk_button_new_with_mnemonic (_("Open as new layer"));
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog1), openAsNewButton, GTK_RESPONSE_APPLY);
+
+  skipButton = gtk_button_new_with_mnemonic (_("Skip loading"));
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog1), skipButton, GTK_RESPONSE_CANCEL);
+
+  gtk_widget_show_all (dialog1);
+
+  ret = gtk_dialog_run (GTK_DIALOG(dialog1));
+  gtk_widget_destroy (dialog1);
+
+  return ret;
+}
+
+
+/* ----------------------------------------------------  */
+/**
   * This dialog box shows a textmessage and one button:
   * "OK".  It does not return anything.
   *
diff --git a/src/interface.h b/src/interface.h
index 2d95172..e26c387 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -187,6 +187,9 @@ interface_get_alert_dialog_response (const gchar *primaryText,
 				     const gchar *true_button_label,
 				     const gchar *false_button_label);
 
+int
+interface_reopen_question (const gchar *filename);
+
 void
 interface_show_alert_dialog (gchar *primaryText,
 			     gchar *secondaryText,
diff --git a/src/project.c b/src/project.c
index 8119044..6e410e2 100644
--- a/src/project.c
+++ b/src/project.c
@@ -56,6 +56,7 @@
 #endif
 
 #include <errno.h>
+#include <glib/gstdio.h>
 #include <locale.h>
 #include <math.h>
 
@@ -92,6 +93,7 @@
  */
 #define GERBV_DEFAULT_PROJECT_FILE_VERSION "1.9A"
 
+#define MAXL 200
 /* 
  * List of versions that we can load with this version of 
  * gerbv 
@@ -894,6 +896,35 @@ gerbv_file_version(scheme *sc, pointer args)
     return sc->NIL;
 } /* gerbv_file_version */
 
+/** Checks whether the supplied file look like a gerbv project by
+ * reading the first line and checking if it contains gerbv-file-version
+ *
+ * Returns 0 on success -1 on open error
+  */
+int
+project_is_gerbv_p(const char *filename, gboolean *ret)
+{
+	FILE *fd;
+	*ret = FALSE;
+	char *buf;
+
+	fd = g_fopen(filename, "rb");
+	if (fd == NULL) {
+		GERB_MESSAGE(_("Failed to open %s for reading: %s"), filename, strerror(errno));
+		return -1;
+	}
+
+	buf = (char *) g_malloc(MAXL);
+	if (buf == NULL)
+		GERB_FATAL_ERROR(_("malloc buf failed while checking for gerbv project"));
+
+	if (fgets(buf, MAXL, fd) != NULL) {
+		*ret = (g_strrstr(buf, "gerbv-file-version") != NULL);
+	}
+	fclose(fd);
+	free(buf);
+	return 0;
+}
 
 /** Reads the content of a project file.
   *  Global:\n
diff --git a/src/project.h b/src/project.h
index 3ffaa7d..1ad3642 100644
--- a/src/project.h
+++ b/src/project.h
@@ -56,6 +56,7 @@ enum conv_type {
     UNIX_MINGW = 1
 };
 
+int project_is_gerbv_p(const char *filename, gboolean *ret);
 
 /*
  * Reads a project from a file and returns a linked list describing the project
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gerbv-devel mailing list
Gerbv-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gerbv-devel

Reply via email to