patch-ahoy: gnome_url_show stuff



Hi all,

here are some preliminary patches for gnome-vfs, libgnome and nautilus
to implement the gnome_url_show stuff I have been talking about.

I've done some basic testing on my system and it seems to work fine.
There are a couple of issues however. Once those are worked out I hope
to commit this and make some more patches for the panel to also use
gnome_url_show.


1. Currently gnome_url_show just calls gnome_vfs_url_show but adds
support for the special handlers defined in gconf
(/desktop/gnome/url-handlers) on top of that. Should this just all be
merged into gnome_vfs_url_show or not?

Yes/Pros:
- centralizes all the showing files stuff in one place
- to properly support showing files an app only needs to link against
gnomevfs
- lets us get rid of gnome_url_show

No/Cons:
- url-handlers don't really have anything directly to do with the file
system so that doesn't fully fit gnomevfs
- gnome_url_show provides nice error messages for people, so they don't
have to figure out what the gnomevfs error codes mean

2. In CVS head gnome-mime-data in the gnome-vfs.applications file the
"expects_uris" parameter is set to 'false' for all the apps. This is
actually not a boolean parameter but an enum that has 3 possible values:

0 = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS,
1 = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_PATHS,
2 = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS_FOR_NON_FILES

The last one means _NON_LOCAL_FILES I assume, at least that's what I
coded it to mean. By setting this to false (0) the effect is exactly
what you don't want. So this needs to be set to 1 for the apps in that
file and anybody else that adds applications to the registry needs to be
aware of this.

3. I am reusing GnomeVFSResult error codes that already exist. It might
be a good idea to add a few new ones that have more intuitive names for
what is actually going on. Is that ok?

4. In fm-directory-view.c in the Nautilus patch the
use_external_viewer_auto_value is not updated for me, no matter what I
set the gconf value too. I can't see anything wrong with my code. Ideas
anyone?


Alrighty, so what do people think?

- Frank

Index: libgnomevfs/gnome-vfs-mime-handlers.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-mime-handlers.c,v
retrieving revision 1.97
diff -u -p -r1.97 gnome-vfs-mime-handlers.c
--- libgnomevfs/gnome-vfs-mime-handlers.c	16 May 2002 15:06:02 -0000	1.97
+++ libgnomevfs/gnome-vfs-mime-handlers.c	11 Mar 2003 02:57:53 -0000
@@ -34,6 +34,17 @@
 #include <stdio.h>
 #include <string.h>
 
+#define GCONF_DEFAULT_TERMINAL_EXEC_PATH "/desktop/gnome/applications/terminal/exec"
+#define GCONF_DEFAULT_TERMINAL_ARG_PATH  "/desktop/gnome/applications/terminal/exec_arg"
+#define GCONF_DEFAULT_VIEWER_EXEC_PATH   "/desktop/gnome/applications/component_viewer/exec"
+
+static GnomeVFSResult launch_component                        (Bonobo_ServerInfo       *component,
+                                                               GList                   *uris,
+                                                               char                   **envp);
+static char *         expand_parameters                       (GnomeVFSMimeApplication *app,
+                                                               GList                   *uris);
+static gboolean       prepend_terminal                        (int                     *argc,
+                                                               char                  ***argv);
 static GList *        Bonobo_ServerInfoList_to_ServerInfo_g_list (Bonobo_ServerInfoList *info_list);
 static GList *        copy_str_list                           (GList *string_list);
 static GList *        comma_separated_str_to_str_list         (const char         *str);
@@ -1764,6 +1775,500 @@ gnome_vfs_mime_application_new_from_id (
 {
 	return gnome_vfs_application_registry_get_mime_application (id);
 }
+
+/**
+ * gnome_vfs_mime_action_launch:
+ * @action: the GnomeVFSMimeAction to launch
+ * @uris: parameters for the GnomeVFSMimeAction
+ *
+ * Launches the given mime action with the given parameters. If 
+ * the action is an application the command line parameters will
+ * be expanded as required by the application. The application
+ * will also be launched in a terminal if that is required. If the
+ * application only supports one argument per instance then multile
+ * instances of the application will be launched.
+ *
+ * If the default action is a component it will be launched with
+ * the component viewer application defined using the gconf value:
+ * /desktop/gnome/application/component_viewer/exec. The parameters
+ * %s and %c in the command line will be replaced with the list of
+ * parameters and the default component IID respectively.
+ *
+ * Return value: GNOME_VFS_OK if the action was launched,
+ * GNOME_VFS_ERROR_BAD_PARAMETERS for an invalid action or
+ * if the uri protocol is not supported by the action,
+ * GNOME_VFS_ERROR_INTERNAL if the action command can not
+ * be parsed or if the component viewer is invalid.
+ */
+GnomeVFSResult
+gnome_vfs_mime_action_launch (GnomeVFSMimeAction *action,
+                              GList              *uris)
+{
+	return gnome_vfs_mime_action_launch_with_env (action, uris, NULL);
+}
+
+/**
+ * gnome_vfs_mime_action_launch_with_env:
+ *
+ * Same as gnome_vfs_mime_action_launch except that the
+ * application or component viewer will be launched with
+ * the given environment.
+ *
+ * Return value: same as gnome_vfs_mime_action_launch
+ */
+GnomeVFSResult
+gnome_vfs_mime_action_launch_with_env (GnomeVFSMimeAction *action,
+                                       GList              *uris,
+				       char              **envp)
+{
+	switch (action->action_type) {
+	case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION:
+	
+		return gnome_vfs_mime_application_launch_with_env
+			 		(action->action.application,
+			 		 uris, envp);
+					 
+	case GNOME_VFS_MIME_ACTION_TYPE_COMPONENT:
+	
+		return launch_component (action->action.component, uris, envp);
+	
+	default:
+		g_assert_not_reached ();
+	}
+	
+	return GNOME_VFS_ERROR_BAD_PARAMETERS;
+}
+
+/**
+ * gnome_vfs_mime_application_launch:
+ * @app: the GnomeVFSMimeApplication to launch
+ * @uris: parameters for the GnomeVFSMimeApplication
+ *
+ * Launches the given mime application with the given parameters.
+ * Command line parameters will be expanded as required by the
+ * application. The application will also be launched in a terminal
+ * if that is required. If the application only supports one argument 
+ * per instance then multiple instances of the application will be 
+ * launched.
+ *
+ * Return value: GNOME_VFS_OK if the application was launched,
+ * GNOME_VFS_ERROR_BAD_PARAMETERS if the uri protocol is not
+ * supported by the application.
+ * GNOME_VFS_ERROR_INTERNAL if the application command can not
+ * be parsed.
+ */
+GnomeVFSResult
+gnome_vfs_mime_application_launch (GnomeVFSMimeApplication *app,
+                                   GList                   *uris)
+{
+	return gnome_vfs_mime_application_launch_with_env (app, uris, NULL);
+}
+
+/**
+ * gnome_vfs_mime_application_launch_with_env:
+ *
+ * Same as gnome_vfs_mime_application_launch except that
+ * the application will be launched with the given environment.
+ *
+ * Return value: same as gnome_vfs_mime_application_launch
+ */
+GnomeVFSResult 
+gnome_vfs_mime_application_launch_with_env (GnomeVFSMimeApplication *app,
+                                            GList                   *uris,
+                                            char                    **envp)
+{
+	GnomeVFSURI *uri;
+	GList *i, *u;
+	char *command;
+	char **argv;
+	int argc;
+	
+	/* check that all uri schemes are supported */
+	if (app->supported_uri_schemes != NULL) {
+		for (u = uris; u != NULL; u = u->next) {
+		
+			uri = gnome_vfs_uri_new (u->data);
+
+			for (i = app->supported_uri_schemes; i != NULL; i = i->next) {
+				if (!strcmp (i->data, gnome_vfs_uri_get_scheme (uri))) {
+					break;
+				}
+			}
+
+			gnome_vfs_uri_unref (uri);
+	
+			if (i == NULL && app->supported_uri_schemes != NULL) {
+				return GNOME_VFS_ERROR_BAD_PARAMETERS;
+			}
+		}
+	}
+
+	while (uris != NULL) {
+		
+		command = expand_parameters (app, uris);
+		
+		g_warning ("command is: %s", command);
+		
+		if (!g_shell_parse_argv (command,
+        	                     &argc,
+                	             &argv,
+                        	     NULL)) {
+		
+				g_free (command);
+				g_warning ("error parsing command: %s", command);
+				return GNOME_VFS_ERROR_INTERNAL;
+		}		
+		
+		g_free (command);
+		
+		if (app->requires_terminal) {
+			if (!prepend_terminal (&argc, &argv)) {
+				g_strfreev (argv);
+				return GNOME_VFS_ERROR_INTERNAL;
+			}
+		}
+		
+		if (!g_spawn_async (NULL /* working directory */,
+                            argv,
+                            envp,
+                            G_SPAWN_SEARCH_PATH /* flags */,
+                            NULL /* child_setup */,
+                            NULL /* data */,
+                            NULL /* child_pid */,
+                            NULL /* error */)) {
+
+			g_strfreev (argv);
+			g_warning ("error launching command");
+			return GNOME_VFS_ERROR_INTERNAL;
+		}
+		
+		g_strfreev (argv);
+		uris = uris->next;
+		
+		if (app->can_open_multiple_files) {
+			break;
+		}
+	}
+	
+	return GNOME_VFS_OK;		
+}
+
+static char *
+expand_parameters (GnomeVFSMimeApplication *app,
+                   GList                   *uris)
+{
+	char *uri_list = NULL;
+	char *path = NULL;
+	char *temp = NULL;
+	char *quoted;
+	char **tokens;
+	
+	while (uris != NULL) {
+	
+		switch (app->expects_uris) {
+		case GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS:
+
+			quoted = g_shell_quote (uris->data);
+	
+			if (uri_list == NULL) {
+				uri_list = quoted;
+			} else {
+				temp = g_strconcat (uri_list, " ", quoted, NULL);
+				g_free (uri_list);
+				g_free (quoted);				
+				uri_list = temp;
+			}
+	
+			break;
+	
+		case GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_PATHS:
+		
+			path = gnome_vfs_get_local_path_from_uri (uris->data);
+			quoted = g_shell_quote (path);
+			
+			if (path != NULL && uri_list == NULL) {
+				uri_list = quoted;
+			} else if (path != NULL) {
+				temp = g_strconcat (uri_list, " ", quoted, NULL);
+				g_free (uri_list);
+				g_free (quoted);
+				uri_list = temp;
+			}
+
+			g_free (path);
+			
+			break;
+			
+		case GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS_FOR_NON_FILES:
+			/* this really means use URIs for non local files */
+			
+			path = gnome_vfs_get_local_path_from_uri (uris->data);
+			
+			if (path != NULL) {
+				
+				quoted = g_shell_quote (path);
+			
+				if (uri_list == NULL) {
+					uri_list = quoted;
+				} else {
+					temp = g_strconcat (uri_list, " ", quoted, NULL);
+					g_free (uri_list);
+					g_free (quoted);
+					uri_list = temp;
+				}
+				
+				g_free (path);
+				
+			} else {
+			
+				quoted = g_shell_quote (uris->data);
+				
+				if (uri_list == NULL) {
+					uri_list = quoted;
+				} else {
+					temp = g_strconcat (uri_list, " ", quoted, NULL);
+					g_free (uri_list);
+					g_free (quoted);
+					uri_list = temp;
+				}
+			}
+							
+			break;
+			
+		default:
+			g_assert_not_reached ();
+		}
+		
+		uris = uris->next;
+
+		if (!app->can_open_multiple_files && uri_list != NULL) {
+			break;
+		}
+	}
+	
+	/* assume there's only one %s in the command */
+	tokens = g_strsplit (app->command, "%s", 2);
+	if (tokens[1] == NULL) {
+		temp = g_strconcat (tokens[0], " ", uri_list, NULL);
+	} else {
+		temp = g_strconcat (tokens[0], uri_list, tokens[1], NULL);
+	}
+	
+	g_strfreev (tokens);
+	g_free (uri_list);
+	
+	return temp;
+}
+
+static GnomeVFSResult
+launch_component (Bonobo_ServerInfo  *component,
+                  GList              *uris,
+                  char              **envp)
+{
+	GConfClient *client;
+	GList *item;
+	char *command;
+	char *uri_list, *temp, *quoted;
+	char **argv;
+	int argc;
+	
+	uri_list = NULL;
+	for (item = uris; item != NULL; item = item->next) {
+		
+		quoted = g_shell_quote (item->data);
+	
+		if (uri_list == NULL) {
+			uri_list = quoted;
+		} else {
+			temp = g_strconcat (uri_list, " ", quoted, NULL);
+			g_free (uri_list);
+			g_free (quoted);
+			uri_list = temp;
+		}
+	}
+	
+	if (!gconf_is_initialized ()) {
+		if (!gconf_init (0, NULL, NULL)) {
+			return GNOME_VFS_ERROR_INTERNAL;
+		}
+	}
+	
+	client = gconf_client_get_default ();
+	
+	g_return_val_if_fail (client != NULL, GNOME_VFS_ERROR_INTERNAL);
+	
+	command = gconf_client_get_string (client, GCONF_DEFAULT_VIEWER_EXEC_PATH, NULL);
+	
+	g_object_unref (client);
+	
+	g_return_val_if_fail (command != NULL, GNOME_VFS_ERROR_INTERNAL);
+	
+	/* assume there is only one %s */
+	argv = g_strsplit (command, "%s", 2);
+	if (argv[1] == NULL) {
+		temp = g_strconcat (argv[0], " ", uri_list, NULL);
+	} else {
+		temp = g_strconcat (argv[0], uri_list, argv[1], NULL);
+	}
+	g_free (command);
+	g_free (uri_list);
+	g_strfreev (argv);
+	command = temp;
+	
+	/* if there is no %c then don't append the IID */
+	argv = g_strsplit (command, "%c", 2);
+	if (argv[1] != NULL) {
+		temp = g_strconcat (argv[0], component->iid, argv[1], NULL);
+		g_free (command);
+		g_strfreev (argv);
+		command = temp;
+	} else {
+		g_strfreev (argv);
+	}
+
+	g_warning ("viewer command is: %s", command);
+
+	if (!g_shell_parse_argv (command,
+                             &argc,
+                             &argv,
+                             NULL)) {
+		
+			g_free (command);
+			return FALSE;
+	}
+		
+	g_free (command);
+	
+	if (!g_spawn_async (NULL /* working directory */,
+                            argv,
+                            envp,
+                            G_SPAWN_SEARCH_PATH /* flags */,
+                            NULL /* child_setup */,
+                            NULL /* data */,
+                            NULL /* child_pid */,
+                            NULL /* error */)) {
+
+			g_strfreev (argv);
+			return GNOME_VFS_ERROR_INTERNAL;
+	}
+	
+	g_strfreev (argv);
+	
+	return GNOME_VFS_OK;
+}
+
+/* copied from libgnome */
+static gboolean
+prepend_terminal (int    *argc,
+                  char ***argv)
+{
+        char **real_argv;
+        int real_argc;
+        int i, j;
+	char **term_argv = NULL;
+	int term_argc = 0;
+	GConfClient *client;
+
+	char *terminal = NULL;
+	char **the_argv;
+
+        g_return_val_if_fail (argc != NULL, FALSE);
+        g_return_val_if_fail (argv != NULL, FALSE);
+
+	/* sanity */
+        if(*argv == NULL)
+                *argc = 0;
+
+	the_argv = *argv;
+
+	/* compute size if not given */
+	if (*argc < 0) {
+		for (i = 0; the_argv[i] != NULL; i++)
+			;
+		*argc = i;
+	}
+
+	if (!gconf_is_initialized ()) {
+		if (!gconf_init (0, NULL, NULL)) {
+			return FALSE;
+		}
+	}
+
+	client = gconf_client_get_default ();
+	terminal = gconf_client_get_string (client, GCONF_DEFAULT_TERMINAL_EXEC_PATH, NULL);
+	
+	if (terminal) {
+		gchar *exec_flag;
+		exec_flag = gconf_client_get_string (client, GCONF_DEFAULT_TERMINAL_ARG_PATH, NULL);
+
+		if (exec_flag == NULL) {
+			term_argc = 1;
+			term_argv = g_new0 (char *, 2);
+			term_argv[0] = terminal;
+			term_argv[1] = NULL;
+		} else {
+			term_argc = 2;
+			term_argv = g_new0 (char *, 3);
+			term_argv[0] = terminal;
+			term_argv[1] = exec_flag;
+			term_argv[2] = NULL;
+		}
+	}
+
+	g_object_unref (G_OBJECT (client));
+
+	if (term_argv == NULL) {
+		char *check;
+
+		term_argc = 2;
+		term_argv = g_new0 (char *, 3);
+
+		check = g_find_program_in_path ("gnome-terminal");
+		if (check != NULL) {
+			term_argv[0] = check;
+			/* Note that gnome-terminal takes -x and
+			 * as -e in gnome-terminal is broken we use that. */
+			term_argv[1] = g_strdup ("-x");
+		} else {
+			if (check == NULL)
+				check = g_find_program_in_path ("nxterm");
+			if (check == NULL)
+				check = g_find_program_in_path ("color-xterm");
+			if (check == NULL)
+				check = g_find_program_in_path ("rxvt");
+			if (check == NULL)
+				check = g_find_program_in_path ("xterm");
+			if (check == NULL)
+				check = g_find_program_in_path ("dtterm");
+			if (check == NULL) {
+				check = g_strdup ("xterm");
+			}
+			term_argv[0] = check;
+			term_argv[1] = g_strdup ("-e");
+		}
+	}
+
+        real_argc = term_argc + *argc;
+        real_argv = g_new (char *, real_argc + 1);
+
+        for (i = 0; i < term_argc; i++)
+                real_argv[i] = term_argv[i];
+
+        for (j = 0; j < *argc; j++, i++)
+                real_argv[i] = (char *)the_argv[j];
+
+	real_argv[i] = NULL;
+
+	g_free (*argv);
+	*argv = real_argv;
+	*argc = real_argc;
+
+	/* we use g_free here as we sucked all the inner strings
+	 * out from it into real_argv */
+	g_free (term_argv);
+
+	return TRUE;
+}		  
 
 static gboolean
 application_known_to_be_nonexistent (const char *application_id)
Index: libgnomevfs/gnome-vfs-mime-handlers.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-mime-handlers.h,v
retrieving revision 1.36
diff -u -p -r1.36 gnome-vfs-mime-handlers.h
--- libgnomevfs/gnome-vfs-mime-handlers.h	18 Dec 2002 16:40:00 -0000	1.36
+++ libgnomevfs/gnome-vfs-mime-handlers.h	11 Mar 2003 02:57:53 -0000
@@ -150,6 +150,19 @@ GList *                  gnome_vfs_mime_
 GList *                  gnome_vfs_mime_id_list_from_component_list        (GList                   *components);
 GList *                  gnome_vfs_mime_id_list_from_application_list      (GList                   *applications);
 
+
+/* For launching mime actions & application */
+GnomeVFSResult           gnome_vfs_mime_action_launch                      (GnomeVFSMimeAction      *action,
+                                                                            GList                   *uris);
+GnomeVFSResult           gnome_vfs_mime_action_launch_with_env             (GnomeVFSMimeAction      *action,
+                                                                            GList                   *uris,
+									    char                   **envp);
+GnomeVFSResult           gnome_vfs_mime_application_launch                 (GnomeVFSMimeApplication *app,
+                                                                            GList                   *uris);
+GnomeVFSResult           gnome_vfs_mime_application_launch_with_env	   (GnomeVFSMimeApplication *app,
+									    GList                   *uris,
+									    char                   **envp);
+
 G_END_DECLS
 
 #endif /* GNOME_VFS_MIME_HANDLERS_H */
Index: libgnomevfs/gnome-vfs-utils.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-utils.c,v
retrieving revision 1.61
diff -u -p -r1.61 gnome-vfs-utils.c
--- libgnomevfs/gnome-vfs-utils.c	19 Dec 2002 17:57:19 -0000	1.61
+++ libgnomevfs/gnome-vfs-utils.c	11 Mar 2003 02:57:54 -0000
@@ -35,6 +35,7 @@
 #include "gnome-vfs-i18n.h"
 #include "gnome-vfs-private-utils.h"
 #include "gnome-vfs-ops.h"
+#include "gnome-vfs-mime-handlers.h"
 #include <glib/gstrfuncs.h>
 #include <glib/gutils.h>
 #include <pwd.h>
@@ -2116,4 +2117,66 @@ _gnome_vfs_uri_is_in_subdir (GnomeVFSURI
 	return is_in_dir;
 }
 
-			  
+/**
+ * gnome_vfs_url_show:
+ * 
+ * Launches the default application or component associated with the given url.
+ *
+ * Return value: GNOME_VFS_OK if the default action was launched,
+ * GNOME_VFS_ERROR_BAD_PARAMETERS for an invalid or non-existant url,
+ * GNOME_VFS_ERROR_NOT_SUPPORTED if no default action is associated with the URL,
+ * error codes from gnome_vfs_mime_action_launch for any other errors.
+ *
+ * Since: 2.4
+ **/
+
+GnomeVFSResult
+gnome_vfs_url_show (const char *url)
+{
+	return gnome_vfs_url_show_with_env (url, NULL);
+}
+
+/**
+ * gnome_vfs_url_show_with_env:
+ * 
+ * Like gnome_vfs_url_show except that the default action will be launched
+ * with the given environment.
+ *
+ * Return value: GNOME_VFS_OK if the default action was launched.
+ *
+ * Since: 2.4
+ **/
+
+GnomeVFSResult
+gnome_vfs_url_show_with_env (const char  *url,
+                             char       **envp)
+{
+	GnomeVFSMimeAction *action;
+	GnomeVFSResult result;
+	GList params;
+	char *type;
+
+	g_return_val_if_fail (url != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
+
+	type = gnome_vfs_get_mime_type (url);
+	
+	g_return_val_if_fail (type != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
+	
+	action = gnome_vfs_mime_get_default_action (type);
+	
+	if (action == NULL) {
+		g_free (type);
+		return GNOME_VFS_ERROR_NOT_SUPPORTED;
+	}
+	
+	params.data = (char *) url;
+	params.prev = NULL;
+	params.next = NULL;
+	
+	result = gnome_vfs_mime_action_launch_with_env (action, &params, envp);
+	
+	gnome_vfs_mime_action_free (action);
+	g_free (type);
+	
+	return result;
+}	  
Index: libgnomevfs/gnome-vfs-utils.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-utils.h,v
retrieving revision 1.37
diff -u -p -r1.37 gnome-vfs-utils.h
--- libgnomevfs/gnome-vfs-utils.h	5 Dec 2002 09:42:29 -0000	1.37
+++ libgnomevfs/gnome-vfs-utils.h	11 Mar 2003 02:57:54 -0000
@@ -151,6 +151,10 @@ char * gnome_vfs_make_uri_from_shell_arg
 char * gnome_vfs_make_uri_full_from_relative (const char *base_uri,
 					      const char *relative_uri);
 
+GnomeVFSResult gnome_vfs_url_show          (const char  *url);
+GnomeVFSResult gnome_vfs_url_show_with_env (const char  *url, 
+                                            char       **envp);
+
 G_END_DECLS
 
 #endif /* GNOME_VFS_UTILS_H */
Index: schemas/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-vfs/schemas/Makefile.am,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile.am
--- schemas/Makefile.am	19 Feb 2003 09:50:06 -0000	1.2
+++ schemas/Makefile.am	11 Mar 2003 02:57:54 -0000
@@ -1,6 +1,7 @@
 schemadir   = $(GCONF_SCHEMA_FILE_DIR)
 schema_DATA = \
-	system_http_proxy.schemas
+	system_http_proxy.schemas,
+	desktop_default_applications.schemas
 
 # don't do this if we are building in eg. rpm
 if GCONF_SCHEMAS_INSTALL
Index: libnautilus-private/nautilus-global-preferences.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-global-preferences.h,v
retrieving revision 1.116
diff -u -p -r1.116 nautilus-global-preferences.h
--- libnautilus-private/nautilus-global-preferences.h	2 Mar 2003 02:34:52 -0000	1.116
+++ libnautilus-private/nautilus-global-preferences.h	11 Mar 2003 02:58:36 -0000
@@ -33,6 +33,9 @@ G_BEGIN_DECLS
 /* Which theme is active */
 #define NAUTILUS_PREFERENCES_THEME				"/desktop/gnome/file_views/icon_theme"
 
+/* Should we use an external component viewer */
+#define NAUTILUS_PREFERENCES_USE_EXTERNAL_VIEWER		"/desktop/gnome/applications/component_viewer/always_use_viewer"
+
 /* Desktop Background options */
 #define NAUTILUS_PREFERENCES_BACKGROUND_SET                     "preferences/background_set" 
 #define NAUTILUS_PREFERENCES_BACKGROUND_COLOR                   "preferences/background_color" 
Index: libnautilus-private/nautilus-program-chooser.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-chooser.c,v
retrieving revision 1.81
diff -u -p -r1.81 nautilus-program-chooser.c
--- libnautilus-private/nautilus-program-chooser.c	7 Nov 2002 19:20:39 -0000	1.81
+++ libnautilus-private/nautilus-program-chooser.c	11 Mar 2003 02:58:37 -0000
@@ -1597,27 +1597,87 @@ nautilus_program_chooser_show_no_choices
 	if (action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) {
 		unavailable_message = g_strdup_printf (_("No viewers are available for \"%s\"."), file_name);
 		dialog_title = g_strdup (_("No Viewers Available"));
-	} else {
-		g_assert (action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION);
+	} else if (action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) {
 		unavailable_message = g_strdup_printf (_("There is no application associated with \"%s\"."), file_name);
 		dialog_title = g_strdup (_("No Application Associated"));
-	}
+	} else {
+		unavailable_message = g_strdup_printf (_("There is no action associated with \"%s\"."), file_name);
+		dialog_title = g_strdup (_("No Action Associated"));
+	}		
 
 	/* Note: This might be misleading in the components case, since the
 	 * user can't add components to the complete list even from the capplet.
 	 * (They can add applications though.)
 	 */
+	if (action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT ||
+	    action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) {
+		prompt = g_strdup_printf (_("%s\n\n"
+					    "You can configure GNOME to associate applications "
+					    "with file types. Do you want to associate an "
+					    "application with this file type now?"),
+					  unavailable_message);
+	
+		dialog = eel_show_yes_no_dialog 
+			(prompt, dialog_title, _("Associate Application"), GTK_STOCK_CANCEL, parent_window);
+		
+	} else {
+		prompt = g_strdup_printf (_("%s\n\n"
+					    "You can configure GNOME to associate applications "
+					    "with file types or view files using a viewer. "
+					    "Do you want to associate an application or viewer "
+					    "with this file type now?"),
+					  unavailable_message);	
+
+		dialog = eel_show_yes_no_dialog 
+			(prompt, dialog_title, _("Associate Action"), GTK_STOCK_CANCEL, parent_window);
+	}
+	
+	g_signal_connect_object (dialog, "response",
+	G_CALLBACK (launch_mime_capplet_on_ok),
+	file, 0);
+
+	g_free (unavailable_message);
+	g_free (file_name);
+	g_free (prompt);
+	g_free (dialog_title);
+}
+
+void
+nautilus_program_chooser_show_invalid_message (GnomeVFSMimeActionType action_type,
+					       NautilusFile *file, 
+					       GtkWindow *parent_window)
+{
+	char *prompt;
+	char *unavailable_message;
+	char *file_name;
+	char *dialog_title;
+	GtkDialog *dialog;
+
+	file_name = get_file_name_for_display (file);
+
+	if (action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) {
+		unavailable_message = g_strdup_printf (_("The viewer associated with \"%s\" is invalid."), file_name);
+		dialog_title = g_strdup (_("No Viewers Available"));
+	} else if (action_type == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) {
+		unavailable_message = g_strdup_printf (_("The application associated with \"%s\" is invalid."), file_name);
+		dialog_title = g_strdup (_("No Application Associated"));
+	} else {
+		unavailable_message = g_strdup_printf (_("The action associated with \"%s\" is invalid."), file_name);
+		dialog_title = g_strdup (_("No Action Associated"));
+	}		
+
 	prompt = g_strdup_printf (_("%s\n\n"
-				    "You can configure GNOME to associate applications "
-				    "with file types.  Do you want to associate an "
-				    "application with this file type now?"),
+				    "You can configure GNOME to associate a different application "
+				    "or viewer with this file type. Do you want to associate an "
+				    "application or viewer with this file type now?"),
 				  unavailable_message);
-	dialog = eel_show_yes_no_dialog 
-		(prompt, dialog_title, _("Associate Application"), GTK_STOCK_CANCEL, parent_window);
 
+	dialog = eel_show_yes_no_dialog 
+		(prompt, dialog_title, _("Associate Action"), GTK_STOCK_CANCEL, parent_window);
+	
 	g_signal_connect_object (dialog, "response",
-		G_CALLBACK (launch_mime_capplet_on_ok),
-		file, 0);
+	G_CALLBACK (launch_mime_capplet_on_ok),
+	file, 0);
 
 	g_free (unavailable_message);
 	g_free (file_name);
Index: libnautilus-private/nautilus-program-chooser.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-chooser.h,v
retrieving revision 1.8
diff -u -p -r1.8 nautilus-program-chooser.h
--- libnautilus-private/nautilus-program-chooser.h	4 Feb 2003 10:36:06 -0000	1.8
+++ libnautilus-private/nautilus-program-chooser.h	11 Mar 2003 02:58:37 -0000
@@ -65,4 +65,8 @@ void			 nautilus_program_chooser_show_no
 									   NautilusFile	  	  *file,
 									   GtkWindow		  *parent_window);
 
+void			 nautilus_program_chooser_show_invalid_message    (GnomeVFSMimeActionType action_type,
+									   NautilusFile *file, 
+									   GtkWindow *parent_window);
+
 #endif /* NAUTILUS_PROGRAM_CHOOSER_H */
Index: libnautilus-private/nautilus-program-choosing.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-choosing.c,v
retrieving revision 1.64
diff -u -p -r1.64 nautilus-program-choosing.c
--- libnautilus-private/nautilus-program-choosing.c	7 Nov 2002 19:20:40 -0000	1.64
+++ libnautilus-private/nautilus-program-choosing.c	11 Mar 2003 02:58:37 -0000
@@ -41,6 +41,7 @@
 #include <libgnome/gnome-i18n.h>
 #include <libgnome/gnome-util.h>
 #include <libgnome/gnome-desktop-item.h>
+#include <libgnome/gnome-url.h>
 #include <libgnomeui/gnome-uidefs.h>
 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
@@ -527,6 +528,146 @@ application_cannot_open_location (GnomeV
 }
 
 /**
+ * nautilus_launch_show_file:
+ *
+ * Shows a file using gnome_url_show.
+ *
+ * @file: the file whose uri will be shown.
+ * @parent_window: window to use as parent for error dialog.
+ */
+void nautilus_launch_show_file (NautilusFile *file,
+                                GtkWindow *parent_window)
+{
+	GError     *error;
+	GdkScreen  *screen;
+	gboolean    result;
+	char      **envp;
+	char       *uri;
+
+	uri = NULL;
+	error = NULL;
+	
+	if (nautilus_file_is_nautilus_link (file)) {
+		uri = nautilus_file_get_activation_uri (file);
+	}
+	
+	if (uri == NULL) {
+		uri = nautilus_file_get_uri (file);
+	}
+
+	screen = gtk_window_get_screen (parent_window);
+	envp = egg_screen_exec_environment (screen);	
+	
+	result = gnome_url_show_with_env (uri, envp, &error);
+	
+	if (!result) {
+		if (error != NULL &&
+		    error->code == GNOME_URL_ERROR_NO_DEFAULT) {
+
+			nautilus_program_chooser_show_no_choices_message
+						(GNOME_VFS_MIME_ACTION_TYPE_NONE,
+						 file, parent_window);
+		} else {
+			
+			nautilus_program_chooser_show_invalid_message
+						(GNOME_VFS_MIME_ACTION_TYPE_NONE,
+						 file, parent_window);
+		}
+
+		if (error != NULL) {
+			g_error_free (error);
+		}
+	}
+	
+
+	g_strfreev (envp);
+	g_free (uri);
+}
+
+/**
+ * nautilus_launch_action:
+ *
+ * Forks off a process to launch the action with a given file
+ * as a parameter. Provide parent window for error dialogs.
+ *
+ * @action: the action to launch
+ * @file: the file whose location should be passed as a parameter.
+ * @parent_window: window to use as parent for error dialogs.
+ */
+void nautilus_launch_action (GnomeVFSMimeAction *action,
+                             NautilusFile *file,
+			     GtkWindow *parent_window)
+{
+	GdkScreen      *screen;
+	GnomeVFSResult  result;
+	GList           uris;
+	char           *uri;
+	char          **envp;
+	
+	switch (action->action_type) {
+	case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION:
+		
+		nautilus_launch_application (action->action.application, file, parent_window);
+		
+		break;
+		
+	case GNOME_VFS_MIME_ACTION_TYPE_COMPONENT:
+
+		uri = NULL;
+		if (nautilus_file_is_nautilus_link (file)) {
+			uri = nautilus_file_get_activation_uri (file);
+		}
+		
+		if (uri == NULL) {
+			uri = nautilus_file_get_uri (file);
+		}
+
+		uris.next = NULL;
+		uris.prev = NULL;
+		uris.data = uri;
+		
+		screen = gtk_window_get_screen (parent_window);
+		envp = egg_screen_exec_environment (screen);	
+		
+		result = gnome_vfs_mime_action_launch_with_env (action, &uris, envp);
+		
+		switch (result) {
+		case GNOME_VFS_OK:
+			break;
+			
+		case GNOME_VFS_ERROR_BAD_PARAMETERS:
+			eel_show_error_dialog
+				(_("There was an error launching the component associated "
+				   "with this file. The component viewer specified in the "
+				   "configuration database is invalid."),
+				 _("Error launching action"),
+				 parent_window);
+				 
+			break;
+			
+		default:
+			eel_show_error_dialog
+				(_("There was an unknown error launching the component "
+				   "associated with this file."),
+				 _("Error launching action"),
+				 parent_window);
+		}
+		
+		g_strfreev (envp);
+		g_free (uri);
+
+		break;
+		
+	default:
+		eel_show_error_dialog
+			(_("Error launching the default action associated with this "
+			 "file. The action type is not supported."),
+			 _("Error launching action."),
+			 parent_window);
+	}	 
+}
+
+/**
  * nautilus_launch_application:
  * 
  * Fork off a process to launch an application with a given file as a
@@ -541,9 +682,12 @@ nautilus_launch_application (GnomeVFSMim
 			     NautilusFile *file,
 			     GtkWindow *parent_window)
 {
-	GdkScreen *screen;
-	char      *parameter;
-	char      *uri_scheme, *uri;
+	GdkScreen       *screen;
+	char            *parameter;
+	char            *uri_scheme, *uri;
+	GList            uris;
+	char           **envp;
+	GnomeVFSResult   result;
 
 	uri_scheme = nautilus_file_get_uri_scheme (file);
 
@@ -565,7 +709,20 @@ nautilus_launch_application (GnomeVFSMim
 			g_free (uri_scheme);
 			return;
 		}
-		parameter = nautilus_file_get_uri (file);
+		
+		/* FIXME: this is bad, but for nautilus links we want the activation
+		 * uri not the file uri. So really we should check the activation
+		 * scheme and not the file uri scheme.
+		 */
+		parameter = NULL;
+		
+		if (nautilus_file_is_nautilus_link (file)) {
+			parameter = nautilus_file_get_activation_uri (file);
+		}
+		
+		if (parameter == NULL) {
+			parameter = nautilus_file_get_uri (file);
+		}
 	} else {
 		uri = nautilus_file_get_uri (file);
 		parameter = gnome_vfs_get_local_path_from_uri (uri);
@@ -589,14 +746,48 @@ nautilus_launch_application (GnomeVFSMim
 	}
 	g_free (uri_scheme);
 
+	uris.next = NULL;
+	uris.prev = NULL;
+	uris.data = parameter;
+	
 	screen = gtk_window_get_screen (parent_window);
+	envp = egg_screen_exec_environment (screen);
+	
+	result = gnome_vfs_mime_application_launch_with_env (application, &uris, envp);
 
-	nautilus_launch_application_from_command (screen,
-						  application->name,
-						  application->command,
-						  parameter, 
-						  application->requires_terminal);
+	switch (result) {
+	case GNOME_VFS_OK:
+		break;
+		
+	case GNOME_VFS_ERROR_BAD_PARAMETERS:
+		eel_show_error_dialog
+			(_("There was an error launching the default application associated "
+			   "with this file. The application does not support this protocol."), 
+			 _("Error launching application"),
+			 parent_window);
+			 
+		break;
+				
+	case GNOME_VFS_ERROR_INTERNAL:
+		eel_show_error_dialog
+			(_("There was an error launching the default application associated "
+			   "with this file. The application command is in an invalid format."), 
+			 _("Error launching application"),
+			 parent_window);
+			 
+		break;
+	
+	default:
+		eel_show_error_dialog
+			(_("There was an unknown error launching the default application associated "
+			   "with this file."), 
+			 _("Error launching application"),
+			 parent_window);
+			 
+		break;
+	}
 
+	g_strfreev (envp);
 	g_free (parameter);
 }
 
Index: libnautilus-private/nautilus-program-choosing.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-choosing.h,v
retrieving revision 1.16
diff -u -p -r1.16 nautilus-program-choosing.h
--- libnautilus-private/nautilus-program-choosing.h	2 Oct 2002 05:36:50 -0000	1.16
+++ libnautilus-private/nautilus-program-choosing.h	11 Mar 2003 02:58:37 -0000
@@ -53,6 +53,9 @@ void nautilus_choose_component_for_file 
 void nautilus_cancel_choose_component_for_file   (NautilusFile                      *file,
 						  NautilusComponentChoiceCallback    callback,
 						  gpointer                           callback_data);
+void nautilus_launch_action                      (GnomeVFSMimeAction                *action,
+                                                  NautilusFile                      *file,
+						  GtkWindow                         *parent_window);
 void nautilus_launch_application                 (GnomeVFSMimeApplication           *application,
 						  NautilusFile                      *file,
 						  GtkWindow                         *parent_window);
@@ -65,5 +68,7 @@ void nautilus_launch_desktop_file		 (Gdk
 						  const char                        *desktop_file_uri,
 						  const GList                       *parameter_uris,
 						  GtkWindow                         *parent_window);
-
+void nautilus_launch_show_file                   (NautilusFile                      *file,
+                                                  GtkWindow                         *parent_window);
+						  
 #endif /* NAUTILUS_PROGRAM_CHOOSING_H */
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.563
diff -u -p -r1.563 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	28 Feb 2003 15:15:04 -0000	1.563
+++ src/file-manager/fm-directory-view.c	11 Mar 2003 02:58:38 -0000
@@ -181,6 +181,7 @@ static GdkAtom copied_files_atom;
 static gboolean show_delete_command_auto_value;
 static gboolean confirm_trash_auto_value;
 static gboolean use_new_window_auto_value;
+static gboolean use_external_viewer_auto_value;
 
 static char *scripts_directory_uri;
 static int scripts_directory_uri_length;
@@ -589,9 +590,11 @@ fm_directory_view_launch_application (Gn
 	g_assert (FM_IS_DIRECTORY_VIEW (directory_view));
 
 	nautilus_launch_application
-		(application, file, fm_directory_view_get_containing_window (directory_view));
-	
+			(application, file, 
+			 fm_directory_view_get_containing_window (directory_view));
+
 	uri = nautilus_file_get_uri (file);
+
 	egg_recent_model_add (nautilus_recent_get_model (), uri);
 
 	g_free (uri);
@@ -1282,6 +1285,8 @@ fm_directory_view_init (FMDirectoryView 
 						  &show_delete_command_auto_value);
 		eel_preferences_add_auto_boolean (NAUTILUS_PREFERENCES_WINDOW_ALWAYS_NEW,
 						  &use_new_window_auto_value);
+		eel_preferences_add_auto_boolean (NAUTILUS_PREFERENCES_USE_EXTERNAL_VIEWER,
+						  &use_external_viewer_auto_value);
 	}
 
 	view->details = g_new0 (FMDirectoryViewDetails, 1);
@@ -5068,7 +5073,7 @@ activate_callback (NautilusFile *file, g
 	FMDirectoryView *view;
 	char *uri, *file_uri;
 	char *executable_path, *quoted_path, *name;
-	GnomeVFSMimeApplication *application;
+	GnomeVFSMimeAction *launch_action;
 	ActivationAction action;
 	GdkScreen *screen;
 	
@@ -5143,32 +5148,20 @@ activate_callback (NautilusFile *file, g
 	}
 
 	if (action == ACTIVATION_ACTION_DISPLAY) {
-		/* BADHACK(tm) to make desktop web links work */
-		if (nautilus_file_is_nautilus_link (file) &&
-		    uri != NULL &&
-		    (eel_str_has_prefix (uri, "http:") ||
-		     eel_str_has_prefix (uri, "https:"))) {
-			gnome_url_show (uri, NULL);
+	
+		launch_action = nautilus_mime_get_default_action_for_file (file);
+
+		if (launch_action != NULL &&
+		    launch_action->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT &&
+		    !use_external_viewer_auto_value) {
+			open_location (view, uri, parameters->choice);
 		} else {
-			if (nautilus_mime_get_default_action_type_for_file (file)
-			    == GNOME_VFS_MIME_ACTION_TYPE_APPLICATION) {
-				application = nautilus_mime_get_default_application_for_file (file);
-			} else {
-				/* If the action type is unspecified, treat it like
-				 * the component case. This is most likely to happen
-				 * (only happens?) when there are no registered
-				 * viewers or apps, or there are errors in the
-				 * mime.keys files.
-				 */
-				application = NULL;
-			}
-			
-			if (application != NULL) {
-				fm_directory_view_launch_application (application, file, view);
-				gnome_vfs_mime_application_free (application);
-			} else {
-				open_location (view, uri, parameters->choice);
-			}
+			nautilus_launch_show_file
+				(file, fm_directory_view_get_containing_window (view));
+		}
+		
+		if (launch_action != NULL) {
+			gnome_vfs_mime_action_free (launch_action);		
 		}
 	}
 
Index: libgnome/gnome-url.c
===================================================================
RCS file: /cvs/gnome/libgnome/libgnome/gnome-url.c,v
retrieving revision 1.45
diff -u -p -r1.45 gnome-url.c
--- libgnome/gnome-url.c	16 Oct 2002 03:51:36 -0000	1.45
+++ libgnome/gnome-url.c	11 Mar 2003 03:17:38 -0000
@@ -33,6 +33,8 @@
 #include "gnome-i18nP.h"
 
 #include <gconf/gconf-client.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
 
 #include "gnome-exec.h"
 #include "gnome-util.h"
@@ -45,95 +47,73 @@
 #include <popt.h>
 
 #define URL_HANDLER_DIR      "/desktop/gnome/url-handlers/"
-#define DEFAULT_HANDLER_PATH "/desktop/gnome/url-handlers/unknown/command"
 
-/**
- * gnome_url_show_with_env:
- * @url: The url to display. Should begin with the protocol to use (e.g.
- * "http:", "ghelp:", etc)
- * @envp: child's environment, or %NULL to inherit parent's.
- * @error: Used to store any errors that result from trying to display the @url.
- *
- * Description: Like gnome_url_show(), but the the contents of @envp
- * will become the url viewer's environment rather than inheriting
- * from the parents environment.
- *
- * Returns: %TRUE if everything went fine, %FALSE otherwise (in which case
- * @error will contain the actual error).
- */
-gboolean
-gnome_url_show_with_env (const char  *url,
-			 char       **envp,
-			 GError     **error)
+static gboolean
+use_handler_for_scheme (const char *scheme)
 {
 	GConfClient *client;
-	gint i;
-	gchar *pos, *template;
-	int argc;
-	char **argv;
 	gboolean ret;
+	char *path;
 	
-	g_return_val_if_fail (url != NULL, FALSE);
-
-	pos = strchr (url, ':');
-
-	/* init our gconf stuff if necessary */
 	gnome_gconf_lazy_init ();
 	
 	client = gconf_client_get_default ();
+	path = g_strconcat (URL_HANDLER_DIR, scheme, "/enabled", NULL);
+	ret = gconf_client_get_bool (client, path, NULL);
+	
+	g_free (path);
+	g_object_unref (G_OBJECT (client));
+	
+	return ret;
+}
 
-	if (pos != NULL) {
-		gchar *protocol, *path;
-		
-		g_return_val_if_fail (pos >= url, FALSE);
-
-		protocol = g_new (gchar, pos - url + 1);
-		strncpy (protocol, url, pos - url);
-		protocol[pos - url] = '\0';
-		g_ascii_strdown (protocol, -1);
-
-		path = g_strconcat (URL_HANDLER_DIR, protocol, "/command", NULL);
-		template = gconf_client_get_string (client, path, NULL);
 
-		if (template == NULL) {
-			gchar* template_temp;
+static gboolean
+launch_handler_for_scheme (const char *scheme, 
+                           const char *url,
+			   char      **envp,
+			   GError **error)
+{
+	GConfClient *client;
+	char *path;
+	char *template;
+	char **argv;
+	int argc;
+	int i;
+	gboolean ret;
 			
-			template_temp = gconf_client_get_string (client,
-								 DEFAULT_HANDLER_PATH,
-								 NULL);
-						
-			/* Retry to get the right url handler */
-			template = gconf_client_get_string (client, path, NULL);
-
-			if (template == NULL) 
-				template = template_temp;
-			else
-				g_free (template_temp);
-
-		}
-		
-		g_free (path);
-		g_free (protocol);
-
-	} else {
-		/* no ':' ? this shouldn't happen. Use default handler */
-		template = gconf_client_get_string (client, 
-						    DEFAULT_HANDLER_PATH, 
-						    NULL);
-	}
-
-	g_object_unref (G_OBJECT (client));
+	gnome_gconf_lazy_init ();
 
+	client = gconf_client_get_default ();
+	path = g_strconcat (URL_HANDLER_DIR, scheme, "/command", NULL);
+	template = gconf_client_get_string (client, path, NULL);
+	g_free (path);
+	
 	if (!g_shell_parse_argv (template,
 				 &argc,
 				 &argv,
 				 error)) {
+		
+		g_set_error (error,
+		             GNOME_URL_ERROR,
+			     GNOME_URL_ERROR_PARSE,
+			     _("Unable to parse URL handler: %s"),
+			     template);
+
 		g_free (template);
 		return FALSE;
 	}
 
 	g_free (template);
 
+	path = g_strconcat (URL_HANDLER_DIR, scheme, "/needs_terminal", NULL);
+	if (gconf_client_get_bool (client, path, NULL)) {
+		gnome_prepend_terminal_to_vector (&argc, &argv);
+	}
+	g_free (path);
+	
+	g_object_unref (G_OBJECT (client));
+
 	for (i = 0; i < argc; i++) {
 		char *arg;
 
@@ -144,8 +124,7 @@ gnome_url_show_with_env (const char  *ur
 		argv[i] = g_strdup (url);
 		g_free (arg);
 	}
-	
-	/* This can return some errors */
+
 	ret = g_spawn_async (NULL /* working directory */,
 			     argv,
 			     envp,
@@ -154,32 +133,187 @@ gnome_url_show_with_env (const char  *ur
 			     NULL /* data */,
 			     NULL /* child_pid */,
 			     error);
-
 	g_strfreev (argv);
 
+	if (!ret) {
+		g_set_error (
+			error,
+			GNOME_URL_ERROR,
+			GNOME_URL_ERROR_LAUNCH,
+			_("Error launching default URL handler."));
+	}
+
 	return ret;
 }
 
 /**
+ * gnome_url_get_from_input:
+ * @in: a relative or absolute path
+ *
+ * Determines a fully qualified URL from a relative or absolute input path.
+ * If the path contains a ':' it assumes the path is a valid url and simply
+ * returns the result of gnome_vfs_make_uri_canconical.
+ * If the path is not absolute it checks to see if it exists relative to
+ * the current directory and the user's home directory. If it doesn't then
+ * it converts it into a http url.
+ *
+ * Return value: the fully qualified URL
+ *
+ * Since: 2.4
+ */
+char *
+gnome_url_get_from_input (const char *in)
+{
+	char *path = NULL;
+	char *temp;
+ 
+	if (strchr (in, ':') == NULL) {
+		if (!g_file_test (in, G_FILE_TEST_EXISTS) && in[0] != '/') {
+		
+			temp = g_get_current_dir ();
+			path = g_build_filename (temp, in, NULL);
+			g_free (temp);
+
+			if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+				g_free (path);
+				path = g_build_filename (g_get_home_dir (), in, NULL);				
+			
+				if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+					g_free (path);
+					path = NULL;
+				}
+			}
+		}
+		
+		if (path != NULL) {
+			temp = g_strconcat ("file://", path, NULL);
+			g_free (path);
+		} else {
+			temp = g_strconcat ("http://";, path, NULL);
+			g_free (path);
+		}
+	} else {
+		temp = (char *) in;
+	}
+	
+	return gnome_vfs_make_uri_canonical (temp);
+}
+
+/**
+ * gnome_url_show_with_env:
+ * @url: The url or path to display.
+ * @envp: child's environment, or %NULL to inherit parent's.
+ * @error: Used to store any errors that result from trying to display the @url.
+ *
+ * Description: Like gnome_url_show(), but the contents of @envp
+ * will become the url viewer's environment rather than inheriting
+ * from the parents environment.
+ *
+ * Returns: %TRUE if everything went fine, %FALSE otherwise (in which case
+ * @error will contain the actual error).
+ */
+gboolean
+gnome_url_show_with_env (const char  *in,
+                         char       **envp,
+			 GError     **error)
+{
+	GnomeVFSURI *uri;
+	GnomeVFSResult result;
+	char *url;
+	char *scheme;
+	gboolean ret;
+
+	g_return_val_if_fail (in != NULL, FALSE);
+
+	url = gnome_url_get_from_input (in);
+
+	g_warning ("got url: %s", url);
+	
+	uri = gnome_vfs_uri_new (url);
+
+	if (uri == NULL) {
+		g_set_error (error,
+			     GNOME_URL_ERROR,
+			     GNOME_URL_ERROR_INVALID_URL,
+			     _("The URL could not be parsed."));
+			     
+		g_free (url);
+		return FALSE;
+	}
+		
+	scheme = g_strdup (gnome_vfs_uri_get_scheme (uri));
+	gnome_vfs_uri_unref (uri);
+
+	/* check if this scheme requires special handling */
+	if (use_handler_for_scheme (scheme)) {
+		ret = launch_handler_for_scheme (scheme, url, envp, error);
+
+		g_free (url);
+		g_free (scheme);
+		return ret;
+	}
+
+	result = gnome_vfs_url_show_with_env (url, envp);
+	
+	if (result != GNOME_VFS_OK) {
+		switch (result) {
+		case GNOME_VFS_ERROR_INTERNAL:
+			g_set_error (error,
+			             GNOME_URL_ERROR,
+				     GNOME_URL_ERROR_PARSE,
+				     _("The default action type is invalid or the default application "
+				       "command is in an invalid format."));
+			break;
+			
+		case GNOME_VFS_ERROR_BAD_PARAMETERS:
+			g_set_error (error,
+				     GNOME_URL_ERROR,
+				     GNOME_URL_ERROR_INVALID_PROTOCOL,
+				     _("The default action does not support this protocol."));
+			break;
+			
+		case GNOME_VFS_ERROR_NOT_SUPPORTED:
+			g_set_error (error,
+				     GNOME_URL_ERROR,
+				     GNOME_URL_ERROR_NO_DEFAULT,
+				     _("There is no default action associated with this file type."));
+			break;
+				     
+		default:
+			g_set_error (error,
+				     GNOME_URL_ERROR,
+				     GNOME_URL_ERROR_VFS,
+				     _("Unknown error code: %d"), result);
+		}
+
+		g_free (url);
+		g_free (scheme);
+		return FALSE;
+	}
+
+	g_free (url);
+	g_free (scheme);
+	return TRUE;
+ }
+
+
+/**
  * gnome_url_show:
- * @url: The url to display. Should begin with the protocol to use (e.g.
- * "http:", "ghelp:", etc)
+ * @url: The url or path to display. The path can be relative to the current working
+ * directory or the user's home directory. This function will convert it into a fully
+ * qualified url using the gnome_url_get_from_input function.
  * @error: Used to store any errors that result from trying to display the @url.
  *
- * Displays the given URL in an appropriate viewer. The appropriate viewer is
- * user definable. It is determined by extracting the protocol from the @url,
- * then seeing if the /desktop/gnome/url-handlers/&lt;protocol&gt;/command key
- * exists in the configuration database. It it does, this entry is used as the
- * template for the command. 
- *
- * If no protocol specific handler exists, the
- * /desktop/gnome/url-handlers/unknown/command key is used to determine the
- * viewer.
+ * Displays the given URL in an appropriate viewer. This is either the default
+ * application or a user defined handler. The handler is determined by extracting
+ * the protocol from the @url, then seeing if the 
+ * /desktop/gnome/url-handlers/&lt;protocol&gt;/command key exists in the
+ * configuration database. It it does, this entry is used as the template
+ * for the command if the enabled key is set to true.
  *
  * Once a viewer is determined, it is called with the @url as a parameter. If
  * any errors occur, they are returned in the @error parameter. These errors
- * will either be in the %GNOME_URL_ERROR, %GNOME_SHELL_ERROR, or
- * %G_SPAWN_ERROR domains.
+ * will be in the %GNOME_URL_ERROR domain.
  *
  * Returns: %TRUE if everything went fine, %FALSE otherwise (in which case
  * @error will contain the actual error).
Index: libgnome/gnome-url.h
===================================================================
RCS file: /cvs/gnome/libgnome/libgnome/gnome-url.h,v
retrieving revision 1.18
diff -u -p -r1.18 gnome-url.h
--- libgnome/gnome-url.h	16 Oct 2002 03:51:36 -0000	1.18
+++ libgnome/gnome-url.h	11 Mar 2003 03:17:38 -0000
@@ -37,34 +37,27 @@ G_BEGIN_DECLS
  * gnome_url_show().
  */
 typedef enum {
-  GNOME_URL_ERROR_PARSE
+  GNOME_URL_ERROR_INPUT,
+  GNOME_URL_ERROR_PARSE,
+  GNOME_URL_ERROR_LAUNCH,
+  GNOME_URL_ERROR_NO_DEFAULT,
+  GNOME_URL_ERROR_INVALID_URL,
+  GNOME_URL_ERROR_INVALID_PROTOCOL,
+  GNOME_URL_ERROR_VFS
 } GnomeURLError;
 
 #define GNOME_URL_ERROR (gnome_url_error_quark ())
-GQuark gnome_url_error_quark (void) G_GNUC_CONST;
+GQuark   gnome_url_error_quark (void) G_GNUC_CONST;
 
-/* This function displays the given URL in the appropriate viewer.  The
- * Appropriate viewer is user definable, according to these rules:
- *  1) Extract the protocol from URL.  This is defined as everything before
- *     the first colon
- *  2) Check if the key /desktop/gnome/url-handlers/<protocol>-show exists in the
- *     gnome config database.  If it does, use use this as a command
- *     template.  If it doesn't, check for the key
- *     /desktop/gnome/url-handlers/default-show, and if that doesn't exist fallback
- *     on the compiled in default.
- *  3) substitute the %s in the template with the URL.
- *  4) call gnome_execute_shell, with this expanded command as the second
- *     argument.
- */
 
-/* returns FALSE on error, TRUE if everything went fine */
-/* Errors returned are either the GNOME_URL_ERROR_ ones or G_SPAWN_ERROR_ ones */
-gboolean gnome_url_show          (const char  *url,
-				  GError     **error);
+char *   gnome_url_get_from_input (const char *in);
 
-gboolean gnome_url_show_with_env (const char  *url,
-				  char       **envp,
-				  GError     **error);
+gboolean gnome_url_show           (const char  *url,
+				   GError     **error);
+
+gboolean gnome_url_show_with_env  (const char  *url,
+				   char       **envp,
+				   GError     **error);
 
 G_END_DECLS
 #endif
Index: schemas/Makefile.am
===================================================================
RCS file: /cvs/gnome/libgnome/schemas/Makefile.am,v
retrieving revision 1.14
diff -u -p -r1.14 Makefile.am
--- schemas/Makefile.am	9 Jan 2003 11:59:14 -0000	1.14
+++ schemas/Makefile.am	11 Mar 2003 03:17:38 -0000
@@ -5,7 +5,6 @@ schema_in_files = \
 	desktop_gnome_accessibility_keyboard.schemas.in		\
 	desktop_gnome_applications_browser.schemas.in		\
 	desktop_gnome_applications_help_viewer.schemas.in		\
-	desktop_gnome_applications_terminal.schemas.in		\
 	desktop_gnome_applications_window_manager.schemas.in	\
 	desktop_gnome_file_views.schemas.in			\
 	desktop_gnome_interface.schemas.in				\
Index: schemas/desktop_gnome_url_handlers.schemas.in
===================================================================
RCS file: /cvs/gnome/libgnome/schemas/desktop_gnome_url_handlers.schemas.in,v
retrieving revision 1.3
diff -u -p -r1.3 desktop_gnome_url_handlers.schemas.in
--- schemas/desktop_gnome_url_handlers.schemas.in	1 Oct 2002 09:17:31 -0000	1.3
+++ schemas/desktop_gnome_url_handlers.schemas.in	11 Mar 2003 03:17:38 -0000
@@ -3,40 +3,6 @@
   <schemalist>
 
     <schema>   
-      <key>/schemas/desktop/gnome/url-handlers/unknown/enabled</key>
-      <applyto>/desktop/gnome/url-handlers/unknown/enabled</applyto>
-      <owner>gnome</owner>
-      <type>bool</type>
-      <default>true</default>
-      <locale name="C">
-        <short>How to handle unknown URLs</short>
-        <long>Set to true to have a program specified in programs/unknown handle unknown URLs</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/unknown/command</key>
-      <applyto>/desktop/gnome/url-handlers/unknown/command</applyto>
-      <owner>gnome</owner>
-      <type>string</type>
-      <default>mozilla "%s"</default>
-      <locale name="C">
-        <short>Default URL show handler</short>
-        <long>Default URL show handler</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/unknown/need-terminal</key>
-      <applyto>/desktop/gnome/url-handlers/unknown/need-terminal</applyto>
-      <owner>gnome</owner>
-      <type>bool</type>
-      <default>false</default>
-      <locale name="C">
-        <short>Run program in terminal</short>
-        <long>True if the program to handle this URL should be run in a terminal</long>
-      </locale>
-    </schema>
-
-    <schema>   
       <key>/schemas/desktop/gnome/url-handlers/info/enabled</key>
       <applyto>/desktop/gnome/url-handlers/info/enabled</applyto>
       <owner>gnome</owner>
<?xml version="1.0"?>
<gconfschemafile>
  <schemalist>
    <schema>
      <key>/schemas/desktop/gnome/applications/terminal/exec</key>
      <applyto>/desktop/gnome/applications/terminal/exec</applyto>
      <owner>gnome-vfs</owner>
      <type>string</type>
      <default>gnome-terminal</default>
      <locale name="C">
        <short>Default terminal application</short>
        <long>The default terminal application to use for applications that require a terminal.</long>
      </locale>
    </schema>
    <schema>
      <key>/schemas/desktop/gnome/applications/terminal/exec_arg</key>
      <applyto>/desktop/gnome/applications/terminal/exec_arg</applyto>
      <owner>gnome-vfs</owner>
      <type>string</type>
      <default>-x</default>
      <locale name="C">
        <short>Exec argument for default terminal</short>
        <long>The exec argument to use for the default terminal application.</long>
      </locale>
    </schema>
    <schema>
      <key>/schemas/desktop/gnome/applications/component_viewer/exec</key>
      <applyto>/desktop/gnome/applications/component_viewer/exec</applyto>
      <owner>gnome-vfs</owner>
      <type>string</type>
      <default>nautilus %s</default>
      <locale name="C">
        <short>Default component viewer application</short>
        <long>The application to use for viewing files that require a component to view them. The parameter %s will be replaced by the file's URIs, the parameter %c will be replaced by the component IID.</long>
      </locale>
    </schema>
    <schema>
      <key>/schemas/desktop/gnome/applications/component_viewer/always_use_viewer</key>
      <applyto>/desktop/gnome/applications/component_viewer/always_use_viewer</applyto>
      <owner>gnome-vfs</owner>
      <type>bool</type>
      <default>false</default>
      <locale name="C">
        <short>If TRUE the default component viewer should always be used</short>
        <long>If this is set to TRUE an application should always use the default component viewer, even if the application itself supports viewing files with components. For example, if you set this to true and open a file in Nautilus, then Nautilus will use the default component viewer instead of embedding the viewing component in itself. This depends on applications honouring this key. Generally you want this set to FALSE.</long>
      </locale>
    </schema>
  </schemalist>
</gconfschemafile>


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