[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
gEDA-user: [Patches] GTK Recent-file-manager
Hello,
as written in october, I am working at introducing the GTK
recent-file-manager to pcb. Since the required gtk-version of pcb is >
2.10 now, it makes this task a bit easier :-).
I have attached two patches: One is for PCB (0015-Add-recent....), the
other one for gschem (0002-Replace-recent...).
Some issues with this are still remaining, perhaps someone of you can
help me with this:
The pcb-patch (0015-Add-recent.......):
- The recent-file - list can only be placed in the first submenu
(normally 'File'). This is, because in 'add_recent_file_list_to_menue()'
in the file 'gui-top-window.c' uses an absolute path to the place-holder
in the ui-manager
The gschem-patch (0002-Replace-recent...) have some differences to the
actual implementation:
- No 'free recent list' option (is this function really needed?)
- Shows just filename (not full path) as menu-label
- Full file-path available as tooltip
- Shows filetype-icons
Both patches need GTK 2.10 or newer. For pcb this requirement is valid
since some days, for gschem I don't know.
I wish you much fun with testing this new features (if you like) and
would be very glad to hear/read some comments!
Kind regards,
Felix
From 4cb5fd1d1cfd1062028fa85e4888cd0e9a0950f0 Mon Sep 17 00:00:00 2001
From: Felix Ruoff <Felix@xxxxxxxxxxxxxxxxxx>
Date: Sat, 1 Jan 2011 18:06:08 +0100
Subject: [PATCH] Add recent-file-list to pcb-menu
This patch adds the GTK recent-file-manager to pcb and a list of recently
used files to the menu. The position of this menuitem can be set with
the strin @recentfiles in the gpcb-menu.res, but just in the first submenu (mostly 'File').
---
src/gpcb-menu.res | 2 +
src/hid/gtk/gui-dialog.c | 1 +
src/hid/gtk/gui-top-window.c | 79 ++++++++++++++++++++++++++++++++++++++++++
src/hid/gtk/gui.h | 2 +
4 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/src/gpcb-menu.res b/src/gpcb-menu.res
index bd9acac..3a8c31b 100644
--- a/src/gpcb-menu.res
+++ b/src/gpcb-menu.res
@@ -58,6 +58,8 @@ MainMenu =
{"Load netlist file" Load(Netlist)}
{"Load vendor resource file" LoadVendorFrom()}
-
+ @recentfiles
+ -
{"Save connection data of"
{" a single element" GetXY(Click to set the element mark <>) Save(ElementConnections)}
{" all elements" Save(AllConnections)}
diff --git a/src/hid/gtk/gui-dialog.c b/src/hid/gtk/gui-dialog.c
index 80c1157..27fbc0e 100644
--- a/src/hid/gtk/gui-dialog.c
+++ b/src/hid/gtk/gui-dialog.c
@@ -351,6 +351,7 @@ ghid_dialog_file_select_open (gchar * title, gchar ** path, gchar * shortcuts)
dup_string (path, folder);
g_free (folder);
}
+ gtk_recent_manager_add_item (ghidgui->recent_manager, g_filename_to_uri(result, NULL, NULL));
}
gtk_widget_destroy (dialog);
diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index 828c524..c1ca402 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -1154,6 +1154,75 @@ make_menu_actions (GtkActionGroup * actions, GHidPort * port)
}
+#define MAX_RECENT_FILES 10
+/*
+ * Callback-function for the recent-files-menue.
+ * Calls the load-function depending on the file-mime-type.
+ */
+static void
+recent_chooser_item_activated (GtkRecentChooser *chooser)
+{
+ gchar *uri;
+ gchar *file;
+ GtkRecentInfo *recentInfo;
+
+ uri = gtk_recent_chooser_get_current_uri (chooser);
+ file = g_filename_from_uri(uri, NULL, NULL);
+
+ recentInfo = gtk_recent_chooser_get_current_item(chooser);
+ gtk_recent_manager_add_item(ghidgui->recent_manager, uri);
+
+ if(strcmp(gtk_recent_info_get_mime_type(recentInfo), "application/x-pcb-layout") == 0) {
+ /* Load PCB-Layout */
+ hid_actionl ("LoadFrom", "Layout", file, NULL);
+ }
+
+ if(strcmp(gtk_recent_info_get_mime_type(recentInfo), "application/x-pcb-footprint") == 0) {
+ /* Load footprint */
+ hid_actionl ("LoadFrom", "ElementToBuffer", file, NULL);
+ }
+
+ if(strcmp(gtk_recent_info_get_mime_type(recentInfo), "application/x-pcb-netlist") == 0) {
+ /* Load netlist */
+ hid_actionl ("LoadFrom", "Netlist", file, NULL);
+ }
+ gtk_recent_info_unref(recentInfo);
+ g_free(uri);
+ g_free(file);
+}
+
+/*
+ * Adds recent-file-list to menu
+ */
+static void
+add_recent_file_list_to_menue(GtkUIManager *ui)
+{
+ GtkWidget* menuitem_to_append_to;
+ GtkRecentFilter *recent_filter;
+ GtkWidget *menuitem_file_recent_items;
+
+ Message(gtk_ui_manager_get_ui(ui));
+ ghidgui->recent_manager = gtk_recent_manager_get_default();
+
+ recent_filter = gtk_recent_filter_new();
+ gtk_recent_filter_add_mime_type(recent_filter, "application/x-pcb-layout");
+ gtk_recent_filter_add_mime_type(recent_filter, "application/x-pcb-footprint");
+ gtk_recent_filter_add_mime_type(recent_filter, "application/x-pcb-netlist");
+
+ menuitem_file_recent_items = gtk_recent_chooser_menu_new_for_manager(ghidgui->recent_manager);
+
+ gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);
+ gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
+ gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
+ GTK_RECENT_SORT_MRU);
+ gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menuitem_file_recent_items), MAX_RECENT_FILES);
+ gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
+ gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menuitem_file_recent_items), TRUE);
+ menuitem_to_append_to = gtk_ui_manager_get_widget ((GtkUIManager*) ui, "/MenuBar/MenuItem0/Recentfiles");
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_to_append_to), menuitem_file_recent_items);
+ g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
+ G_CALLBACK(recent_chooser_item_activated), NULL);
+}
/*
* Make a frame for the top menubar, load in actions for the menus and
@@ -1191,6 +1260,7 @@ make_top_menubar (GtkWidget * hbox, GHidPort * port)
g_error_free (error);
}
+ add_recent_file_list_to_menue(ui);
gtk_ui_manager_set_add_tearoffs (ui, TRUE);
gtk_container_add (GTK_CONTAINER (frame),
@@ -3606,6 +3676,15 @@ add_resource_to_menu (char * menu, Resource * node, void * callback, int indent)
ghid_ui_info_append (tmpid);
}
}
+ else if (strcmp (node->v[i].value, "@recentfiles") == 0)
+ {
+ ghid_append_action ("Recentfiles", NULL,
+ "Recent Files", accel,
+ "Last used documents");
+ new_entries[menuitem_cnt-1].callback = NULL;
+ ghid_ui_info_indent(indent);
+ ghid_ui_info_append("<menuitem action='Recentfiles' />");
+ }
else
{
Message (_("GTK GUI currently ignores \"%s\" in the menu\n"
diff --git a/src/hid/gtk/gui.h b/src/hid/gtk/gui.h
index d2a76ce..9cce802 100644
--- a/src/hid/gtk/gui.h
+++ b/src/hid/gtk/gui.h
@@ -146,6 +146,8 @@ typedef struct
library_window_width,
library_window_height,
netlist_window_height, history_size, settings_mode, auto_pan_speed;
+
+ GtkRecentManager *recent_manager;
}
GhidGui;
--
1.7.1
From 7086b2c8c46b6a0cdcfdb590de7a598363bffd44 Mon Sep 17 00:00:00 2001
From: Felix Ruoff <Felix@xxxxxxxxxxxxxxxxxx>
Date: Sat, 1 Jan 2011 19:05:40 +0100
Subject: [PATCH] Replace recent file list by gtk recent-manager
This patch replaces the implemented recent-file - list by the recent-manager provided by GTK since version 2.10.
Known differences to previous version:
* No 'free recent list' option
* Shows just filename (not full path) as menu-label
* Full file-path avaiable as tooltip
* Shows filetype-icons
---
gschem/include/globals.h | 3 +
gschem/include/prototype.h | 3 -
gschem/src/gschem.c | 5 -
gschem/src/x_menus.c | 326 ++++++--------------------------------------
gschem/src/x_window.c | 6 +-
5 files changed, 51 insertions(+), 292 deletions(-)
diff --git a/gschem/include/globals.h b/gschem/include/globals.h
index 86ec43a..49dcd39 100644
--- a/gschem/include/globals.h
+++ b/gschem/include/globals.h
@@ -27,6 +27,9 @@ extern GSCHEM_TOPLEVEL *global_window_current;
/* window list */
extern GList *global_window_list;
+/* Manager for recently used files */
+GtkRecentManager *recent_manager;
+
/* colors */
extern GdkColor white;
extern GdkColor black;
diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 5948c74..d0439a3 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -828,9 +828,6 @@ gint do_popup(GSCHEM_TOPLEVEL *w_current, GdkEventButton *event);
void x_menus_sensitivity(GSCHEM_TOPLEVEL *w_current, const char *buf, int flag);
void x_menus_popup_sensitivity(GSCHEM_TOPLEVEL *w_current, const char *buf, int flag);
void x_menu_attach_recent_files_submenu(GSCHEM_TOPLEVEL *w_current);
-void recent_files_load();
-void recent_files_save(gpointer user_data);
-void recent_files_add(const char *filename);
/* x_multiattrib.c */
void x_multiattrib_open (GSCHEM_TOPLEVEL *w_current);
void x_multiattrib_close (GSCHEM_TOPLEVEL *w_current);
diff --git a/gschem/src/gschem.c b/gschem/src/gschem.c
index fc15726..9efb61d 100644
--- a/gschem/src/gschem.c
+++ b/gschem/src/gschem.c
@@ -259,11 +259,6 @@ void main_prog(void *closure, int argc, char *argv[])
free (input_str); /* M'allocated by scm_to_locale_string() */
scm_remember_upto_here_1 (scm_tmp);
- /* Load recent files list. This must be done
- * before calling x_window_setup(). */
- recent_files_load();
- gschem_atexit(recent_files_save, NULL);
-
/* Set default icon */
x_window_set_default_icon();
diff --git a/gschem/src/x_menus.c b/gschem/src/x_menus.c
index 63fe5a6..47278b4 100644
--- a/gschem/src/x_menus.c
+++ b/gschem/src/x_menus.c
@@ -359,91 +359,29 @@ void x_menus_popup_sensitivity (GSCHEM_TOPLEVEL *w_current, const char *buf, int
}
}
-/* The list of recently loaded files. */
-static GList *recent_files = NULL;
-
-#define RECENT_FILES_STORE "gschem-recent-files"
#define MAX_RECENT_FILES 10
-
-struct recent_file_menu_data {
- GSCHEM_TOPLEVEL *w_current;
- gchar *filename;
-};
-
-/*! \brief Make all toplevels reflect changes to the
- * recent files list.
- */
-static void update_recent_files_menus()
-{
- GSCHEM_TOPLEVEL *w_current;
- GtkWidget *submenu, *recent_menu_item;
- GList *iter;
-
- for (iter = global_window_list;
- iter != NULL;
- iter = g_list_next (iter)) {
- w_current = (GSCHEM_TOPLEVEL *)iter->data;
-
- if (w_current->menubar == NULL)
- continue;
-
- recent_menu_item =
- (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar),
- "_File/Open Recen_t");
- if(recent_menu_item == NULL)
- return;
-
- submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(recent_menu_item));
- gtk_widget_destroy(submenu);
- x_menu_attach_recent_files_submenu(w_current);
- }
-}
-
-/*! \brief Remove all entries from the recent files
- * list and update all toplevels.
+/*! \brief Callback for recent-chooser.
+ *
+ * Will be proceeded if element of recent-file-list is activated
*/
-static void clear_recent_file_list(gpointer data)
+void
+recent_chooser_item_activated (GtkRecentChooser *chooser, GSCHEM_TOPLEVEL *w_current)
{
- GList *p;
-
- p = recent_files;
- while(p) {
- g_free(p->data);
- p = g_list_next(p);
- }
- g_list_free(recent_files);
- recent_files = NULL;
-
- update_recent_files_menus();
-}
-
-static void
-recent_file_free_menu_data (gpointer data, GClosure *closure) {
- g_free (data);
-}
-
-static void recent_file_clicked(GtkMenuItem *menuitem, gpointer user_data)
-{
- FILE *fp;
- PAGE *page;
- struct recent_file_menu_data *data =
- (struct recent_file_menu_data *) user_data;
- GSCHEM_TOPLEVEL *w_current = data->w_current;
- gchar *filename = data->filename;
-
- /* Check if the file exists */
- fp = fopen((char *) filename, "r");
- if(fp == NULL) {
- /* Remove this entry from all menus */
- s_log_message(_("Couldn't open file %s\n"), (char *) filename);
- recent_files = g_list_remove(recent_files, filename);
- update_recent_files_menus();
- return;
- }
- fclose(fp);
-
- page = x_window_open_page(w_current, (char *)filename);
- x_window_set_current_page(w_current, page);
+ PAGE *page;
+ gchar *uri;
+ gchar *filename;
+ GtkRecentInfo *recentInfo;
+
+ uri = gtk_recent_chooser_get_current_uri (chooser);
+ filename = g_filename_from_uri(uri, NULL, NULL);
+ recentInfo = gtk_recent_chooser_get_current_item(chooser);
+ gtk_recent_manager_add_item(recent_manager, uri);
+ page = x_window_open_page(w_current, (char *)filename);
+ x_window_set_current_page(w_current, page);
+
+ gtk_recent_info_unref(recentInfo);
+ g_free(uri);
+ g_free(filename);
}
/*! \brief Attach a submenu with filenames to the 'Open Recent'
@@ -453,203 +391,29 @@ static void recent_file_clicked(GtkMenuItem *menuitem, gpointer user_data)
*/
void x_menu_attach_recent_files_submenu(GSCHEM_TOPLEVEL *w_current)
{
- gulong id;
- GtkWidget *tmp;
- GtkWidget *recent_menu_item, *recent_submenu;
-
- recent_menu_item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(
- w_current->menubar), "_File/Open Recen_t");
- if(recent_menu_item == NULL)
- return;
-
- /* disconnect all unblocked signals */
- while(1) {
- id = g_signal_handler_find(recent_menu_item, G_SIGNAL_MATCH_UNBLOCKED,
- 0, 0, NULL, NULL, NULL);
- if(id == 0)
- break;
- gtk_signal_disconnect(recent_menu_item, id);
- }
-
- recent_submenu = gtk_menu_new();
- GList *p = recent_files;
- while(p) {
- struct recent_file_menu_data *menu_data = g_new0 (struct recent_file_menu_data, 1);
- menu_data->filename = p->data;
- menu_data->w_current = w_current;
- tmp = gtk_menu_item_new_with_label((gchar *)p->data);
- g_signal_connect_data (GTK_OBJECT(tmp), "activate",
- (GCallback) recent_file_clicked,
- menu_data,
- (GClosureNotify) recent_file_free_menu_data,
- 0);
- gtk_menu_append(GTK_MENU(recent_submenu), tmp);
- p = g_list_next(p);
- }
-
- if(recent_files != NULL) {
- /* Append the 'Clear' menu item to the submenu */
- GtkWidget *alignment = gtk_alignment_new(0.5, 0, 0, 0);
-
- tmp = gtk_menu_item_new();
- gtk_container_add(GTK_CONTAINER(alignment), gtk_label_new(_("Clear")));
- gtk_container_add(GTK_CONTAINER(tmp), alignment);
-
- gtk_signal_connect_object(GTK_OBJECT(tmp), "activate",
- GTK_SIGNAL_FUNC (clear_recent_file_list), NULL);
-
- gtk_menu_append(GTK_MENU(recent_submenu), gtk_separator_menu_item_new());
- gtk_menu_append(GTK_MENU(recent_submenu), tmp);
- }
-
- gtk_widget_show_all(recent_submenu);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_menu_item), recent_submenu);
-}
-
-/*! \brief Add a filename to the list of recent files.
- *
- * If filename is already in the list, moves it to the head of the
- * list.
- */
-void recent_files_add(const char *filename)
-{
- gchar *basename;
- gchar *save_fn;
- GError *err = NULL;
- GList *p = recent_files;
-
- basename = g_path_get_basename(filename);
- if(strstr(basename, "untitled_") == basename) {
- g_free(basename);
- return;
- }
-
- g_free(basename);
-
- /* Normalize the filename. */
- save_fn = f_normalize_filename (filename, &err);
- if (err != NULL) {
- save_fn = g_strdup (filename);
- g_error_free (err);
- }
-
- /* Check if the file is already in the list. */
- while (p != NULL) {
- if (strcmp (save_fn, (gchar *) p->data) == 0) {
- break;
- }
- p = g_list_next (p);
- }
-
- if (p != NULL) {
- /* Since we found the filename already in the list, move it to
- * the head of the list. */
- g_free (save_fn);
- save_fn = (gchar *) p->data;
- recent_files = g_list_delete_link (recent_files, p);
- recent_files = g_list_prepend (recent_files, save_fn);
- } else {
- /* Otherwise, just add the new filename to the front of the
- * list. */
- recent_files = g_list_prepend (recent_files, save_fn);
- }
-
- update_recent_files_menus();
-}
-
-/*! \brief Make RECENT_FILES_STORE contain an empty file list.
- */
-static void recent_files_create_empty()
-{
- gchar *c;
- const gchar * const tmp[] = { NULL };
- GKeyFile *kf = g_key_file_new();
- gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
- g_key_file_set_string_list(kf, "Recent files", "Files", tmp, 0);
- c = g_key_file_to_data(kf, NULL, NULL);
- g_key_file_free(kf);
-
- g_file_set_contents(file, c, -1, NULL);
- g_free(c);
- g_free(file);
-}
-
-/*! \brief Save the list of recent files to RECENT_FILES_STORE.
- *
- * \param [in] user_data unused
- */
-void recent_files_save(gpointer user_data)
-{
- gchar *files[MAX_RECENT_FILES];
- int num = 0;
- gchar *c;
- gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
- GList *p = recent_files;
- if(p == NULL) {
- recent_files_create_empty();
- return;
- }
-
- while((p != NULL) && (num < MAX_RECENT_FILES)) {
- files[num++] = (gchar *)p->data;
- p = g_list_next(p);
- }
-
- GKeyFile *kf = g_key_file_new();
-
- g_key_file_set_string_list(kf, "Recent files", "Files",
- (const gchar **)files, num);
- c = g_key_file_to_data(kf, NULL, NULL);
- g_file_set_contents(file, c, -1, NULL);
-
- g_free(c);
- g_free(file);
- g_key_file_free(kf);
-}
-
-/*! \brief Load the recent file list using data from
- * RECENT_FILES_STORE.
- *
- * Must be called before any other recent-files-related
- * functions.
- */
-void recent_files_load()
-{
- GKeyFile *kf = g_key_file_new();
- gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
- if(!g_file_test(file, G_FILE_TEST_EXISTS)) {
- g_mkdir(s_path_user_config (), S_IRWXU | S_IRWXG);
-
- recent_files_create_empty();
- }
-
- if(!g_key_file_load_from_file(kf, file, G_KEY_FILE_NONE, NULL)) {
- /* error opening key file, create an empty one and try again */
- recent_files_create_empty();
- if(!g_key_file_load_from_file(kf, file, G_KEY_FILE_NONE, NULL))
- return;
- }
-
- gsize len;
- gchar **list = g_key_file_get_string_list(kf, "Recent files",
- "Files", &len, NULL);
-
- if(list == NULL) {
- /* error reading key file, don't bother to correct;
- * just overwrite it with an empty one */
- recent_files_create_empty();
- return;
- }
-
- while(len > 0) {
- len--;
- recent_files = g_list_prepend(recent_files, list[len]);
- }
-
- g_free(list);
- g_free(file);
- g_key_file_free(kf);
+ GtkWidget* menuitem_to_append_to = NULL;
+ GtkRecentFilter *recent_filter;
+ GtkWidget *menuitem_file_recent_items;
+ recent_manager = gtk_recent_manager_get_default();
+
+ recent_filter = gtk_recent_filter_new();
+ gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-schematic");
+ gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-symbol");
+
+ menuitem_file_recent_items = gtk_recent_chooser_menu_new_for_manager(recent_manager);
+
+ gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);
+ gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
+ gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
+ GTK_RECENT_SORT_MRU);
+ gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menuitem_file_recent_items), MAX_RECENT_FILES);
+ gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
+ gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menuitem_file_recent_items), TRUE);
+ g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
+ G_CALLBACK(recent_chooser_item_activated), w_current);
+
+ menuitem_to_append_to = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar), "_File/Open Recen_t");
+ if(menuitem_to_append_to == NULL)
+ return;
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_to_append_to), menuitem_file_recent_items);
}
diff --git a/gschem/src/x_window.c b/gschem/src/x_window.c
index 3d9d608..2f79e36 100644
--- a/gschem/src/x_window.c
+++ b/gschem/src/x_window.c
@@ -743,7 +743,7 @@ x_window_open_page (GSCHEM_TOPLEVEL *w_current, const gchar *filename)
gtk_widget_destroy (dialog);
g_error_free (err);
} else {
- recent_files_add (fn);
+ gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL));
}
} else {
if (!quiet_mode)
@@ -871,8 +871,8 @@ x_window_save_page (GSCHEM_TOPLEVEL *w_current, PAGE *page, const gchar *filenam
/* reset page CHANGED flag */
page->CHANGED = 0;
- /* update recent file list */
- recent_files_add(filename);
+ /* add to recent file list */
+ gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(filename, NULL, NULL));
}
/* log status of operation */
--
1.7.1
_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user