[gedit] Replace bacon with dbus



commit 9f1f71435c8552526704f2d5c4f85ac93e7a65c9
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sat May 15 09:56:45 2010 +0200

    Replace bacon with dbus

 configure.ac                                       |    7 +-
 data/Makefile.am                                   |    9 +
 data/org.gnome.gedit.service.in                    |    3 +
 gedit/Makefile.am                                  |   20 +-
 gedit/bacon-message-connection.c                   |  397 -----
 gedit/bacon-message-connection.h                   |   44 -
 gedit/gedit-app-osx.c                              |    4 +
 gedit/gedit-app-win32.c                            |    4 +
 gedit/gedit-app-x11.c                              |    2 +
 gedit/gedit-command-line.c                         |  435 +++++
 gedit/gedit-command-line.h                         |   81 +
 gedit/gedit-commands-file.c                        |   81 +-
 gedit/gedit-commands.h                             |    8 +-
 gedit/gedit-dbus.c                                 | 1660 ++++++++++++++++++++
 gedit/gedit-dbus.h                                 |   69 +
 gedit/gedit-document-loader.c                      |  139 ++-
 gedit/gedit-document-loader.h                      |    8 +-
 gedit/gedit-document.c                             |   32 +
 gedit/gedit-document.h                             |    6 +
 gedit/gedit-fifo.c                                 |  411 +++++
 gedit/gedit-fifo.h                                 |   82 +
 gedit/gedit-tab.c                                  |   99 +-
 gedit/gedit-tab.h                                  |   13 +
 gedit/gedit-utils.c                                |   14 +
 gedit/gedit-utils.h                                |    2 +
 gedit/gedit-window.c                               |   90 +-
 gedit/gedit-window.h                               |    9 +-
 gedit/gedit.c                                      |  786 ++--------
 gedit/update-from-bacon.sh                         |   25 -
 plugin-loaders/python/bindings/geditcommands.defs  |    2 +-
 .../python/bindings/geditcommands.override         |   33 +-
 31 files changed, 3340 insertions(+), 1235 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index bc05a17..200898c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,11 +261,6 @@ fi
 AM_CONDITIONAL(ENABLE_ENCHANT, test x"$enable_enchant" = "xyes")
 
 dnl ================================================================
-dnl libsocket checks - needed for bacon-connection on solaris.
-dnl ================================================================
-AC_SEARCH_LIBS(bind, socket)
-
-dnl ================================================================
 dnl Start of pkg-config checks
 dnl ================================================================
 
@@ -286,7 +281,7 @@ PKG_CHECK_MODULES(GEDIT, [
 	libxml-2.0 >= 2.5.0
 	glib-2.0 >= 2.25.0
 	gthread-2.0 >= 2.13.0
-	gio-2.0 >= 2.25.4
+	gio-2.0 >= 2.25.5
 	$GTK_REQUIRED >= $GTK_REQUIRED_VERSION
 	gtksourceview-2.0 >= 2.9.7
 	gconf-2.0 >= 2.31.1
diff --git a/data/Makefile.am b/data/Makefile.am
index 194f4a7..46b354d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -8,6 +8,13 @@ gsettingsschema_DATA = $(gsettingsschema_in_files:.gschema.in=.gschema.xml)
 org.gnome.gedit.gschema.xml: org.gnome.gedit.gschema.in
 	gsettings-schema-convert -f $< -o $@
 
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gnome.gedit.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+	@sed -e "s|\ bindir\@|$(bindir)|" $<> $@
+
 man_MANS = gedit.1
 
 pkgconfigdir = $(libdir)/pkgconfig
@@ -26,6 +33,7 @@ endif
 
 EXTRA_DIST = 				\
 	$(desktop_in_files)		\
+	$(service_in_files)		\
 	$(man_MANS)			\
 	gedit.pc.in			\
 	gedit-bugreport.sh.in		\
@@ -33,6 +41,7 @@ EXTRA_DIST = 				\
 
 CLEANFILES =	 			\
 	$(desktop_DATA)			\
+	$(service_DATA)			\
 	$(pkgconfig_DATA)
 
 
diff --git a/data/org.gnome.gedit.service.in b/data/org.gnome.gedit.service.in
new file mode 100644
index 0000000..9e6d0af
--- /dev/null
+++ b/data/org.gnome.gedit.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.gedit
+Exec= bindir@/gedit
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index 82090db..606fdab 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -92,6 +92,8 @@ BUILT_SOURCES = 			\
 
 NOINST_H_FILES =			\
 	gedit-close-button.h		\
+	gedit-command-line.h		\
+	gedit-dbus.h			\
 	gedit-dirs.h			\
 	gedit-document-input-stream.h	\
 	gedit-document-loader.h		\
@@ -152,9 +154,9 @@ header_DATA = 				\
 
 libgedit_la_SOURCES = 			\
 	$(BUILT_SOURCES)		\
-	$(BACON_FILES)			\
 	gedit-app.c			\
 	gedit-close-button.c		\
+	gedit-command-line.c		\
 	gedit-commands-documents.c	\
 	gedit-commands-edit.c		\
 	gedit-commands-file.c		\
@@ -162,6 +164,7 @@ libgedit_la_SOURCES = 			\
 	gedit-commands-help.c		\
 	gedit-commands-search.c		\
 	gedit-commands-view.c		\
+	gedit-dbus.c			\
 	gedit-debug.c			\
 	gedit-dirs.c			\
 	gedit-document.c 		\
@@ -209,6 +212,11 @@ if !ENABLE_GVFS_METADATA
 libgedit_la_SOURCES += gedit-metadata-manager.c
 endif
 
+if !PLATFORM_WIN32
+libgedit_la_SOURCES += gedit-fifo.c
+NOINST_H_FILES += gedit-fifo.h
+endif
+
 gedit-enum-types.h: gedit-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
 	$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template gedit-enum-types.h.template $(INST_H_FILES)) > $@
 
@@ -248,16 +256,6 @@ else
 	ln -s gedit $(DESTDIR)$(bindir)/gnome-text-editor
 endif
 
-if !OS_WIN32
-BACON_DIR=$(srcdir)/../../libbacon/src/
-BACON_FILES=bacon-message-connection.h bacon-message-connection.c
-
-regenerate-built-sources:
-	BACONFILES="$(BACON_FILES)" BACONDIR="$(BACON_DIR)" $(top_srcdir)/gedit/update-from-bacon.sh
-else
-BACON_DIR=
-endif
-
 if BUILD_MESSAGE_AREA
 libgedit_la_SOURCES += gedit-message-area.c
 INST_H_FILES += gedit-message-area.h
diff --git a/gedit/gedit-app-osx.c b/gedit/gedit-app-osx.c
index af8bf6f..1d1858d 100644
--- a/gedit/gedit-app-osx.c
+++ b/gedit/gedit-app-osx.c
@@ -159,6 +159,10 @@ gedit_app_osx_init (GeditAppOSX *self)
 	                        (GDestroyNotify)destroy_delegate);
 
 	ige_mac_menu_set_global_key_handler_enabled (FALSE);
+
+	/* manually set name and icon */
+	g_set_application_name("gedit");
+	gtk_window_set_default_icon_name ("accessories-text-editor");
 }
 
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-app-win32.c b/gedit/gedit-app-win32.c
index d477968..42885cc 100644
--- a/gedit/gedit-app-win32.c
+++ b/gedit/gedit-app-win32.c
@@ -123,6 +123,10 @@ gedit_app_win32_init (GeditAppWin32 *self)
 {
 	setup_path ();
 	prep_console ();
+
+	/* manually set name and icon */
+	g_set_application_name("gedit");
+	gtk_window_set_default_icon_name ("accessories-text-editor");
 }
 
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-app-x11.c b/gedit/gedit-app-x11.c
index 050ebd1..03c934f 100644
--- a/gedit/gedit-app-x11.c
+++ b/gedit/gedit-app-x11.c
@@ -21,6 +21,7 @@
  */
 
 #include "gedit-app-x11.h"
+#include "eggdesktopfile.h"
 
 #define GEDIT_APP_X11_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_APP_X11, GeditAppX11Private))
 
@@ -43,6 +44,7 @@ gedit_app_x11_class_init (GeditAppX11Class *klass)
 static void
 gedit_app_x11_init (GeditAppX11 *self)
 {
+	egg_set_desktop_file (DATADIR "/applications/gedit.desktop");
 }
 
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-command-line.c b/gedit/gedit-command-line.c
new file mode 100644
index 0000000..4e1ab25
--- /dev/null
+++ b/gedit/gedit-command-line.c
@@ -0,0 +1,435 @@
+/*
+ * gedit-command-line.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include "gedit-command-line.h"
+#include "eggsmclient.h"
+
+#define GEDIT_COMMAND_LINE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_COMMAND_LINE, GeditCommandLinePrivate))
+
+struct _GeditCommandLinePrivate
+{
+	/* These are directly set as options */
+	gchar *line_column_position;
+	gchar *encoding_charset;
+	gchar *geometry;
+	gboolean new_window;
+	gboolean new_document;
+	gchar **remaining_args;
+
+	gboolean wait;
+	gboolean background;
+	gboolean standalone;
+
+	/* This result from post-processing command line arguments */
+	gint line_position;
+	gint column_position;
+	GSList *file_list;
+	const GeditEncoding *encoding;
+};
+
+G_DEFINE_TYPE (GeditCommandLine, gedit_command_line, G_TYPE_INITIALLY_UNOWNED)
+
+static void
+gedit_command_line_finalize (GObject *object)
+{
+	GeditCommandLine *command_line = GEDIT_COMMAND_LINE (object);
+
+	g_free (command_line->priv->encoding_charset);
+	g_free (command_line->priv->line_column_position);
+	g_strfreev (command_line->priv->remaining_args);
+
+	g_free (command_line->priv->geometry);
+
+	g_slist_foreach (command_line->priv->file_list, (GFunc)g_object_unref, NULL);
+	g_slist_free (command_line->priv->file_list);
+
+	G_OBJECT_CLASS (gedit_command_line_parent_class)->finalize (object);
+}
+
+static GObject *
+gedit_command_line_constructor (GType                  gtype,
+                                guint                  n_construct_params,
+                                GObjectConstructParam *construct_params)
+{
+	static GObject *command_line = NULL;
+
+	if (!command_line)
+	{
+		command_line = G_OBJECT_CLASS (gedit_command_line_parent_class)->constructor (gtype,
+		                                                                              n_construct_params,
+		                                                                              construct_params);
+
+		g_object_add_weak_pointer (command_line, (gpointer *) &command_line);
+		return command_line;
+	}
+
+	return g_object_ref (command_line);
+}
+static void
+gedit_command_line_class_init (GeditCommandLineClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gedit_command_line_finalize;
+	object_class->constructor = gedit_command_line_constructor;
+
+	g_type_class_add_private (object_class, sizeof(GeditCommandLinePrivate));
+}
+
+static void
+gedit_command_line_init (GeditCommandLine *self)
+{
+	self->priv = GEDIT_COMMAND_LINE_GET_PRIVATE (self);
+}
+
+GeditCommandLine *
+gedit_command_line_get_default (void)
+{
+	GeditCommandLine *command_line;
+
+	command_line = g_object_new (GEDIT_TYPE_COMMAND_LINE, NULL);
+
+	if (g_object_is_floating (command_line))
+	{
+		g_object_ref_sink (command_line);
+	}
+	else
+	{
+		g_object_unref (command_line);
+	}
+
+	return command_line;
+}
+
+static void
+show_version_and_quit (void)
+{
+	g_print ("%s - Version %s\n", g_get_application_name (), VERSION);
+
+	exit (0);
+}
+
+static void
+list_encodings_and_quit (void)
+{
+	gint i = 0;
+	const GeditEncoding *enc;
+
+	while ((enc = gedit_encoding_get_from_index (i)) != NULL)
+	{
+		g_print ("%s\n", gedit_encoding_get_charset (enc));
+
+		++i;
+	}
+
+	exit (0);
+}
+
+static void
+get_line_column_position (GeditCommandLine *command_line,
+                          const gchar      *arg)
+{
+	gchar **split;
+
+	split = g_strsplit (arg, ":", 2);
+
+	if (split != NULL)
+	{
+		if (split[0] != NULL)
+		{
+			command_line->priv->line_position = atoi (split[0]);
+		}
+
+		if (split[1] != NULL)
+		{
+			command_line->priv->column_position = atoi (split[1]);
+		}
+	}
+
+	g_strfreev (split);
+}
+
+static void
+process_remaining_arguments (GeditCommandLine *command_line)
+{
+	gint i;
+
+	if (!command_line->priv->remaining_args)
+	{
+		return;
+	}
+
+	for (i = 0; command_line->priv->remaining_args[i]; i++)
+	{
+		if (*command_line->priv->remaining_args[i] == '+')
+		{
+			if (*(command_line->priv->remaining_args[i] + 1) == '\0')
+			{
+				/* goto the last line of the document */
+				command_line->priv->line_position = G_MAXINT;
+				command_line->priv->column_position = 0;
+			}
+			else
+			{
+				get_line_column_position (command_line, command_line->priv->remaining_args[i] + 1);
+			}
+		}
+		else
+		{
+			GFile *file;
+
+			file = g_file_new_for_commandline_arg (command_line->priv->remaining_args[i]);
+			command_line->priv->file_list = g_slist_prepend (command_line->priv->file_list, file);
+		}
+	}
+
+	command_line->priv->file_list = g_slist_reverse (command_line->priv->file_list);
+}
+
+static void
+process_command_line (GeditCommandLine *command_line)
+{
+	/* Parse encoding */
+	if (command_line->priv->encoding_charset)
+	{
+		command_line->priv->encoding = gedit_encoding_get_from_charset (command_line->priv->encoding_charset);
+
+		if (command_line->priv->encoding == NULL)
+		{
+			g_print (_("%s: invalid encoding.\n"), command_line->priv->encoding_charset);
+		}
+
+		g_free (command_line->priv->encoding_charset);
+		command_line->priv->encoding_charset = NULL;
+	}
+
+	/* Parse remaining arguments */
+	process_remaining_arguments (command_line);
+}
+
+gboolean
+gedit_command_line_parse (GeditCommandLine   *command_line,
+                          int                *argc,
+                          char             ***argv)
+{
+	GOptionContext *context;
+	GError *error = NULL;
+
+	const GOptionEntry options[] =
+	{
+		/* Version */
+		{
+			"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+			show_version_and_quit, N_("Show the application's version"), NULL
+		},
+
+		/* List available encodings */
+		{
+			"list-encodings", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+			list_encodings_and_quit, N_("Display list of possible values for the encoding option"),
+			NULL
+		},
+
+		/* Encoding */
+		{
+			"encoding", '\0', 0, G_OPTION_ARG_STRING,
+			&command_line->priv->encoding_charset,
+			N_("Set the character encoding to be used to open the files listed on the command line"),
+			N_("ENCODING")
+		},
+
+		/* Open a new window */
+		{
+			"new-window", '\0', 0, G_OPTION_ARG_NONE,
+			&command_line->priv->new_window,
+			N_("Create a new top-level window in an existing instance of gedit"),
+			NULL
+		},
+
+		/* Create a new empty document */
+		{
+			"new-document", '\0', 0, G_OPTION_ARG_NONE,
+			&command_line->priv->new_document,
+			N_("Create a new document in an existing instance of gedit"),
+			NULL
+		},
+
+		/* Window geometry */
+		{
+			"geometry", 'g', 0, G_OPTION_ARG_STRING,
+			&command_line->priv->geometry,
+			N_("Set the X geometry window size (WIDTHxHEIGHT+X+Y)"),
+			N_("GEOMETRY")
+		},
+
+		/* Wait for closing documents */
+		{
+			"wait", 'w', 0, G_OPTION_ARG_NONE,
+			&command_line->priv->wait,
+			N_("Open files and block process until files are closed"),
+			NULL
+		},
+
+		/* Run in the background */
+		{
+			"background", 'b', 0, G_OPTION_ARG_NONE,
+			&command_line->priv->background,
+			N_("Run gedit in the background"),
+			NULL
+		},
+		
+		/* Wait for closing documents */
+		{
+			"standalone", 's', 0, G_OPTION_ARG_NONE,
+			&command_line->priv->standalone,
+			N_("Run gedit in standalone mode"),
+			NULL
+		},
+
+		/* collects file arguments */
+		{
+			G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY,
+			&command_line->priv->remaining_args,
+			NULL,
+			N_("[FILE...] [+LINE[:COLUMN]]")
+		},
+
+		{NULL}
+	};
+
+	/* Setup command line options */
+	context = g_option_context_new (_("- Edit text files"));
+	g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
+	g_option_context_add_group (context, gtk_get_option_group (FALSE));
+	g_option_context_add_group (context, egg_sm_client_get_option_group ());
+
+	gtk_init (argc, argv);
+
+	if (!g_option_context_parse (context, argc, argv, &error))
+	{
+		g_print(_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
+			error->message, (*argv)[0]);
+
+		g_error_free (error);
+		return FALSE;
+	}
+
+	g_option_context_free (context);
+
+	/* Do some post-processing */
+	process_command_line (command_line);
+
+	return TRUE;
+}
+
+gboolean
+gedit_command_line_get_new_window (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), FALSE);
+	return command_line->priv->new_window;
+}
+
+void
+gedit_command_line_set_new_window (GeditCommandLine *command_line,
+                                   gboolean          new_window)
+{
+	g_return_if_fail (GEDIT_IS_COMMAND_LINE (command_line));
+
+	command_line->priv->new_window = new_window;
+}
+
+gboolean
+gedit_command_line_get_new_document (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), FALSE);
+	return command_line->priv->new_document;
+}
+
+gint
+gedit_command_line_get_line_position (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), 0);
+	return command_line->priv->line_position;
+}
+
+gint
+gedit_command_line_get_column_position (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), 0);
+	return command_line->priv->column_position;
+}
+
+GSList *
+gedit_command_line_get_file_list (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), NULL);
+	return command_line->priv->file_list;
+}
+
+const GeditEncoding *
+gedit_command_line_get_encoding (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), NULL);
+	return command_line->priv->encoding;
+}
+
+gboolean
+gedit_command_line_get_wait (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), FALSE);
+	return command_line->priv->wait;
+}
+
+gboolean
+gedit_command_line_get_background (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), FALSE);
+	return command_line->priv->background;
+}
+
+gboolean
+gedit_command_line_get_standalone (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), FALSE);
+	return command_line->priv->standalone;
+}
+
+const gchar *
+gedit_command_line_get_geometry (GeditCommandLine *command_line)
+{
+	g_return_val_if_fail (GEDIT_IS_COMMAND_LINE (command_line), NULL);
+	return command_line->priv->geometry;
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-command-line.h b/gedit/gedit-command-line.h
new file mode 100644
index 0000000..5c7c67b
--- /dev/null
+++ b/gedit/gedit-command-line.h
@@ -0,0 +1,81 @@
+/*
+ * gedit-command-line.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GEDIT_COMMAND_LINE_H__
+#define __GEDIT_COMMAND_LINE_H__
+
+#include <glib-object.h>
+#include <gedit/gedit-encodings.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_COMMAND_LINE			(gedit_command_line_get_type ())
+#define GEDIT_COMMAND_LINE(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_COMMAND_LINE, GeditCommandLine))
+#define GEDIT_COMMAND_LINE_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_COMMAND_LINE, GeditCommandLine const))
+#define GEDIT_COMMAND_LINE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_COMMAND_LINE, GeditCommandLineClass))
+#define GEDIT_IS_COMMAND_LINE(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_COMMAND_LINE))
+#define GEDIT_IS_COMMAND_LINE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_COMMAND_LINE))
+#define GEDIT_COMMAND_LINE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_COMMAND_LINE, GeditCommandLineClass))
+
+typedef struct _GeditCommandLine	GeditCommandLine;
+typedef struct _GeditCommandLineClass	GeditCommandLineClass;
+typedef struct _GeditCommandLinePrivate	GeditCommandLinePrivate;
+
+typedef struct _GeditCommandLineGeometry GeditCommandLineGeometry;
+
+struct _GeditCommandLine {
+	GInitiallyUnowned parent;
+
+	GeditCommandLinePrivate *priv;
+};
+
+struct _GeditCommandLineClass {
+	GObjectClass parent_class;
+};
+
+GType gedit_command_line_get_type (void) G_GNUC_CONST;
+
+GeditCommandLine *gedit_command_line_get_default (void);
+
+gboolean gedit_command_line_parse (GeditCommandLine *command_line, int *argc, char ***argv);
+
+gboolean gedit_command_line_get_new_window (GeditCommandLine *command_line);
+void gedit_command_line_set_new_window (GeditCommandLine *command_line, gboolean new_window);
+
+gboolean gedit_command_line_get_new_document (GeditCommandLine *command_line);
+gint gedit_command_line_get_line_position (GeditCommandLine *command_line);
+gint gedit_command_line_get_column_position (GeditCommandLine *command_line);
+
+GSList *gedit_command_line_get_file_list (GeditCommandLine *command_line);
+const GeditEncoding *gedit_command_line_get_encoding (GeditCommandLine *command_line);
+
+gboolean gedit_command_line_get_wait (GeditCommandLine *command_line);
+gboolean gedit_command_line_get_background (GeditCommandLine *command_line);
+gboolean gedit_command_line_get_standalone (GeditCommandLine *command_line);
+
+const gchar *gedit_command_line_get_geometry (GeditCommandLine *command_line);
+
+G_END_DECLS
+
+#endif /* __GEDIT_COMMAND_LINE_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index 1afeb9f..1a8d0c6 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -118,7 +118,7 @@ is_duplicated_file (GSList *files, GFile *file)
 }
 
 /* File loading */
-static gint
+static GSList *
 load_file_list (GeditWindow         *window,
 		const GSList        *files,
 		const GeditEncoding *encoding,
@@ -127,11 +127,12 @@ load_file_list (GeditWindow         *window,
 		gboolean             create)
 {
 	GeditTab      *tab;
-	gint           loaded_files = 0; /* Number of files to load */
+	GSList        *loaded_files = NULL; /* Number of files to load */
 	gboolean       jump_to = TRUE; /* Whether to jump to the new tab */
 	GList         *win_docs;
 	GSList        *files_to_load = NULL;
 	const GSList  *l;
+	gint num_loaded_files = 0;
 
 	gedit_debug (DEBUG_COMMANDS);
 
@@ -148,24 +149,38 @@ load_file_list (GeditWindow         *window,
 			{
 				if (l == files)
 				{
+					GeditDocument *doc;
+
 					gedit_window_set_active_tab (window, tab);
 					jump_to = FALSE;
+					doc = gedit_tab_get_document (tab);
 
 					if (line_pos > 0)
 					{
-						GeditDocument *doc;
-						GeditView *view;
-
-						doc = gedit_tab_get_document (tab);
-						view = gedit_tab_get_view (tab);
-
 						/* document counts lines starting from 0 */
-						gedit_document_goto_line (doc, line_pos - 1);
-						gedit_view_scroll_to_cursor (view);
+						if (column_pos > 0)
+						{
+							GtkTextIter iter;
+
+							gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc),
+							                                         &iter,
+							                                         line_pos - 1,
+							                                         column_pos - 1);
+
+							gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+						}
+						else
+						{
+							gedit_document_goto_line (doc, line_pos - 1);
+						}
+
+						gedit_view_scroll_to_cursor (gedit_tab_get_view (tab));
 					}
 				}
 
-				++loaded_files;
+				++num_loaded_files;
+				loaded_files = g_slist_prepend (loaded_files,
+				                                gedit_tab_get_document (tab));
 			}
 			else
 			{
@@ -178,8 +193,10 @@ load_file_list (GeditWindow         *window,
 	g_list_free (win_docs);
 
 	if (files_to_load == NULL)
-		return loaded_files;
-	
+	{
+		return g_slist_reverse (loaded_files);
+	}
+
 	files_to_load = g_slist_reverse (files_to_load);
 	l = files_to_load;
 
@@ -206,7 +223,9 @@ load_file_list (GeditWindow         *window,
 			l = g_slist_next (l);
 			jump_to = FALSE;
 
-			++loaded_files;
+			++num_loaded_files;
+			loaded_files = g_slist_prepend (loaded_files,
+			                                gedit_tab_get_document (tab));
 		}
 	}
 
@@ -225,13 +244,18 @@ load_file_list (GeditWindow         *window,
 		if (tab != NULL)
 		{
 			jump_to = FALSE;
-			++loaded_files;
+
+			++num_loaded_files;
+			loaded_files = g_slist_prepend (loaded_files,
+			                                gedit_tab_get_document (tab));
 		}
 
 		l = g_slist_next (l);
 	}
 
-	if (loaded_files == 1)
+	loaded_files = g_slist_reverse (loaded_files);
+
+	if (num_loaded_files == 1)
 	{
 		GeditDocument *doc;
 		gchar *uri_for_display;
@@ -254,8 +278,8 @@ load_file_list (GeditWindow         *window,
 					       window->priv->generic_message_cid,
 					       ngettext("Loading %d file\342\200\246",
 							"Loading %d files\342\200\246",
-							loaded_files),
-					       loaded_files);
+							num_loaded_files),
+					       num_loaded_files);
 	}
 
 	/* Free uris_to_load. Note that l points to the first element of uris_to_load */
@@ -278,6 +302,7 @@ gedit_commands_load_location (GeditWindow         *window,
 {
 	GSList *locations = NULL;
 	gchar *uri;
+	GSList *ret;
 
 	g_return_if_fail (GEDIT_IS_WINDOW (window));
 	g_return_if_fail (G_IS_FILE (location));
@@ -289,7 +314,8 @@ gedit_commands_load_location (GeditWindow         *window,
 
 	locations = g_slist_prepend (locations, location);
 
-	load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
+	ret = load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
+	g_slist_free (ret);
 
 	g_slist_free (locations);
 }
@@ -299,7 +325,7 @@ gedit_commands_load_location (GeditWindow         *window,
  *
  * Ignore non-existing locations 
  */
-gint
+GSList *
 gedit_commands_load_locations (GeditWindow         *window,
 			       const GSList        *locations,
 			       const GeditEncoding *encoding,
@@ -319,7 +345,7 @@ gedit_commands_load_locations (GeditWindow         *window,
  * first doc. Beside specifying a not existing uri creates a
  * titled document.
  */
-gint
+GSList *
 _gedit_cmd_load_files_from_prompt (GeditWindow         *window,
 				   GSList              *files,
 				   const GeditEncoding *encoding,
@@ -349,6 +375,7 @@ open_dialog_response_cb (GeditFileChooserDialog *dialog,
 {
 	GSList *files;
 	const GeditEncoding *encoding;
+	GSList *loaded;
 
 	gedit_debug (DEBUG_COMMANDS);
 
@@ -369,11 +396,13 @@ open_dialog_response_cb (GeditFileChooserDialog *dialog,
 	/* Remember the folder we navigated to */
 	 _gedit_window_set_default_location (window, files->data);
 
-	gedit_commands_load_locations (window,
-				       files,
-				       encoding,
-				       0,
-				       0);
+	loaded = gedit_commands_load_locations (window,
+	                                        files,
+	                                        encoding,
+	                                        0,
+	                                        0);
+
+	g_slist_free (loaded);
 
 	g_slist_foreach (files, (GFunc) g_object_unref, NULL);
 	g_slist_free (files);
diff --git a/gedit/gedit-commands.h b/gedit/gedit-commands.h
index 497e1fb..4f30b01 100644
--- a/gedit/gedit-commands.h
+++ b/gedit/gedit-commands.h
@@ -47,11 +47,11 @@ void		 gedit_commands_load_location		(GeditWindow         *window,
 							 gint                 column_pos);
 
 /* Ignore non-existing URIs */
-gint		 gedit_commands_load_locations		(GeditWindow         *window,
+GSList		*gedit_commands_load_locations		(GeditWindow         *window,
 							 const GSList        *locations,
 							 const GeditEncoding *encoding,
 							 gint                 line_pos,
-							 gint                 column_pos);
+							 gint                 column_pos) G_GNUC_WARN_UNUSED_RESULT;
 
 void		 gedit_commands_save_document		(GeditWindow         *window,
                                                          GeditDocument       *document);
@@ -63,11 +63,11 @@ void		 gedit_commands_save_all_documents 	(GeditWindow         *window);
  */
 
 /* Create titled documens for non-existing URIs */
-gint		_gedit_cmd_load_files_from_prompt	(GeditWindow         *window,
+GSList	        *_gedit_cmd_load_files_from_prompt	(GeditWindow         *window,
 							 GSList              *files,
 							 const GeditEncoding *encoding,
 							 gint                 line_pos,
-							 gint                 column_pos);
+							 gint                 column_pos) G_GNUC_WARN_UNUSED_RESULT;
 
 void		_gedit_cmd_file_new			(GtkAction   *action,
 							 GeditWindow *window);
diff --git a/gedit/gedit-dbus.c b/gedit/gedit-dbus.c
new file mode 100644
index 0000000..bd7a16e
--- /dev/null
+++ b/gedit/gedit-dbus.c
@@ -0,0 +1,1660 @@
+/*
+ * gedit-dbus.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#include "gedit-dbus.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <gdk/gdk.h>
+#include "gedit-utils.h"
+#include "gedit-command-line.h"
+#include "gedit-window.h"
+#include "gedit-app.h"
+#include "gedit-commands.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#ifdef G_OS_UNIX
+#include <gio/gunixinputstream.h>
+#include <gio/gunixconnection.h>
+#include <gio/gunixfdlist.h>
+#include <unistd.h>
+#include "gedit-fifo.h"
+#endif
+
+typedef struct _WaitData WaitData;
+typedef void (*WaitHandlerFunc)(GObject *object, WaitData *data);
+
+struct _WaitData
+{
+	GeditDBus *dbus;
+	GeditWindow *window;
+	guint32 wait_id;
+
+	guint num_handlers;
+	WaitHandlerFunc func;
+
+	guint close_window : 1;
+};
+
+typedef struct _DisplayParameters DisplayParameters;
+
+struct _DisplayParameters
+{
+	gchar *display_name;
+	gint32 screen_number;
+	gint32 workspace;
+	gint32 viewport_x;
+	gint32 viewport_y;
+};
+
+typedef struct _OpenParameters OpenParameters;
+
+struct _OpenParameters
+{
+	const GeditEncoding *encoding;
+	gint32 line_position;
+	gint32 column_position;
+};
+
+#define GEDIT_DBUS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_DBUS, GeditDBusPrivate))
+
+typedef struct
+{
+	GeditDBus *dbus;
+	GCancellable *cancellable;
+
+	GeditWindow *window;
+
+	OpenParameters oparams;
+	WaitData *wait_data;
+
+	guint jump_to : 1;
+} AsyncData;
+
+struct _GeditDBusPrivate
+{
+	GeditDBusResult result;
+	GMainLoop *main_loop;
+	guint32 wait_id;
+
+	guint32 next_wait_id;
+
+	GeditFifo *stdin_fifo;
+	GInputStream *stdin_in_stream;
+	GOutputStream *stdin_out_stream;
+	GCancellable *stdin_cancellable;
+};
+
+G_DEFINE_TYPE (GeditDBus, gedit_dbus, G_TYPE_OBJECT)
+
+static void
+async_window_destroyed (AsyncData *async,
+                        GObject   *where_the_object_was)
+{
+	g_cancellable_cancel (async->cancellable);
+	async->window = NULL;
+}
+
+static void
+async_data_free (AsyncData *async)
+{
+	g_object_unref (async->cancellable);
+
+	if (async->window)
+	{
+		g_object_weak_unref (G_OBJECT (async->window),
+		                     (GWeakNotify)async_window_destroyed,
+		                     async);
+	}
+
+	g_slice_free (AsyncData, async);
+}
+
+static AsyncData *
+async_data_new (GeditDBus *dbus)
+{
+	AsyncData *async;
+
+	async = g_slice_new0 (AsyncData);
+
+	async->dbus = dbus;
+	async->cancellable = g_cancellable_new ();
+
+	dbus->priv->stdin_cancellable = g_object_ref (async->cancellable);
+
+	return async;
+}
+
+static void
+gedit_dbus_dispose (GObject *object)
+{
+	GeditDBus *dbus = GEDIT_DBUS (object);
+
+	if (dbus->priv->stdin_cancellable)
+	{
+		g_cancellable_cancel (dbus->priv->stdin_cancellable);
+		g_object_unref (dbus->priv->stdin_cancellable);
+
+		dbus->priv->stdin_cancellable = NULL;
+	}
+
+	if (dbus->priv->stdin_fifo)
+	{
+		g_object_unref (dbus->priv->stdin_fifo);
+		dbus->priv->stdin_fifo = NULL;
+	}
+
+	if (dbus->priv->stdin_out_stream)
+	{
+		g_object_unref (dbus->priv->stdin_out_stream);
+		dbus->priv->stdin_out_stream = NULL;
+	}
+
+	if (dbus->priv->stdin_in_stream)
+	{
+		g_object_unref (dbus->priv->stdin_in_stream);
+		dbus->priv->stdin_in_stream = NULL;
+	}
+
+	G_OBJECT_CLASS (gedit_dbus_parent_class)->dispose (object);
+}
+
+static void
+gedit_dbus_class_init (GeditDBusClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = gedit_dbus_dispose;
+
+	g_type_class_add_private (object_class, sizeof(GeditDBusPrivate));
+}
+
+static void
+gedit_dbus_init (GeditDBus *self)
+{
+	self->priv = GEDIT_DBUS_GET_PRIVATE (self);
+}
+
+GeditDBus *
+gedit_dbus_new ()
+{
+	return g_object_new (GEDIT_TYPE_DBUS, NULL);
+}
+
+static guint32
+get_startup_timestamp (void)
+{
+	const gchar *startup_id_env;
+	gchar *time_str;
+	gchar *end;
+	gulong retval = 0;
+
+	/* we don't unset the env, since startup-notification
+	 * may still need it */
+	startup_id_env = g_getenv ("DESKTOP_STARTUP_ID");
+
+	if (startup_id_env == NULL)
+	{
+		return 0;
+	}
+
+	time_str = g_strrstr (startup_id_env, "_TIME");
+
+	if (time_str == NULL)
+	{
+		return 0;
+	}
+
+	errno = 0;
+
+	/* Skip past the "_TIME" part */
+	time_str += 5;
+
+	retval = strtoul (time_str, &end, 0);
+
+	if (end == time_str || errno != 0)
+	{
+		return 0;
+	}
+	else
+	{
+		return retval;
+	}
+}
+
+static GeditDBusResult
+activate_service (GeditDBus *dbus,
+                  guint     *result)
+{
+	GDBusConnection *conn;
+	GVariant *ret;
+
+	conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+	if (conn == NULL)
+	{
+		return GEDIT_DBUS_RESULT_FAILED;
+	}
+
+	ret = g_dbus_connection_call_sync (conn,
+	                                   "org.freedesktop.DBus",
+	                                   "/org/freedesktop/DBus",
+	                                   "org.freedesktop.DBus",
+	                                   "StartServiceByName",
+	                                   g_variant_new ("(su)", "org.gnome.gedit", 0),
+	                                   G_DBUS_CALL_FLAGS_NONE,
+	                                   -1,
+	                                   NULL,
+	                                   NULL);
+
+	g_object_unref (conn);
+
+	if (ret)
+	{
+		if (result)
+		{
+			g_variant_get (ret, "(u)", result);
+		}
+
+		g_variant_unref (ret);
+		return GEDIT_DBUS_RESULT_SUCCESS;
+	}
+	else
+	{
+		return GEDIT_DBUS_RESULT_FAILED;
+	}
+}
+
+static void
+get_display_arguments (GeditDBus         *dbus,
+                       DisplayParameters *dparams)
+{
+	GdkScreen *screen;
+	GdkDisplay *display;
+
+	screen = gdk_screen_get_default ();
+	display = gdk_screen_get_display (screen);
+
+	dparams->display_name = g_strdup (gdk_display_get_name (display));
+	dparams->screen_number = gdk_screen_get_number (screen);
+
+	dparams->workspace = gedit_utils_get_current_workspace (screen);
+	gedit_utils_get_current_viewport (screen, &dparams->viewport_x, &dparams->viewport_y);
+}
+
+static GVariant *
+compose_open_parameters (GeditDBus *dbus)
+{
+	GVariantBuilder file_list;
+	GVariantBuilder options;
+	GSList *item;
+	const GeditEncoding *encoding;
+	DisplayParameters dparams;
+	GeditCommandLine *command_line;
+	const char *geometry;
+
+	command_line = gedit_command_line_get_default ();
+
+	/* Compose files as uris */
+	g_variant_builder_init (&file_list, G_VARIANT_TYPE ("as"));
+
+	item = gedit_command_line_get_file_list (command_line);
+
+	while (item)
+	{
+		gchar *uri = g_file_get_uri (item->data);
+		g_variant_builder_add (&file_list, "s", uri);
+		g_free (uri);
+
+		item = g_slist_next (item);
+	}
+
+	/* Compose additional options */
+	g_variant_builder_init (&options, G_VARIANT_TYPE ("a{sv}"));
+
+	/* see if we need to add the pipe_path */
+	if (dbus->priv->stdin_fifo)
+	{
+		GFile *file;
+		gchar *path;
+
+		file = gedit_fifo_get_file (dbus->priv->stdin_fifo);
+		path = g_file_get_path (file);
+
+		g_variant_builder_add (&options,
+		                       "{sv}",
+		                       "pipe_path",
+		                       g_variant_new_string (path));
+
+		g_object_unref (file);
+		g_free (path);
+	}
+
+	/* add the encoding, line position, column position */
+	encoding = gedit_command_line_get_encoding (command_line);
+
+	if (encoding)
+	{
+		g_variant_builder_add (&options,
+		                       "{sv}", "encoding",
+		                       g_variant_new_string (gedit_encoding_get_charset (encoding)));
+	}
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "line_position",
+	                       g_variant_new_int32 (gedit_command_line_get_line_position (command_line)));
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "column_position",
+	                       g_variant_new_int32 (gedit_command_line_get_column_position (command_line)));
+
+	/* whether the make a new window, new document */
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "new_window",
+	                       g_variant_new_boolean (gedit_command_line_get_new_window (command_line)));
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "new_document",
+	                       g_variant_new_boolean (gedit_command_line_get_new_document (command_line)));
+
+	/* whether to wait */
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "wait",
+	                       g_variant_new_boolean (gedit_command_line_get_wait (command_line)));
+
+	/* the proper startup time */
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "startup_time",
+	                       g_variant_new_uint32 (get_startup_timestamp ()));
+
+	/* display parameters like display name, screen, workspace, viewport */
+	get_display_arguments (dbus, &dparams);
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "display_name",
+	                       g_variant_new_string (dparams.display_name));
+
+	g_free (dparams.display_name);
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "screen_number",
+	                       g_variant_new_int32 (dparams.screen_number));
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "workspace",
+	                       g_variant_new_int32 (dparams.workspace));
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "viewport_x",
+	                       g_variant_new_int32 (dparams.viewport_x));
+
+	g_variant_builder_add (&options,
+	                       "{sv}",
+	                       "viewport_y",
+	                       g_variant_new_int32 (dparams.viewport_y));
+
+	/* set geometry */
+	geometry = gedit_command_line_get_geometry (command_line);
+
+	if (geometry)
+	{
+		g_variant_builder_add (&options,
+		                       "{sv}",
+		                       "geometry",
+		                       g_variant_new_string (geometry));
+	}
+
+	return g_variant_new ("(asa{sv})", &file_list, &options);
+}
+
+static void
+slave_open_ready_cb (GDBusConnection *connection,
+                     GAsyncResult    *result,
+                     GeditDBus       *dbus)
+{
+	GDBusMessage *ret;
+	GError *error = NULL;
+	GeditCommandLine *command_line;
+
+	ret = g_dbus_connection_send_message_with_reply_finish (connection,
+	                                                        result,
+	                                                        &error);
+	command_line = gedit_command_line_get_default ();
+
+	if (ret == NULL)
+	{
+		g_warning ("Failed to call gedit service: %s", error->message);
+		g_error_free (error);
+
+		dbus->priv->result = GEDIT_DBUS_RESULT_FAILED;
+		g_main_loop_quit (dbus->priv->main_loop);
+	}
+	else
+	{
+		g_variant_get (g_dbus_message_get_body (ret),
+		               "(u)",
+		               &dbus->priv->wait_id);
+
+		dbus->priv->result = GEDIT_DBUS_RESULT_SUCCESS;
+
+		if (!gedit_command_line_get_wait (command_line) &&
+		    !dbus->priv->stdin_cancellable)
+		{
+			g_main_loop_quit (dbus->priv->main_loop);
+		}
+	}
+}
+
+static void
+on_open_proxy_signal (GDBusProxy *proxy,
+                      gchar      *sender_name,
+                      gchar      *signal_name,
+                      GVariant   *parameters,
+                      GeditDBus  *dbus)
+{
+	if (g_strcmp0 (signal_name, "WaitDone") == 0)
+	{
+		guint wait_id;
+
+		g_variant_get (parameters, "(u)", &wait_id);
+
+		if (wait_id == dbus->priv->wait_id)
+		{
+			g_main_loop_quit (dbus->priv->main_loop);
+		}
+	}
+}
+
+#ifdef G_OS_UNIX
+static void
+stdin_write_finish (GOutputStream *stream,
+                    GAsyncResult  *result,
+                    AsyncData     *async)
+{
+	GError *error = NULL;
+	gssize written;
+	GeditDBusPrivate *priv;
+	GeditCommandLine *command_line;
+
+	if (g_cancellable_is_cancelled (async->cancellable))
+	{
+		async_data_free (async);
+		return;
+	}
+
+	written = g_output_stream_splice_finish (stream, result, &error);
+	priv = async->dbus->priv;
+
+	g_object_unref (priv->stdin_out_stream);
+	g_object_unref (priv->stdin_in_stream);
+
+	priv->stdin_out_stream = NULL;
+	priv->stdin_in_stream = NULL;
+
+	if (written == -1)
+	{
+		g_warning ("Failed to write stdin: %s", error->message);
+		g_error_free (error);
+	}
+
+	async_data_free (async);
+
+	g_object_unref (priv->stdin_fifo);
+	priv->stdin_fifo = NULL;
+
+	g_object_unref (priv->stdin_cancellable);
+	priv->stdin_cancellable = NULL;
+
+	command_line = gedit_command_line_get_default ();
+
+	if (priv->main_loop && !gedit_command_line_get_wait (command_line))
+	{
+		/* only quit the main loop if it's there and if we don't need
+		   to wait */
+		g_main_loop_quit (priv->main_loop);
+	}
+}
+
+static void
+stdin_pipe_ready_to_write (GeditFifo    *fifo,
+                           GAsyncResult *result,
+                           AsyncData    *async)
+{
+	GeditDBusPrivate *priv;
+	GOutputStream *stream;
+	GError *error = NULL;
+
+	if (g_cancellable_is_cancelled (async->cancellable))
+	{
+		async_data_free (async);
+		return;
+	}
+
+	stream = gedit_fifo_open_write_finish (fifo, result, &error);
+
+	if (stream == NULL)
+	{
+		g_warning ("Could not open fifo for writing: %s", error->message);
+		g_error_free (error);
+
+		/* Can't do that then */
+		async_data_free (async);
+		return;
+	}
+
+	priv = async->dbus->priv;
+
+	priv->stdin_out_stream = stream;
+	priv->stdin_in_stream = g_unix_input_stream_new (STDIN_FILENO, TRUE);
+
+	g_output_stream_splice_async (priv->stdin_out_stream,
+	                              priv->stdin_in_stream,
+	                              G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+	                              G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+	                              G_PRIORITY_DEFAULT,
+	                              async->cancellable,
+	                              (GAsyncReadyCallback)stdin_write_finish,
+	                              async);
+}
+
+static void
+open_command_add_stdin_pipe (GeditDBus *dbus)
+{
+	AsyncData *async;
+
+	dbus->priv->stdin_fifo = gedit_fifo_new (NULL);
+
+	if (!dbus->priv->stdin_fifo)
+	{
+		g_warning ("Failed to create fifo for standard in");
+		return;
+	}
+
+	async = async_data_new (dbus);
+
+	gedit_fifo_open_write_async (dbus->priv->stdin_fifo,
+	                             G_PRIORITY_DEFAULT,
+	                             async->cancellable,
+	                             (GAsyncReadyCallback)stdin_pipe_ready_to_write,
+	                             async);
+}
+#endif
+
+static void
+open_command_add_stdin (GeditDBus       *dbus,
+                        GDBusConnection *connection,
+                        GDBusMessage    *message)
+{
+#ifdef G_OS_UNIX
+	GUnixFDList *fdlist;
+	GError *error = NULL;
+	gint ret;
+
+	if (!gedit_utils_can_read_from_stdin ())
+	{
+		return;
+	}
+
+	if (!(g_dbus_connection_get_capabilities (connection) &
+	      G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING))
+	{
+		/* Fallback with named pipe */
+		open_command_add_stdin_pipe (dbus);
+		return;
+	}
+
+	fdlist = g_unix_fd_list_new ();
+	ret = g_unix_fd_list_append (fdlist, STDIN_FILENO, &error);
+
+	if (ret == -1)
+	{
+		g_warning ("Could not read from standard in: %s", error->message);
+		g_error_free (error);
+	}
+	else
+	{
+		/* Here we can close STDIN because it's dupped */
+		close (STDIN_FILENO);
+	}
+
+	g_dbus_message_set_unix_fd_list (message, fdlist);
+	g_object_unref (fdlist);
+#endif
+}
+
+static void
+command_line_proxy_appeared (GDBusConnection *connection,
+                             const gchar     *name,
+                             const gchar     *owner_name,
+                             GDBusProxy      *proxy,
+                             GeditDBus       *dbus)
+{
+	GeditCommandLine *command_line;
+	GDBusMessage *message;
+
+	command_line = gedit_command_line_get_default ();
+
+	if (gedit_command_line_get_wait (command_line))
+	{
+		g_signal_connect (proxy,
+		                  "g-signal",
+		                  G_CALLBACK (on_open_proxy_signal),
+		                  dbus);
+	}
+
+	message = g_dbus_message_new_method_call (g_dbus_proxy_get_unique_bus_name (proxy),
+	                                          "/org/gnome/gedit",
+	                                          "org.gnome.gedit.CommandLine",
+	                                          "Open");
+
+	open_command_add_stdin (dbus, connection, message);
+	g_dbus_message_set_body (message, compose_open_parameters (dbus));
+
+	g_dbus_connection_send_message_with_reply (g_dbus_proxy_get_connection (proxy),
+	                                           message,
+	                                           -1,
+	                                           NULL,
+	                                           NULL,
+	                                           (GAsyncReadyCallback)slave_open_ready_cb,
+	                                           dbus);
+
+	g_object_unref (message);
+}
+
+static void
+command_line_proxy_vanished (GDBusConnection *connection,
+                             const gchar     *name,
+                             GeditDBus       *dbus)
+{
+	dbus->priv->result = GEDIT_DBUS_RESULT_FAILED;
+	g_main_loop_quit (dbus->priv->main_loop);
+}
+
+static GeditDBusResult
+handle_slave (GeditDBus *dbus)
+{
+	/* send the requested commands to the master */
+	GDBusConnection *conn;
+	GDBusCallFlags flags;
+	GeditCommandLine *command_line;
+
+	conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+	if (conn == NULL)
+	{
+		g_warning ("Could not connect to session bus");
+		return GEDIT_DBUS_RESULT_FAILED;
+	}
+
+	flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
+	command_line = gedit_command_line_get_default ();
+
+	if (!gedit_command_line_get_wait (command_line))
+	{
+		flags |= G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
+	}
+
+	g_bus_watch_proxy (G_BUS_TYPE_SESSION,
+	                   "org.gnome.gedit",
+	                   G_BUS_NAME_WATCHER_FLAGS_NONE,
+	                   "/org/gnome/gedit",
+	                   "org.gnome.gedit.CommandLine",
+	                   G_TYPE_DBUS_PROXY,
+	                   flags,
+	                   (GBusProxyAppearedCallback)command_line_proxy_appeared,
+	                   (GBusProxyVanishedCallback)command_line_proxy_vanished,
+	                   dbus,
+	                   NULL);
+
+	dbus->priv->main_loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (dbus->priv->main_loop);
+
+	g_object_unref (conn);
+	g_main_loop_unref (dbus->priv->main_loop);
+
+	return dbus->priv->result;
+}
+
+static GeditDBusResult
+handle_master (GeditDBus *dbus)
+{
+	/* let the main gedit thing do its thing */
+	if (g_getenv ("DBUS_STARTER_ADDRESS"))
+	{
+		/* started as a service, we don't want to popup a window on
+		   some random display */
+		return GEDIT_DBUS_RESULT_PROCEED_SERVICE;
+	}
+	else
+	{
+		return GEDIT_DBUS_RESULT_PROCEED;
+	}
+}
+
+static GeditDBusResult
+handle_service (GeditDBus *dbus)
+{
+	guint result;
+	GeditCommandLine *command_line;
+
+	if (activate_service (dbus, &result) == GEDIT_DBUS_RESULT_FAILED)
+	{
+		g_warning ("Could not activate gedit service");
+		return GEDIT_DBUS_RESULT_FAILED;
+	}
+
+	command_line = gedit_command_line_get_default ();
+
+	/* Finally, act as a slave. */
+	return handle_slave (dbus);
+}
+
+static GSList *
+variant_iter_list_to_locations (GVariantIter *iter)
+{
+	gchar *uri;
+	GSList *ret = NULL;
+
+	while (g_variant_iter_loop (iter, "s", &uri))
+	{
+		ret = g_slist_prepend (ret, g_file_new_for_uri (uri));
+	}
+
+	return g_slist_reverse (ret);
+}
+
+static GdkDisplay *
+display_open_if_needed (const gchar *name)
+{
+	GSList *displays;
+	GSList *l;
+	GdkDisplay *display = NULL;
+
+	displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+
+	for (l = displays; l != NULL; l = l->next)
+	{
+		if (g_strcmp0 (gdk_display_get_name (l->data), name) == 0)
+		{
+			display = l->data;
+			break;
+		}
+	}
+
+	g_slist_free (displays);
+
+	return display != NULL ? display : gdk_display_open (name);
+}
+
+static GeditWindow *
+window_from_display_arguments (gboolean           new_window,
+                               DisplayParameters *dparams,
+                               gboolean           create)
+{
+	GdkScreen *screen;
+	GeditApp *app;
+	GeditWindow *ret;
+
+	/* get correct screen using the display_name and screen_number */
+	if (dparams->display_name != NULL && *dparams->display_name)
+	{
+		GdkDisplay *display;
+
+		display = display_open_if_needed (dparams->display_name);
+		screen = gdk_display_get_screen (display,
+		                                 dparams->screen_number == -1 ? 0 : dparams->screen_number);
+	}
+
+	app = gedit_app_get_default ();
+
+	if (new_window)
+	{
+		ret = gedit_app_create_window (app, screen);
+		gedit_window_create_tab (ret, TRUE);
+
+		return ret;
+	}
+
+	if (screen != NULL)
+	{
+		ret = _gedit_app_get_window_in_viewport (app,
+		                                         screen,
+		                                         dparams->workspace == -1 ? 0 : dparams->workspace,
+		                                         dparams->viewport_x == -1 ? 0 : dparams->viewport_x,
+		                                         dparams->viewport_y == -1 ? 0 : dparams->viewport_y);
+	}
+	else
+	{
+		ret = gedit_app_get_active_window (app);
+	}
+
+	if (!ret && create)
+	{
+		ret = gedit_app_create_window (app, screen);
+		gedit_window_create_tab (ret, TRUE);
+	}
+
+	return ret;
+}
+
+static gboolean
+is_empty_window (GeditWindow *window,
+                 gboolean     check_untouched)
+{
+	GList *views;
+	gboolean ret = FALSE;
+
+	views = gedit_window_get_views (window);
+
+	if (!views)
+	{
+		ret = TRUE;
+	}
+	else if (check_untouched && views->next == NULL)
+	{
+		GeditView *view = GEDIT_VIEW (views->data);
+		GeditDocument *doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+		if (gedit_document_is_untouched (doc) &&
+		    gedit_tab_get_state (gedit_tab_get_from_document (doc)) == GEDIT_TAB_STATE_NORMAL)
+		{
+			ret = TRUE;
+		}
+	}
+
+	g_list_free (views);
+	return ret;
+}
+
+static void
+set_interaction_time_and_present (GeditWindow *window,
+                                  guint        startup_time)
+{
+	/* set the proper interaction time on the window.
+	* Fall back to roundtripping to the X server when we
+	* don't have the timestamp, e.g. when launched from
+	* terminal. We also need to make sure that the window
+	* has been realized otherwise it will not work. lame.
+	*/
+
+	if (!GTK_WIDGET_REALIZED (window))
+	{
+		gtk_widget_realize (GTK_WIDGET (window));
+	}
+
+#ifdef GDK_WINDOWING_X11
+	if (startup_time <= 0)
+	{
+		startup_time = gdk_x11_get_server_time (GTK_WIDGET (window)->window);
+	}
+
+	gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, startup_time);
+#endif
+
+	gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+wait_handler_dbus (GObject  *object,
+                   WaitData *data)
+{
+	GDBusConnection *conn;
+
+	conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+	if (conn == NULL)
+	{
+		g_warning ("Could not emit WaitDone signal because session bus is gone");
+		return;
+	}
+
+	/* Emit the WaitDone signal */
+	g_dbus_connection_emit_signal (conn,
+	                               NULL,
+	                               "/org/gnome/gedit",
+	                               "org.gnome.gedit.CommandLine",
+	                               "WaitDone",
+	                               g_variant_new ("(u)", data->wait_id),
+	                               NULL);
+	g_object_unref (conn);
+
+	if (data->window && object != G_OBJECT (data->window) && data->close_window &&
+	    is_empty_window (data->window, FALSE))
+	{
+		/* Close the window */
+		gtk_widget_destroy (GTK_WIDGET (data->window));
+	}
+}
+
+static void
+unref_wait_handler (WaitData  *data,
+                    GObject   *object)
+{
+	if (data->num_handlers == 0)
+	{
+		return;
+	}
+
+	--data->num_handlers;
+
+	if (data->num_handlers == 0)
+	{
+		data->func (object, data);
+	
+		/* Free the wait data */
+		g_slice_free (WaitData, data);
+	}
+}
+
+static void
+install_wait_handler (GeditDBus       *dbus,
+                      WaitData        *data,
+                      GObject         *object,
+                      WaitHandlerFunc  func)
+{
+	++data->num_handlers;
+	data->func = func;
+
+	g_object_weak_ref (object, (GWeakNotify)unref_wait_handler, data);
+}
+
+#ifdef G_OS_UNIX
+static GeditTab *
+tab_from_stream (GeditWindow    *window,
+                 GInputStream   *stream,
+                 OpenParameters *oparams,
+                 gboolean        jump_to)
+{
+	GList *documents;
+	GeditDocument *doc = NULL;
+	GeditTab *tab = NULL;
+
+	documents = gedit_window_get_documents (window);
+
+	if (documents)
+	{
+		doc = GEDIT_DOCUMENT (documents->data);
+		tab = gedit_tab_get_from_document (doc);
+	}
+
+	if (documents && !documents->next &&
+	    gedit_document_is_untouched (doc) &&
+	    gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)
+	{
+		/* open right in that document */
+		GeditDocument *doc = GEDIT_DOCUMENT (documents->data);
+
+		tab = gedit_tab_get_from_document (doc);
+
+		_gedit_tab_load_stream (tab,
+		                        stream,
+		                        oparams->encoding,
+		                        oparams->line_position,
+		                        oparams->column_position);
+	}
+	else
+	{
+		tab = gedit_window_create_tab_from_stream (window,
+		                                           stream,
+		                                           oparams->encoding,
+		                                           oparams->line_position,
+		                                           oparams->column_position,
+		                                           jump_to);
+	}
+
+	g_list_free (documents);
+	return tab;
+}
+#endif
+
+static GSList *
+create_tabs_for_fds (GeditDBus             *dbus,
+                     GDBusMethodInvocation *invocation,
+                     GeditWindow           *window,
+                     OpenParameters        *oparams,
+                     gboolean               jump_to)
+{
+#ifdef G_OS_UNIX
+	GDBusMessage *message;
+	GDBusConnection *connection;
+	GUnixFDList *fdlist;
+	GSList *ret = NULL;
+	gint num;
+	gint i;
+
+	connection = g_dbus_method_invocation_get_connection (invocation);
+
+	if (!(g_dbus_connection_get_capabilities (connection) &
+	      G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING))
+	{
+		return NULL;
+	}
+
+	message = g_dbus_method_invocation_get_message (invocation);
+	fdlist = g_dbus_message_get_unix_fd_list (message);
+
+	if (!fdlist)
+	{
+		return NULL;
+	}
+
+	num = g_unix_fd_list_get_length (fdlist);
+
+	for (i = 0; i < num; ++i)
+	{
+		gint fd;
+		GError *error = NULL;
+
+		fd = g_unix_fd_list_get (fdlist, i, &error);
+
+		if (fd == -1)
+		{
+			g_warning ("Could not open stream for service: %s", error->message);
+			g_error_free (error);
+			error = NULL;
+		}
+		else
+		{
+			GeditTab *tab;
+			GInputStream *stream;
+
+			/* fd is dupped, so we close it when the stream closes */
+			stream = g_unix_input_stream_new (fd, TRUE);
+
+			tab = tab_from_stream (window,
+			                       stream,
+			                       oparams,
+			                       jump_to);
+
+			g_object_unref (stream);
+
+			if (tab)
+			{
+				ret = g_slist_prepend (ret, tab);
+				jump_to = FALSE;
+			}
+		}
+	}
+
+	return g_slist_reverse (ret);
+#else
+	return NULL;
+#endif
+}
+
+#ifdef G_OS_UNIX
+static void
+stdin_pipe_ready_to_read (GeditFifo    *fifo,
+                          GAsyncResult *result,
+                          AsyncData    *async)
+{
+	GInputStream *stream;
+	GError *error = NULL;
+	GeditTab *tab;
+
+	if (g_cancellable_is_cancelled (async->cancellable))
+	{
+		async_data_free (async);
+		return;
+	}
+
+	stream = gedit_fifo_open_read_finish (fifo, result, &error);
+
+	if (!stream)
+	{
+		g_warning ("Opening stdin pipe error: %s", error->message);
+
+		g_error_free (error);
+
+		g_object_unref (async->dbus->priv->stdin_cancellable);
+		async->dbus->priv->stdin_cancellable = NULL;
+
+		g_object_unref (fifo);
+		async->dbus->priv->stdin_fifo = NULL;
+
+		async_data_free (async);
+		return;
+	}
+
+	tab = tab_from_stream (async->window,
+	                       stream,
+	                       &async->oparams,
+	                       async->jump_to);
+
+	g_object_unref (stream);
+
+	if (async->wait_data)
+	{
+		install_wait_handler (async->dbus,
+		                      async->wait_data,
+		                      G_OBJECT (tab),
+		                      wait_handler_dbus);
+	}
+}
+#endif
+
+static gboolean
+handle_open_pipe (GeditDBus      *dbus,
+                  const gchar    *pipe_path,
+                  GeditWindow    *window,
+                  OpenParameters *oparams,
+                  gboolean        jump_to,
+                  WaitData       *wait_data)
+{
+#ifdef G_OS_UNIX
+	/* We'll do this async */
+	GFile *file;
+	AsyncData *async;
+
+	if (!pipe_path)
+	{
+		return FALSE;
+	}
+
+	file = g_file_new_for_path (pipe_path);
+	dbus->priv->stdin_fifo = gedit_fifo_new (file);
+	g_object_unref (file);
+
+	if (dbus->priv->stdin_fifo == NULL)
+	{
+		return FALSE;
+	}
+
+	async = async_data_new (dbus);
+	async->window = window;
+	async->oparams = *oparams;
+	async->jump_to = jump_to;
+	async->wait_data = wait_data;
+
+	g_object_weak_ref (G_OBJECT (window),
+	                   (GWeakNotify)async_window_destroyed,
+	                   async);
+
+	gedit_fifo_open_read_async (dbus->priv->stdin_fifo,
+	                            G_PRIORITY_DEFAULT,
+	                            async->cancellable,
+	                            (GAsyncReadyCallback)stdin_pipe_ready_to_read,
+	                            async);
+
+	return TRUE;
+#else
+	return FALSE;
+#endif
+}
+
+static gboolean
+extract_optional_parameters (GHashTable  *parameters,
+                             ...) G_GNUC_NULL_TERMINATED;
+
+static gboolean
+extract_optional_parameters (GHashTable  *parameters,
+                             ...)
+{
+	va_list va_args;
+	const gchar *key;
+	gboolean ret = FALSE;
+
+	va_start (va_args, parameters);
+
+	while ((key = va_arg (va_args, const gchar *)) != NULL)
+	{
+		GVariant *value;
+
+		value = g_hash_table_lookup (parameters, key);
+
+		if (!value)
+		{
+			/* ignore the next */
+			va_arg (va_args, gpointer);
+			continue;
+		}
+
+		ret = TRUE;
+
+		g_variant_get_va (value,
+		                  g_variant_get_type_string (value),
+		                  NULL,
+		                  &va_args);
+	}
+
+	va_end (va_args);
+	return ret;
+}
+
+static GHashTable *
+optional_parameters_hash_table (GVariantIter *iter)
+{
+	GVariant *value;
+	GHashTable *ret;
+	const gchar *key;
+
+	ret = g_hash_table_new_full (g_str_hash,
+	                             g_str_equal,
+	                             (GDestroyNotify)g_free,
+	                             (GDestroyNotify)g_variant_unref);
+
+	while (g_variant_iter_loop (iter, "{sv}", &key, &value))
+	{
+		g_hash_table_insert (ret,
+		                     g_strdup (key),
+		                     g_variant_ref (value));
+	}
+
+	return ret;
+}
+
+static GSList *
+handle_open_fds (GeditDBus             *dbus,
+                 GDBusMethodInvocation *invocation,
+                 GSList                *loaded,
+                 GeditWindow           *window,
+                 OpenParameters        *oparams)
+{
+	GSList *item;
+	GSList *tabs;
+	GSList *ret = NULL;
+
+	/* This is for creating tabs from unix file descriptors supplied with
+	   the dbus message */
+	tabs = create_tabs_for_fds (dbus,
+	                            invocation,
+	                            window,
+	                            oparams,
+	                            loaded == NULL);
+
+	for (item = tabs; item; item = g_slist_next (item))
+	{
+		ret = g_slist_prepend (ret, gedit_tab_get_document (item->data));
+	}
+
+	g_slist_free (tabs);
+
+	return g_slist_concat (loaded, g_slist_reverse (ret));
+
+}
+
+static void
+dbus_handle_open (GeditDBus             *dbus,
+                  GVariant              *parameters,
+                  GDBusMethodInvocation *invocation)
+{
+	GVariantIter *file_list;
+	GVariantIter *optional_parameters;
+	GHashTable *options_hash;
+
+	gchar *charset_encoding = NULL;
+	guint32 startup_time;
+
+	OpenParameters open_parameters = {NULL, 0, 0};
+
+	gboolean new_window = FALSE;
+	gboolean new_document = FALSE;
+	gboolean wait = FALSE;
+	gchar *pipe_path = NULL;
+
+	GSList *locations = NULL;
+	GeditWindow *window;
+	GSList *loaded_documents = NULL;
+	gboolean empty_window;
+	WaitData *data;
+	guint32 wait_id = 0;
+
+	g_variant_get (parameters,
+	               "(asa{sv})",
+	               &file_list,
+	               &optional_parameters);
+
+	locations = variant_iter_list_to_locations (file_list);
+	g_variant_iter_free (file_list);
+
+	options_hash = optional_parameters_hash_table (optional_parameters);
+	g_variant_iter_free (optional_parameters);
+
+	{
+		DisplayParameters display_parameters = {NULL, -1, -1, -1, -1};
+		gchar *geometry;
+
+		extract_optional_parameters (options_hash,
+		                             "new_window", &new_window,
+		                             "display_name", &display_parameters.display_name,
+		                             "screen_number", &display_parameters.screen_number,
+		                             "workspace", &display_parameters.workspace,
+		                             "viewport_x", &display_parameters.viewport_x,
+		                             "viewport_y", &display_parameters.viewport_y,
+		                             NULL);
+
+		window = window_from_display_arguments (new_window,
+		                                        &display_parameters,
+		                                        TRUE);
+
+		g_free (display_parameters.display_name);
+
+		if (extract_optional_parameters (options_hash,
+		                                 "geometry", &geometry,
+		                                 NULL))
+		{
+			gtk_window_parse_geometry (GTK_WINDOW (window),
+			                           geometry);
+			g_free (geometry);
+		}
+	}
+
+	extract_optional_parameters (options_hash, "encoding", &charset_encoding, NULL);
+
+	if (charset_encoding && *charset_encoding)
+	{
+		open_parameters.encoding = gedit_encoding_get_from_charset (charset_encoding);
+	}
+
+	g_free (charset_encoding);
+
+	empty_window = is_empty_window (window, TRUE);
+
+	extract_optional_parameters (options_hash,
+	                             "line_position", &open_parameters.line_position,
+	                             "column_position", &open_parameters.column_position,
+	                             NULL);
+
+	if (locations)
+	{
+		loaded_documents = _gedit_cmd_load_files_from_prompt (window,
+		                                                      locations,
+		                                                      open_parameters.encoding,
+		                                                      open_parameters.line_position,
+		                                                      open_parameters.column_position);
+	}
+
+	g_slist_free (locations);
+
+	loaded_documents = handle_open_fds (dbus,
+	                                    invocation,
+	                                    loaded_documents,
+	                                    window,
+	                                    &open_parameters);
+
+	extract_optional_parameters (options_hash,
+	                             "wait", &wait,
+	                             "pipe_path", &pipe_path,
+	                             "new_document", &new_document,
+	                             "startup_time", &startup_time,
+	                             NULL);
+
+	set_interaction_time_and_present (window, startup_time);
+
+	if (!wait)
+	{
+		gboolean jump_to = loaded_documents == NULL;
+
+		if (new_document)
+		{
+			gedit_window_create_tab (window, jump_to);
+			jump_to = FALSE;
+		}
+
+		handle_open_pipe (dbus,
+		                  pipe_path,
+		                  window,
+		                  &open_parameters,
+		                  jump_to,
+		                  NULL);
+	}
+	else
+	{
+		gboolean jump_to = loaded_documents == NULL;
+		gboolean has_pipe;
+
+		data = g_slice_new (WaitData);
+
+		data->dbus = dbus;
+		data->window = window;
+		data->close_window = empty_window;
+		data->wait_id = ++dbus->priv->next_wait_id;
+		data->num_handlers = 0;
+
+		/* for the return value */
+		wait_id = data->wait_id;
+
+		if (new_document)
+		{
+			GeditTab *tab;
+			tab = gedit_window_create_tab (window, jump_to);
+			jump_to = FALSE;
+
+			loaded_documents = g_slist_append (loaded_documents,
+			                                   gedit_tab_get_document (tab));
+		}
+
+		has_pipe = handle_open_pipe (dbus,
+		                             pipe_path,
+		                             window,
+		                             &open_parameters,
+		                             jump_to,
+		                             data);
+
+		/* Install wait handler on the window if there were no documents
+		   opened */
+		if (loaded_documents == NULL && !has_pipe)
+		{
+			/* Add wait handler on the window */
+			install_wait_handler (dbus,
+			                      data,
+			                      G_OBJECT (window),
+			                      wait_handler_dbus);
+		}
+		else
+		{
+			GSList *item;
+
+			/* Add wait handler on the documents */
+			for (item = loaded_documents; item; item = item->next)
+			{
+				install_wait_handler (dbus,
+				                      data,
+				                      G_OBJECT (item->data),
+				                      wait_handler_dbus);
+			}
+		}
+	}
+
+	g_free (pipe_path);
+
+	g_slist_free (loaded_documents);
+	g_hash_table_destroy (options_hash);
+
+	g_dbus_method_invocation_return_value (invocation,
+	                                       g_variant_new ("(u)", wait_id));
+}
+
+static void
+dbus_command_line_method_call_cb (GDBusConnection       *connection,
+                                  const gchar           *sender,
+                                  const gchar           *object_path,
+                                  const gchar           *interface_name,
+                                  const gchar           *method_name,
+                                  GVariant              *parameters,
+                                  GDBusMethodInvocation *invocation,
+                                  gpointer               user_data)
+{
+	g_return_if_fail (g_strcmp0 (object_path, "/org/gnome/gedit") == 0);
+	g_return_if_fail (g_strcmp0 (interface_name, "org.gnome.gedit.CommandLine") == 0);
+
+	if (g_strcmp0 (method_name, "Open") == 0)
+	{
+		dbus_handle_open (user_data, parameters, invocation);
+	}
+	else
+	{
+		g_warning ("Unsupported method called on gedit service: %s", method_name);
+	}
+}
+
+static const gchar introspection_xml[] =
+	"<node>"
+	"  <interface name='org.gnome.gedit.CommandLine'>"
+	"    <method name='Open'>"
+	"      <arg type='as' name='files' direction='in'/>"
+	"      <arg type='a{sv}' name='options' direction='in'/>"
+	"      <arg type='u' name='wait_id' direction='out'/>"
+	"    </method>"
+	"    <signal name='WaitDone'>"
+	"      <arg type='u' name='wait_id'/>"
+	"    </signal>"
+	"  </interface>"
+	"</node>";
+
+static const GDBusInterfaceVTable command_line_vtable = {
+	dbus_command_line_method_call_cb,
+};
+
+static gboolean
+register_dbus_interface (GeditDBus       *dbus,
+                         GDBusConnection *connection)
+{
+	guint ret;
+	GDBusNodeInfo *info;
+
+	info = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+
+	ret = g_dbus_connection_register_object (connection,
+	                                         "/org/gnome/gedit",
+	                                         info->interfaces[0],
+	                                         &command_line_vtable,
+	                                         dbus,
+	                                         NULL,
+	                                         NULL);
+
+	return ret != 0;
+}
+
+static void
+bus_acquired_cb (GDBusConnection *connection,
+                 const gchar     *name,
+                 GeditDBus       *dbus)
+{
+	if (connection == NULL)
+	{
+		g_warning ("Failed to acquire dbus connection");
+		dbus->priv->result = GEDIT_DBUS_RESULT_PROCEED;
+
+		g_main_loop_quit (dbus->priv->main_loop);
+	}
+	else
+	{
+		/* setup the dbus interface that other gedit processes can call. we do
+		   this here even though we might not own the name, because the docs say
+		   it should be done here... */
+		register_dbus_interface (dbus, connection);
+	}
+}
+
+static void
+name_acquired_cb (GDBusConnection *connection,
+                  const gchar     *name,
+                  GeditDBus       *dbus)
+{
+	dbus->priv->result = GEDIT_DBUS_RESULT_SUCCESS;
+	g_main_loop_quit (dbus->priv->main_loop);
+}
+
+static void
+name_lost_cb (GDBusConnection *connection,
+              const gchar     *name,
+              GeditDBus       *dbus)
+{
+	dbus->priv->result = GEDIT_DBUS_RESULT_FAILED;
+	g_main_loop_quit (dbus->priv->main_loop);
+}
+
+GeditDBusResult
+gedit_dbus_run (GeditDBus *dbus)
+{
+	guint id;
+	GeditCommandLine *command_line;
+
+	g_return_val_if_fail (GEDIT_IS_DBUS (dbus), GEDIT_DBUS_RESULT_PROCEED);
+
+	command_line = gedit_command_line_get_default ();
+
+	if (gedit_command_line_get_standalone (command_line))
+	{
+		return GEDIT_DBUS_RESULT_PROCEED;
+	}
+
+	if (gedit_command_line_get_wait (command_line) ||
+	    gedit_command_line_get_background (command_line))
+	{
+		GeditDBusResult ret = handle_service (dbus);
+
+		/* We actually continue if it failed, because it's nicer to
+		   still start some kind of gedit in that case */
+		if (ret != GEDIT_DBUS_RESULT_FAILED)
+		{
+			return ret;
+		}
+	}
+
+	id = g_bus_own_name (G_BUS_TYPE_SESSION,
+	                     "org.gnome.gedit",
+	                     G_BUS_NAME_OWNER_FLAGS_NONE,
+	                     (GBusAcquiredCallback)bus_acquired_cb,
+	                     (GBusNameAcquiredCallback)name_acquired_cb,
+	                     (GBusNameLostCallback)name_lost_cb,
+	                     dbus,
+	                     NULL);
+
+	dbus->priv->main_loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (dbus->priv->main_loop);
+	g_main_loop_unref (dbus->priv->main_loop);
+
+	switch (dbus->priv->result)
+	{
+		case GEDIT_DBUS_RESULT_PROCEED:
+			/* could not initialize dbus, gonna be standalone */
+			return GEDIT_DBUS_RESULT_PROCEED;
+		break;
+		case GEDIT_DBUS_RESULT_FAILED:
+			/* there is already a gedit process */
+			return handle_slave (dbus);
+		break;
+		case GEDIT_DBUS_RESULT_SUCCESS:
+			/* we are the main gedit process */
+			return handle_master (dbus);
+		break;
+		default:
+			g_assert_not_reached ();
+		break;
+	}
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-dbus.h b/gedit/gedit-dbus.h
new file mode 100644
index 0000000..9246d5f
--- /dev/null
+++ b/gedit/gedit-dbus.h
@@ -0,0 +1,69 @@
+/*
+ * gedit-dbus.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GEDIT_DBUS_H__
+#define __GEDIT_DBUS_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_DBUS			(gedit_dbus_get_type ())
+#define GEDIT_DBUS(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DBUS, GeditDBus))
+#define GEDIT_DBUS_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DBUS, GeditDBus const))
+#define GEDIT_DBUS_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DBUS, GeditDBusClass))
+#define GEDIT_IS_DBUS(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DBUS))
+#define GEDIT_IS_DBUS_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DBUS))
+#define GEDIT_DBUS_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DBUS, GeditDBusClass))
+
+typedef struct _GeditDBus		GeditDBus;
+typedef struct _GeditDBusClass		GeditDBusClass;
+typedef struct _GeditDBusPrivate	GeditDBusPrivate;
+
+typedef enum
+{
+	GEDIT_DBUS_RESULT_SUCCESS,
+	GEDIT_DBUS_RESULT_FAILED,
+	GEDIT_DBUS_RESULT_PROCEED,
+	GEDIT_DBUS_RESULT_PROCEED_SERVICE
+} GeditDBusResult;
+
+struct _GeditDBus {
+	GObject parent;
+
+	GeditDBusPrivate *priv;
+};
+
+struct _GeditDBusClass {
+	GObjectClass parent_class;
+};
+
+GType gedit_dbus_get_type (void) G_GNUC_CONST;
+GeditDBus *gedit_dbus_new (void);
+
+GeditDBusResult gedit_dbus_run (GeditDBus *bus);
+
+G_END_DECLS
+
+#endif /* __GEDIT_DBUS_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-document-loader.c b/gedit/gedit-document-loader.c
index 54ab1a3..1969ab9 100644
--- a/gedit/gedit-document-loader.c
+++ b/gedit/gedit-document-loader.c
@@ -78,7 +78,8 @@ enum
 	PROP_DOCUMENT,
 	PROP_LOCATION,
 	PROP_ENCODING,
-	PROP_NEWLINE_TYPE
+	PROP_NEWLINE_TYPE,
+	PROP_STREAM
 };
 
 #define READ_CHUNK_SIZE 8192
@@ -120,6 +121,7 @@ struct _GeditDocumentLoaderPrivate
 	gchar                     buffer[READ_CHUNK_SIZE];
 
 	GError                   *error;
+	gboolean                  guess_content_type_from_content;
 };
 
 G_DEFINE_TYPE(GeditDocumentLoader, gedit_document_loader, G_TYPE_OBJECT)
@@ -149,6 +151,9 @@ gedit_document_loader_set_property (GObject      *object,
 		case PROP_NEWLINE_TYPE:
 			loader->priv->auto_detected_newline_type = g_value_get_enum (value);
 			break;
+		case PROP_STREAM:
+			loader->priv->stream = g_value_dup_object (value);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -177,6 +182,9 @@ gedit_document_loader_get_property (GObject    *object,
 		case PROP_NEWLINE_TYPE:
 			g_value_set_enum (value, loader->priv->auto_detected_newline_type);
 			break;
+		case PROP_STREAM:
+			g_value_set_object (value, loader->priv->stream);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -290,6 +298,15 @@ gedit_document_loader_class_init (GeditDocumentLoaderClass *klass)
 	                                                    G_PARAM_STATIC_NAME |
 	                                                    G_PARAM_STATIC_BLURB));
 
+	g_object_class_install_property (object_class,
+					 PROP_STREAM,
+					 g_param_spec_object ("stream",
+							      "STREAM",
+							      "The STREAM this GeditDocumentLoader loads the document from",
+							      G_TYPE_INPUT_STREAM,
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT_ONLY));
+
 	signals[LOADING] =
 		g_signal_new ("loading",
 			      G_OBJECT_CLASS_TYPE (object_class),
@@ -318,6 +335,21 @@ gedit_document_loader_init (GeditDocumentLoader *loader)
 }
 
 GeditDocumentLoader *
+gedit_document_loader_new_from_stream (GeditDocument       *doc,
+                                       GInputStream        *stream,
+                                       const GeditEncoding *encoding)
+{
+	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
+	g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
+
+	return GEDIT_DOCUMENT_LOADER (g_object_new (GEDIT_TYPE_DOCUMENT_LOADER,
+						    "document", doc,
+						    "stream", stream,
+						    "encoding", encoding,
+						    NULL));
+}
+
+GeditDocumentLoader *
 gedit_document_loader_new (GeditDocument       *doc,
 			   GFile               *location,
 			   const GeditEncoding *encoding)
@@ -356,14 +388,18 @@ get_metadata_encoding (GeditDocumentLoader *loader)
 {
 	const GeditEncoding *enc = NULL;
 
+	if (loader->priv->location == NULL)
+	{
+		/* If we are reading from a stream directly, then there is
+		   nothing to do */
+		return NULL;
+	}
+
 #ifndef ENABLE_GVFS_METADATA
 	gchar *charset;
-	GFile *location;
 	gchar *uri;
 
-	location = gedit_document_loader_get_location (loader);
-	uri = g_file_get_uri (location);
-	g_object_unref (location);
+	uri = g_file_get_uri (loader->priv->location);
 
 	charset = gedit_metadata_manager_get (uri, "encoding");
 	g_free (uri);
@@ -541,6 +577,25 @@ async_read_cb (GInputStream *stream,
 		return;
 	}
 
+	if (loader->priv->guess_content_type_from_content &&
+	    async->read > 0 &&
+	    loader->priv->bytes_read == 0)
+	{
+		gchar *guessed;
+
+		guessed = g_content_type_guess (NULL,
+		                                (guchar *)loader->priv->buffer,
+		                                async->read,
+		                                NULL);
+
+		if (guessed != NULL)
+		{
+			g_file_info_set_attribute_string (loader->priv->info,
+			                                  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+			                                  guessed);
+		}
+	}
+
 	/* Bump the size. */
 	loader->priv->bytes_read += async->read;
 
@@ -615,30 +670,16 @@ get_candidate_encodings (GeditDocumentLoader *loader)
 }
 
 static void
-finish_query_info (AsyncData *async)
+start_stream_read (AsyncData *async)
 {
-	GeditDocumentLoader *loader;
-	GFileInfo *info;
 	GSList *candidate_encodings;
+	GeditDocumentLoader *loader;
 	GInputStream *base_stream;
-	
+	GFileInfo *info;
+
 	loader = async->loader;
 	info = loader->priv->info;
 
-	/* if it's not a regular file, error out... */
-	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
-	    g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
-	{
-		g_set_error (&loader->priv->error,
-			     G_IO_ERROR,
-			     G_IO_ERROR_NOT_REGULAR_FILE,
-			     "Not a regular file");
-
-		loader_load_completed_or_failed (loader, async);
-
-		return;
-	}
-
 	/* Get the candidate encodings */
 	if (loader->priv->encoding == NULL)
 	{
@@ -646,7 +687,7 @@ finish_query_info (AsyncData *async)
 	}
 	else
 	{
-		candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->priv->encoding);
+		candidate_encodings = g_slist_prepend (NULL, (gpointer)loader->priv->encoding);
 	}
 
 	loader->priv->converter = gedit_smart_charset_converter_new (candidate_encodings);
@@ -682,6 +723,32 @@ finish_query_info (AsyncData *async)
 }
 
 static void
+finish_query_info (AsyncData *async)
+{
+	GeditDocumentLoader *loader;
+	GFileInfo *info;
+	
+	loader = async->loader;
+	info = loader->priv->info;
+
+	/* if it's not a regular file, error out... */
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
+	    g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
+	{
+		g_set_error (&loader->priv->error,
+			     G_IO_ERROR,
+			     G_IO_ERROR_NOT_REGULAR_FILE,
+			     "Not a regular file");
+
+		loader_load_completed_or_failed (loader, async);
+
+		return;
+	}
+
+	start_stream_read (async);
+}
+
+static void
 query_info_cb (GFile        *source,
 	       GAsyncResult *res,
 	       AsyncData    *async)
@@ -882,8 +949,18 @@ gedit_document_loader_load (GeditDocumentLoader *loader)
 
 	loader->priv->cancellable = g_cancellable_new ();
 	async = async_data_new (loader);
-	
-	open_async_read (async);
+
+	if (loader->priv->stream)
+	{
+		loader->priv->guess_content_type_from_content = TRUE;
+		loader->priv->info = g_file_info_new ();
+
+		start_stream_read (async);
+	}
+	else
+	{
+		open_async_read (async);
+	}
 }
 
 gboolean
@@ -916,13 +993,19 @@ gedit_document_loader_get_document (GeditDocumentLoader *loader)
 	return loader->priv->document;
 }
 
-/* Returns STDIN_URI if loading from stdin */
 GFile *
 gedit_document_loader_get_location (GeditDocumentLoader *loader)
 {
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL);
 
-	return g_file_dup (loader->priv->location);
+	if (loader->priv->location)
+	{
+		return g_file_dup (loader->priv->location);
+	}
+	else
+	{
+		return NULL;
+	}
 }
 
 goffset
diff --git a/gedit/gedit-document-loader.h b/gedit/gedit-document-loader.h
index 644af20..33bcaf0 100644
--- a/gedit/gedit-document-loader.h
+++ b/gedit/gedit-document-loader.h
@@ -93,9 +93,11 @@ void			 gedit_document_loader_loading		(GeditDocumentLoader *loader,
 								 GError              *error);
 
 void			 gedit_document_loader_load		(GeditDocumentLoader *loader);
-#if 0
-gboolean		 gedit_document_loader_load_from_stdin	(GeditDocumentLoader *loader);
-#endif		 
+
+GeditDocumentLoader	*gedit_document_loader_new_from_stream	(GeditDocument       *doc,
+								 GInputStream        *stream,
+								 const GeditEncoding *encoding);
+
 gboolean		 gedit_document_loader_cancel		(GeditDocumentLoader *loader);
 
 GeditDocument		*gedit_document_loader_get_document	(GeditDocumentLoader *loader);
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 4572a26..7a9dd1d 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -1460,6 +1460,38 @@ gedit_document_load_real (GeditDocument       *doc,
 	gedit_document_loader_load (doc->priv->loader);
 }
 
+void
+gedit_document_load_stream (GeditDocument       *doc,
+                            GInputStream        *stream,
+                            const GeditEncoding *encoding,
+                            gint                 line_pos,
+                            gint                 column_pos)
+{
+	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
+	g_return_if_fail (G_IS_INPUT_STREAM (stream));
+	g_return_if_fail (doc->priv->loader == NULL);
+
+	gedit_debug_message (DEBUG_DOCUMENT, "load stream");
+
+	/* create a loader. It will be destroyed when loading is completed */
+	doc->priv->loader = gedit_document_loader_new_from_stream (doc, stream, encoding);
+
+	g_signal_connect (doc->priv->loader,
+			  "loading",
+			  G_CALLBACK (document_loader_loading),
+			  doc);
+
+	doc->priv->create = FALSE;
+	doc->priv->requested_encoding = encoding;
+	doc->priv->requested_line_pos = line_pos;
+	doc->priv->requested_column_pos = column_pos;
+
+	set_location (doc, NULL);
+	set_content_type (doc, NULL);
+
+	gedit_document_loader_load (doc->priv->loader);
+}
+
 /**
  * gedit_document_load:
  * @doc: the #GeditDocument.
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index fe6b623..b5a80ed 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -209,6 +209,12 @@ void		 gedit_document_load 		(GeditDocument       *doc,
 						 gint                 column_pos,
 						 gboolean             create);
 
+void		 gedit_document_load_stream	(GeditDocument       *doc,
+						 GInputStream        *stream,
+						 const GeditEncoding *encoding,
+						 gint                 line_pos,
+						 gint                 column_pos);
+
 gboolean	 gedit_document_load_cancel	(GeditDocument       *doc);
 
 void		 gedit_document_save 		(GeditDocument       *doc,
diff --git a/gedit/gedit-fifo.c b/gedit/gedit-fifo.c
new file mode 100644
index 0000000..94c2d62
--- /dev/null
+++ b/gedit/gedit-fifo.c
@@ -0,0 +1,411 @@
+/*
+ * gedit-fifo.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#include "gedit-fifo.h"
+#include <stdio.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <errno.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#define GEDIT_FIFO_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_FIFO, GeditFifoPrivate))
+
+/* Properties */
+enum
+{
+	PROP_0,
+	PROP_FILE
+};
+
+typedef enum
+{
+	GEDIT_FIFO_OPEN_MODE_READ,
+	GEDIT_FIFO_OPEN_MODE_WRITE
+} GeditFifoOpenMode;
+
+struct _GeditFifoPrivate
+{
+	GFile *file;
+	GeditFifoOpenMode open_mode;
+};
+
+static void gedit_fifo_initable_iface_init (gpointer giface, gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (GeditFifo,
+                         gedit_fifo,
+                         G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gedit_fifo_initable_iface_init))
+
+static gboolean
+gedit_fifo_initable_init (GInitable     *initable,
+                          GCancellable  *cancellable,
+                          GError       **error)
+{
+	g_return_val_if_fail (GEDIT_IS_FIFO (initable), FALSE);
+
+	if (cancellable && g_cancellable_set_error_if_cancelled (cancellable, error))
+	{
+		return FALSE;
+	}
+
+	return GEDIT_FIFO (initable)->priv->file != NULL;
+}
+
+static void
+gedit_fifo_initable_iface_init (gpointer giface, gpointer iface_data)
+{
+	GInitableIface *iface = giface;
+
+	iface->init = gedit_fifo_initable_init;
+}
+
+static void
+gedit_fifo_finalize (GObject *object)
+{
+	GeditFifo *self = GEDIT_FIFO (object);
+
+	if (self->priv->file)
+	{
+		if (self->priv->open_mode == GEDIT_FIFO_OPEN_MODE_WRITE)
+		{
+			gchar *path = g_file_get_path (self->priv->file);
+			g_unlink (path);
+			g_free (path);
+		}
+
+		g_object_unref (self->priv->file);
+	}
+
+	G_OBJECT_CLASS (gedit_fifo_parent_class)->finalize (object);
+}
+
+static void
+gedit_fifo_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	GeditFifo *self = GEDIT_FIFO (object);
+	
+	switch (prop_id)
+	{
+		case PROP_FILE:
+			self->priv->file = g_value_dup_object (value);
+		break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gedit_fifo_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	GeditFifo *self = GEDIT_FIFO (object);
+	
+	switch (prop_id)
+	{
+		case PROP_FILE:
+			g_value_set_object (value, self->priv->file);
+		break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+init_fifo (GeditFifo *fifo)
+{
+	gchar tmpl[] = "gedit-fifo.XXXXXX";
+	gchar *tmp;
+	gint fd;
+	GError *error = NULL;
+
+	fd = g_file_open_tmp (tmpl, &tmp, &error);
+
+	if (fd == -1)
+	{
+		g_warning ("Could not generate temporary name for fifo: %s",
+		           error->message);
+		g_error_free (error);
+
+		return;
+	}
+
+	close (fd);
+
+	if (g_unlink (tmp) == -1)
+	{
+		return;
+	}
+
+	if (mkfifo (tmp, 0600) == -1)
+	{
+		g_warning ("Could not create named pipe for standard in: %s",
+		           strerror (errno));
+		return;
+	}
+
+	fifo->priv->file = g_file_new_for_path (tmp);
+}
+
+static void
+gedit_fifo_constructed (GObject *object)
+{
+	GeditFifo *self = GEDIT_FIFO (object);
+
+	if (!self->priv->file)
+	{
+		init_fifo (self);
+	}
+	else if (!g_file_query_exists (self->priv->file, NULL))
+	{
+		g_object_unref (self->priv->file);
+		self->priv->file = NULL;
+	}
+}
+
+static void
+gedit_fifo_class_init (GeditFifoClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gedit_fifo_finalize;
+
+	object_class->set_property = gedit_fifo_set_property;
+	object_class->get_property = gedit_fifo_get_property;
+
+	object_class->constructed = gedit_fifo_constructed;
+
+	g_object_class_install_property (object_class, PROP_FILE,
+				 g_param_spec_object ("file",
+						      "FILE",
+						      "The fifo file",
+						      G_TYPE_FILE,
+						      G_PARAM_READWRITE |
+						      G_PARAM_CONSTRUCT_ONLY |
+						      G_PARAM_STATIC_STRINGS));
+
+	g_type_class_add_private (object_class, sizeof(GeditFifoPrivate));
+}
+
+static void
+gedit_fifo_init (GeditFifo *self)
+{
+	self->priv = GEDIT_FIFO_GET_PRIVATE (self);
+}
+
+GeditFifo *
+gedit_fifo_new (GFile *file)
+{
+	return g_initable_new (GEDIT_TYPE_FIFO, NULL, NULL, "file", file, NULL);
+}
+
+static void
+fifo_open_in_thread (GSimpleAsyncResult *res,
+                     GObject            *object,
+                     GCancellable       *cancellable)
+{
+	GError *error = NULL;
+	gchar *path;
+	gint fd;
+	GeditFifo *fifo;
+	gpointer stream;
+	gint flags = 0;
+
+	if (cancellable && g_cancellable_set_error_if_cancelled (cancellable, &error))
+	{
+		g_simple_async_result_set_from_error (res, error);
+		g_error_free (error);
+		return;
+	}
+
+	fifo = GEDIT_FIFO (object);
+	
+	switch (fifo->priv->open_mode)
+	{
+		case GEDIT_FIFO_OPEN_MODE_READ:
+			flags = O_RDONLY;
+		break;
+		case GEDIT_FIFO_OPEN_MODE_WRITE:
+			flags = O_WRONLY;
+		break;
+	}
+	
+	path = g_file_get_path (fifo->priv->file);
+	fd = g_open (path, flags, 0);
+	g_free (path);
+
+	if (cancellable && g_cancellable_set_error_if_cancelled (cancellable, &error))
+	{
+		if (fd != -1)
+		{
+			close (fd);
+		}
+
+		g_simple_async_result_set_from_error (res, error);
+		g_error_free (error);
+		return;
+	}
+
+	if (fd == -1)
+	{
+		g_simple_async_result_set_error (res,
+		                                 G_IO_ERROR,
+		                                 g_io_error_from_errno (errno),
+		                                 "%s",
+		                                 strerror (errno));
+		return;
+	}
+
+	if (fifo->priv->open_mode == GEDIT_FIFO_OPEN_MODE_WRITE)
+	{
+		stream = g_unix_output_stream_new (fd, TRUE);
+	}
+	else
+	{
+		stream = g_unix_input_stream_new (fd, TRUE);
+	}
+
+	g_simple_async_result_set_op_res_gpointer (res,
+	                                           stream,
+	                                           (GDestroyNotify)g_object_unref);
+}
+
+static void
+async_open (GeditFifo           *fifo,
+            GeditFifoOpenMode    open_mode,
+            gint                 io_priority,
+            GCancellable        *cancellable,
+            GAsyncReadyCallback  callback,
+            gpointer             user_data)
+{
+	GSimpleAsyncResult *ret;
+
+	fifo->priv->open_mode = open_mode;
+
+	ret = g_simple_async_result_new (G_OBJECT (fifo),
+	                                 callback,
+	                                 user_data,
+	                                 fifo_open_in_thread);
+
+	g_simple_async_result_run_in_thread (ret,
+	                                     fifo_open_in_thread,
+	                                     io_priority,
+	                                     cancellable);
+}
+
+GInputStream *
+gedit_fifo_open_read_finish (GeditFifo     *fifo,
+                             GAsyncResult  *result,
+                             GError       **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (GEDIT_IS_FIFO (fifo), NULL);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result,
+	                                                      G_OBJECT (fifo),
+	                                                      fifo_open_in_thread),
+	                      NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+	{
+		return NULL;
+	}
+
+	return G_INPUT_STREAM (g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)));
+}
+
+GOutputStream *
+gedit_fifo_open_write_finish (GeditFifo     *fifo,
+                              GAsyncResult  *result,
+                              GError       **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (GEDIT_IS_FIFO (fifo), NULL);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result,
+	                                                      G_OBJECT (fifo),
+	                                                      fifo_open_in_thread),
+	                      NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+	{
+		return NULL;
+	}
+
+	return G_OUTPUT_STREAM (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+void
+gedit_fifo_open_read_async (GeditFifo           *fifo,
+                            gint                 io_priority,
+                            GCancellable        *cancellable,
+                            GAsyncReadyCallback  callback,
+                            gpointer             user_data)
+{
+	g_return_if_fail (GEDIT_IS_FIFO (fifo));
+
+	async_open (fifo,
+	            GEDIT_FIFO_OPEN_MODE_READ,
+	            io_priority,
+	            cancellable,
+	            callback,
+	            user_data);
+}
+
+void
+gedit_fifo_open_write_async (GeditFifo           *fifo,
+                             gint                 io_priority,
+                             GCancellable        *cancellable,
+                             GAsyncReadyCallback  callback,
+                             gpointer             user_data)
+{
+	g_return_if_fail (GEDIT_IS_FIFO (fifo));
+
+	async_open (fifo,
+	            GEDIT_FIFO_OPEN_MODE_WRITE,
+	            io_priority,
+	            cancellable,
+	            callback,
+	            user_data);
+}
+
+GFile *
+gedit_fifo_get_file (GeditFifo *fifo)
+{
+	g_return_val_if_fail (GEDIT_IS_FIFO (fifo), NULL);
+
+	return g_file_dup (fifo->priv->file);
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-fifo.h b/gedit/gedit-fifo.h
new file mode 100644
index 0000000..e3f7ff4
--- /dev/null
+++ b/gedit/gedit-fifo.h
@@ -0,0 +1,82 @@
+/*
+ * gedit-fifo.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GEDIT_FIFO_H__
+#define __GEDIT_FIFO_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_FIFO				(gedit_fifo_get_type ())
+#define GEDIT_FIFO(obj)				(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FIFO, GeditFifo))
+#define GEDIT_FIFO_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FIFO, GeditFifo const))
+#define GEDIT_FIFO_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FIFO, GeditFifoClass))
+#define GEDIT_IS_FIFO(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FIFO))
+#define GEDIT_IS_FIFO_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FIFO))
+#define GEDIT_FIFO_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FIFO, GeditFifoClass))
+
+typedef struct _GeditFifo			GeditFifo;
+typedef struct _GeditFifoClass		GeditFifoClass;
+typedef struct _GeditFifoPrivate	GeditFifoPrivate;
+
+struct _GeditFifo {
+	GObject parent;
+	
+	GeditFifoPrivate *priv;
+};
+
+struct _GeditFifoClass {
+	GObjectClass parent_class;
+};
+
+GType gedit_fifo_get_type (void) G_GNUC_CONST;
+
+GeditFifo *gedit_fifo_new (GFile *file);
+GFile *gedit_fifo_get_file (GeditFifo *fifo);
+
+void gedit_fifo_open_read_async (GeditFifo           *fifo,
+                                 gint                 io_priority,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data);
+
+void gedit_fifo_open_write_async (GeditFifo           *fifo,
+                                  gint                 io_priority,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data);
+
+GOutputStream *gedit_fifo_open_write_finish (GeditFifo     *fifo,
+                                             GAsyncResult  *result,
+                                             GError       **error);
+
+GInputStream *gedit_fifo_open_read_finish (GeditFifo     *fifo,
+                                           GAsyncResult  *result,
+                                           GError       **error);
+
+G_END_DECLS
+
+#endif /* __GEDIT_FIFO_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index 07f0ca4..e3ba9a1 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -944,7 +944,10 @@ document_loaded (GeditDocument *document,
 		}
 		else
 		{
-			_gedit_recent_remove (GEDIT_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), location);
+			if (location)
+			{
+				_gedit_recent_remove (GEDIT_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), location);
+			}
 
 			if (tab->priv->state == GEDIT_TAB_STATE_LOADING_ERROR)
 			{
@@ -982,23 +985,28 @@ document_loaded (GeditDocument *document,
 
 		gtk_widget_show (emsg);
 
-		g_object_unref (location);
+		if (location)
+		{
+			g_object_unref (location);
+		}
 
 		return;
 	}
 	else
 	{
-		gchar *mime;
 		GList *all_documents;
 		GList *l;
 
-		g_return_if_fail (location != NULL);
+		if (location != NULL)
+		{
+			gchar *mime;
+			mime = gedit_document_get_mime_type (document);
 
-		mime = gedit_document_get_mime_type (document);
-		_gedit_recent_add (GEDIT_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))),
-				   location,
-				   mime);
-		g_free (mime);
+			_gedit_recent_add (GEDIT_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))),
+					   location,
+					   mime);
+			g_free (mime);
+		}
 
 		if (error &&
 		    error->domain == GEDIT_DOCUMENT_ERROR &&
@@ -1045,7 +1053,7 @@ document_loaded (GeditDocument *document,
 
 				loc = gedit_document_get_location (d);
 
-				if ((loc != NULL) &&
+				if (loc != NULL && location != NULL &&
 			    	    g_file_equal (location, loc))
 			    	{
 			    		GtkWidget *w;
@@ -1086,14 +1094,24 @@ document_loaded (GeditDocument *document,
 		g_list_free (all_documents);
 
 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
-		
+
+		if (location == NULL)
+		{
+			/* FIXME: hackish */
+			gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (gedit_tab_get_document (tab)),
+			                              TRUE);
+		}
+
 		install_auto_save_timeout_if_needed (tab);
 
 		tab->priv->ask_if_externally_modified = TRUE;
 	}
 
  end:
-	g_object_unref (location);
+ 	if (location)
+ 	{
+		g_object_unref (location);
+	}
 
 	tab->priv->tmp_line_pos = 0;
 	tab->priv->tmp_encoding = NULL;
@@ -1653,6 +1671,28 @@ _gedit_tab_new_from_location (GFile               *location,
 	return GTK_WIDGET (tab);
 }
 
+GtkWidget *
+_gedit_tab_new_from_stream (GInputStream        *stream,
+                            const GeditEncoding *encoding,
+                            gint                 line_pos,
+                            gint                 column_pos)
+{
+	GeditTab *tab;
+
+	g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
+
+	tab = GEDIT_TAB (_gedit_tab_new ());
+
+	_gedit_tab_load_stream (tab,
+	                        stream,
+	                        encoding,
+	                        line_pos,
+	                        column_pos);
+
+	return GTK_WIDGET (tab);
+
+}
+
 /**
  * gedit_tab_get_view:
  * @tab: a #GeditTab
@@ -2050,6 +2090,41 @@ _gedit_tab_load (GeditTab            *tab,
 }
 
 void
+_gedit_tab_load_stream (GeditTab            *tab,
+                        GInputStream        *stream,
+                        const GeditEncoding *encoding,
+                        gint                 line_pos,
+                        gint                 column_pos)
+{
+	GeditDocument *doc;
+
+	g_return_if_fail (GEDIT_IS_TAB (tab));
+	g_return_if_fail (G_IS_INPUT_STREAM (stream));
+	g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL);
+
+	doc = gedit_tab_get_document (tab);
+	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
+
+	gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
+
+	tab->priv->tmp_line_pos = line_pos;
+	tab->priv->tmp_column_pos = column_pos;
+	tab->priv->tmp_encoding = encoding;
+
+	if (tab->priv->auto_save_timeout > 0)
+	{
+		remove_auto_save_timeout (tab);
+	}
+
+	gedit_document_load_stream (doc,
+	                            stream,
+	                            encoding,
+	                            line_pos,
+	                            column_pos);
+
+}
+
+void
 _gedit_tab_revert (GeditTab *tab)
 {
 	GeditDocument *doc;
diff --git a/gedit/gedit-tab.h b/gedit/gedit-tab.h
index acb632f..f607a96 100644
--- a/gedit/gedit-tab.h
+++ b/gedit/gedit-tab.h
@@ -135,6 +135,12 @@ GtkWidget	*_gedit_tab_new_from_location	(GFile               *location,
 						 gint                 line_pos,
 						 gint                 column_pos,
 						 gboolean             create);
+
+GtkWidget	*_gedit_tab_new_from_stream	(GInputStream        *stream,
+						 const GeditEncoding *encoding,
+						 gint                 line_pos,
+						 gint                 column_pos);
+
 gchar 		*_gedit_tab_get_name		(GeditTab            *tab);
 gchar 		*_gedit_tab_get_tooltips	(GeditTab            *tab);
 GdkPixbuf 	*_gedit_tab_get_icon		(GeditTab            *tab);
@@ -144,6 +150,13 @@ void		 _gedit_tab_load		(GeditTab            *tab,
 						 gint                 line_pos,
 						 gint                 column_pos,
 						 gboolean             create);
+
+void		 _gedit_tab_load_stream		(GeditTab            *tab,
+						 GInputStream        *location,
+						 const GeditEncoding *encoding,
+						 gint                 line_pos,
+						 gint                 column_pos);
+
 void		 _gedit_tab_revert		(GeditTab            *tab);
 void		 _gedit_tab_save		(GeditTab            *tab);
 void		 _gedit_tab_save_as		(GeditTab            *tab,
diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c
index c6e7ef2..beddc24 100644
--- a/gedit/gedit-utils.c
+++ b/gedit/gedit-utils.c
@@ -58,6 +58,10 @@
 #include <X11/Xatom.h>
 #endif
 
+#ifdef G_OS_UNIX
+#include <unistd.h>
+#endif
+
 #include "gseal-gtk-compat.h"
 
 #define STDIN_DELAY_MICROSECONDS 100000
@@ -1525,4 +1529,14 @@ gedit_utils_decode_uri (const gchar *uri,
 	return TRUE;
 }
 
+gboolean
+gedit_utils_can_read_from_stdin (void)
+{
+#ifdef G_OS_UNIX
+	return !isatty (STDIN_FILENO);
+#else
+	return FALSE;
+#endif
+}
+
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h
index cbc50cd..7225a3f 100644
--- a/gedit/gedit-utils.h
+++ b/gedit/gedit-utils.h
@@ -155,6 +155,8 @@ gboolean	 gedit_utils_decode_uri 		(const gchar *uri,
 /* Turns data from a drop into a list of well formatted uris */
 gchar 	       **gedit_utils_drop_get_uris		(GtkSelectionData *selection_data);
 
+gboolean	 gedit_utils_can_read_from_stdin	(void);
+
 G_END_DECLS
 
 #endif /* __GEDIT_UTILS_H__ */
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index fac316c..69f2255 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -1238,15 +1238,18 @@ open_recent_file (GFile       *location,
 		  GeditWindow *window)
 {
 	GSList *locations = NULL;
+	GSList *loaded = NULL;
 
 	locations = g_slist_prepend (locations, (gpointer) location);
-
-	if (gedit_commands_load_locations (window, locations, NULL, 0, 0) != 1)
+	loaded = gedit_commands_load_locations (window, locations, NULL, 0, 0);
+	
+	if (!loaded || loaded->next) /* if it doesn't contain just 1 element */
 	{
 		_gedit_recent_remove (window, location);
 	}
 
 	g_slist_free (locations);
+	g_slist_free (loaded);
 }
 
 static void
@@ -2873,7 +2876,8 @@ load_uris_from_drop (GeditWindow  *window,
 {
 	GSList *locations = NULL;
 	gint i;
-	
+	GSList *loaded;
+
 	if (uri_list == NULL)
 		return;
 	
@@ -2883,11 +2887,13 @@ load_uris_from_drop (GeditWindow  *window,
 	}
 
 	locations = g_slist_reverse (locations);
-	gedit_commands_load_locations (window,
-				       locations,
-				       NULL,
-				       0,
-				       0);
+	loaded = gedit_commands_load_locations (window,
+	                                        locations,
+	                                        NULL,
+	                                        0,
+	                                        0);
+
+	g_slist_free (loaded);
 
 	g_slist_foreach (locations, (GFunc) g_object_unref, NULL);
 	g_slist_free (locations);
@@ -4235,6 +4241,31 @@ gedit_window_create_tab (GeditWindow *window,
 	return tab;
 }
 
+static GeditTab *
+process_create_tab (GeditWindow *window,
+                    GeditTab    *tab,
+                    gboolean     jump_to)
+{
+	if (tab == NULL)
+	{
+		return NULL;
+	}
+
+	gtk_widget_show (GTK_WIDGET (tab));
+	
+	gedit_notebook_add_tab (GEDIT_NOTEBOOK (window->priv->notebook),
+	                        tab,
+	                        -1,
+	                        jump_to);
+
+	if (!gtk_widget_get_visible (GTK_WIDGET (window)))
+	{
+		gtk_window_present (GTK_WINDOW (window));
+	}
+
+	return tab;
+}
+
 /**
  * gedit_window_create_tab_from_location:
  * @window: a #GeditWindow
@@ -4266,28 +4297,35 @@ gedit_window_create_tab_from_location (GeditWindow         *window,
 	g_return_val_if_fail (G_IS_FILE (location), NULL);
 
 	tab = _gedit_tab_new_from_location (location,
-					    encoding,
-					    line_pos,
-					    column_pos,
-					    create);
-	if (tab == NULL)
-		return NULL;
+	                                    encoding,
+	                                    line_pos,
+	                                    column_pos,
+	                                    create);
 
-	gtk_widget_show (tab);	
-	
-	gedit_notebook_add_tab (GEDIT_NOTEBOOK (window->priv->notebook),
-				GEDIT_TAB (tab),
-				-1,
-				jump_to);
+	return process_create_tab (window, GEDIT_TAB (tab), jump_to);
+}
+
+GeditTab *
+gedit_window_create_tab_from_stream (GeditWindow         *window,
+                                     GInputStream        *stream,
+                                     const GeditEncoding *encoding,
+                                     gint                 line_pos,
+                                     gint                 column_pos,
+                                     gboolean             jump_to)
+{
+	GtkWidget *tab;
 
+	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+	g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
 
-	if (!gtk_widget_get_visible (GTK_WIDGET (window)))
-	{
-		gtk_window_present (GTK_WINDOW (window));
-	}
+	tab = _gedit_tab_new_from_stream (stream,
+	                                  encoding,
+	                                  line_pos,
+	                                  column_pos);
 
-	return GEDIT_TAB (tab);
-}				  
+	return process_create_tab (window, GEDIT_TAB (tab), jump_to);
+
+}
 
 /**
  * gedit_window_get_active_tab:
diff --git a/gedit/gedit-window.h b/gedit/gedit-window.h
index 4e8c55a..84d056b 100644
--- a/gedit/gedit-window.h
+++ b/gedit/gedit-window.h
@@ -112,7 +112,14 @@ GeditTab	*gedit_window_create_tab_from_location	(GeditWindow         *window,
 							 gint                 column_pos,
 							 gboolean             create,
 							 gboolean             jump_to);
-							 
+
+GeditTab	*gedit_window_create_tab_from_stream	(GeditWindow         *window,
+							 GInputStream        *stream,
+							 const GeditEncoding *encoding,
+							 gint                 line_pos,
+							 gint                 column_pos,
+							 gboolean             jump_to);
+
 void		 gedit_window_close_tab			(GeditWindow         *window,
 							 GeditTab            *tab);
 							 
diff --git a/gedit/gedit.c b/gedit/gedit.c
index f517a2c..ba20b11 100644
--- a/gedit/gedit.c
+++ b/gedit/gedit.c
@@ -32,20 +32,18 @@
 #include <config.h>
 #endif
 
-#include <errno.h>
 #include <locale.h>
-#include <stdlib.h>
-#include <string.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
-#include <gtk/gtk.h>
 
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
+#include "gedit-command-line.h"
+#include "gedit-dbus.h"
 
 #include "gedit-app.h"
+#include "gedit-encodings.h"
+
+#include "gseal-gtk-compat.h"
 #include "gedit-commands.h"
 #include "gedit-debug.h"
 #include "gedit-dirs.h"
@@ -55,531 +53,170 @@
 #include "gedit-utils.h"
 #include "gedit-window.h"
 
-#include "eggsmclient.h"
-#include "eggdesktopfile.h"
-
-#include "gseal-gtk-compat.h"
-
-#ifdef G_OS_WIN32
-#define SAVE_DATADIR DATADIR
-#undef DATADIR
-#include <io.h>
-#include <conio.h>
-#define _WIN32_WINNT 0x0500
-#include <windows.h>
-#define DATADIR SAVE_DATADIR
-#undef SAVE_DATADIR
-#endif
-
-#ifdef OS_OSX
-#include <ige-mac-dock.h>
-#include <ige-mac-integration.h>
-#include "osx/gedit-osx.h"
-#endif
-
 #ifndef ENABLE_GVFS_METADATA
 #include "gedit-metadata-manager.h"
 #endif
 
-static guint32 startup_timestamp = 0;
-
-#ifndef G_OS_WIN32
-#include "bacon-message-connection.h"
-
-static BaconMessageConnection *connection;
+#ifdef G_OS_UNIX
+#include <gio/gunixinputstream.h>
+#include <unistd.h>
 #endif
 
-/* command line */
-static gint line_position = 0;
-static gint column_position = 0;
-static gchar *encoding_charset = NULL;
-static gboolean new_window_option = FALSE;
-static gboolean new_document_option = FALSE;
-static gchar **remaining_args = NULL;
-static GSList *file_list = NULL;
-
 static void
-show_version_and_quit (void)
+gedit_main_load_from_stdin (GeditWindow *window,
+                            gboolean jump_to)
 {
-	g_print ("%s - Version %s\n", g_get_application_name (), VERSION);
-
-	exit (0);
+#ifdef G_OS_UNIX
+	GInputStream *stream;
+	const GeditEncoding *encoding;
+	gint line_position;
+	gint column_position;
+	GeditCommandLine *command_line;
+
+	command_line = gedit_command_line_get_default ();
+
+	encoding = gedit_command_line_get_encoding (command_line);
+	line_position = gedit_command_line_get_line_position (command_line);
+	column_position = gedit_command_line_get_column_position (command_line);
+
+	/* Construct a stream for stdin */
+	stream = g_unix_input_stream_new (STDIN_FILENO, TRUE);
+
+	gedit_window_create_tab_from_stream (window,
+	                                     stream,
+	                                     encoding,
+	                                     line_position,
+	                                     column_position,
+	                                     jump_to);
+	g_object_unref (stream);
+#endif
 }
 
 static void
-list_encodings_and_quit (void)
-{
-	gint i = 0;
-	const GeditEncoding *enc;
-
-	while ((enc = gedit_encoding_get_from_index (i)) != NULL) 
-	{
-		g_print ("%s\n", gedit_encoding_get_charset (enc));
-
-		++i;
-	}
-
-	exit (0);
-}
-
-static const GOptionEntry options [] =
+gedit_main_window (void)
 {
-	{ "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
-	  show_version_and_quit, N_("Show the application's version"), NULL },
-
-	{ "encoding", '\0', 0, G_OPTION_ARG_STRING, &encoding_charset,
-	  N_("Set the character encoding to be used to open the files listed on the command line"), N_("ENCODING")},
-
-	{ "list-encodings", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
-	  list_encodings_and_quit, N_("Display list of possible values for the encoding option"), NULL},
-
-	{ "new-window", '\0', 0, G_OPTION_ARG_NONE, &new_window_option,
-	  N_("Create a new top-level window in an existing instance of gedit"), NULL },
-
-	{ "new-document", '\0', 0, G_OPTION_ARG_NONE, &new_document_option,
-	  N_("Create a new document in an existing instance of gedit"), NULL },
-
-	{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &remaining_args,
-	  NULL, N_("[FILE...] [+LINE[:COLUMN]]") }, /* collects file arguments */
-
-	{NULL}
-};
+	GSList *file_list;
+	GeditWindow *window;
+	GeditCommandLine *command_line;
+	GeditApp *app;
+	gboolean doc_created = FALSE;
+	const gchar *geometry;
 
-static void
-free_command_line_data (void)
-{
-	g_slist_foreach (file_list, (GFunc) g_object_unref, NULL);
-	g_slist_free (file_list);
-	file_list = NULL;
-
-	g_strfreev (remaining_args);
-	remaining_args = NULL;
-
-	g_free (encoding_charset);
-	encoding_charset = NULL;
-	
-	new_window_option = FALSE;
-	new_document_option = FALSE;
-	line_position = 0;
-	column_position = 0;
-}
+	app = gedit_app_get_default ();
 
-static void
-get_line_column_position (const gchar *arg)
-{
-	gchar **split;
+	gedit_debug_message (DEBUG_APP, "Create main window");
+	window = gedit_app_create_window (app, NULL);
 
-	split = g_strsplit (arg, ":", 2);
+	command_line = gedit_command_line_get_default ();
+	file_list = gedit_command_line_get_file_list (command_line);
 
-	if (split != NULL)
+	if (file_list != NULL)
 	{
-		if (split[0] != NULL)
-			line_position = atoi (split[0]);
-
-		if (split[1] != NULL)
-			column_position = atoi (split[1]);
+		GSList *loaded;
+		const GeditEncoding *encoding;
+		gint line_position;
+		gint column_position;
+
+		encoding = gedit_command_line_get_encoding (command_line);
+		line_position = gedit_command_line_get_line_position (command_line);
+		column_position = gedit_command_line_get_column_position (command_line);
+
+		gedit_debug_message (DEBUG_APP, "Load files");
+		loaded = _gedit_cmd_load_files_from_prompt (window,
+		                                            file_list,
+		                                            encoding,
+		                                            line_position,
+		                                            column_position);
+
+		doc_created = loaded != NULL;
+		g_slist_free (loaded);
 	}
 
-	g_strfreev (split);
-}
-
-static void
-gedit_get_command_line_data (void)
-{
-	if (remaining_args)
+	if (gedit_utils_can_read_from_stdin ())
 	{
-		gint i;
-
-		for (i = 0; remaining_args[i]; i++) 
-		{
-			if (*remaining_args[i] == '+')
-			{
-				if (*(remaining_args[i] + 1) == '\0')
-				{
-					/* goto the last line of the document */
-					line_position = G_MAXINT;
-					column_position = 0;
-				}
-				else
-					get_line_column_position (remaining_args[i] + 1);
-			}
-			else
-			{
-				GFile *file;
-
-				file = g_file_new_for_commandline_arg (remaining_args[i]);
-				file_list = g_slist_prepend (file_list, file);
-			} 
-		}
-
-		file_list = g_slist_reverse (file_list);
+		gedit_main_load_from_stdin (window, !doc_created);
+		doc_created = TRUE;
 	}
-	
-	if (encoding_charset &&
-	    (gedit_encoding_get_from_charset (encoding_charset) == NULL))
+
+	if (!doc_created || gedit_command_line_get_new_document (command_line))
 	{
-		g_print (_("%s: invalid encoding.\n"),
-			 encoding_charset);
+		gedit_debug_message (DEBUG_APP, "Create tab");
+		gedit_window_create_tab (window, TRUE);
 	}
-}
-
-static guint32
-get_startup_timestamp (void)
-{
-	const gchar *startup_id_env;
-	gchar *startup_id = NULL;
-	gchar *time_str;
-	gchar *end;
-	gulong retval = 0;
-
-	/* we don't unset the env, since startup-notification
-	 * may still need it */
-	startup_id_env = g_getenv ("DESKTOP_STARTUP_ID");
-	if (startup_id_env == NULL)
-		goto out;
-
-	startup_id = g_strdup (startup_id_env);
-
-	time_str = g_strrstr (startup_id, "_TIME");
-	if (time_str == NULL)
-		goto out;
-
-	errno = 0;
-
-	/* Skip past the "_TIME" part */
-	time_str += 5;
-
-	retval = strtoul (time_str, &end, 0);
-	if (end == time_str || errno != 0)
-		retval = 0;
-
- out:
-	g_free (startup_id);
 
-	return (retval > 0) ? retval : 0;
-}
-
-#ifndef G_OS_WIN32
-static GdkDisplay *
-display_open_if_needed (const gchar *name)
-{
-	GSList *displays;
-	GSList *l;
-	GdkDisplay *display = NULL;
+	geometry = gedit_command_line_get_geometry (command_line);
 
-	displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+	gedit_debug_message (DEBUG_APP, "Show window");
+	gtk_widget_show (GTK_WIDGET (window));
 
-	for (l = displays; l != NULL; l = l->next)
+	if (geometry)
 	{
-		if (strcmp (gdk_display_get_name ((GdkDisplay *) l->data), name) == 0)
-		{
-			display = l->data;
-			break;
-		}
+		gtk_window_parse_geometry (GTK_WINDOW (window),
+		                           geometry);
 	}
-
-	g_slist_free (displays);
-
-	return display != NULL ? display : gdk_display_open (name);
 }
 
-/* serverside */
 static void
-on_message_received (const char *message,
-		     gpointer    data)
+gedit_main (gboolean service)
 {
-	const GeditEncoding *encoding = NULL;
-	gchar **commands;
-	gchar **params;
-	gint workspace;
-	gint viewport_x;
-	gint viewport_y;
-	gchar *display_name;
-	gint screen_number;
-	gint i;
+	GeditPluginsEngine *engine;
 	GeditApp *app;
-	GeditWindow *window;
-	GdkDisplay *display;
-	GdkScreen *screen;
-
-	g_return_if_fail (message != NULL);
-
-	gedit_debug_message (DEBUG_APP, "Received message:\n%s\n", message);
-
-	commands = g_strsplit (message, "\v", -1);
-
-	/* header */
-	params = g_strsplit (commands[0], "\t", 6);
-	startup_timestamp = atoi (params[0]);
-	display_name = params[1];
-	screen_number = atoi (params[2]);
-	workspace = atoi (params[3]);
-	viewport_x = atoi (params[4]);
-	viewport_y = atoi (params[5]);
+	gboolean restored = FALSE;
+	gchar *dir;
+	gchar *icon_dir;
 
-	display = display_open_if_needed (display_name);
-	if (display == NULL)
-	{
-		g_warning ("Could not open display %s\n", display_name);
-		g_strfreev (params);
-		goto out;
-	}
+	gedit_debug_message (DEBUG_APP, "Set icon");
 
-	screen = gdk_display_get_screen (display, screen_number);
+	dir = gedit_dirs_get_gedit_data_dir ();
+	icon_dir = g_build_filename (dir, "icons", NULL);
+	g_free (dir);
 
-	g_strfreev (params);
+	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir);
+	g_free (icon_dir);
 
-	/* body */
-	for (i = 1; commands[i] != NULL; i++)
-	{
-		params = g_strsplit (commands[i], "\t", -1);
-
-		if (strcmp (params[0], "NEW-WINDOW") == 0)
-		{
-			new_window_option = TRUE;
-		}
-		else if (strcmp (params[0], "NEW-DOCUMENT") == 0)
-		{
-			new_document_option = TRUE;
-		}
-		else if (strcmp (params[0], "OPEN-URIS") == 0)
-		{
-			gint n_uris, j;
-			gchar **uris;
-
-			get_line_column_position (params[1]);
-
-			if (params[2] != '\0')
-				encoding = gedit_encoding_get_from_charset (params[2]);
-
-			n_uris = atoi (params[3]);
-			uris = g_strsplit (params[4], " ", n_uris);
-
-			for (j = 0; j < n_uris; j++)
-			{
-				GFile *file;
-
-				file = g_file_new_for_uri (uris[j]);
-				file_list = g_slist_prepend (file_list, file);
-			}
-
-			file_list = g_slist_reverse (file_list);
-
-			/* the list takes ownerhip of the strings,
-			 * only free the array */
-			g_free (uris);
-		}
-		else
-		{
-			g_warning ("Unexpected bacon command");
-		}
-
-		g_strfreev (params);
-	}
+	/* Init plugins engine */
+	gedit_debug_message (DEBUG_APP, "Init plugins");
+	engine = gedit_plugins_engine_get_default ();
 
-	/* execute the commands */
+	gtk_about_dialog_set_url_hook (gedit_utils_activate_url, NULL, NULL);
 
 	app = gedit_app_get_default ();
 
-	if (new_window_option)
-	{
-		window = gedit_app_create_window (app, screen);
-	}
-	else
-	{
-		/* get a window in the current workspace (if exists) and raise it */
-		window = _gedit_app_get_window_in_viewport (app,
-							    screen,
-							    workspace,
-							    viewport_x,
-							    viewport_y);
-	}
-
-	if (file_list != NULL)
-	{
-		_gedit_cmd_load_files_from_prompt (window,
-						   file_list,
-						   encoding,
-						   line_position,
-						   column_position);
-
-		if (new_document_option)
-			gedit_window_create_tab (window, TRUE);
-	}
-	else
-	{
-		GeditDocument *doc;
-		doc = gedit_window_get_active_document (window);
-
-		if (doc == NULL ||
-		    !gedit_document_is_untouched (doc) ||
-		    new_document_option)
-			gedit_window_create_tab (window, TRUE);
-	}
-
-	/* set the proper interaction time on the window.
-	 * Fall back to roundtripping to the X server when we
-	 * don't have the timestamp, e.g. when launched from
-	 * terminal. We also need to make sure that the window
-	 * has been realized otherwise it will not work. lame.
-	 */
-	if (!gtk_widget_get_realized (GTK_WIDGET (window)))
-		gtk_widget_realize (GTK_WIDGET (window));
-
-#ifdef GDK_WINDOWING_X11
-	if (startup_timestamp <= 0)
-		startup_timestamp = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
-
-	gdk_x11_window_set_user_time (gtk_widget_get_window (GTK_WIDGET (window)),
-				      startup_timestamp);
-#endif
-
-	gtk_window_present (GTK_WINDOW (window));
-
- out:
-	g_strfreev (commands);
-	
-	free_command_line_data ();
-}
-
-/* clientside */
-static void
-send_bacon_message (void)
-{
-	GdkScreen *screen;
-	GdkDisplay *display;
-	const gchar *display_name;
-	gint screen_number;
-	gint ws;
-	gint viewport_x;
-	gint viewport_y;
-	GString *command;
-
-	/* the messages have the following format:
-	 * <---                                  header                                     ---> <----            body             ----->
-	 * timestamp \t display_name \t screen_number \t workspace \t viewport_x \t viewport_y \v OP1 \t arg \t arg \v OP2 \t arg \t arg|...
-	 *
-	 * when the arg is a list of uri, they are separated by a space.
-	 * So the delimiters are \v for the commands, \t for the tokens in
-	 * a command and ' ' for the uris: note that such delimiters cannot
-	 * be part of an uri, this way parsing is easier.
-	 */
-
-	gedit_debug (DEBUG_APP);
-
-	screen = gdk_screen_get_default ();
-	display = gdk_screen_get_display (screen);
-
-	display_name = gdk_display_get_name (display);
-	screen_number = gdk_screen_get_number (screen);
-
-	gedit_debug_message (DEBUG_APP, "Display: %s", display_name);
-	gedit_debug_message (DEBUG_APP, "Screen: %d", screen_number);	
-
-	ws = gedit_utils_get_current_workspace (screen);
-	gedit_utils_get_current_viewport (screen, &viewport_x, &viewport_y);
-
-	command = g_string_new (NULL);
-
-	/* header */
-	g_string_append_printf (command,
-				"%" G_GUINT32_FORMAT "\t%s\t%d\t%d\t%d\t%d",
-				startup_timestamp,
-				display_name,
-				screen_number,
-				ws,
-				viewport_x,
-				viewport_y);
-
-	/* NEW-WINDOW command */
-	if (new_window_option)
-	{
-		command = g_string_append_c (command, '\v');
-		command = g_string_append (command, "NEW-WINDOW");
-	}
+	/* Initialize session management */
+	gedit_debug_message (DEBUG_APP, "Init session manager");
+	gedit_session_init ();
 
-	/* NEW-DOCUMENT command */
-	if (new_document_option)
+	if (!service && gedit_session_is_restored ())
 	{
-		command = g_string_append_c (command, '\v');
-		command = g_string_append (command, "NEW-DOCUMENT");
+		restored = gedit_session_load ();
 	}
 
-	/* OPEN_URIS command, optionally specify line_num and encoding */
-	if (file_list)
+	if (!service && !restored)
 	{
-		GSList *l;
-
-		command = g_string_append_c (command, '\v');
-		command = g_string_append (command, "OPEN-URIS");
-
-		g_string_append_printf (command,
-					"\t%d:%d\t%s\t%u\t",
-					line_position, column_position,
-					encoding_charset ? encoding_charset : "",
-					g_slist_length (file_list));
-
-		for (l = file_list; l != NULL; l = l->next)
-		{
-			gchar *uri;
-
-			uri = g_file_get_uri (G_FILE (l->data));
-			command = g_string_append (command, uri);
-			if (l->next != NULL)
-				command = g_string_append_c (command, ' ');
-
-			g_free (uri);
-		}
+		gedit_main_window ();
 	}
 
-	gedit_debug_message (DEBUG_APP, "Bacon Message: %s", command->str);
-	
-	bacon_message_connection_send (connection,
-				       command->str);
-
-	g_string_free (command, TRUE);
-}
-#endif /* G_OS_WIN32 */
-
-#ifdef G_OS_WIN32
-static void
-setup_path (void)
-{
-	gchar *path;
-	gchar *installdir;
-	gchar *bin;
-
-	installdir = g_win32_get_package_installation_directory_of_module (NULL);
-
-	bin = g_build_filename (installdir,
-				"bin", NULL);
-	g_free (installdir);
-
-	/* Set PATH to include the gedit executable's folder */
-	path = g_build_path (";",
-			     bin,
-			     g_getenv ("PATH"),
-			     NULL);
-	g_free (bin);
+	gedit_debug_message (DEBUG_APP, "Start gtk-main");
+	gtk_main ();
 
-	if (!g_setenv ("PATH", path, TRUE))
-		g_warning ("Could not set PATH for gedit");
+	/* Cleanup */
+	g_object_unref (engine);
+	g_object_unref (app);
 
-	g_free (path);
-}
+#ifndef ENABLE_GVFS_METADATA
+	gedit_metadata_manager_shutdown ();
 #endif
+}
 
 int
 main (int argc, char *argv[])
 {
-	GOptionContext *context;
-	GeditPluginsEngine *engine;
-	GeditWindow *window;
-	GeditApp *app;
-	gboolean restored = FALSE;
-	GError *error = NULL;
 	gchar *dir;
-	gchar *icon_dir;
+	GeditCommandLine *command_line;
+	gboolean ret;
+	GeditDBus *dbus;
+	GeditDBusResult dbusret;
+	gboolean service = FALSE;
 
 	/* Init type system as soon as possible */
 	g_type_init ();
@@ -594,196 +231,51 @@ main (int argc, char *argv[])
 	/* FIXME: Remove when gconf not needed anymore */
 	g_setenv ("GSETTINGS_BACKEND", "gconf", FALSE);
 
+	/* Setup locale/gettext */
 	setlocale (LC_ALL, "");
 
 	dir = gedit_dirs_get_gedit_locale_dir ();
 	bindtextdomain (GETTEXT_PACKAGE, dir);
 	g_free (dir);
+
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
 
-	startup_timestamp = get_startup_timestamp();
-
-	/* Setup command line options */
-	context = g_option_context_new (_("- Edit text files"));
-	g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
-	g_option_context_add_group (context, gtk_get_option_group (FALSE));
-	g_option_context_add_group (context, egg_sm_client_get_option_group ());
+	/* Parse command line arguments */
+	command_line = gedit_command_line_get_default ();
 
-#ifdef G_OS_WIN32
-	setup_path ();
+	ret = gedit_command_line_parse (command_line, &argc, &argv);
 
-	/* If we open gedit from a console get the stdout printing */
-	if (fileno (stdout) != -1 &&
-		_get_osfhandle (fileno (stdout)) != -1)
+	if (!ret)
 	{
-		/* stdout is fine, presumably redirected to a file or pipe */
-	}
-	else
-	{
-		typedef BOOL (* WINAPI AttachConsole_t) (DWORD);
-
-		AttachConsole_t p_AttachConsole =
-			(AttachConsole_t) GetProcAddress (GetModuleHandle ("kernel32.dll"),
-							  "AttachConsole");
-
-		if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS))
-		{
-			freopen ("CONOUT$", "w", stdout);
-			dup2 (fileno (stdout), 1);
-			freopen ("CONOUT$", "w", stderr);
-			dup2 (fileno (stderr), 2);
-		}
-	}
-#endif
-
-	gtk_init (&argc, &argv);
-
-	if (!g_option_context_parse (context, &argc, &argv, &error))
-	{
-	        g_print(_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
-			error->message, argv[0]);
-		g_error_free (error);
+		g_object_unref (command_line);
 		return 1;
 	}
 
-	g_option_context_free (context);
-
-#ifndef G_OS_WIN32
-	gedit_debug_message (DEBUG_APP, "Create bacon connection");
-
-	connection = bacon_message_connection_new ("gedit");
+	/* Run over dbus */
+	dbus = gedit_dbus_new ();
+	dbusret = gedit_dbus_run (dbus);
 
-	if (connection != NULL)
-	{
-		if (!bacon_message_connection_get_is_server (connection)) 
-		{
-			gedit_debug_message (DEBUG_APP, "I'm a client");
-
-			gedit_get_command_line_data ();
-
-			send_bacon_message ();
-			
-			free_command_line_data ();
-			
-			/* we never popup a window... tell startup-notification
-			 * that we are done.
-			 */
-			gdk_notify_startup_complete ();
-
-			bacon_message_connection_free (connection);
-
-			exit (0);
-		}
-		else 
-		{
-		  	gedit_debug_message (DEBUG_APP, "I'm a server");
-
-			bacon_message_connection_set_callback (connection,
-							       on_message_received,
-							       NULL);
-		}
-	}
-	else
+	switch (dbusret)
 	{
-		g_warning ("Cannot create the 'gedit' connection.");
+		case GEDIT_DBUS_RESULT_SUCCESS:
+		case GEDIT_DBUS_RESULT_FAILED: /* fallthrough */
+			g_object_unref (command_line);
+			g_object_unref (dbus);
+
+			return dbusret == GEDIT_DBUS_RESULT_SUCCESS ? 0 : 1;
+		break;
+		case GEDIT_DBUS_RESULT_PROCEED_SERVICE:
+			service = TRUE;
+		break;
+		case GEDIT_DBUS_RESULT_PROCEED:
+		break;
 	}
-#endif
-
-	gedit_debug_message (DEBUG_APP, "Set icon");
-	
-	dir = gedit_dirs_get_gedit_data_dir ();
-	icon_dir = g_build_filename (dir,
-				     "icons",
-				     NULL);
-	g_free (dir);
-	
-	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
-					   icon_dir);
-	g_free (icon_dir);
 
-#ifdef GDK_WINDOWING_X11
-	/* Set the associated .desktop file */
-	egg_set_desktop_file (DATADIR "/applications/gedit.desktop");
-#else
-	/* manually set name and icon */
-	g_set_application_name("gedit");
-	gtk_window_set_default_icon_name ("accessories-text-editor");
-#endif
-
-	/* Init plugins engine */
-	gedit_debug_message (DEBUG_APP, "Init plugins");
-	engine = gedit_plugins_engine_get_default ();
+	gedit_main (service);
 
-	gtk_about_dialog_set_url_hook (gedit_utils_activate_url, NULL, NULL);
-	
-	/* Initialize session management */
-	gedit_debug_message (DEBUG_APP, "Init session manager");		
-	gedit_session_init ();
-
-#ifdef OS_OSX
-	ige_mac_menu_set_global_key_handler_enabled (FALSE);
-#endif
-
-	if (gedit_session_is_restored ())
-		restored = gedit_session_load ();
-
-	if (!restored)
-	{
-		gedit_debug_message (DEBUG_APP, "Analyze command line data");
-		gedit_get_command_line_data ();
-		
-		gedit_debug_message (DEBUG_APP, "Get default app");
-		app = gedit_app_get_default ();
-
-		gedit_debug_message (DEBUG_APP, "Create main window");
-		window = gedit_app_create_window (app, NULL);
-
-		if (file_list != NULL)
-		{
-			const GeditEncoding *encoding = NULL;
-		
-			if (encoding_charset)
-				encoding = gedit_encoding_get_from_charset (encoding_charset);
-		
-			gedit_debug_message (DEBUG_APP, "Load files");
-			_gedit_cmd_load_files_from_prompt (window, 
-							   file_list, 
-							   encoding, 
-							   line_position,
-							   column_position);
-		}
-		else
-		{
-			gedit_debug_message (DEBUG_APP, "Create tab");
-			gedit_window_create_tab (window, TRUE);
-		}
-		
-		gedit_debug_message (DEBUG_APP, "Show window");
-		gtk_widget_show (GTK_WIDGET (window));
-
-		free_command_line_data ();
-	}
-
-	gedit_debug_message (DEBUG_APP, "Start gtk-main");
-	
-#ifdef OS_OSX
-	gedit_osx_init(gedit_app_get_default ());
-#endif
-	gtk_main();
-
-#ifndef G_OS_WIN32
-	bacon_message_connection_free (connection);
-#endif
-
-	/* We kept the original engine reference here. So let's unref it to
-	 * finalize it properly. 
-	 */
-	g_object_unref (engine);
-
-#ifndef ENABLE_GVFS_METADATA
-	gedit_metadata_manager_shutdown ();
-#endif
+	g_object_unref (dbus);
+	g_object_unref (command_line);
 
 	return 0;
 }
diff --git a/plugin-loaders/python/bindings/geditcommands.defs b/plugin-loaders/python/bindings/geditcommands.defs
index f5ad9ba..ed8121d 100644
--- a/plugin-loaders/python/bindings/geditcommands.defs
+++ b/plugin-loaders/python/bindings/geditcommands.defs
@@ -19,7 +19,7 @@
 
 (define-function load_locations
   (c-name "gedit_commands_load_locations")
-  (return-type "gint")
+  (return-type "GSList*")
   (parameters
     '("GeditWindow*" "window")
     '("const-GSList*" "locations")
diff --git a/plugin-loaders/python/bindings/geditcommands.override b/plugin-loaders/python/bindings/geditcommands.override
index 3a9f57e..17229d1 100644
--- a/plugin-loaders/python/bindings/geditcommands.override
+++ b/plugin-loaders/python/bindings/geditcommands.override
@@ -72,6 +72,8 @@ _wrap_gedit_commands_load_locations (PyObject *self, PyObject *args, PyObject *k
 	GeditEncoding *encoding = NULL;
 	int len;
 	int i;
+	GSList *loaded;
+	GSList *doc;
 
 	if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!O|Oii:load_locations",
 	                                  kwlist, &PyGeditWindow_Type,
@@ -116,10 +118,33 @@ _wrap_gedit_commands_load_locations (PyObject *self, PyObject *args, PyObject *k
 	}
 
 	locations = g_slist_reverse (locations);
-	gedit_commands_load_locations (GEDIT_WINDOW (window->obj), locations,
-	                               encoding, line_pos, column_pos);
+	loaded = gedit_commands_load_locations (GEDIT_WINDOW (window->obj), locations,
+	                                        encoding, line_pos, column_pos);
 	g_slist_free (locations);
 
-	Py_INCREF (Py_None);
-	return Py_None;
+	if ((list = PyList_New(0)) == NULL)
+	{
+		g_slist_free (loaded);
+		return NULL;
+	}
+
+	for (doc = loaded; doc; doc = g_slist_next (doc))
+	{
+		PyObject *py_obj = pygobject_new (G_OBJECT (doc->data));
+
+		if (py_obj == NULL)
+		{
+			g_slist_free (loaded);
+
+			Py_DECREF(list);
+			return NULL;
+		}
+
+		PyList_Append(list, py_obj);
+		Py_DECREF(py_obj);
+	}
+
+	g_slist_free (loaded);
+
+	return list;
 }



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