summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2001-03-06 23:33:19 +0000
committerDarin Adler <darin@src.gnome.org>2001-03-06 23:33:19 +0000
commite7d9f82a0f48921d9ead9da0a584466d43dc11df (patch)
tree32858b98ff9089b89c03615b78261e38b20798c8
parente0d6ca4c742dc0d59c4544996d2eecd989ff052b (diff)
downloadgnome-control-center-gnome-vfs-1-0.tar.gz
-rw-r--r--capplets/file-types/.cvsignore3
-rw-r--r--capplets/file-types/Makefile.am43
-rw-r--r--capplets/file-types/file-types-capplet-dialogs.c690
-rw-r--r--capplets/file-types/file-types-capplet-dialogs.h3
-rw-r--r--capplets/file-types/file-types-capplet.c462
-rw-r--r--capplets/file-types/file-types-capplet.desktop.in7
-rw-r--r--capplets/file-types/file-types-capplet.h12
-rw-r--r--capplets/file-types/file-types-icon-entry.c130
-rw-r--r--capplets/file-types/file-types-icon-entry.h2
-rw-r--r--capplets/file-types/libuuid/.cvsignore3
-rw-r--r--capplets/file-types/libuuid/Makefile.am27
-rw-r--r--capplets/file-types/libuuid/clear.c20
-rw-r--r--capplets/file-types/libuuid/compare.c32
-rw-r--r--capplets/file-types/libuuid/copy.c21
-rw-r--r--capplets/file-types/libuuid/gen_uuid.c257
-rw-r--r--capplets/file-types/libuuid/gen_uuid_nt.c92
-rw-r--r--capplets/file-types/libuuid/isnull.c25
-rw-r--r--capplets/file-types/libuuid/pack.c46
-rw-r--r--capplets/file-types/libuuid/parse.c52
-rw-r--r--capplets/file-types/libuuid/tst_uuid.c119
-rw-r--r--capplets/file-types/libuuid/unpack.c40
-rw-r--r--capplets/file-types/libuuid/unparse.c28
-rw-r--r--capplets/file-types/libuuid/uuid.h50
-rw-r--r--capplets/file-types/libuuid/uuidP.h40
-rw-r--r--capplets/file-types/libuuid/uuid_time.c138
-rw-r--r--capplets/file-types/nautilus-mime-type.desktop21
26 files changed, 1788 insertions, 575 deletions
diff --git a/capplets/file-types/.cvsignore b/capplets/file-types/.cvsignore
index 7ef4ea673..5ec9e2d05 100644
--- a/capplets/file-types/.cvsignore
+++ b/capplets/file-types/.cvsignore
@@ -2,4 +2,5 @@ Makefile
Makefile.in
.deps
.libs
-nautilus-mime-type-capplet
+file-types-capplet
+file-types-capplet.desktop
diff --git a/capplets/file-types/Makefile.am b/capplets/file-types/Makefile.am
index 8b2afcdcd..14faaa9e1 100644
--- a/capplets/file-types/Makefile.am
+++ b/capplets/file-types/Makefile.am
@@ -1,6 +1,10 @@
-INCLUDES = -I. \
- -I$(top_srcdir) \
- -I$(srcdir) \
+NULL =
+
+SUBDIRS = libuuid
+
+INCLUDES = -I. \
+ -I$(top_srcdir) \
+ -I$(srcdir) \
-I$(top_srcdir)/intl -I$(top_builddir)/intl \
-I$(top_srcdir)/libgnomevfs \
$(CAPPLET_INCLUDEDIR) \
@@ -9,36 +13,49 @@ INCLUDES = -I. \
$(GTK_CFLAGS) \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-I$(includedir) \
- $(VFS_CFLAGS) $(WERROR)
+ $(VFS_CFLAGS) $(WERROR) \
+ $(NULL)
-bin_PROGRAMS = nautilus-mime-type-capplet
-nautilus_mime_type_capplet_SOURCES = \
+bin_PROGRAMS = file-types-capplet
+
+file_types_capplet_SOURCES = \
nautilus-mime-type-capplet.h \
nautilus-mime-type-capplet-dialogs.h \
nautilus-mime-type-icon-entry.h \
nautilus-mime-type-capplet.c \
nautilus-mime-type-capplet-dialogs.c \
- nautilus-mime-type-icon-entry.c
+ nautilus-mime-type-icon-entry.c \
+ $(NULL)
+
-nautilus_mime_type_capplet_LDADD = \
+file_types_capplet_LDADD = \
$(CAPPLET_LIBDIR) \
$(CAPPLET_LIBS) \
$(ORBIT_LIBS) \
$(OAF_LIBS) \
$(INTLLIBS) \
$(top_builddir)/libgnomevfs/libgnomevfs.la \
- -lgdk_pixbuf
+ -lgdk_pixbuf \
+ $/libuuid/libuuid.a \
+ $(NULL)
-sysdir = $(datadir)/control-center
-sys_DATA = nautilus-mime-type.desktop
+sysdir = $(datadir)/control-center/Documents
+sys_in_files = file-types-capplet.desktop.in
+sys_DATA = $(sys_in_files:.desktop.in=.desktop)
settingsdir = $(datadir)/gnome/apps/Settings
-settings_DATA = nautilus-mime-type.desktop
+settings_DATA = $(sys_DATA)
+
+desktop_in_file = file-types-capplet.desktop.in
+
+desktop_file = $(desktop_in_file:.desktop.in=.desktop)
+
+@XML_I18N_MERGE_DESKTOP_RULE@
EXTRA_DIST = \
- $(sys_DATA)
+ $(sys_DATA) $(desktop_in_file)
diff --git a/capplets/file-types/file-types-capplet-dialogs.c b/capplets/file-types/file-types-capplet-dialogs.c
index 8af403ea7..c554c72b1 100644
--- a/capplets/file-types/file-types-capplet-dialogs.c
+++ b/capplets/file-types/file-types-capplet-dialogs.c
@@ -35,7 +35,9 @@
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-application-registry.h>
#include <libgnomevfs/gnome-vfs-mime-info.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include "libuuid/uuid.h"
#include "nautilus-mime-type-capplet.h"
#include "nautilus-mime-type-capplet-dialogs.h"
@@ -67,7 +69,8 @@ static edit_dialog_details *edit_component_details = NULL;
static void show_new_application_window (GtkWidget *button, GtkWidget *list);
static void show_edit_application_window (GtkWidget *button, GtkWidget *list);
static void delete_selected_application (GtkWidget *button, GtkWidget *list);
-static void add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position);
+static void add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, int position);
static void find_message_label_callback (GtkWidget *widget, gpointer callback_data);
static void find_message_label (GtkWidget *widget, const char *message);
@@ -139,12 +142,73 @@ application_button_toggled_callback (GtkToggleButton *button, gpointer user_data
}
static void
+insert_item (GtkList *list_widget, GtkListItem *item, int position)
+{
+ GList *singleton_list;
+
+ g_assert (GTK_IS_LIST (list_widget));
+ g_assert (GTK_IS_LIST_ITEM (item));
+
+ /* Due to GTK inheritance stupidity, the "Add" signal, which we
+ * rely on for widget sensitivity updates, is not sent if you
+ * use the GtkList API to add items. So when we add new items,
+ * which always go at the end, we must use the GtkContainer API.
+ */
+ if (position < 0) {
+ gtk_container_add (GTK_CONTAINER (list_widget), GTK_WIDGET (item));
+ } else {
+ singleton_list = g_list_prepend (NULL, item);
+ gtk_list_insert_items (list_widget, singleton_list, position);
+ /* This looks like a leak of a singleton_list, but believe it or not
+ * gtk_list takes ownership of the list of items.
+ */
+ }
+}
+
+static GtkListItem *
+create_application_list_item (const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, GList *short_list)
+{
+ GtkWidget *list_item;
+ GtkWidget *hbox, *check_button, *label;
+
+ list_item = gtk_list_item_new ();
+
+ hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
+ gtk_container_add (GTK_CONTAINER (list_item), hbox);
+
+ check_button = gtk_check_button_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
+
+ label = gtk_label_new (name);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (list_item);
+
+ /* Save ID and mime type*/
+ gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (id), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (id), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
+ gtk_object_set_data (GTK_OBJECT (list_item), "user_owned", GINT_TO_POINTER(user_owned));
+
+ /* Check and see if component is in preferred list */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
+ application_is_in_list (id, short_list));
+
+ /* Connect to toggled signal */
+ gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+ GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
+
+ return GTK_LIST_ITEM (list_item);
+}
+
+static void
populate_default_applications_list (GtkWidget *list, const char *mime_type)
{
GList *short_list, *app_list, *list_element;
GnomeVFSMimeApplication *application;
- GtkWidget *button, *list_item;
- GtkWidget *hbox, *label;
+ GtkListItem *list_item;
/* Get the application short list */
short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
@@ -156,43 +220,20 @@ populate_default_applications_list (GtkWidget *list, const char *mime_type)
application = list_element->data;
/* Create list item */
- list_item = gtk_list_item_new ();
-
- /* Create check button */
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (list_item), hbox);
-
- button = gtk_check_button_new ();
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-
- label = gtk_label_new (application->name);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- /* Add list item to list */
- gtk_container_add (GTK_CONTAINER (list), list_item);
+ list_item = create_application_list_item (application->id, application->name,
+ mime_type,
+ gnome_vfs_application_is_user_owned_application (application),
+ short_list);
- /* Save ID and mime type*/
- gtk_object_set_data_full (GTK_OBJECT (button), "application_id", g_strdup (application->id), g_free);
- gtk_object_set_data_full (GTK_OBJECT (button), "mime_type", g_strdup (mime_type), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (application->id), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
+ insert_item (GTK_LIST (list), list_item, -1);
- /* Check and see if component is in preferred list */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
- application_is_in_list (application->id, short_list));
-
- /* Connect to toggled signal */
- gtk_signal_connect (GTK_OBJECT (button), "toggled",
- GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
- }
+ }
gnome_vfs_mime_application_list_free (app_list);
}
- if (short_list != NULL) {
- gnome_vfs_mime_application_list_free (short_list);
- }
+ gnome_vfs_mime_application_list_free (short_list);
}
@@ -314,11 +355,17 @@ check_button_status (GtkList *list, GtkWidget *widget, ButtonHolder *button_hold
gtk_widget_set_sensitive (button_holder->delete_button, FALSE);
gtk_widget_set_sensitive (button_holder->edit_button, FALSE);
} else {
- gtk_widget_set_sensitive (button_holder->delete_button, TRUE);
gtk_widget_set_sensitive (button_holder->edit_button, TRUE);
}
}
+static void
+update_delete_button (GtkList *list, GtkWidget *widget, ButtonHolder *button_holder)
+{
+ gtk_widget_set_sensitive (button_holder->delete_button,
+ GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), "user_owned")));
+}
+
/*
* initialize_edit_applications_dialog
@@ -342,6 +389,8 @@ initialize_edit_applications_dialog (const char *mime_type)
NULL,
NULL);
+ /* FIXME: dialog should be parented on Control Center window */
+
gtk_container_set_border_width (GTK_CONTAINER (edit_application_details->window), GNOME_PAD);
gtk_window_set_policy (GTK_WINDOW (edit_application_details->window), FALSE, TRUE, FALSE);
gtk_window_set_default_size (GTK_WINDOW (edit_application_details->window),
@@ -357,7 +406,7 @@ initialize_edit_applications_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_application_details->window)->vbox;
/* Add label */
- label_text = g_strdup_printf (_("Select applications to appear in menu for mime type \"%s\""), mime_type);
+ label_text = g_strdup_printf (_("Select applications to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -403,11 +452,12 @@ initialize_edit_applications_dialog (const char *mime_type)
/* Watch container so we can update buttons */
gtk_signal_connect (GTK_OBJECT (list), "add", check_button_status, button_holder);
gtk_signal_connect_full (GTK_OBJECT (list), "remove", check_button_status, NULL, button_holder,
- g_free, FALSE, FALSE);
+ g_free, FALSE, FALSE);
+ gtk_signal_connect (GTK_OBJECT (list), "select_child", update_delete_button, button_holder);
- populate_default_applications_list (list, mime_type);
-
gtk_widget_show_all (main_vbox);
+
+ populate_default_applications_list (list, mime_type);
}
@@ -447,7 +497,7 @@ initialize_edit_components_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_component_details->window)->vbox;
/* Add label */
- label_text = g_strdup_printf (_("Select views to appear in menu for mime type \"%s\""), mime_type);
+ label_text = g_strdup_printf (_("Select views to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -482,19 +532,13 @@ show_edit_applications_dialog (const char *mime_type)
if (edit_application_details == NULL) {
initialize_edit_applications_dialog (mime_type);
}
-
- switch(gnome_dialog_run (GNOME_DIALOG (edit_application_details->window))) {
- case 0:
- nautilus_mime_type_capplet_update_application_info (mime_type);
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_application_details->window);
- break;
-
- case 1:
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_application_details->window);
- break;
- }
+
+ /* FIXME: This is a modal dialog with no Cancel button, so the close box
+ * has to do the same thing as the OK button, which is pretty darn confusing.
+ * It would be better to make it modeless someday.
+ */
+ gnome_dialog_run_and_close (GNOME_DIALOG (edit_application_details->window));
+ nautilus_mime_type_capplet_update_application_info (mime_type);
}
@@ -511,18 +555,13 @@ show_edit_components_dialog (const char *mime_type)
initialize_edit_components_dialog (mime_type);
}
- switch(gnome_dialog_run (GNOME_DIALOG (edit_component_details->window))) {
- case 0:
- nautilus_mime_type_capplet_update_viewer_info (mime_type);
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_component_details->window);
- break;
-
- case 1:
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_component_details->window);
- break;
- }
+ /* FIXME: This is a modal dialog with no Cancel button, so the close box
+ * has to do the same thing as the OK button, which is pretty darn confusing.
+ * It would be better to make it modeless someday.
+ */
+ gnome_dialog_run_and_close (GNOME_DIALOG (edit_component_details->window));
+
+ nautilus_mime_type_capplet_update_viewer_info (mime_type);
}
@@ -688,6 +727,30 @@ display_upper_case_dialog (void)
gnome_dialog_run_and_close (dialog);
}
+/* Do some basic validation of the text entry and enable the OK button if the text is
+ * determined to be a valid string.
+ */
+static void
+validate_text_and_update_button (GtkEntry *entry, gpointer data)
+{
+ char *text, *token;
+ gboolean sensitize;
+
+ sensitize = TRUE;
+
+ text = gtk_entry_get_text (entry);
+ if (text == NULL) {
+ sensitize = FALSE;
+ } else {
+ token = strtok (text, " ");
+ if (token == NULL || strlen (token) <= 0) {
+ /* Entered text is invalid as best as we can detect. */
+ sensitize = FALSE;
+ }
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (data), sensitize);
+}
char *
nautilus_mime_type_capplet_show_new_mime_window (void)
@@ -696,8 +759,6 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
GtkWidget *mime_entry;
GtkWidget *label;
GtkWidget *desc_entry;
- GtkWidget *hbox;
- GtkWidget *vbox;
const char *description;
char *mime_type, *tmp_str, c;
gboolean upper_case_alert;
@@ -705,70 +766,62 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
mime_type = NULL;
upper_case_alert = FALSE;
- dialog = gnome_dialog_new (_("Add Mime Type"), GNOME_STOCK_BUTTON_OK,
+ dialog = gnome_dialog_new (_("Add MIME Type"), GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 1);
- label = gtk_label_new (_("Add a new Mime Type\n"
- "For example: image/tiff; text/x-scheme"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Mime Type:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ label = gtk_label_new (_("New MIME type (e.g. image/x-thumper):"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
+
mime_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), mime_entry, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), mime_entry, TRUE, TRUE, 0);
-
- vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), vbox, FALSE, FALSE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
- label = gtk_label_new (_("Type in a description for this mime-type."));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Description:")), FALSE, FALSE, 0);
+ label = gtk_label_new (_("Description (e.g. Thumper image):"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
+
desc_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), desc_entry, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), desc_entry, TRUE, TRUE, 0);
+ /* Set up text entry validation signal */
+ gtk_signal_connect (GTK_OBJECT (mime_entry), "changed",
+ GTK_SIGNAL_FUNC (validate_text_and_update_button), GNOME_DIALOG (dialog)->buttons->data);
- gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
+ /* Set initial OK button state to desensitized */
+ gtk_widget_set_sensitive (GTK_WIDGET (GNOME_DIALOG (dialog)->buttons->data), FALSE);
+
+ /* Set focus to text entry widget */
+ gtk_widget_grab_focus (mime_entry);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
- g_assert (mime_type != NULL);
-
- /* Handle illegal mime types as best we can */
- for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
- if (isascii (c) && isupper (c)) {
- *tmp_str = tolower (c);
- upper_case_alert = TRUE;
- }
- }
-
- description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
-
- /* Add new mime type here */
- if (strlen (mime_type) > 3) {
- gnome_vfs_mime_set_value (mime_type,
- "description",
- description);
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
+ g_assert (mime_type != NULL);
+
+ /* Handle illegal mime types as best we can */
+ for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
+ if (isascii ((guchar) c) && isupper ((guchar) c)) {
+ *tmp_str = tolower (c);
+ upper_case_alert = TRUE;
}
- /* Fall through to close dialog */
- break;
-
- case 1:
- default:
- break;
+ }
+
+ description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
+
+ /* Add new mime type here */
+ if (strlen (mime_type) > 3) {
+ /* This call creates the key */
+ gnome_vfs_mime_set_registered_type_key (mime_type,
+ "description",
+ description);
+
+ /* Ths call sets the user information */
+ gnome_vfs_mime_set_value (mime_type,
+ "description",
+ description);
+ }
}
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -793,6 +846,13 @@ add_extension_clicked (GtkWidget *widget, gpointer data)
extension_list = GTK_LIST (data);
new_extension = nautilus_mime_type_capplet_show_new_extension_window ();
+
+ /* Filter out bogus extensions */
+ if (new_extension == NULL || strlen (new_extension) <= 0 || new_extension[0] == ' ') {
+ g_free (new_extension);
+ return;
+ }
+
new_list_item = gtk_list_item_new_with_label (new_extension);
gtk_widget_show (new_list_item);
@@ -874,14 +934,16 @@ get_extensions_from_gtk_list (GtkList *list)
}
char *
-nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
+nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type, gboolean *new_list)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *list;
- char *extensions_list;
+ char *extensions_list_str;
+ *new_list = FALSE;
+
dialog = gnome_dialog_new (_("File Extensions "),
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
@@ -933,7 +995,6 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
extensions_list = gnome_vfs_mime_get_extensions_list (mime_type);
-
if (extensions_list != NULL) {
widget_list = NULL;
for (temp = extensions_list; temp != NULL; temp = temp->next) {
@@ -950,22 +1011,21 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- extensions_list = get_extensions_from_gtk_list (GTK_LIST (list));
- if (extensions_list == NULL) {
- extensions_list = g_strdup ("");
- }
- break;
- case 1:
- default:
- extensions_list = g_strdup ("");
- break;
- }
+ extensions_list_str = NULL;
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ *new_list = TRUE;
+ extensions_list_str = get_extensions_from_gtk_list (GTK_LIST (list));
+ if (extensions_list_str == NULL) {
+ extensions_list_str = g_strdup ("");
+ }
+ }
+ if (extensions_list_str == NULL) {
+ extensions_list_str = g_strdup ("");
+ }
gnome_dialog_close (GNOME_DIALOG (dialog));
- return extensions_list;
+ return extensions_list_str;
}
@@ -982,7 +1042,9 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
- label = gtk_label_new (_("Type in the extensions for this mime-type.\nFor example: .html, .htm"));
+ label = gtk_label_new (_("Type in the extensions for this mime-type (without dot).\n"
+ "You can enter several extensions seperated by a space,\n"
+ "for example: html htm"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
@@ -998,17 +1060,13 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), mime_entry);
+ gtk_widget_grab_focus (mime_entry);
- new_extension = g_strdup ("");
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
- case 1:
- break;
- default:
- break;
- }
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
+ } else {
+ new_extension = g_strdup ("");
+ }
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -1020,17 +1078,19 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
* Create or update a GnomeVFSMimeApplication and register
* it with the mime database.
*/
-static void
+static char *
add_or_update_application (GtkWidget *list, const char *name, const char *command,
gboolean multiple, gboolean expects_uris,
gboolean update)
{
GnomeVFSMimeApplication app, *original;
const char *mime_type;
-
+ uuid_t app_uuid;
+ char app_uuid_string[100];
+
/* Check for empty strings. Command can be empty. */
if (name[0] == '\0') {
- return;
+ return NULL;
}
mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
@@ -1039,7 +1099,11 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* It's ok to cast, we don't modify the application
* structure and thus the name/command, this should really
* use the application registry explicitly */
- app.id = (char *)name;
+
+ /* Generate unique application id */
+ uuid_generate(app_uuid);
+ uuid_unparse(app_uuid, app_uuid_string);
+ app.id = app_uuid_string;
app.name = (char *)name;
app.command = (char *)command;
app.can_open_multiple_files = multiple;
@@ -1049,7 +1113,7 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
app.requires_terminal = FALSE;
if (update) {
- original = gnome_vfs_mime_application_new_from_id (name);
+ original = gnome_vfs_mime_application_new_from_id (app.id);
if (original == NULL) {
const char *original_id;
GList *selection;
@@ -1059,20 +1123,20 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* If there isn't a selection we cannot allow an edit */
selection = GTK_LIST (list)->selection;
if (selection == NULL || g_list_length (selection) <= 0) {
- return;
+ return NULL;
}
/* Get application id and info */
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
- return;
+ return NULL;
}
original_id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
if (original_id == NULL) {
- return;
+ return NULL;
}
-
+
/* Remove original application data */
gnome_vfs_application_registry_remove_mime_type (original_id, mime_type);
gnome_vfs_application_registry_sync ();
@@ -1083,77 +1147,122 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (item));
/* Add new widget and restore position */
- add_item_to_application_list (list, name, mime_type, position);
+ add_item_to_application_list (list, original_id, name, mime_type,
+ gnome_vfs_application_is_user_owned_application (original),
+ position);
}
}
gnome_vfs_application_registry_save_mime_application (&app);
- gnome_vfs_application_registry_add_mime_type (name, mime_type);
+ gnome_vfs_application_registry_add_mime_type (app.id, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_add_application_to_short_list (mime_type, app.id);
+
+ return g_strdup (app.id);
}
static void
-add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position)
+add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, int position)
{
- GtkWidget *check_button, *list_item, *hbox, *label;
-
- /* Create list item */
- list_item = gtk_list_item_new ();
-
- /* Create check button */
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (list_item), hbox);
-
- check_button = gtk_check_button_new ();
- gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
+ GtkListItem *list_item;
+ GList *short_list;
- label = gtk_label_new (name);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- /* Add list item to list */
- if (position == -1) {
- gtk_container_add (GTK_CONTAINER (list), list_item);
- } else {
- GList *items;
- items = g_list_alloc ();
- items->data = list_item;
- gtk_list_insert_items (GTK_LIST (list), items, position);
- gtk_list_select_child (GTK_LIST (list), list_item);
+ short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
+ list_item = create_application_list_item (id, name, mime_type, user_owned, short_list);
+ gnome_vfs_mime_application_list_free (short_list);
+
+ insert_item (GTK_LIST (list), list_item, position);
+ gtk_list_select_child (GTK_LIST (list), GTK_WIDGET (list_item));
+}
+
+static gboolean
+handle_invalid_application_input (GtkWindow *parent_window, const char *name, const char *command)
+{
+ char *message;
+ char *stripped_name;
+ GnomeDialog *error_dialog;
+ gboolean error_in_name;
+
+ message = NULL;
+ error_in_name = FALSE;
+
+ stripped_name = g_strstrip (g_strdup (name));
+
+ if (strlen (stripped_name) == 0) {
+ message = g_strdup (_("You must enter a name."));
+ error_in_name = TRUE;
+ } else if (strlen (command) == 0) {
+ message = g_strdup (_("You must enter a command."));
+ } else if (!gnome_vfs_is_executable_command_string (command)) {
+ if (command[0] == '/') {
+ /* FIXME: Should strip parameters off before using in this message. */
+ /* FIXME: Should use separate messages for doesn't exist/isn't executable. */
+ /* Both of these FIXMEs would need to handle quoting to work correctly,
+ * since otherwise a space might be part of path or separator before parameters.
+ */
+ /* FIXME: Should use some line-wrapping technology a la nautilus-stock-dialogs.c */
+ message = g_strdup_printf
+ (_("\"%s\" does not exist or is not executable.\n"
+ "Check your spelling and make sure you have\n"
+ "the right permissions to execute this file."), command);
+ } else {
+ /* FIXME: Should strip parameters off before using in this message */
+ message = g_strdup_printf
+ (_("The command \"%s\" cannot be found.\n"
+ "You must use a command that can work from any command line."), command);
+ }
}
-
- gtk_widget_show_all (list);
-
- /* Save ID and mime type*/
- gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (name), g_free);
- gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (name), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
- /* Check and see if component is in preferred list */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
+ g_free (stripped_name);
+
+ if (message != NULL) {
+ error_dialog = GNOME_DIALOG (gnome_error_dialog_parented (message,
+ parent_window));
+ gtk_window_set_title (GTK_WINDOW (error_dialog),
+ error_in_name
+ ? _("Bad Application Name")
+ : _("Bad Application Command"));
+
+ gnome_dialog_run (error_dialog);
+ g_free (message);
+
+ return TRUE;
+ }
- /* Connect to toggled signal */
- gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
- GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
+ return FALSE;
}
+
static void
-show_new_application_window (GtkWidget *button, GtkWidget *list)
+run_edit_or_new_application_dialog (const char *mime_type, GtkWidget *list, GnomeVFSMimeApplication *application)
{
- GtkWidget *app_entry, *command_entry;
GtkWidget *dialog;
+ GtkWidget *app_entry, *command_entry;
GtkWidget *label;
GtkWidget *behavior_frame, *frame_vbox;
GtkWidget *multiple_check_box, *uri_check_box;
GtkWidget *table;
- char *name, *command, *mime_type;
- gboolean multiple, uri;
-
- dialog = gnome_dialog_new (_("New Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
-
+ gboolean initial_toggle_state;
+ const char *name;
+ const char *command;
+ int dialog_result;
+ gboolean entry_validated;
+ char *invalid_entry_message, *app_id;
+
+ g_assert (mime_type != NULL || application != NULL);
+ g_assert (GTK_IS_WIDGET (list));
+
+ dialog = gnome_dialog_new (
+ application == NULL
+ ? _("Add Application")
+ : _("Edit Application"),
+ GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
+
+ /* FIXME: Dialog should be parented on Edit Applications dialog */
+
/* Create table */
- table = gtk_table_new (3, 2, FALSE);
+ table = gtk_table_new (4, 2, FALSE);
gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
@@ -1161,21 +1270,26 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
/* Application Name label and entry */
label = gtk_label_new (_("Application Name:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 0, 1);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
app_entry = gtk_entry_new ();
gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
+ if (application != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
+ }
/* Application Command label and entry */
label = gtk_label_new (_("Application Command:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 1, 2);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
command_entry = gtk_entry_new ();
- gtk_table_attach_defaults ( GTK_TABLE (table), command_entry, 1, 2, 1, 2);
-
+ gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
+ if (application != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
+ }
+
/* Open Behavior frame */
- /* FIXME bugzilla.eazel.com 6066: Need to add expected uri schemes */
behavior_frame = gtk_frame_new (_("Open Behavior"));
gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
@@ -1184,52 +1298,70 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
+ initial_toggle_state = application == NULL
+ ? FALSE
+ : application->can_open_multiple_files;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), initial_toggle_state);
- uri_check_box = gtk_check_button_new_with_label (_("Expects URIs as arguments"));
+ /* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
+ uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
-
-
+ initial_toggle_state = application == NULL
+ ? FALSE
+ : application->expects_uris;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), initial_toggle_state);
+
+
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
+ gtk_widget_grab_focus (app_entry);
+
+ do {
+ dialog_result = gnome_dialog_run (GNOME_DIALOG (dialog));
+ entry_validated = FALSE;
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
+ if (dialog_result == GNOME_OK) {
name = gtk_entry_get_text (GTK_ENTRY (app_entry));
command = gtk_entry_get_text (GTK_ENTRY (command_entry));
- multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box));
- uri = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box));
-
- if (strlen (name) > 0 && strlen (command) > 0) {
- mime_type = gtk_object_get_data (GTK_OBJECT (button), "mime_type");
- add_or_update_application (list,
- gtk_entry_get_text (GTK_ENTRY (app_entry)),
- gtk_entry_get_text (GTK_ENTRY (command_entry)),
-
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
- FALSE);
- add_item_to_application_list (list, name, mime_type, -1);
+
+ invalid_entry_message = NULL;
+
+ if (!handle_invalid_application_input (GTK_WINDOW (dialog), name, command)) {
+ entry_validated = TRUE;
+ app_id = add_or_update_application (list,
+ name,
+ command,
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
+ application != NULL);
+ if (application == NULL && app_id != NULL) {
+ add_item_to_application_list (list, app_id, name, mime_type, TRUE, -1);
+ }
+ g_free (app_id);
}
- case 1:
- gtk_widget_destroy (dialog);
- break;
-
- default:
- break;
- }
+ }
+ } while (dialog_result == GNOME_OK && !entry_validated);
+
+ /* FIXME: Close box is treated like Cancel, which loses user changes silently.
+ * Would be better to either do nothing at all (force use of OK or Cancel) or
+ * even put up a little dialog telling them they have to use OK or Cancel.
+ * Too bad we can't prevent the close box from appearing. Window Managers suck.
+ */
+ if (dialog_result >= 0) {
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+ }
}
static void
+show_new_application_window (GtkWidget *button, GtkWidget *list)
+{
+ run_edit_or_new_application_dialog (gtk_object_get_data (GTK_OBJECT (button), "mime_type"), list, NULL);
+}
+
+static void
show_edit_application_window (GtkWidget *button, GtkWidget *list)
{
- GtkWidget *app_entry, *command_entry;
- GtkWidget *dialog;
- GtkWidget *label;
- GtkWidget *behavior_frame, *frame_vbox;
- GtkWidget *multiple_check_box, *uri_check_box;
- GtkWidget *table;
GList *selection;
const char *id;
GnomeVFSMimeApplication *application;
@@ -1257,78 +1389,16 @@ show_edit_application_window (GtkWidget *button, GtkWidget *list)
return;
}
- dialog = gnome_dialog_new (_("Edit Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
-
- /* Create table */
- table = gtk_table_new (4, 2, FALSE);
- gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
- gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
- gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
-
- /* Application Name label and entry */
- label = gtk_label_new (_("Application Name:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
-
- app_entry = gtk_entry_new ();
- gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
- gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
+ run_edit_or_new_application_dialog (NULL, list, application);
- /* Application Command label and entry */
- label = gtk_label_new (_("Application Command:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
-
- command_entry = gtk_entry_new ();
- gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
- gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
-
- /* Open Behavior frame */
- behavior_frame = gtk_frame_new (_("Open Behavior"));
- gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
-
- frame_vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (behavior_frame), frame_vbox);
-
- multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
- gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), application->can_open_multiple_files);
-
- /* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
- uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
- gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), application->expects_uris);
-
-
- gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
-
- /* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
-
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- add_or_update_application (list,
- gtk_entry_get_text (GTK_ENTRY (app_entry)),
- gtk_entry_get_text (GTK_ENTRY (command_entry)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
- TRUE);
-
- case 1:
- gnome_vfs_mime_application_free (application);
- gtk_widget_destroy (dialog);
- break;
-
- default:
- break;
- }
+ gnome_vfs_mime_application_free (application);
}
static void
delete_selected_application (GtkWidget *button, GtkWidget *list)
{
GtkListItem *item;
- const char *mime_type, *name;
+ const char *mime_type, *id;
GList *selection;
/* Get selected list item */
@@ -1342,14 +1412,16 @@ delete_selected_application (GtkWidget *button, GtkWidget *list)
return;
}
- name = gtk_object_get_data (GTK_OBJECT (item), "application_id");
+ g_return_if_fail (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (item), "user_owned")));
+
+ id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
mime_type = gtk_object_get_data (GTK_OBJECT (item), "mime_type");
- /* Remove mime data */
- if (name != NULL && mime_type != NULL) {
- gnome_vfs_application_registry_remove_mime_type (name, mime_type);
+ /* Remove application if it is user owned */
+ if (id != NULL && mime_type != NULL) {
+ gnome_vfs_application_registry_remove_mime_type (id, mime_type);
gnome_vfs_application_registry_sync ();
- gnome_vfs_mime_remove_application_from_short_list (mime_type, name);
+ gnome_vfs_mime_remove_application_from_short_list (mime_type, id);
}
/* Remove widget from list */
diff --git a/capplets/file-types/file-types-capplet-dialogs.h b/capplets/file-types/file-types-capplet-dialogs.h
index d472c95fe..5567b6141 100644
--- a/capplets/file-types/file-types-capplet-dialogs.h
+++ b/capplets/file-types/file-types-capplet-dialogs.h
@@ -30,6 +30,7 @@ void show_edit_components_dialog (const char *mime_type);
char *name_from_oaf_server_info (OAF_ServerInfo *server);
char *nautilus_mime_type_capplet_show_new_mime_window (void);
char *nautilus_mime_type_capplet_show_new_extension_window (void);
-char *nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type);
+char *nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type,
+ gboolean *new_list);
#endif /* NAUTILUS_MIME_TYPE_CAPPLET_DIALOGS_H */
diff --git a/capplets/file-types/file-types-capplet.c b/capplets/file-types/file-types-capplet.c
index cbbbda318..b40ce7d58 100644
--- a/capplets/file-types/file-types-capplet.c
+++ b/capplets/file-types/file-types-capplet.c
@@ -48,8 +48,11 @@
#include "nautilus-mime-type-capplet.h"
-#define DEFAULT_REGULAR_ICON "/nautilus/i-regular-24.png"
-#define DEFAULT_ACTION_ICON "/nautilus/i-executable.png"
+#define DEFAULT_REGULAR_ICON "nautilus/i-regular-24.png"
+#define DEFAULT_ACTION_ICON "nautilus/i-executable.png"
+
+#define MAX_ICON_WIDTH_IN_LIST 18
+#define MAX_ICON_HEIGHT_IN_LIST 18
enum {
COLUMN_DESCRIPTION = 0,
@@ -90,6 +93,8 @@ static void populate_mime_list (GList *type_li
static GdkPixbuf *capplet_get_icon_pixbuf (const char *mime_string,
gboolean is_executable);
+
+/* FIXME: Using global variables here is yucky */
GtkWidget *capplet;
GtkWidget *delete_button;
GtkWidget *remove_button;
@@ -99,6 +104,8 @@ GtkWidget *default_menu;
GtkWidget *application_button, *viewer_button;
GtkLabel *mime_label;
GtkWidget *description_entry;
+gboolean description_has_changed;
+gboolean sort_column_clicked [TOTAL_COLUMNS];
/*
* main
@@ -261,11 +268,6 @@ nautilus_mime_type_capplet_add_extension (const char *extension)
return;
}
- /* Check for starting space in string */
- if (extension[0] == ' ') {
- return;
- }
-
/* Copy only contiguous part of string. No spaces allowed. */
search_string = g_strdup (extension);
token = strtok (search_string, " ");
@@ -274,7 +276,7 @@ nautilus_mime_type_capplet_add_extension (const char *extension)
title[0] = g_strdup (extension);
} else if (strlen (token) <= 0) {
return;
- }else {
+ } else {
title[0] = g_strdup (token);
}
g_free (search_string);
@@ -377,26 +379,34 @@ get_selected_mime_type (void)
static void
really_change_icon (gpointer user_data)
{
-
+ NautilusMimeIconEntry *icon_entry;
char *filename;
const char *mime_type;
+ g_assert (NAUTILUS_MIME_IS_ICON_ENTRY (user_data));
+
mime_type = get_selected_mime_type ();
if (mime_type == NULL) {
return;
}
-
- filename = nautilus_mime_type_icon_entry_get_relative_filename (NAUTILUS_MIME_ICON_ENTRY (user_data));
+
+ icon_entry = NAUTILUS_MIME_ICON_ENTRY (user_data);
+
+ filename = nautilus_mime_type_icon_entry_get_relative_filename (icon_entry);
+ if (filename == NULL) {
+ filename = nautilus_mime_type_icon_entry_get_full_filename (icon_entry);
+ }
gnome_vfs_mime_set_icon (mime_type, filename);
- nautilus_mime_type_capplet_update_mime_list_icon (mime_type);
+ nautilus_mime_type_capplet_update_mime_list_icon_and_description (mime_type);
+ nautilus_mime_type_capplet_update_info (mime_type);
g_free (filename);
}
static void
-gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer user_data)
+icon_chosen_callback (GnomeIconList *gil, gint num, GdkEvent *event, gpointer user_data)
{
NautilusMimeIconEntry *icon_entry;
const gchar * icon;
@@ -420,6 +430,7 @@ gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer us
if(event && event->type == GDK_2BUTTON_PRESS && ((GdkEventButton *)event)->button == 1) {
gnome_icon_selection_stop_loading(gis);
really_change_icon (user_data);
+ gtk_widget_hide(icon_entry->pick_dialog);
}
@@ -428,7 +439,7 @@ gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer us
static void
change_icon_clicked_cb_real (GnomeDialog *dialog, gint button_number, gpointer user_data)
{
- if (button_number == 0) {
+ if (button_number == GNOME_OK) {
really_change_icon (user_data);
}
}
@@ -440,13 +451,14 @@ change_icon_clicked (GtkWidget *entry, gpointer user_data)
GnomeIconSelection * gis;
nautilus_mime_type_show_icon_selection (NAUTILUS_MIME_ICON_ENTRY (user_data));
+
dialog = GNOME_DIALOG (NAUTILUS_MIME_ICON_ENTRY (user_data)->pick_dialog);
gtk_signal_connect (GTK_OBJECT (dialog), "clicked", change_icon_clicked_cb_real, user_data);
gis = gtk_object_get_user_data(GTK_OBJECT(user_data));
gtk_signal_connect_after (GTK_OBJECT(GNOME_ICON_SELECTION(gis)->gil),
- "select_icon", gil_icon_selected_cb, user_data);
+ "select_icon", icon_chosen_callback, user_data);
}
@@ -474,15 +486,17 @@ change_file_extensions_clicked (GtkWidget *widget, gpointer user_data)
{
const char *mime_type;
char *new_extensions;
+ gboolean use_new_list;
mime_type = get_selected_mime_type ();
if (mime_type == NULL) {
return;
}
- new_extensions = nautilus_mime_type_capplet_show_change_extension_window (mime_type);
-
- gnome_vfs_mime_set_extensions_list (mime_type, new_extensions);
+ new_extensions = nautilus_mime_type_capplet_show_change_extension_window (mime_type, &use_new_list);
+ if (use_new_list) {
+ gnome_vfs_mime_set_extensions_list (mime_type, new_extensions);
+ }
update_extensions_list (mime_type);
}
@@ -551,6 +565,97 @@ list_reveal_row (GtkCList *clist, int row_index)
}
}
+
+
+static int
+find_row_for_mime_type (const char *mime_type, GtkCList *mime_list)
+{
+ gboolean found_one;
+ int index;
+ const char *row_data;
+
+ if (mime_type == NULL) {
+ return -1;
+ }
+
+ found_one = FALSE;
+
+ for (index = 0; index < mime_list->rows; index++) {
+ row_data = gtk_clist_get_row_data (mime_list, index);
+ if (row_data != NULL && strcmp (row_data, mime_type) == 0) {
+ found_one = TRUE;
+ break;
+ }
+ }
+
+ if (found_one) {
+ return index;
+ }
+
+ return -1;
+}
+
+
+static void
+update_description_from_input (GtkEntry *entry)
+{
+ char *new_description;
+ const char *mime_type;
+
+ g_assert (GTK_IS_ENTRY (entry));
+ g_assert ((gpointer)entry == (gpointer)description_entry);
+
+ description_has_changed = FALSE;
+
+ mime_type = get_selected_mime_type ();
+ if (mime_type == NULL) {
+ return;
+ }
+
+ new_description = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ gnome_vfs_mime_set_description (mime_type, new_description);
+ nautilus_mime_type_capplet_update_mime_list_icon_and_description (mime_type);
+ g_free (new_description);
+}
+
+static void
+description_entry_activate (GtkEntry *entry, gpointer user_data)
+{
+ g_assert (GTK_IS_ENTRY (entry));
+ g_assert ((gpointer)entry == (gpointer)description_entry);
+ g_assert (user_data == NULL);
+
+ if (description_has_changed) {
+ update_description_from_input (entry);
+ }
+}
+
+static void
+description_entry_changed (GtkEntry *entry, gpointer user_data)
+{
+ g_assert (GTK_IS_ENTRY (entry));
+ g_assert ((gpointer)entry == (gpointer)description_entry);
+ g_assert (user_data == NULL);
+
+ description_has_changed = TRUE;
+}
+
+static gboolean
+description_entry_lost_focus (GtkEntry *entry,
+ GdkEventFocus *event,
+ gpointer user_data)
+{
+ g_assert (GTK_IS_ENTRY (entry));
+ g_assert ((gpointer)entry == (gpointer)description_entry);
+ g_assert (user_data == NULL);
+
+ if (description_has_changed) {
+ update_description_from_input (entry);
+ }
+
+ return FALSE;
+}
+
static void
init_mime_capplet (const char *scroll_to_mime_type)
{
@@ -560,9 +665,7 @@ init_mime_capplet (const char *scroll_to_mime_type)
GtkWidget *mime_list_container;
GtkWidget *frame;
GtkWidget *table;
- int index, list_width, column_width;
- gboolean found_one;
- const char *row_data;
+ int index, list_width, column_width, found_index;
capplet = capplet_widget_new ();
@@ -610,13 +713,26 @@ init_mime_capplet (const char *scroll_to_mime_type)
(GtkAttachOptions) (GTK_FILL), 0, 0);
description_entry = gtk_entry_new ();
+ description_has_changed = FALSE;
gtk_box_pack_start (GTK_BOX (vbox), description_entry, FALSE, FALSE, 0);
gtk_widget_make_bold (GTK_WIDGET (description_entry));
+ gtk_signal_connect (GTK_OBJECT (description_entry), "activate",
+ GTK_SIGNAL_FUNC (description_entry_activate),
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT (description_entry), "changed",
+ GTK_SIGNAL_FUNC (description_entry_changed),
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT (description_entry), "focus_out_event",
+ GTK_SIGNAL_FUNC (description_entry_lost_focus),
+ NULL);
+
hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (hbox), FALSE, FALSE, 0);
- mime_label = GTK_LABEL (gtk_label_new (_("Mime Type")));
+ mime_label = GTK_LABEL (gtk_label_new (_("MIME Type")));
gtk_label_set_justify (GTK_LABEL (mime_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (mime_label), FALSE, FALSE, 0);
@@ -665,11 +781,10 @@ init_mime_capplet (const char *scroll_to_mime_type)
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
default_menu = gtk_option_menu_new();
- gtk_widget_set_usize (GTK_WIDGET (default_menu), 170, 0);
gtk_box_pack_start (GTK_BOX (hbox), default_menu, TRUE, TRUE, 0);
button = gtk_button_new_with_label (_("Edit List"));
- gtk_widget_set_usize (GTK_WIDGET (button), 70, 0);
+ gtk_misc_set_padding (GTK_MISC (GTK_BIN(button)->child), 2, 1);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", edit_default_clicked, mime_list);
}
@@ -693,13 +808,13 @@ init_mime_capplet (const char *scroll_to_mime_type)
(GtkAttachOptions) (0), 0, 0);
gtk_widget_set_usize (hbox, 1, 11);
- button = gtk_button_new_with_label (_("Add new Mime type..."));
+ button = gtk_button_new_with_label (_("Add New MIME Type..."));
gtk_signal_connect (GTK_OBJECT (button), "clicked", add_mime_clicked, NULL);
gtk_table_attach (GTK_TABLE (small_table), button, 0, 1, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
- button = gtk_button_new_with_label (_("Delete this Mime type..."));
+ button = gtk_button_new_with_label (_("Delete This MIME Type"));
gtk_signal_connect (GTK_OBJECT (button), "clicked", delete_mime_clicked, NULL);
gtk_table_attach (GTK_TABLE (small_table), button, 0, 1, 2, 3,
(GtkAttachOptions) (GTK_FILL),
@@ -718,12 +833,6 @@ init_mime_capplet (const char *scroll_to_mime_type)
}
-
- /* FIXME bugzilla.eazel.com 2765: this call generates a
- Gtk-WARNING **: gtk_signal_disconnect_by_data(): could not find handler containing data (0x80FA6F8)
- I think it is a bug in the control-center...
- */
-
/* Yes, show all widgets */
gtk_widget_show_all (capplet);
@@ -744,32 +853,80 @@ init_mime_capplet (const char *scroll_to_mime_type)
/* Sort by description. The description is the first column in the list. */
gtk_clist_set_sort_column (GTK_CLIST (mime_list), COLUMN_DESCRIPTION);
gtk_clist_sort (GTK_CLIST (mime_list));
+ GTK_CLIST (mime_list)->sort_type = GTK_SORT_ASCENDING;
+
+ /* Set up initial column click tracking state. We do this so the initial clicks on
+ * columns will allow us to set the proper sort state for the user.
+ */
+ sort_column_clicked[0] = TRUE; /* First sort column has been click by us in setup code */
+ for (index = 1; index < TOTAL_COLUMNS; index++) {
+ sort_column_clicked[index] = FALSE;
+ }
/* Attempt to select specified mime type in list */
- if (scroll_to_mime_type != NULL) {
- found_one = FALSE;
-
- for (index = 0; index < GTK_CLIST (mime_list)->rows; index++) {
- row_data = gtk_clist_get_row_data (GTK_CLIST (mime_list), index);
- if (row_data != NULL && strcmp (row_data, scroll_to_mime_type) == 0) {
- /* Select mime type and bail */
- found_one = TRUE;
- gtk_clist_select_row (GTK_CLIST (mime_list), index, 1);
- list_reveal_row (GTK_CLIST (mime_list), index);
- break;
- }
- }
-
- if (!found_one) {
- gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
+ if (scroll_to_mime_type != NULL) {
+ found_index = find_row_for_mime_type (scroll_to_mime_type, GTK_CLIST (mime_list));
+ if (found_index != -1) {
+ gtk_clist_select_row (GTK_CLIST (mime_list), found_index, 1);
+ list_reveal_row (GTK_CLIST (mime_list), found_index);
+ } else {
+ gtk_clist_select_row (GTK_CLIST (mime_list), 0, 1);
+ list_reveal_row (GTK_CLIST (mime_list), 0);
}
} else {
gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
+ list_reveal_row (GTK_CLIST (mime_list), 0);
}
-
- capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE);
+
+ /* Inform control center that our changes are immediate */
+ capplet_widget_changes_are_immediate (CAPPLET_WIDGET (capplet));
+}
+
+static gboolean
+is_full_path (const char *path_or_name)
+{
+ return path_or_name[0] == '/';
}
+static char *
+capplet_get_icon_path (const char *path_or_name)
+{
+ char *result;
+ char *alternate_relative_filename;
+
+ if (is_full_path (path_or_name) && g_file_exists (path_or_name)) {
+ return g_strdup (path_or_name);
+ }
+
+ result = gnome_vfs_icon_path_from_filename (path_or_name);
+ if (result != NULL) {
+ return result;
+ }
+
+ /* FIXME bugzilla.eazel.com 639:
+ * It is somewhat evil to special-case the nautilus directory here.
+ * We should clean this up if/when we come up with a way to handle
+ * Nautilus themes here.
+ */
+ alternate_relative_filename = g_strconcat ("nautilus/", path_or_name, NULL);
+ result = gnome_vfs_icon_path_from_filename (alternate_relative_filename);
+ g_free (alternate_relative_filename);
+ if (result != NULL) {
+ return result;
+ }
+
+ /* FIXME bugzilla.eazel.com 639:
+ * To work correctly with Nautilus themed icons, if there's no
+ * suffix we will also try looking in the nautilus dir for a ".png" name.
+ * This will return the icon for the default theme; there is no
+ * mechanism for getting a themed icon in the capplet.
+ */
+ alternate_relative_filename = g_strconcat ("nautilus/", path_or_name, ".png", NULL);
+ result = gnome_vfs_icon_path_from_filename (alternate_relative_filename);
+ g_free (alternate_relative_filename);
+
+ return result;
+}
/*
* nautilus_mime_type_capplet_update_info
@@ -788,14 +945,9 @@ nautilus_mime_type_capplet_update_info (const char *mime_type) {
gtk_label_set_text (GTK_LABEL (mime_label), mime_type);
description = gnome_vfs_mime_get_description (mime_type);
- if (description != NULL && strlen (description) > 0) {
- gtk_entry_set_text (GTK_ENTRY (description_entry), description);
- } else {
- gtk_entry_set_text (GTK_ENTRY (description_entry), _("No Description"));
- }
+ gtk_entry_set_text (GTK_ENTRY (description_entry), description != NULL ? description : "");
+ description_has_changed = FALSE;
- gtk_editable_set_editable (GTK_EDITABLE (description_entry), FALSE);
-
/* Update menus */
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (application_button))) {
populate_application_menu (default_menu, mime_type);
@@ -810,23 +962,16 @@ nautilus_mime_type_capplet_update_info (const char *mime_type) {
/* Set icon for mime type */
icon_name = gnome_vfs_mime_get_icon (mime_type);
+ path = NULL;
if (icon_name != NULL) {
- path = gnome_vfs_icon_path_from_filename (icon_name);
- if (path != NULL) {
- nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry), path);
- g_free (path);
- } else {
- /* No icon */
- nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry),
- NULL);
- }
- } else {
- /* No icon */
- path = gnome_vfs_icon_path_from_filename (DEFAULT_REGULAR_ICON);
- nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry),
- path);
- g_free (path);
+ path = capplet_get_icon_path (icon_name);
+ }
+ if (path == NULL) {
+ /* No custom icon specified, or custom icon not found, use default */
+ path = capplet_get_icon_path (DEFAULT_REGULAR_ICON);
}
+ nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry), path);
+ g_free (path);
/* Indicate default action */
action = gnome_vfs_mime_get_default_action (mime_type);
@@ -1147,9 +1292,18 @@ revert_real_cb (gint reply, gpointer data)
gnome_vfs_mime_info_reload ();
mime_types_list = gnome_vfs_get_registered_mime_types ();
-
+
+ gtk_clist_freeze (GTK_CLIST (mime_list));
gtk_clist_clear (GTK_CLIST (mime_list));
populate_mime_list (mime_types_list, GTK_CLIST (mime_list));
+
+ /* Sort list using current sort type and select the first item. */
+ gtk_clist_sort (GTK_CLIST (mime_list));
+ gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
+ list_reveal_row (GTK_CLIST (mime_list), 0);
+
+ gtk_clist_thaw (GTK_CLIST (mime_list));
+
} else {
/* NO */
}
@@ -1161,10 +1315,9 @@ revert_mime_clicked (GtkWidget *widget, gpointer data)
{
GtkWidget *dialog;
- dialog = gnome_question_dialog_modal (_("Reverting to system settings\n"
- "will lose all your personal \n"
- "Mime configuration.\n"
- "Revert to System Settings ?\n"),
+ dialog = gnome_question_dialog_modal (_("Reverting to system settings will lose any changes\n"
+ "you have ever made to File Types and Programs.\n"
+ "Revert anyway?"),
revert_real_cb, NULL);
}
@@ -1204,9 +1357,10 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
GnomeVFSMimeAction *action;
GnomeVFSMimeApplication *default_app;
OAF_ServerInfo *default_component;
+ int found_index;
mime_string = nautilus_mime_type_capplet_show_new_mime_window ();
- if (mime_string != NULL) {
+ if (mime_string != NULL && mime_string[0] != '\0') {
/* Add new type to mime list */
pixbuf = NULL;
@@ -1240,7 +1394,7 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 0, text[0], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1257,7 +1411,11 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
g_free (text[3]);
text[3] = g_strdup (default_app->name);
- pixbuf = capplet_get_icon_pixbuf (mime_string, TRUE);
+ filename = capplet_get_icon_path (DEFAULT_ACTION_ICON);
+ if (filename != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (filename);
+ g_free (filename);
+ }
gnome_vfs_mime_application_free (default_app);
break;
@@ -1269,9 +1427,11 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
tmp_text = name_from_oaf_server_info (default_component);
text[3] = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
- filename = gnome_vfs_icon_path_from_filename ("nautilus/gnome-library.png");
- pixbuf = gdk_pixbuf_new_from_file (filename);
- g_free (filename);
+ filename = capplet_get_icon_path ("nautilus/gnome-library.png");
+ if (filename != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (filename);
+ g_free (filename);
+ }
CORBA_free (default_component);
break;
@@ -1283,12 +1443,20 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
/* Set column icon */
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 3, text[3], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
}
+ /* Sort, select and scroll to new mime type */
+ gtk_clist_sort (GTK_CLIST (mime_list));
+ found_index = find_row_for_mime_type (mime_string, GTK_CLIST (mime_list));
+ if (found_index != -1) {
+ gtk_clist_select_row (GTK_CLIST (mime_list), found_index, 1);
+ list_reveal_row (GTK_CLIST (mime_list), found_index);
+ }
+
g_free (text[0]);
g_free (text[1]);
g_free (text[2]);
@@ -1336,7 +1504,7 @@ edit_default_clicked (GtkWidget *widget, gpointer data)
void
-nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string)
+nautilus_mime_type_capplet_update_mime_list_icon_and_description (const char *mime_string)
{
char *text;
const char *description;
@@ -1366,7 +1534,7 @@ nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 0, text, 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1410,9 +1578,7 @@ update_mime_list_action (const char *mime_string)
GnomeVFSMimeAction *action;
GnomeVFSMimeApplication *default_app;
OAF_ServerInfo *default_component;
- const char *action_icon_name;
- char *text, *tmp_text;
- char *action_icon_path;
+ char *text, *tmp_text, *icon_path;
int row;
pixbuf = NULL;
@@ -1423,22 +1589,19 @@ update_mime_list_action (const char *mime_string)
action = gnome_vfs_mime_get_default_action (mime_string);
if (action != NULL) {
switch (action->action_type) {
+ /* FIXME: Big hunks of this code are copied/pasted in several
+ * places in this file. Need to use common routines. One way
+ * to find them is to search for "nautilus/gnome-library.png"
+ */
case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION:
/* Get the default application */
default_app = gnome_vfs_mime_get_default_application (mime_string);
g_free (text);
- text = g_strdup (default_app->name);
- action_icon_name = gnome_vfs_mime_get_icon (mime_string);
- if (action_icon_name != NULL) {
- /* Get custom icon */
- action_icon_path = gnome_pixmap_file (action_icon_name);
- if (action_icon_path != NULL) {
- pixbuf = gdk_pixbuf_new_from_file (action_icon_path);
- g_free (action_icon_path);
- }
- } else {
- /* Use default icon */
- pixbuf = gdk_pixbuf_new_from_file (DEFAULT_ACTION_ICON);
+ text = g_strdup (default_app->name);
+ icon_path = capplet_get_icon_path (DEFAULT_ACTION_ICON);
+ if (icon_path != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (icon_path);
+ g_free (icon_path);
}
gnome_vfs_mime_application_free (default_app);
break;
@@ -1450,7 +1613,11 @@ update_mime_list_action (const char *mime_string)
tmp_text = name_from_oaf_server_info (default_component);
text = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
- pixbuf = gdk_pixbuf_new_from_file ("/gnome/share/pixmaps/nautilus/gnome-library.png");
+ icon_path = capplet_get_icon_path ("nautilus/gnome-library.png");
+ if (icon_path != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (icon_path);
+ g_free (icon_path);
+ }
CORBA_free (default_component);
break;
@@ -1462,7 +1629,7 @@ update_mime_list_action (const char *mime_string)
/* Set column icon */
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 3, text, 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1473,30 +1640,30 @@ update_mime_list_action (const char *mime_string)
g_free (text);
}
+/* FIXME:
+ * This routine is never called with is_executable TRUE anymore. It
+ * could be simplified, possibly out of existence.
+ */
static GdkPixbuf *
capplet_get_icon_pixbuf (const char *mime_string, gboolean is_executable)
{
- const char *description_icon_name;
- char *description_icon_path;
+ const char *icon_name;
+ char *icon_path;
GdkPixbuf *pixbuf;
pixbuf = NULL;
- description_icon_name = gnome_vfs_mime_get_icon (mime_string);
- if (description_icon_name != NULL) {
- /* Get custom icon */
- description_icon_path = gnome_vfs_icon_path_from_filename (description_icon_name);
- if (description_icon_path != NULL) {
- pixbuf = gdk_pixbuf_new_from_file (description_icon_path);
- g_free (description_icon_path);
- }
- } else {
- if (!is_executable) {
- description_icon_path = gnome_vfs_icon_path_from_filename (DEFAULT_REGULAR_ICON);
- } else {
- description_icon_path = gnome_vfs_icon_path_from_filename (DEFAULT_ACTION_ICON);
- }
- pixbuf = gdk_pixbuf_new_from_file (description_icon_path);
+ icon_name = gnome_vfs_mime_get_icon (mime_string);
+ if (icon_name == NULL) {
+ icon_name = is_executable
+ ? DEFAULT_ACTION_ICON
+ : DEFAULT_REGULAR_ICON;
+ }
+
+ icon_path = capplet_get_icon_path (icon_name);
+ if (icon_path != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (icon_path);
+ g_free (icon_path);
}
return pixbuf;
@@ -1507,6 +1674,7 @@ populate_mime_list (GList *type_list, GtkCList *clist)
{
char *text[4], *tmp_text;
const char *description;
+ char *icon_path;
char *extensions, *mime_string;
gint row;
GList *element;
@@ -1552,7 +1720,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ /* FIXME: Big hunks of this code are copied/pasted in several
+ * places in this file. Need to use common routines. One way
+ * to find them is to search for MAX_ICON_WIDTH_IN_LIST
+ */
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 0, text[0], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1569,7 +1741,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
g_free (text[3]);
text[3] = g_strdup (default_app->name);
- pixbuf = capplet_get_icon_pixbuf (mime_string, TRUE);
+ icon_path = capplet_get_icon_path (DEFAULT_ACTION_ICON);
+ if (icon_path != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (icon_path);
+ g_free (icon_path);
+ }
gnome_vfs_mime_application_free (default_app);
break;
@@ -1580,7 +1756,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
tmp_text = name_from_oaf_server_info (default_component);
text[3] = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
- pixbuf = gdk_pixbuf_new_from_file ("/gnome/share/pixmaps/nautilus/gnome-library.png");
+ icon_path = capplet_get_icon_path ("nautilus/gnome-library.png");
+ if (icon_path != NULL) {
+ pixbuf = gdk_pixbuf_new_from_file (icon_path);
+ g_free (icon_path);
+ }
CORBA_free (default_component);
break;
@@ -1592,7 +1772,7 @@ populate_mime_list (GList *type_list, GtkCList *clist)
/* Set column icon */
if (pixbuf != NULL) {
- pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
+ pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 3, text[3], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1650,16 +1830,22 @@ sort_case_insensitive (GtkCList *clist, gpointer ptr1, gpointer ptr2)
return strcasecmp (text1, text2);
}
-
static void
column_clicked (GtkCList *clist, gint column, gpointer user_data)
{
gtk_clist_set_sort_column (clist, column);
+ /* If the user has not clicked the column yet, make sure
+ * that the sort type is descending the first time.
+ */
+ if (!sort_column_clicked [column]) {
+ clist->sort_type = GTK_SORT_DESCENDING;
+ sort_column_clicked [column] = TRUE;
+ }
+
/* Toggle sort type */
if (clist->sort_type == GTK_SORT_ASCENDING) {
gtk_clist_set_sort_type (clist, GTK_SORT_DESCENDING);
-
} else {
gtk_clist_set_sort_type (clist, GTK_SORT_ASCENDING);
}
@@ -1667,6 +1853,17 @@ column_clicked (GtkCList *clist, gint column, gpointer user_data)
gtk_clist_sort (clist);
}
+static void
+mime_list_reset_row_height (GtkCList *list)
+{
+ guint height_for_icon;
+ guint height_for_text;
+
+ height_for_icon = MAX_ICON_HEIGHT_IN_LIST + 1;
+ height_for_text = GTK_WIDGET (list)->style->font->ascent +
+ GTK_WIDGET (list)->style->font->descent + 1;
+ gtk_clist_set_row_height (list, MAX (height_for_icon, height_for_text));
+}
static GtkWidget *
create_mime_list_and_scroller (void)
@@ -1677,7 +1874,7 @@ create_mime_list_and_scroller (void)
int index;
titles[0] = _("Description");
- titles[1] = _("Mime Type");
+ titles[1] = _("MIME Type");
titles[2] = _("Extension");
titles[3] = _("Default Action");
@@ -1706,6 +1903,17 @@ create_mime_list_and_scroller (void)
for (index = 0; index < TOTAL_COLUMNS; index++) {
gtk_clist_set_column_auto_resize (GTK_CLIST (mime_list), index, FALSE);
}
+
+ /* Make height tall enough for icons to look good.
+ * This must be done after the list widget is realized, due to
+ * a bug/design flaw in nautilus_clist_set_row_height. Connecting to
+ * the "realize" signal is slightly too early, so we connect to
+ * "map".
+ */
+ gtk_signal_connect (GTK_OBJECT (mime_list),
+ "map",
+ mime_list_reset_row_height,
+ NULL);
return window;
}
diff --git a/capplets/file-types/file-types-capplet.desktop.in b/capplets/file-types/file-types-capplet.desktop.in
new file mode 100644
index 000000000..63ce82810
--- /dev/null
+++ b/capplets/file-types/file-types-capplet.desktop.in
@@ -0,0 +1,7 @@
+[Desktop Entry]
+_Name=File Types and Programs
+_Comment=Specify which programs are used to open or view each file type
+Icon=gnome-ccmime.png
+Exec=file-types-capplet
+Terminal=0
+Type=Application
diff --git a/capplets/file-types/file-types-capplet.h b/capplets/file-types/file-types-capplet.h
index 245fe4388..914a2cb58 100644
--- a/capplets/file-types/file-types-capplet.h
+++ b/capplets/file-types/file-types-capplet.h
@@ -25,11 +25,11 @@
#ifndef NAUTILUS_MIME_TYPE_CAPPLET_H
#define NAUTILUS_MIME_TYPE_CAPPLET_H
-void nautilus_mime_type_capplet_update_info (const char *mime_type);
-void nautilus_mime_type_capplet_update_application_info (const char *mime_type);
-void nautilus_mime_type_capplet_update_viewer_info (const char *mime_type);
-void nautilus_mime_type_capplet_add_extension (const char *extension);
-const char *nautilus_mime_type_capplet_get_selected_item_mime_type (void);
-void nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string);
+void nautilus_mime_type_capplet_update_info (const char *mime_type);
+void nautilus_mime_type_capplet_update_application_info (const char *mime_type);
+void nautilus_mime_type_capplet_update_viewer_info (const char *mime_type);
+void nautilus_mime_type_capplet_add_extension (const char *extension);
+const char *nautilus_mime_type_capplet_get_selected_item_mime_type (void);
+void nautilus_mime_type_capplet_update_mime_list_icon_and_description (const char *mime_string);
#endif /* NAUTILUS_MIME_TYPE_CAPPLET_H */
diff --git a/capplets/file-types/file-types-icon-entry.c b/capplets/file-types/file-types-icon-entry.c
index 78365ad56..e2133743a 100644
--- a/capplets/file-types/file-types-icon-entry.c
+++ b/capplets/file-types/file-types-icon-entry.c
@@ -142,6 +142,7 @@ entry_activated(GtkWidget *widget, NautilusMimeIconEntry *ientry)
struct stat buf;
GnomeIconSelection * gis;
gchar *filename;
+ GtkButton *OK_button;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_ENTRY (widget));
@@ -161,9 +162,11 @@ entry_activated(GtkWidget *widget, NautilusMimeIconEntry *ientry)
if (gis->file_list)
gnome_icon_selection_show_icons(gis);
} else {
- /* We pretend like ok has been called */
- entry_changed (NULL, ientry);
- gtk_widget_hide (ientry->pick_dialog);
+ /* FIXME: This is a hack to act exactly like we've clicked the
+ * OK button. This should be structured more cleanly.
+ */
+ OK_button = GTK_BUTTON (GNOME_DIALOG (ientry->pick_dialog)->buttons->data);
+ gtk_button_clicked (OK_button);
}
}
@@ -275,41 +278,6 @@ browse_clicked (GnomeFileEntry *fentry, NautilusMimeIconEntry *ientry)
}
static void
-icon_selected_cb (GtkButton *button, NautilusMimeIconEntry *icon_entry)
-{
- const gchar *icon;
- GnomeIconSelection *gis;
- gchar *path, *filename;
- const char *mime_type;
- GtkWidget *entry;
-
- g_return_if_fail (icon_entry != NULL);
- g_return_if_fail (NAUTILUS_MIME_IS_ICON_ENTRY (icon_entry));
-
- gis = gtk_object_get_user_data (GTK_OBJECT (icon_entry));
- gnome_icon_selection_stop_loading (gis);
- icon = gnome_icon_selection_get_icon (gis, TRUE);
-
- if (icon != NULL) {
- entry = nautilus_mime_type_icon_entry_gtk_entry (icon_entry);
- gtk_entry_set_text (GTK_ENTRY (entry), icon);
- entry_changed (NULL, icon_entry);
-
- path = nautilus_mime_type_icon_entry_get_relative_filename (NAUTILUS_MIME_ICON_ENTRY (icon_entry));
- if (path != NULL) {
- filename = strrchr (path, '/');
- if (filename != NULL) {
- filename++;
- mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
- gnome_vfs_mime_set_icon (mime_type, filename);
- nautilus_mime_type_capplet_update_mime_list_icon (mime_type);
- }
- g_free (path);
- }
- }
-}
-
-static void
cancel_pressed (GtkButton * button, NautilusMimeIconEntry * icon_entry)
{
GnomeIconSelection * gis;
@@ -322,31 +290,6 @@ cancel_pressed (GtkButton * button, NautilusMimeIconEntry * icon_entry)
}
-static void
-gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, NautilusMimeIconEntry *icon_entry)
-{
- const gchar * icon;
- GnomeIconSelection * gis;
-
- g_return_if_fail (icon_entry != NULL);
- g_return_if_fail (NAUTILUS_MIME_IS_ICON_ENTRY (icon_entry));
-
- gis = gtk_object_get_user_data(GTK_OBJECT(icon_entry));
- icon = gnome_icon_selection_get_icon(gis, TRUE);
-
- if (icon != NULL) {
- GtkWidget *e = nautilus_mime_type_icon_entry_gtk_entry(icon_entry);
- gtk_entry_set_text(GTK_ENTRY(e),icon);
-
- }
-
- if(event && event->type == GDK_2BUTTON_PRESS && ((GdkEventButton *)event)->button == 1) {
- gnome_icon_selection_stop_loading(gis);
- entry_changed (NULL, icon_entry);
- gtk_widget_hide(icon_entry->pick_dialog);
- }
-}
-
void
nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
{
@@ -360,7 +303,7 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
fe = GNOME_FILE_ENTRY (icon_entry->fentry);
p = gnome_file_entry_get_full_path (fe, FALSE);
- curfile = nautilus_mime_type_icon_entry_get_filename (icon_entry);
+ curfile = nautilus_mime_type_icon_entry_get_full_filename (icon_entry);
/* Are we part of a modal window? If so, we need to be modal too. */
tl = gtk_widget_get_toplevel (GTK_WIDGET (icon_entry->frame));
@@ -434,12 +377,12 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gtk_object_set_user_data(GTK_OBJECT(icon_entry), iconsel);
gnome_icon_selection_add_directory (GNOME_ICON_SELECTION(iconsel), icon_entry->pick_dialog_dir);
-
- /* Hide the file entry until we figure out how to deal with icon paths
- outside of the standard gnome paths */
- /*gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (icon_entry->pick_dialog)->vbox),
+
+ gtk_window_set_title (GTK_WINDOW (icon_entry->pick_dialog), _("Select an icon"));
+
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (icon_entry->pick_dialog)->vbox),
icon_entry->fentry, FALSE, FALSE, 0);
- */
+
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(icon_entry->pick_dialog)->vbox),
iconsel, TRUE, TRUE, 0);
@@ -451,17 +394,15 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gnome_icon_selection_select_icon(GNOME_ICON_SELECTION(iconsel),
g_filename_pointer(curfile));
- gnome_dialog_button_connect(GNOME_DIALOG (icon_entry->pick_dialog),
- 0, /* OK button */
- GTK_SIGNAL_FUNC (icon_selected_cb),
- icon_entry);
+ /* FIXME:
+ * OK button is handled by caller, Cancel button is handled here.
+ * This could be cleaned up further.
+ */
gnome_dialog_button_connect(GNOME_DIALOG(icon_entry->pick_dialog),
1, /* Cancel button */
GTK_SIGNAL_FUNC(cancel_pressed),
icon_entry);
- gtk_signal_connect_after(GTK_OBJECT(GNOME_ICON_SELECTION(iconsel)->gil), "select_icon",
- GTK_SIGNAL_FUNC(gil_icon_selected_cb),
- icon_entry);
+
} else {
GnomeIconSelection *gis =
gtk_object_get_user_data(GTK_OBJECT(icon_entry));
@@ -476,27 +417,24 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gchar *
nautilus_mime_type_icon_entry_get_relative_filename (NautilusMimeIconEntry *ientry)
{
- char *filename;
- char **path_parts;
-
-
- filename = nautilus_mime_type_icon_entry_get_filename (NAUTILUS_MIME_ICON_ENTRY (ientry));
-
- path_parts = g_strsplit (filename, "/share/pixmaps/", 0);
- g_free (filename);
- filename = NULL;
+ char *filename;
+ char *result;
+ char **path_parts;
+
+ result = NULL;
+ filename = nautilus_mime_type_icon_entry_get_full_filename (NAUTILUS_MIME_ICON_ENTRY (ientry));
+ if (filename != NULL) {
+ path_parts = g_strsplit (filename, "/share/pixmaps/", 0);
+ g_free (filename);
+
+ if (path_parts[1] != NULL) {
+ result = g_strdup (path_parts[1]);
+ }
- if (path_parts[1] != NULL) {
- filename = g_strdup (path_parts[1]);
- } else {
- /* FIXME: bugzilla.eazel.com 4797 */
- g_warning ("user picked up an icon not in $(prefix)/share/pixmaps\n");
- filename = g_strdup ("");
+ g_strfreev (path_parts);
}
- g_strfreev (path_parts);
-
- return filename;
+ return result;
}
static void
@@ -690,7 +628,7 @@ nautilus_mime_type_icon_entry_set_icon (NautilusMimeIconEntry *ientry, const gch
}
/**
- * nautilus_mime_type_icon_entry_get_filename:
+ * nautilus_mime_type_icon_entry_get_full_filename:
* @ientry: the NautilusMimeIconEntry to work with
*
* Description: Gets the file name of the image if it was possible
@@ -701,7 +639,7 @@ nautilus_mime_type_icon_entry_set_icon (NautilusMimeIconEntry *ientry, const gch
* couldn't load the file
**/
gchar *
-nautilus_mime_type_icon_entry_get_filename (NautilusMimeIconEntry *ientry)
+nautilus_mime_type_icon_entry_get_full_filename (NautilusMimeIconEntry *ientry)
{
GtkWidget *child;
diff --git a/capplets/file-types/file-types-icon-entry.h b/capplets/file-types/file-types-icon-entry.h
index 7da6f0301..1ffb954fe 100644
--- a/capplets/file-types/file-types-icon-entry.h
+++ b/capplets/file-types/file-types-icon-entry.h
@@ -63,7 +63,7 @@ GtkWidget *nautilus_mime_type_icon_entry_gnome_entry (NautilusMimeIconEntry *ien
GtkWidget *nautilus_mime_type_icon_entry_gtk_entry (NautilusMimeIconEntry *ientry);
/*only return a file if it was possible to load it with imlib*/
-gchar *nautilus_mime_type_icon_entry_get_filename (NautilusMimeIconEntry *ientry);
+gchar *nautilus_mime_type_icon_entry_get_full_filename (NautilusMimeIconEntry *ientry);
gchar *nautilus_mime_type_icon_entry_get_relative_filename (NautilusMimeIconEntry *ientry);
void nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry * ientry);
diff --git a/capplets/file-types/libuuid/.cvsignore b/capplets/file-types/libuuid/.cvsignore
new file mode 100644
index 000000000..051d1bd50
--- /dev/null
+++ b/capplets/file-types/libuuid/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+.deps
diff --git a/capplets/file-types/libuuid/Makefile.am b/capplets/file-types/libuuid/Makefile.am
new file mode 100644
index 000000000..b89fb23b5
--- /dev/null
+++ b/capplets/file-types/libuuid/Makefile.am
@@ -0,0 +1,27 @@
+NULL =
+
+noinst_LIBRARIES = libuuid.a
+
+
+noinst_HEADERS = \
+ uuid.h \
+ uuidP.h \
+ $(NULL)
+
+libuuid_a_SOURCES = \
+ clear.c \
+ compare.c \
+ copy.c \
+ gen_uuid.c \
+ isnull.c \
+ pack.c \
+ parse.c \
+ unpack.c \
+ unparse.c \
+ uuid_time.c \
+ $(NULL)
+
+INCLUDES = \
+ $(GLIB_CFLAGS) \
+ $(WERROR) \
+ $(NULL)
diff --git a/capplets/file-types/libuuid/clear.c b/capplets/file-types/libuuid/clear.c
new file mode 100644
index 000000000..32e26d4fb
--- /dev/null
+++ b/capplets/file-types/libuuid/clear.c
@@ -0,0 +1,20 @@
+/*
+ * clear.c -- Clear a UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "string.h"
+
+#include "uuidP.h"
+
+void uuid_clear(uuid_t uu)
+{
+ memset(uu, 0, 16);
+}
+
diff --git a/capplets/file-types/libuuid/compare.c b/capplets/file-types/libuuid/compare.c
new file mode 100644
index 000000000..3d07b5dbc
--- /dev/null
+++ b/capplets/file-types/libuuid/compare.c
@@ -0,0 +1,32 @@
+/*
+ * compare.c --- compare whether or not two UUID's are the same
+ *
+ * Returns 0 if the two UUID's are different, and 1 if they are the same.
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "uuidP.h"
+#include <string.h>
+
+#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
+
+int uuid_compare(uuid_t uu1, uuid_t uu2)
+{
+ struct uuid uuid1, uuid2;
+
+ uuid_unpack(uu1, &uuid1);
+ uuid_unpack(uu2, &uuid2);
+
+ UUCMP(uuid1.time_low, uuid2.time_low);
+ UUCMP(uuid1.time_mid, uuid2.time_mid);
+ UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
+ UUCMP(uuid1.clock_seq, uuid2.clock_seq);
+ return memcmp(uuid1.node, uuid2.node, 6);
+}
+
diff --git a/capplets/file-types/libuuid/copy.c b/capplets/file-types/libuuid/copy.c
new file mode 100644
index 000000000..5d0efc4aa
--- /dev/null
+++ b/capplets/file-types/libuuid/copy.c
@@ -0,0 +1,21 @@
+/*
+ * copy.c --- copy UUIDs
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "uuidP.h"
+
+void uuid_copy(uuid_t uu1, uuid_t uu2)
+{
+ unsigned char *cp1, *cp2;
+ int i;
+
+ for (i=0, cp1 = uu1, cp2 = uu2; i < 16; i++)
+ *cp1++ = *cp2++;
+}
diff --git a/capplets/file-types/libuuid/gen_uuid.c b/capplets/file-types/libuuid/gen_uuid.c
new file mode 100644
index 000000000..1b3b88105
--- /dev/null
+++ b/capplets/file-types/libuuid/gen_uuid.c
@@ -0,0 +1,257 @@
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <config.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "uuidP.h"
+
+#ifdef HAVE_SRANDOM
+#define srand(x) srandom(x)
+#define rand() random()
+#endif
+
+/*
+ * Generate a series of random bytes. Use /dev/urandom if possible,
+ * and if not, use srandom/random.
+ */
+static void get_random_bytes(void *buf, int nbytes)
+{
+ static int fd = -2;
+ int i;
+ char *cp = (char *) buf;
+
+ if (fd == -2) {
+ fd = open("/dev/urandom", O_RDONLY);
+ srand((getpid() << 16) ^ getuid() ^ time(0));
+ }
+ if (fd >= 0) {
+ while (nbytes > 0) {
+ i = read(fd, cp, nbytes);
+ if (i < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ break;
+ }
+ nbytes -= i;
+ cp += i;
+ }
+ }
+ if (nbytes == 0)
+ return;
+
+ /* XXX put something better here if no /dev/random! */
+ for (i=0; i < nbytes; i++)
+ *cp++ = rand() & 0xFF;
+ return;
+
+}
+
+/*
+ * Get the ethernet hardware address, if we can find it...
+ */
+static int get_node_id(unsigned char *node_id)
+{
+#ifdef HAVE_NET_IF_H
+ int sd;
+ struct ifreq ifr, *ifrp;
+ struct ifconf ifc;
+ char buf[1024];
+ int n, i;
+ unsigned char *a;
+
+/*
+ * BSD 4.4 defines the size of an ifreq to be
+ * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+ * However, under earlier systems, sa_len isn't present, so the size is
+ * just sizeof(struct ifreq)
+ */
+#ifdef HAVE_SA_LEN
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#define ifreq_size(i) max(sizeof(struct ifreq),\
+ sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+#define ifreq_size(i) sizeof(struct ifreq)
+#endif /* HAVE_SA_LEN*/
+
+ sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (sd < 0) {
+ return -1;
+ }
+ memset(buf, 0, sizeof(buf));
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
+ close(sd);
+ return -1;
+ }
+ n = ifc.ifc_len;
+ for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
+ ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
+ strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+#ifdef SIOCGIFHWADDR
+ if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#else
+#ifdef SIOCGENADDR
+ if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) ifr.ifr_enaddr;
+#else
+ /*
+ * XXX we don't have a way of getting the hardware
+ * address
+ */
+ close(sd);
+ return 0;
+#endif /* SIOCGENADDR */
+#endif /* SIOCGIFHWADDR */
+ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
+ continue;
+ if (node_id) {
+ memcpy(node_id, a, 6);
+ close(sd);
+ return 1;
+ }
+ }
+ close(sd);
+#endif
+ return 0;
+}
+
+/* Assume that the gettimeofday() has microsecond granularity */
+#define MAX_ADJUSTMENT 10
+
+static int get_clock(guint32 *clock_high, guint32 *clock_low, guint16 *ret_clock_seq)
+{
+ static int adjustment = 0;
+ static struct timeval last = {0, 0};
+ static guint16 clock_seq;
+ struct timeval tv;
+ unsigned long long clock_reg;
+
+try_again:
+ gettimeofday(&tv, 0);
+ if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
+ get_random_bytes(&clock_seq, sizeof(clock_seq));
+ clock_seq &= 0x1FFF;
+ last = tv;
+ last.tv_sec--;
+ }
+ if ((tv.tv_sec < last.tv_sec) ||
+ ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec < last.tv_usec))) {
+ clock_seq = (clock_seq+1) & 0x1FFF;
+ adjustment = 0;
+ } else if ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec == last.tv_usec)) {
+ if (adjustment >= MAX_ADJUSTMENT)
+ goto try_again;
+ adjustment++;
+ } else
+ adjustment = 0;
+
+ clock_reg = tv.tv_usec*10 + adjustment;
+ clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
+ clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
+
+ *clock_high = clock_reg >> 32;
+ *clock_low = clock_reg;
+ *ret_clock_seq = clock_seq;
+ return 0;
+}
+
+void uuid_generate_time(uuid_t out)
+{
+ static unsigned char node_id[6];
+ static int has_init = 0;
+ struct uuid uu;
+ guint32 clock_mid;
+
+ if (!has_init) {
+ if (get_node_id(node_id) <= 0) {
+ get_random_bytes(node_id, 6);
+ /*
+ * Set multicast bit, to prevent conflicts
+ * with IEEE 802 addresses obtained from
+ * network cards
+ */
+ node_id[0] |= 0x80;
+ }
+ has_init = 1;
+ }
+ get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
+ uu.clock_seq |= 0x8000;
+ uu.time_mid = (guint16) clock_mid;
+ uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
+ memcpy(uu.node, node_id, 6);
+ uuid_pack(&uu, out);
+}
+
+void uuid_generate_random(uuid_t out)
+{
+ uuid_t buf;
+ struct uuid uu;
+
+ get_random_bytes(buf, sizeof(buf));
+ uuid_unpack(buf, &uu);
+
+ uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+ uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
+ uuid_pack(&uu, out);
+}
+
+/*
+ * This is the generic front-end to uuid_generate_random and
+ * uuid_generate_time. It uses uuid_generate_random only if
+ * /dev/urandom is available, since otherwise we won't have
+ * high-quality randomness.
+ */
+void uuid_generate(uuid_t out)
+{
+ static int has_random = -1;
+
+ if (has_random < 0) {
+ if (access("/dev/urandom", R_OK) == 0)
+ has_random = 1;
+ else
+ has_random = 0;
+ }
+ if (has_random)
+ uuid_generate_random(out);
+ else
+ uuid_generate_time(out);
+}
+
diff --git a/capplets/file-types/libuuid/gen_uuid_nt.c b/capplets/file-types/libuuid/gen_uuid_nt.c
new file mode 100644
index 000000000..6092c070d
--- /dev/null
+++ b/capplets/file-types/libuuid/gen_uuid_nt.c
@@ -0,0 +1,92 @@
+/*
+ * gen_uuid_nt.c -- Use NT api to generate uuid
+ *
+ * Written by Andrey Shedel (andreys@ns.cr.cyco.com)
+ */
+
+
+#include "uuidP.h"
+
+#pragma warning(push,4)
+
+#pragma comment(lib, "ntdll.lib")
+
+//
+// Here is a nice example why it's not a good idea
+// to use native API in ordinary applications.
+// Number of parameters in function below was changed from 3 to 4
+// for NT5.
+//
+//
+// NTSYSAPI
+// NTSTATUS
+// NTAPI
+// NtAllocateUuids(
+// OUT PULONG p1,
+// OUT PULONG p2,
+// OUT PULONG p3,
+// OUT PUCHAR Seed // 6 bytes
+// );
+//
+//
+
+unsigned long
+__stdcall
+NtAllocateUuids(
+ void* p1, // 8 bytes
+ void* p2, // 4 bytes
+ void* p3 // 4 bytes
+ );
+
+typedef
+unsigned long
+(__stdcall*
+NtAllocateUuids_2000)(
+ void* p1, // 8 bytes
+ void* p2, // 4 bytes
+ void* p3, // 4 bytes
+ void* seed // 6 bytes
+ );
+
+
+
+//
+// Nice, but instead of including ntddk.h ot winnt.h
+// I should define it here because they MISSED __stdcall in those headers.
+//
+
+__declspec(dllimport)
+struct _TEB*
+__stdcall
+NtCurrentTeb(void);
+
+
+//
+// The only way to get version information from the system is to examine
+// one stored in PEB. But it's pretty dangerouse because this value could
+// be altered in image header.
+//
+
+static
+int
+Nt5(void)
+{
+ //return NtCuttentTeb()->Peb->OSMajorVersion >= 5;
+ return (int)*(int*)((char*)(int)(*(int*)((char*)NtCurrentTeb() + 0x30)) + 0xA4) >= 5;
+}
+
+
+
+
+void uuid_generate(uuid_t out)
+{
+ if(Nt5())
+ {
+ unsigned char seed[6];
+ ((NtAllocateUuids_2000)NtAllocateUuids)(out, ((char*)out)+8, ((char*)out)+12, &seed[0] );
+ }
+ else
+ {
+ NtAllocateUuids(out, ((char*)out)+8, ((char*)out)+12);
+ }
+}
diff --git a/capplets/file-types/libuuid/isnull.c b/capplets/file-types/libuuid/isnull.c
new file mode 100644
index 000000000..43b81f879
--- /dev/null
+++ b/capplets/file-types/libuuid/isnull.c
@@ -0,0 +1,25 @@
+/*
+ * isnull.c --- Check whether or not the UUID is null
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "uuidP.h"
+
+/* Returns 1 if the uuid is the NULL uuid */
+int uuid_is_null(uuid_t uu)
+{
+ unsigned char *cp;
+ int i;
+
+ for (i=0, cp = uu; i < 16; i++)
+ if (*cp++)
+ return 0;
+ return 1;
+}
+
diff --git a/capplets/file-types/libuuid/pack.c b/capplets/file-types/libuuid/pack.c
new file mode 100644
index 000000000..94be488aa
--- /dev/null
+++ b/capplets/file-types/libuuid/pack.c
@@ -0,0 +1,46 @@
+/*
+ * Internal routine for packing UUID's
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_pack(struct uuid *uu, uuid_t ptr)
+{
+ guint32 tmp;
+ unsigned char *out = ptr;
+
+ tmp = uu->time_low;
+ out[3] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[2] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[1] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[0] = (unsigned char) tmp;
+
+ tmp = uu->time_mid;
+ out[5] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[4] = (unsigned char) tmp;
+
+ tmp = uu->time_hi_and_version;
+ out[7] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[6] = (unsigned char) tmp;
+
+ tmp = uu->clock_seq;
+ out[9] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[8] = (unsigned char) tmp;
+
+ memcpy(out+10, uu->node, 6);
+}
+
diff --git a/capplets/file-types/libuuid/parse.c b/capplets/file-types/libuuid/parse.c
new file mode 100644
index 000000000..ea6ce7909
--- /dev/null
+++ b/capplets/file-types/libuuid/parse.c
@@ -0,0 +1,52 @@
+/*
+ * parse.c --- UUID parsing
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "uuidP.h"
+
+int uuid_parse(char *in, uuid_t uu)
+{
+ struct uuid uuid;
+ int i;
+ char *cp, buf[3];
+
+ if (strlen(in) != 36)
+ return -1;
+ for (i=0, cp = in; i <= 36; i++,cp++) {
+ if ((i == 8) || (i == 13) || (i == 18) ||
+ (i == 23))
+ if (*cp == '-')
+ continue;
+ if (i== 36)
+ if (*cp == 0)
+ continue;
+ if (!isxdigit((guchar) *cp))
+ return -1;
+ }
+ uuid.time_low = strtoul(in, NULL, 16);
+ uuid.time_mid = strtoul(in+9, NULL, 16);
+ uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
+ uuid.clock_seq = strtoul(in+19, NULL, 16);
+ cp = in+24;
+ buf[2] = 0;
+ for (i=0; i < 6; i++) {
+ buf[0] = *cp++;
+ buf[1] = *cp++;
+ uuid.node[i] = strtoul(buf, NULL, 16);
+ }
+
+ uuid_pack(&uuid, uu);
+ return 0;
+}
diff --git a/capplets/file-types/libuuid/tst_uuid.c b/capplets/file-types/libuuid/tst_uuid.c
new file mode 100644
index 000000000..b9fc5f69a
--- /dev/null
+++ b/capplets/file-types/libuuid/tst_uuid.c
@@ -0,0 +1,119 @@
+/*
+ * tst_uuid.c --- test program from the UUID library
+ *
+ * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <linux/ext2_fs.h>
+
+#include "uuid.h"
+
+int
+main(int argc, char **argv)
+{
+ uuid_t buf, tst;
+ char str[100];
+ struct timeval tv;
+ time_t time_reg;
+ unsigned char *cp;
+ int i;
+ int failed = 0;
+ int type, variant;
+
+ uuid_generate(buf);
+ uuid_unparse(buf, str);
+ printf("UUID generate = %s\n", str);
+ printf("UUID: ");
+ for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
+ printf("%02x", *cp++);
+ }
+ printf("\n");
+ type = uuid_type(buf); variant = uuid_variant(buf);
+ printf("UUID type = %d, UUID variant = %d\n", type, variant);
+ if (variant != UUID_VARIANT_DCE) {
+ printf("Incorrect UUID Variant; was expecting DCE!\n");
+ failed++;
+ }
+ printf("\n");
+
+ uuid_generate_random(buf);
+ uuid_unparse(buf, str);
+ printf("UUID random string = %s\n", str);
+ printf("UUID: ");
+ for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
+ printf("%02x", *cp++);
+ }
+ printf("\n");
+ type = uuid_type(buf); variant = uuid_variant(buf);
+ printf("UUID type = %d, UUID variant = %d\n", type, variant);
+ if (variant != UUID_VARIANT_DCE) {
+ printf("Incorrect UUID Variant; was expecting DCE!\n");
+ failed++;
+ }
+ if (type != 4) {
+ printf("Incorrect UUID type; was expecting "
+ "4 (random type)!\n");
+ failed++;
+ }
+ printf("\n");
+
+ uuid_generate_time(buf);
+ uuid_unparse(buf, str);
+ printf("UUID string = %s\n", str);
+ printf("UUID time: ");
+ for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
+ printf("%02x", *cp++);
+ }
+ printf("\n");
+ type = uuid_type(buf); variant = uuid_variant(buf);
+ printf("UUID type = %d, UUID variant = %d\n", type, variant);
+ if (variant != UUID_VARIANT_DCE) {
+ printf("Incorrect UUID Variant; was expecting DCE!\n");
+ failed++;
+ }
+ if (type != 1) {
+ printf("Incorrect UUID type; was expecting "
+ "1 (time-based type)!\\n");
+ failed++;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ time_reg = uuid_time(buf, &tv);
+ printf("UUID time is: (%d, %d): %s\n", tv.tv_sec, tv.tv_usec,
+ ctime(&time_reg));
+ uuid_parse(str, tst);
+ if (!uuid_compare(buf, tst))
+ printf("UUID parse and compare succeeded.\n");
+ else {
+ printf("UUID parse and compare failed!\n");
+ failed++;
+ }
+ uuid_clear(tst);
+ if (uuid_is_null(tst))
+ printf("UUID clear and is null succeeded.\n");
+ else {
+ printf("UUID clear and is null failed!\n");
+ failed++;
+ }
+ uuid_copy(buf, tst);
+ if (!uuid_compare(buf, tst))
+ printf("UUID copy and compare succeeded.\n");
+ else {
+ printf("UUID copy and compare failed!\n");
+ failed++;
+ }
+ if (failed) {
+ printf("%d failures.\n", failed);
+ exit(1);
+ }
+ return 0;
+}
+
+
+
diff --git a/capplets/file-types/libuuid/unpack.c b/capplets/file-types/libuuid/unpack.c
new file mode 100644
index 000000000..8a80a9962
--- /dev/null
+++ b/capplets/file-types/libuuid/unpack.c
@@ -0,0 +1,40 @@
+/*
+ * Internal routine for unpacking UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_unpack(uuid_t in, struct uuid *uu)
+{
+ guint8 *ptr = in;
+ guint32 tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_low = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_mid = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_hi_and_version = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->clock_seq = tmp;
+
+ memcpy(uu->node, ptr, 6);
+}
+
diff --git a/capplets/file-types/libuuid/unparse.c b/capplets/file-types/libuuid/unparse.c
new file mode 100644
index 000000000..ab904bc16
--- /dev/null
+++ b/capplets/file-types/libuuid/unparse.c
@@ -0,0 +1,28 @@
+/*
+ * unparse.c -- convert a UUID to string
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "uuidP.h"
+
+void uuid_unparse(uuid_t uu, char *out)
+{
+ struct uuid uuid;
+
+ uuid_unpack(uu, &uuid);
+ sprintf(out,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+ uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+ uuid.node[0], uuid.node[1], uuid.node[2],
+ uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
diff --git a/capplets/file-types/libuuid/uuid.h b/capplets/file-types/libuuid/uuid.h
new file mode 100644
index 000000000..12afabffe
--- /dev/null
+++ b/capplets/file-types/libuuid/uuid.h
@@ -0,0 +1,50 @@
+/*
+ * Public include file for the UUID library
+ *
+ * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+typedef unsigned char uuid_t[16];
+
+/* UUID Variant definitions */
+#define UUID_VARIANT_NCS 0
+#define UUID_VARIANT_DCE 1
+#define UUID_VARIANT_MICROSOFT 2
+#define UUID_VARIANT_OTHER 3
+
+/* clear.c */
+void uuid_clear(uuid_t uu);
+
+/* compare.c */
+int uuid_compare(uuid_t uu1, uuid_t uu2);
+
+/* copy.c */
+void uuid_copy(uuid_t uu1, uuid_t uu2);
+
+/* gen_uuid.c */
+void uuid_generate(uuid_t out);
+void uuid_generate_random(uuid_t out);
+void uuid_generate_time(uuid_t out);
+
+/* isnull.c */
+int uuid_is_null(uuid_t uu);
+
+/* parse.c */
+int uuid_parse(char *in, uuid_t uu);
+
+/* unparse.c */
+void uuid_unparse(uuid_t uu, char *out);
+
+/* uuid_time.c */
+time_t uuid_time(uuid_t uu, struct timeval *ret_tv);
+int uuid_type(uuid_t uu);
+int uuid_variant(uuid_t uu);
diff --git a/capplets/file-types/libuuid/uuidP.h b/capplets/file-types/libuuid/uuidP.h
new file mode 100644
index 000000000..995db687c
--- /dev/null
+++ b/capplets/file-types/libuuid/uuidP.h
@@ -0,0 +1,40 @@
+/*
+ * uuid.h -- private header file for uuids
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <sys/types.h>
+#include <glib.h>
+
+#include "uuid.h"
+
+/*
+ * Offset between 15-Oct-1582 and 1-Jan-70
+ */
+#define TIME_OFFSET_HIGH 0x01B21DD2
+#define TIME_OFFSET_LOW 0x13814000
+
+struct uuid {
+ guint32 time_low;
+ guint16 time_mid;
+ guint16 time_hi_and_version;
+ guint16 clock_seq;
+ guint8 node[6];
+};
+
+
+/*
+ * prototypes
+ */
+void uuid_pack(struct uuid *uu, uuid_t ptr);
+void uuid_unpack(uuid_t in, struct uuid *uu);
+
+
+
+
diff --git a/capplets/file-types/libuuid/uuid_time.c b/capplets/file-types/libuuid/uuid_time.c
new file mode 100644
index 000000000..9a302202a
--- /dev/null
+++ b/capplets/file-types/libuuid/uuid_time.c
@@ -0,0 +1,138 @@
+/*
+ * uuid_time.c --- Interpret the time field from a uuid. This program
+ * violates the UUID abstraction barrier by reaching into the guts
+ * of a UUID and interpreting it.
+ *
+ * Copyright (C) 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "uuidP.h"
+
+time_t uuid_time(uuid_t uu, struct timeval *ret_tv)
+{
+ struct uuid uuid;
+ guint32 high;
+ struct timeval tv;
+ unsigned long long clock_reg;
+
+ uuid_unpack(uu, &uuid);
+
+ high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
+ clock_reg = uuid.time_low | ((unsigned long long) high << 32);
+
+ clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
+ tv.tv_sec = clock_reg / 10000000;
+ tv.tv_usec = (clock_reg % 10000000) / 10;
+
+ if (ret_tv)
+ *ret_tv = tv;
+
+ return tv.tv_sec;
+}
+
+int uuid_type(uuid_t uu)
+{
+ struct uuid uuid;
+
+ uuid_unpack(uu, &uuid);
+ return ((uuid.time_hi_and_version >> 12) & 0xF);
+}
+
+int uuid_variant(uuid_t uu)
+{
+ struct uuid uuid;
+ int var;
+
+ uuid_unpack(uu, &uuid);
+ var = uuid.clock_seq;
+
+ if ((var & 0x8000) == 0)
+ return UUID_VARIANT_NCS;
+ if ((var & 0x4000) == 0)
+ return UUID_VARIANT_DCE;
+ if ((var & 0x2000) == 0)
+ return UUID_VARIANT_MICROSOFT;
+ return UUID_VARIANT_OTHER;
+}
+
+#ifdef DEBUG
+static const char *variant_string(int variant)
+{
+ switch (variant) {
+ case UUID_VARIANT_NCS:
+ return "NCS";
+ case UUID_VARIANT_DCE:
+ return "DCE";
+ case UUID_VARIANT_MICROSOFT:
+ return "Microsoft";
+ default:
+ return "Other";
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ uuid_t buf;
+ time_t time_reg;
+ struct timeval tv;
+ int type, variant;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s uuid\n", argv[0]);
+ exit(1);
+ }
+ if (uuid_parse(argv[1], buf)) {
+ fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
+ exit(1);
+ }
+ variant = uuid_variant(buf);
+ type = uuid_type(buf);
+ time_reg = uuid_time(buf, &tv);
+
+ printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
+ if (variant != UUID_VARIANT_DCE) {
+ printf("Warning: This program only knows how to interpret "
+ "DCE UUIDs.\n\tThe rest of the output is likely "
+ "to be incorrect!!\n");
+ }
+ printf("UUID type is %d", type);
+ switch (type) {
+ case 1:
+ printf(" (time based)\n");
+ break;
+ case 2:
+ printf(" (DCE)\n");
+ break;
+ case 3:
+ printf(" (name-based)\n");
+ break;
+ case 4:
+ printf(" (random)\n");
+ break;
+ default:
+ printf("\n");
+ }
+ if (type != 1) {
+ printf("Warning: not a time-based UUID, so UUID time "
+ "decoding will likely not work!\n");
+ }
+ printf("UUID time is: (%u, %u): %s\n", (unsigned)tv.tv_sec, (unsigned)tv.tv_usec,
+ ctime(&time_reg));
+
+ return 0;
+}
+#endif
diff --git a/capplets/file-types/nautilus-mime-type.desktop b/capplets/file-types/nautilus-mime-type.desktop
deleted file mode 100644
index 93e0278d1..000000000
--- a/capplets/file-types/nautilus-mime-type.desktop
+++ /dev/null
@@ -1,21 +0,0 @@
-[Desktop Entry]
-Name=File Types and Programs
-Name[pt_BR]=Tipos de Arquivos e Programas
-Name[da]=Filtyper og programmer
-Name[fi]=Tiedostotyypit ja ohjelmat
-Name[fr]=Type de fichiers et programmes
-Name[no]=Filtyper og programmer
-Name[sk]=Typy súborov a programy
-Name[tr]=Dosya türleri ve uygulamarı
-Comment=We need a good explanation here.
-Comment[fi]=Aseta, millä ohjelmilla tietyn tyyppisiä tiedostoja käsitellään.
-Comment[pt_BR]=Precisamos de uma boa explicação aqui.
-Comment[da]=Vi har brug for en god forklaring her.
-Comment[fr]=Éditeur d'association de type de fichiers et d'applications
-Comment[no]=Koblinger mellom filtyper og programmer
-Comment[sk]=Sem by to chcelo nejaké rozumné vysvetlenie...
-Comment[tr]=Eh, buraya da iyi bir anlatım gerek ...
-Icon=gnome-ccmime.png
-Exec=nautilus-mime-type-capplet
-Terminal=0
-Type=Application