[gedit/dbus] Replaced bacon with dbus



commit c96cb99081b500c01817e9fc7b7cc50cef2ba376
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun May 2 13:02:27 2010 +0200

    Replaced bacon with dbus

 configure.ac                                       |    6 +-
 data/Makefile.am                                   |    9 +
 data/org.gnome.gedit.service.in                    |    3 +
 gedit/Makefile.am                                  |   15 +-
 gedit/bacon-message-connection.c                   |  397 ---------
 gedit/bacon-message-connection.h                   |   44 -
 gedit/gedit-app-win32.c                            |   22 +
 gedit/gedit-app-win32.h                            |    2 +-
 gedit/gedit-command-line.c                         |  417 +++++++++
 gedit/gedit-command-line.h                         |   77 ++
 gedit/gedit-commands-file.c                        |   81 ++-
 gedit/gedit-commands.h                             |    8 +-
 gedit/gedit-dbus.c                                 |  941 ++++++++++++++++++++
 gedit/gedit-dbus.h                                 |   69 ++
 gedit/gedit-window.c                               |   22 +-
 gedit/gedit.c                                      |  758 ++--------------
 gedit/update-from-bacon.sh                         |   25 -
 plugin-loaders/python/bindings/geditcommands.defs  |    2 +-
 .../python/bindings/geditcommands.override         |   33 +-
 19 files changed, 1745 insertions(+), 1186 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9c52eea..2f0e0d3 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 ================================================================
 
@@ -277,6 +272,7 @@ PKG_CHECK_MODULES(GEDIT, [
 	gtk+-2.0 >= 2.16.0
 	gtksourceview-2.0 >= 2.9.7
 	gconf-2.0 >= 1.1.11
+	gdbus-standalone
 ])
 
 if test "$os_osx" = "no" &&
diff --git a/data/Makefile.am b/data/Makefile.am
index 669f1dd..8ff7646 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -8,6 +8,13 @@ schemas_in_files = gedit.schemas.in
 schemas_DATA 	 = $(schemas_in_files:.schemas.in=.schemas)
 @INTLTOOL_SCHEMAS_RULE@
 
+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
@@ -33,6 +40,7 @@ endif
 EXTRA_DIST = 				\
 	$(desktop_in_files)		\
 	$(schemas_in_files)		\
+	$(service_in_files)		\
 	gedit.schemas.in.in		\
 	$(man_MANS)			\
 	gedit.pc.in			\
@@ -41,6 +49,7 @@ EXTRA_DIST = 				\
 CLEANFILES =	 			\
 	$(desktop_DATA)			\
 	$(schemas_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 ea9b59d..838e03e 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		\
@@ -154,9 +156,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		\
@@ -164,6 +166,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 		\
@@ -252,16 +255,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-win32.c b/gedit/gedit-app-win32.c
index 6d9c221..e818dba 100644
--- a/gedit/gedit-app-win32.c
+++ b/gedit/gedit-app-win32.c
@@ -1,3 +1,25 @@
+/*
+ * gedit-app-win32.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-app-win32.h"
 
 #define SAVE_DATADIR DATADIR
diff --git a/gedit/gedit-app-win32.h b/gedit/gedit-app-win32.h
index 23ef3c1..58bc8a2 100644
--- a/gedit/gedit-app-win32.h
+++ b/gedit/gedit-app-win32.h
@@ -1,5 +1,5 @@
 /*
- * gedit-win32.h
+ * gedit-app-win32.h
  * This file is part of gedit
  *
  * Copyright (C) 2010 - Jesse van den Kieboom
diff --git a/gedit/gedit-command-line.c b/gedit/gedit-command-line.c
new file mode 100644
index 0000000..0a0a0cc
--- /dev/null
+++ b/gedit/gedit-command-line.c
@@ -0,0 +1,417 @@
+/*
+ * 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;
+	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_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
+		},
+
+		/* 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;
+}
+
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-command-line.h b/gedit/gedit-command-line.h
new file mode 100644
index 0000000..e17e10e
--- /dev/null
+++ b/gedit/gedit-command-line.h
@@ -0,0 +1,77 @@
+/*
+ * 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-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;
+
+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);
+
+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..3b63391
--- /dev/null
+++ b/gedit/gedit-dbus.c
@@ -0,0 +1,941 @@
+/*
+ * 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 <gdbus/gdbus.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
+
+typedef struct _WaitData WaitData;
+typedef void (*WaitHandlerFunc)(GObject *object, WaitData *data);
+
+struct _WaitData
+{
+	GeditDBus *dbus;
+	GeditWindow *window;
+	gboolean close_window;
+	guint wait_id;
+
+	guint num_handlers;
+	WaitHandlerFunc func;
+};
+
+#define GEDIT_DBUS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_DBUS, GeditDBusPrivate))
+
+struct _GeditDBusPrivate
+{
+	GeditDBusResult result;
+	GMainLoop *main_loop;
+	guint wait_id;
+
+	guint next_wait_id;
+};
+
+G_DEFINE_TYPE (GeditDBus, gedit_dbus, G_TYPE_OBJECT)
+
+static void
+gedit_dbus_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gedit_dbus_parent_class)->finalize (object);
+}
+
+static void
+gedit_dbus_class_init (GeditDBusClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gedit_dbus_finalize;
+
+	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_invoke_method_sync (conn,
+	                                            "org.freedesktop.DBus",
+	                                            "/org/freedesktop/DBus",
+	                                            "org.freedesktop.DBus",
+	                                            "StartServiceByName",
+	                                            g_variant_new ("(su)", "org.gnome.gedit", 0),
+	                                            G_DBUS_INVOKE_METHOD_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,
+                       GeditCommandLine  *command_line,
+                       const gchar      **display_name,
+                       gint              *screen_number,
+                       gint              *workspace,
+                       gint              *viewport_x,
+                       gint              *viewport_y)
+{
+	GdkScreen *screen;
+	GdkDisplay *display;
+
+	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);
+
+	*workspace = gedit_utils_get_current_workspace (screen);
+	gedit_utils_get_current_viewport (screen, viewport_x, viewport_y);
+}
+
+static GVariant *
+compose_open_parameters (GeditDBus *dbus, GeditCommandLine *command_line)
+{
+	GVariantBuilder file_list;
+	GSList *files;
+	const GeditEncoding *encoding;
+	const gchar *display_name;
+	gint screen_number;
+	gint workspace;
+	gint viewport_x;
+	gint viewport_y;
+	GVariant *ret;
+
+	g_variant_builder_init (&file_list, G_VARIANT_TYPE ("as"));
+
+	for (files = gedit_command_line_get_file_list (command_line); files; files = g_slist_next (files))
+	{
+		gchar *uri = g_file_get_uri (files->data);
+		g_variant_builder_add (&file_list, "s", uri);
+		g_free (uri);
+	}
+
+	encoding = gedit_command_line_get_encoding (command_line);
+
+	get_display_arguments (dbus,
+	                       command_line,
+	                       &display_name,
+	                       &screen_number,
+	                       &workspace,
+	                       &viewport_x,
+	                       &viewport_y);
+
+	ret = g_variant_new ("(assiibbbusiiii)",
+	                     &file_list,
+	                     encoding ? gedit_encoding_get_charset (encoding) : "",
+	                     gedit_command_line_get_line_position (command_line),
+	                     gedit_command_line_get_column_position (command_line),
+	                     gedit_command_line_get_new_window (command_line),
+	                     gedit_command_line_get_new_document (command_line),
+	                     gedit_command_line_get_wait (command_line),
+	                     get_startup_timestamp (),
+	                     display_name,
+	                     screen_number,
+	                     workspace,
+	                     viewport_x,
+	                     viewport_y);
+
+	return ret;
+}
+
+static void
+slave_open_ready_cb (GDBusProxy   *proxy,
+                     GAsyncResult *result,
+                     GeditDBus    *dbus)
+{
+	GVariant *ret;
+	GError *error = NULL;
+	GeditCommandLine *command_line;
+
+	ret = g_dbus_proxy_invoke_method_finish (proxy, 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 (ret, "(u)", &dbus->priv->wait_id);
+		dbus->priv->result = GEDIT_DBUS_RESULT_SUCCESS;
+
+		if (!gedit_command_line_get_wait (command_line))
+		{
+			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);
+		}
+	}
+}
+
+static void
+command_line_proxy_appeared (GDBusConnection *connection,
+                             const gchar     *name,
+                             const gchar     *owner_name,
+                             GDBusProxy      *proxy,
+                             GeditDBus       *dbus)
+{
+	GeditCommandLine *command_line;
+
+	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);
+	}
+
+	g_dbus_proxy_invoke_method (proxy,
+	                            "Open",
+	                            compose_open_parameters (dbus, command_line),
+	                            G_DBUS_INVOKE_METHOD_FLAGS_NONE,
+	                           -1,
+	                           NULL,
+	                           (GAsyncReadyCallback)slave_open_ready_cb,
+	                           dbus);
+}
+
+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;
+	GDBusInvokeMethodFlags 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_NOWINDOW;
+	}
+	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 ();
+
+	if (result != 2) /* DBUS_START_REPLY_ALREADY_RUNNING */
+	{
+		/* A new gedit process was launched as a service, this process
+		   will have popped up a window, so we want to ignore
+		   --new-window here */
+
+		gedit_command_line_set_new_window (command_line, FALSE);
+	}
+
+	/* 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,
+                               const gchar *display_name,
+                               gint         screen_number,
+                               gint         workspace,
+                               gint         viewport_x,
+                               gint         viewport_y,
+                               gboolean     create)
+{
+	GdkScreen *screen;
+	GeditApp *app;
+	GeditWindow *ret;
+
+	/* get correct screen using the display_name and screen_number */
+	if (display_name != NULL && *display_name)
+	{
+		GdkDisplay *display;
+
+		display = display_open_if_needed (display_name);
+		screen = gdk_display_get_screen (display, screen_number == -1 ? 0 : screen_number);
+	}
+
+	app = gedit_app_get_default ();
+
+	if (new_window)
+	{
+		return gedit_app_create_window (app, screen);
+	}
+
+	if (screen != NULL)
+	{
+		ret = _gedit_app_get_window_in_viewport (app,
+		                                         screen,
+		                                         workspace == -1 ? 0 : workspace,
+		                                         viewport_x == -1 ? 0 : viewport_x,
+		                                         viewport_y == -1 ? 0 : viewport_y);
+	}
+	else
+	{
+		ret = gedit_app_get_active_window (app);
+	}
+
+	if (!ret && create)
+	{
+		return gedit_app_create_window (app, screen);
+	}
+
+	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);
+}
+
+static void
+dbus_handle_open (GeditDBus             *dbus,
+                  GVariant              *parameters,
+                  GDBusMethodInvocation *invocation)
+{
+	GVariantIter *file_list;
+	gchar *charset_encoding;
+	gint line_position;
+	gint column_position;
+	gboolean new_window;
+	gboolean new_document;
+	gboolean wait;
+	guint startup_time;
+	gchar *display_name;
+	gint screen_number;
+	gint workspace;
+	gint viewport_x;
+	gint viewport_y;
+	GSList *locations = NULL;
+	const GeditEncoding *encoding = NULL;
+	GeditWindow *window;
+	GSList *loaded_documents = NULL;
+	gboolean empty_window;
+	WaitData *data;
+
+	g_variant_get (parameters,
+	               "(assiibbbusiiii)",
+	               &file_list,
+	               &charset_encoding,
+	               &line_position,
+	               &column_position,
+	               &new_window,
+	               &new_document,
+	               &wait,
+	               &startup_time,
+	               &display_name,
+	               &screen_number,
+	               &workspace,
+	               &viewport_x,
+	               &viewport_y);
+
+	locations = variant_iter_list_to_locations (file_list);
+	g_variant_iter_free (file_list);
+
+	if (charset_encoding && *charset_encoding)
+	{
+		encoding = gedit_encoding_get_from_charset (charset_encoding);
+	}
+
+	g_free (charset_encoding);
+
+	window = window_from_display_arguments (new_window,
+	                                        display_name,
+	                                        screen_number,
+	                                        workspace,
+	                                        viewport_x,
+	                                        viewport_y,
+	                                        TRUE);
+
+	empty_window = is_empty_window (window, TRUE);
+
+	if (locations)
+	{
+		loaded_documents = _gedit_cmd_load_files_from_prompt (window,
+		                                                      locations,
+		                                                      encoding,
+		                                                      line_position,
+		                                                      column_position);
+	}
+
+	if (new_document)
+	{
+		GeditTab *tab;
+		tab = gedit_window_create_tab (window, TRUE);
+
+		loaded_documents = g_slist_append (loaded_documents, gedit_tab_get_document (tab));
+	}
+
+	set_interaction_time_and_present (window, startup_time);
+
+	g_slist_free (locations);
+
+	if (!wait)
+	{
+		g_slist_free (loaded_documents);
+		g_dbus_method_invocation_return_value (invocation,
+		                                       g_variant_new ("(u)", 0));
+		return;
+	}
+
+	data = g_slice_new (WaitData);
+
+	data->dbus = dbus;
+	data->window = window;
+	data->close_window = empty_window;
+	data->wait_id = ++dbus->priv->next_wait_id;
+
+	if (loaded_documents == NULL)
+	{
+		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_slist_free (loaded_documents);
+	g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", data->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);
+	}
+}
+
+/* Introspection data for the service we are exporting */
+static const GDBusArgInfo in_args[] = {
+	{"files"          , "as"},
+	{"encoding"       , "s"},
+	{"line_position"  , "i"},
+	{"column_position", "i"},
+	{"new_window"     , "b"},
+	{"new_document"   , "b"},
+	{"wait"           , "b"},
+	{"startup_time"   , "u"},
+	{"display_name"   , "s"},
+	{"screen_number"  , "i"},
+	{"workspace"      , "i"},
+	{"viewport_x"     , "i"},
+	{"viewport_y"     , "i"},
+};
+
+static const GDBusArgInfo out_args[] = {
+	{"wait_id"        , "u"},
+};
+
+static const GDBusMethodInfo command_line_methods[] = {
+	{"Open", "assiibbbusiiii", 13, in_args, "u", 1, out_args}
+};
+
+static const GDBusArgInfo signal_args[] = {
+	{"wait_id", "u"}
+};
+
+static const GDBusSignalInfo command_line_signals[] = {
+	{"WaitDone", "u", 1, signal_args}
+};
+
+static const GDBusInterfaceInfo command_line_interface = {
+	"org.gnome.gedit.CommandLine",
+	1, command_line_methods,
+	1, command_line_signals
+};
+
+static const GDBusInterfaceVTable command_line_vtable = {
+	dbus_command_line_method_call_cb,
+};
+
+static gboolean
+register_dbus_interface (GeditDBus       *dbus,
+                         GDBusConnection *connection)
+{
+	guint ret;
+
+	ret = g_dbus_connection_register_object (connection,
+	                                         "/org/gnome/gedit",
+	                                         "org.gnome.gedit.CommandLine",
+	                                         &command_line_interface,
+	                                         &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..687dbb1
--- /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_NOWINDOW
+} 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-window.c b/gedit/gedit-window.c
index 1faa446..106e156 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -1201,15 +1201,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
@@ -2830,7 +2833,8 @@ load_uris_from_drop (GeditWindow  *window,
 {
 	GSList *locations = NULL;
 	gint i;
-	
+	GSList *loaded;
+
 	if (uri_list == NULL)
 		return;
 	
@@ -2840,11 +2844,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);
diff --git a/gedit/gedit.c b/gedit/gedit.c
index 4956208..a339450 100644
--- a/gedit/gedit.c
+++ b/gedit/gedit.c
@@ -32,20 +32,21 @@
 #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 "eggsmclient.h"
+#include "eggdesktopfile.h"
+
+#include "gseal-gtk-compat.h"
 #include "gedit-commands.h"
 #include "gedit-debug.h"
 #include "gedit-dirs.h"
@@ -56,531 +57,110 @@
 #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;
-#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)
-{
-	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 const GOptionEntry options [] =
-{
-	{ "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}
-};
-
-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;
-}
-
-static void
-get_line_column_position (const gchar *arg)
-{
-	gchar **split;
-
-	split = g_strsplit (arg, ":", 2);
-
-	if (split != NULL)
-	{
-		if (split[0] != NULL)
-			line_position = atoi (split[0]);
-
-		if (split[1] != NULL)
-			column_position = atoi (split[1]);
-	}
-
-	g_strfreev (split);
-}
-
 static void
-gedit_get_command_line_data (void)
-{
-	if (remaining_args)
-	{
-		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);
-	}
-	
-	if (encoding_charset &&
-	    (gedit_encoding_get_from_charset (encoding_charset) == NULL))
-	{
-		g_print (_("%s: invalid encoding.\n"),
-			 encoding_charset);
-	}
-}
-
-static guint32
-get_startup_timestamp (void)
+gedit_main (gboolean service)
 {
-	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);
+	GeditPluginsEngine *engine;
+	GeditWindow *window;
+	GeditApp *app;
+	gboolean restored = FALSE;
+	gchar *dir;
+	gchar *icon_dir;
+	GeditCommandLine *command_line;
 
-	time_str = g_strrstr (startup_id, "_TIME");
-	if (time_str == NULL)
-		goto out;
+	gedit_debug_message (DEBUG_APP, "Set icon");
 
-	errno = 0;
+	dir = gedit_dirs_get_gedit_data_dir ();
+	icon_dir = g_build_filename (dir, "icons", NULL);
+	g_free (dir);
 
-	/* Skip past the "_TIME" part */
-	time_str += 5;
+	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir);
+	g_free (icon_dir);
 
-	retval = strtoul (time_str, &end, 0);
-	if (end == time_str || errno != 0)
-		retval = 0;
+#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
 
- out:
-	g_free (startup_id);
+	/* Init plugins engine */
+	gedit_debug_message (DEBUG_APP, "Init plugins");
+	engine = gedit_plugins_engine_get_default ();
 
-	return (retval > 0) ? retval : 0;
-}
+	gtk_about_dialog_set_url_hook (gedit_utils_activate_url, NULL, NULL);
 
-#ifndef G_OS_WIN32
-static GdkDisplay *
-display_open_if_needed (const gchar *name)
-{
-	GSList *displays;
-	GSList *l;
-	GdkDisplay *display = NULL;
+	/* Initialize session management */
+	gedit_debug_message (DEBUG_APP, "Init session manager");
+	gedit_session_init ();
 
-	displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+	app = gedit_app_get_default ();
 
-	for (l = displays; l != NULL; l = l->next)
+	if (!service && gedit_session_is_restored ())
 	{
-		if (strcmp (gdk_display_get_name ((GdkDisplay *) l->data), name) == 0)
-		{
-			display = l->data;
-			break;
-		}
+		restored = gedit_session_load ();
 	}
 
-	g_slist_free (displays);
-
-	return display != NULL ? display : gdk_display_open (name);
-}
-
-/* serverside */
-static void
-on_message_received (const char *message,
-		     gpointer    data)
-{
-	const GeditEncoding *encoding = NULL;
-	gchar **commands;
-	gchar **params;
-	gint workspace;
-	gint viewport_x;
-	gint viewport_y;
-	gchar *display_name;
-	gint screen_number;
-	gint i;
-	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);
+	command_line = gedit_command_line_get_default ();
 
-	/* 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]);
-
-	display = display_open_if_needed (display_name);
-	if (display == NULL)
+	if (!service && !restored)
 	{
-		g_warning ("Could not open display %s\n", display_name);
-		g_strfreev (params);
-		goto out;
-	}
+		GSList *file_list;
 
-	screen = gdk_display_get_screen (display, screen_number);
-
-	g_strfreev (params);
+		gedit_debug_message (DEBUG_APP, "Create main window");
+		window = gedit_app_create_window (app, NULL);
 
-	/* body */
-	for (i = 1; commands[i] != NULL; i++)
-	{
-		params = g_strsplit (commands[i], "\t", -1);
+		file_list = gedit_command_line_get_file_list (command_line);
 
-		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)
+		if (file_list != NULL)
 		{
-			gint n_uris, j;
-			gchar **uris;
-
-			get_line_column_position (params[1]);
-
-			if (params[2] != '\0')
-				encoding = gedit_encoding_get_from_charset (params[2]);
+			GSList *loaded;
 
-			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);
+			gedit_debug_message (DEBUG_APP, "Load files");
+			loaded = _gedit_cmd_load_files_from_prompt (window,
+			                                            file_list,
+			                                            gedit_command_line_get_encoding (command_line),
+			                                            gedit_command_line_get_line_position (command_line),
+			                                            gedit_command_line_get_column_position (command_line));
 
-			/* the list takes ownerhip of the strings,
-			 * only free the array */
-			g_free (uris);
+			g_slist_free (loaded);
 		}
 		else
 		{
-			g_warning ("Unexpected bacon command");
-		}
-
-		g_strfreev (params);
-	}
-
-	/* execute the commands */
-
-	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_debug_message (DEBUG_APP, "Create tab");
 			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);
+		gedit_debug_message (DEBUG_APP, "Show window");
+		gtk_widget_show (GTK_WIDGET (window));
 	}
 
-	/* 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));
+	gedit_debug_message (DEBUG_APP, "Start gtk-main");
+	gtk_main ();
 
-#ifdef GDK_WINDOWING_X11
-	if (startup_timestamp <= 0)
-		startup_timestamp = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
+	/* Cleanup */
+	g_object_unref (engine);
 
-	gdk_x11_window_set_user_time (gtk_widget_get_window (GTK_WIDGET (window)),
-				      startup_timestamp);
+#ifndef ENABLE_GVFS_METADATA
+	gedit_metadata_manager_shutdown ();
 #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");
-	}
-
-	/* NEW-DOCUMENT command */
-	if (new_document_option)
-	{
-		command = g_string_append_c (command, '\v');
-		command = g_string_append (command, "NEW-DOCUMENT");
-	}
-
-	/* OPEN_URIS command, optionally specify line_num and encoding */
-	if (file_list)
-	{
-		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_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);
-
-	if (!g_setenv ("PATH", path, TRUE))
-		g_warning ("Could not set PATH for gedit");
-
-	g_free (path);
-}
-#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 ();
@@ -591,202 +171,60 @@ main (int argc, char *argv[])
 	/* Setup debugging */
 	gedit_debug_init ();
 	gedit_debug_message (DEBUG_APP, "Startup");
-	
+
+	/* 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();
+	/* Parse command line arguments */
+	command_line = gedit_command_line_get_default ();
 
-	/* 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 ());
+	ret = gedit_command_line_parse (command_line, &argc, &argv);
 
-#ifdef G_OS_WIN32
-	setup_path ();
-
-	/* 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");
-
-	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
-	{
-		g_warning ("Cannot create the 'gedit' connection.");
-	}
-#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
-
-	/* Load user preferences */
+	/* Initialize preferences before launching dbus */
 	gedit_debug_message (DEBUG_APP, "Init prefs manager");
 	gedit_prefs_manager_app_init ();
 
-	/* Init plugins engine */
-	gedit_debug_message (DEBUG_APP, "Init plugins");
-	engine = gedit_plugins_engine_get_default ();
-
-	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
+	/* Run over dbus */
+	dbus = gedit_dbus_new ();
+	dbusret = gedit_dbus_run (dbus);
 
-	if (gedit_session_is_restored ())
-		restored = gedit_session_load ();
-
-	if (!restored)
+	switch (dbusret)
 	{
-		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 ();
+		case GEDIT_DBUS_RESULT_SUCCESS:
+		case GEDIT_DBUS_RESULT_FAILED: /* fallthrough */
+			g_object_unref (command_line);
+			g_object_unref (dbus);
 
-		gedit_debug_message (DEBUG_APP, "Create main window");
-		window = gedit_app_create_window (app, NULL);
+			gedit_prefs_manager_app_shutdown ();
 
-		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 ();
+			return dbusret == GEDIT_DBUS_RESULT_SUCCESS ? 0 : 1;
+		break;
+		case GEDIT_DBUS_RESULT_PROCEED:
+		break;
+		case GEDIT_DBUS_RESULT_PROCEED_NOWINDOW:
+			service = TRUE;
+		break;
 	}
 
-	gedit_debug_message (DEBUG_APP, "Start gtk-main");
-	
-#ifdef OS_OSX
-	gedit_osx_init(gedit_app_get_default ());
-#endif
-	gtk_main();
+	gedit_main (service);
 
-#ifndef G_OS_WIN32
-	bacon_message_connection_free (connection);
-#endif
+	g_object_unref (dbus);
 
-	/* We kept the original engine reference here. So let's unref it to
-	 * finalize it properly. 
-	 */
-	g_object_unref (engine);
 	gedit_prefs_manager_app_shutdown ();
-
-#ifndef ENABLE_GVFS_METADATA
-	gedit_metadata_manager_shutdown ();
-#endif
+	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]