[gedit/dbus] Replace bacon with dbus
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit/dbus] Replace bacon with dbus
- Date: Sat, 15 May 2010 11:19:36 +0000 (UTC)
commit eecaa2bf9f2b43059fbca550be28fe6c6ba7fab6
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 | 91 ++
gedit/gedit-commands-file.c | 81 +-
gedit/gedit-commands.h | 8 +-
gedit/gedit-dbus.c | 1653 ++++++++++++++++++++
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 | 386 +++++
gedit/gedit-fifo.h | 58 +
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, 3294 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..ce2b052
--- /dev/null
+++ b/gedit/gedit-command-line.h
@@ -0,0 +1,91 @@
+/*
+ * 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;
+};
+
+struct _GeditCommandLineGeometry {
+ gint width;
+ gint height;
+ gint xoffset;
+ gint yoffset;
+
+ gint xsign;
+ gint ysign;
+};
+
+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..4d59b0f
--- /dev/null
+++ b/gedit/gedit-dbus.c
@@ -0,0 +1,1653 @@
+/*
+ * 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;
+ gboolean close_window;
+ guint32 wait_id;
+
+ guint num_handlers;
+ WaitHandlerFunc func;
+};
+
+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;
+ gboolean jump_to;
+ WaitData *wait_data;
+} 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_finalize (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);
+ }
+
+ if (dbus->priv->stdin_fifo)
+ {
+ g_object_unref (dbus->priv->stdin_fifo);
+ }
+
+ if (dbus->priv->stdin_out_stream)
+ {
+ g_object_unref (dbus->priv->stdin_out_stream);
+ }
+
+ if (dbus->priv->stdin_in_stream)
+ {
+ g_object_unref (dbus->priv->stdin_in_stream);
+ }
+
+ 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_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..fdc1010
--- /dev/null
+++ b/gedit/gedit-fifo.c
@@ -0,0 +1,386 @@
+#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);
+}
diff --git a/gedit/gedit-fifo.h b/gedit/gedit-fifo.h
new file mode 100644
index 0000000..c59ddb4
--- /dev/null
+++ b/gedit/gedit-fifo.h
@@ -0,0 +1,58 @@
+#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__ */
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]