summaryrefslogtreecommitdiff
path: root/pluma/pluma.c
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-11-07 19:52:18 -0300
committerPerberos <[email protected]>2011-11-07 19:52:18 -0300
commit5ded9cba8563f336939400303d6a841d5089b107 (patch)
treec5676588cff26ba37e12369fe4de24b54e9f6682 /pluma/pluma.c
parentf00b3a11a199f9f85a4d46a600f9d14179b37dbf (diff)
downloadpluma-5ded9cba8563f336939400303d6a841d5089b107.tar.bz2
pluma-5ded9cba8563f336939400303d6a841d5089b107.tar.xz
renaming from gedit to pluma
Diffstat (limited to 'pluma/pluma.c')
-rwxr-xr-xpluma/pluma.c766
1 files changed, 766 insertions, 0 deletions
diff --git a/pluma/pluma.c b/pluma/pluma.c
new file mode 100755
index 00000000..b3a0c232
--- /dev/null
+++ b/pluma/pluma.c
@@ -0,0 +1,766 @@
+/*
+ * pluma.c
+ * This file is part of pluma
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the pluma Team, 2005. See the AUTHORS file for a
+ * list of people on the pluma Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#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 "pluma-app.h"
+#include "pluma-commands.h"
+#include "pluma-debug.h"
+#include "pluma-dirs.h"
+#include "pluma-encodings.h"
+#include "pluma-plugins-engine.h"
+#include "pluma-prefs-manager-app.h"
+#include "pluma-session.h"
+#include "pluma-utils.h"
+#include "pluma-window.h"
+
+#include "eggsmclient.h"
+#include "eggdesktopfile.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/pluma-osx.h"
+#endif
+
+#ifndef ENABLE_GVFS_METADATA
+#include "pluma-metadata-manager.h"
+#endif
+
+static guint32 startup_timestamp = 0;
+
+#ifndef G_OS_WIN32
+#include "bacon-message-connection.h"
+
+static BaconMessageConnection *connection;
+#endif
+
+/* command line */
+static gint line_position = 0;
+static gchar *encoding_charset = NULL;
+static gboolean new_window_option = FALSE;
+static gboolean new_document_option = FALSE;
+static gchar **remaining_args = NULL;
+static GSList *file_list = NULL;
+
+static void
+show_version_and_quit (void)
+{
+ g_print ("%s - Version %s\n", g_get_application_name (), VERSION);
+
+ exit (0);
+}
+
+static void
+list_encodings_and_quit (void)
+{
+ gint i = 0;
+ const PlumaEncoding *enc;
+
+ while ((enc = pluma_encoding_get_from_index (i)) != NULL)
+ {
+ g_print ("%s\n", pluma_encoding_get_charset (enc));
+
+ ++i;
+ }
+
+ exit (0);
+}
+
+static const GOptionEntry options [] =
+{
+ { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ show_version_and_quit, N_("Show the application's version"), NULL },
+
+ { "encoding", '\0', 0, G_OPTION_ARG_STRING, &encoding_charset,
+ N_("Set the character encoding to be used to open the files listed on the command line"), N_("ENCODING")},
+
+ { "list-encodings", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ list_encodings_and_quit, N_("Display list of possible values for the encoding option"), NULL},
+
+ { "new-window", '\0', 0, G_OPTION_ARG_NONE, &new_window_option,
+ N_("Create a new top-level window in an existing instance of pluma"), NULL },
+
+ { "new-document", '\0', 0, G_OPTION_ARG_NONE, &new_document_option,
+ N_("Create a new document in an existing instance of pluma"), NULL },
+
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &remaining_args,
+ NULL, N_("[FILE...]") }, /* collects file arguments */
+
+ {NULL}
+};
+
+static void
+free_command_line_data (void)
+{
+ g_slist_foreach (file_list, (GFunc) g_object_unref, NULL);
+ g_slist_free (file_list);
+ file_list = NULL;
+
+ g_strfreev (remaining_args);
+ remaining_args = NULL;
+
+ g_free (encoding_charset);
+ encoding_charset = NULL;
+
+ new_window_option = FALSE;
+ new_document_option = FALSE;
+ line_position = 0;
+}
+
+static void
+pluma_get_command_line_data (void)
+{
+ if (remaining_args)
+ {
+ gint i;
+
+ for (i = 0; remaining_args[i]; i++)
+ {
+ if (*remaining_args[i] == '+')
+ {
+ if (*(remaining_args[i] + 1) == '\0')
+ /* goto the last line of the document */
+ line_position = G_MAXINT;
+ else
+ line_position = atoi (remaining_args[i] + 1);
+ }
+ else
+ {
+ GFile *file;
+
+ file = g_file_new_for_commandline_arg (remaining_args[i]);
+ file_list = g_slist_prepend (file_list, file);
+ }
+ }
+
+ file_list = g_slist_reverse (file_list);
+ }
+
+ if (encoding_charset &&
+ (pluma_encoding_get_from_charset (encoding_charset) == NULL))
+ {
+ g_print (_("%s: invalid encoding.\n"),
+ encoding_charset);
+ }
+}
+
+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;
+
+ displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+
+ for (l = displays; l != NULL; l = l->next)
+ {
+ if (strcmp (gdk_display_get_name ((GdkDisplay *) l->data), name) == 0)
+ {
+ display = l->data;
+ break;
+ }
+ }
+
+ g_slist_free (displays);
+
+ return display != NULL ? display : gdk_display_open (name);
+}
+
+/* serverside */
+static void
+on_message_received (const char *message,
+ gpointer data)
+{
+ const PlumaEncoding *encoding = NULL;
+ gchar **commands;
+ gchar **params;
+ gint workspace;
+ gint viewport_x;
+ gint viewport_y;
+ gchar *display_name;
+ gint screen_number;
+ gint i;
+ PlumaApp *app;
+ PlumaWindow *window;
+ GdkDisplay *display;
+ GdkScreen *screen;
+
+ g_return_if_fail (message != NULL);
+
+ pluma_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]);
+
+ 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;
+ }
+
+ screen = gdk_display_get_screen (display, screen_number);
+
+ g_strfreev (params);
+
+ /* 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;
+
+ line_position = atoi (params[1]);
+
+ if (params[2] != '\0')
+ encoding = pluma_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);
+ }
+
+ /* execute the commands */
+
+ app = pluma_app_get_default ();
+
+ if (new_window_option)
+ {
+ window = pluma_app_create_window (app, screen);
+ }
+ else
+ {
+ /* get a window in the current workspace (if exists) and raise it */
+ window = _pluma_app_get_window_in_viewport (app,
+ screen,
+ workspace,
+ viewport_x,
+ viewport_y);
+ }
+
+ if (file_list != NULL)
+ {
+ _pluma_cmd_load_files_from_prompt (window,
+ file_list,
+ encoding,
+ line_position);
+
+ if (new_document_option)
+ pluma_window_create_tab (window, TRUE);
+ }
+ else
+ {
+ PlumaDocument *doc;
+ doc = pluma_window_get_active_document (window);
+
+ if (doc == NULL ||
+ !pluma_document_is_untouched (doc) ||
+ new_document_option)
+ pluma_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_REALIZED (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.
+ */
+
+ pluma_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);
+
+ pluma_debug_message (DEBUG_APP, "Display: %s", display_name);
+ pluma_debug_message (DEBUG_APP, "Screen: %d", screen_number);
+
+ ws = pluma_utils_get_current_workspace (screen);
+ pluma_utils_get_current_viewport (screen, &viewport_x, &viewport_y);
+
+ command = g_string_new (NULL);
+
+ /* header */
+ g_string_append_printf (command,
+ "%" G_GUINT32_FORMAT "\t%s\t%d\t%d\t%d\t%d",
+ startup_timestamp,
+ display_name,
+ screen_number,
+ ws,
+ viewport_x,
+ viewport_y);
+
+ /* NEW-WINDOW command */
+ if (new_window_option)
+ {
+ command = g_string_append_c (command, '\v');
+ command = g_string_append (command, "NEW-WINDOW");
+ }
+
+ /* NEW-DOCUMENT command */
+ if (new_document_option)
+ {
+ command = g_string_append_c (command, '\v');
+ command = g_string_append (command, "NEW-DOCUMENT");
+ }
+
+ /* OPEN_URIS command, optionally specify line_num and encoding */
+ if (file_list)
+ {
+ GSList *l;
+
+ command = g_string_append_c (command, '\v');
+ command = g_string_append (command, "OPEN-URIS");
+
+ g_string_append_printf (command,
+ "\t%d\t%s\t%u\t",
+ line_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);
+ }
+ }
+
+ pluma_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 pluma executable's folder */
+ path = g_build_path (";",
+ bin,
+ g_getenv ("PATH"),
+ NULL);
+ g_free (bin);
+
+ if (!g_setenv ("PATH", path, TRUE))
+ g_warning ("Could not set PATH for pluma");
+
+ g_free (path);
+}
+#endif
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ PlumaPluginsEngine *engine;
+ PlumaWindow *window;
+ PlumaApp *app;
+ gboolean restored = FALSE;
+ GError *error = NULL;
+ gchar *dir;
+ gchar *icon_dir;
+
+ /* Init type system as soon as possible */
+ g_type_init ();
+
+ /* Init glib threads asap */
+ g_thread_init (NULL);
+
+ /* Setup debugging */
+ pluma_debug_init ();
+ pluma_debug_message (DEBUG_APP, "Startup");
+
+ setlocale (LC_ALL, "");
+
+ dir = pluma_dirs_get_pluma_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 ());
+
+#ifdef G_OS_WIN32
+ setup_path ();
+
+ /* If we open pluma from a console get the stdout printing */
+ if (fileno (stdout) != -1 &&
+ _get_osfhandle (fileno (stdout)) != -1)
+ {
+ /* 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);
+ return 1;
+ }
+
+ g_option_context_free (context);
+
+#ifndef G_OS_WIN32
+ pluma_debug_message (DEBUG_APP, "Create bacon connection");
+
+ connection = bacon_message_connection_new ("pluma");
+
+ if (connection != NULL)
+ {
+ if (!bacon_message_connection_get_is_server (connection))
+ {
+ pluma_debug_message (DEBUG_APP, "I'm a client");
+
+ pluma_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
+ {
+ pluma_debug_message (DEBUG_APP, "I'm a server");
+
+ bacon_message_connection_set_callback (connection,
+ on_message_received,
+ NULL);
+ }
+ }
+ else
+ {
+ g_warning ("Cannot create the 'pluma' connection.");
+ }
+#endif
+
+ pluma_debug_message (DEBUG_APP, "Set icon");
+
+ dir = pluma_dirs_get_pluma_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/pluma.desktop");
+#else
+ /* manually set name and icon */
+ g_set_application_name("pluma");
+ gtk_window_set_default_icon_name ("accessories-text-editor");
+#endif
+
+ /* Load user preferences */
+ pluma_debug_message (DEBUG_APP, "Init prefs manager");
+ pluma_prefs_manager_app_init ();
+
+ /* Init plugins engine */
+ pluma_debug_message (DEBUG_APP, "Init plugins");
+ engine = pluma_plugins_engine_get_default ();
+
+ #if !GTK_CHECK_VERSION(3, 0, 0)
+ gtk_about_dialog_set_url_hook(pluma_utils_activate_url, NULL, NULL);
+ #endif
+ /* Initialize session management */
+ pluma_debug_message (DEBUG_APP, "Init session manager");
+ pluma_session_init ();
+
+#ifdef OS_OSX
+ ige_mac_menu_set_global_key_handler_enabled (FALSE);
+#endif
+
+ if (pluma_session_is_restored ())
+ restored = pluma_session_load ();
+
+ if (!restored)
+ {
+ pluma_debug_message (DEBUG_APP, "Analyze command line data");
+ pluma_get_command_line_data ();
+
+ pluma_debug_message (DEBUG_APP, "Get default app");
+ app = pluma_app_get_default ();
+
+ pluma_debug_message (DEBUG_APP, "Create main window");
+ window = pluma_app_create_window (app, NULL);
+
+ if (file_list != NULL)
+ {
+ const PlumaEncoding *encoding = NULL;
+
+ if (encoding_charset)
+ encoding = pluma_encoding_get_from_charset (encoding_charset);
+
+ pluma_debug_message (DEBUG_APP, "Load files");
+ _pluma_cmd_load_files_from_prompt (window,
+ file_list,
+ encoding,
+ line_position);
+ }
+ else
+ {
+ pluma_debug_message (DEBUG_APP, "Create tab");
+ pluma_window_create_tab (window, TRUE);
+ }
+
+ pluma_debug_message (DEBUG_APP, "Show window");
+ gtk_widget_show (GTK_WIDGET (window));
+
+ free_command_line_data ();
+ }
+
+ pluma_debug_message (DEBUG_APP, "Start gtk-main");
+
+#ifdef OS_OSX
+ pluma_osx_init(pluma_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);
+ pluma_prefs_manager_app_shutdown ();
+
+#ifndef ENABLE_GVFS_METADATA
+ pluma_metadata_manager_shutdown ();
+#endif
+
+ return 0;
+}
+