Port xed to dbus and GtkApplication

This further improves on the port to GtkSource API's and cleans up a ton of
legacy code in xed based on upstream changes in Gedit.
This commit is contained in:
JosephMcc 2017-02-04 22:17:58 -08:00
parent f05ddd7b63
commit 2aa009cb76
45 changed files with 1434 additions and 6558 deletions

View File

@ -49,12 +49,6 @@ dnl toolbar style for GSettings schemas
TOOLBAR_STYLE="XED_TOOLBAR_SYSTEM"
AC_SUBST(TOOLBAR_STYLE)
# GLib min/max required versions
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_36],
[Warn on use of APIs added after GLib 2.36])
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_36],
[Warn on use of APIs deprecated before GLib 2.36])
dnl ===============================================================
dnl Expanded dirs
dnl ===============================================================
@ -151,12 +145,12 @@ dnl ================================================================
PKG_CHECK_MODULES(GMODULE,gmodule-2.0,[GMODULE_ADD="gmodule-2.0"],[GMODULE_ADD=""])
PKG_CHECK_MODULES(XED, [
libxml-2.0 >= 2.5.0
glib-2.0 >= 2.36.0
glib-2.0 >= 2.40.0
$GMODULE_ADD
gthread-2.0 >= 2.13.0
gio-2.0 >= 2.26.0
gtk+-3.0 >= 3.10.0
gtksourceview-3.0 >= 2.9.7
gio-2.0 >= 2.40.0
gtk+-3.0 >= 3.14.0
gtksourceview-3.0 >= 3.14.3
libpeas-1.0 >= 1.12.0
libpeas-gtk-1.0 >= 1.12.0
])
@ -169,19 +163,14 @@ XED_LIBS="$XED_LIBS $X11_LIBS"
AC_SUBST(XED_CFLAGS)
AC_SUBST(XED_LIBS)
PKG_CHECK_MODULES(EGG_SMCLIENT, [sm >= 1.0.0])
AC_SUBST(EGG_SMCLIENT_CFLAGS)
AC_SUBST(EGG_SMCLIENT_LIBS)
# Introspection
GOBJECT_INTROSPECTION_CHECK([0.9.3])
if test "$found_introspection" = "yes"; then
have_introspection=yes
AC_DEFINE([HAVE_INTROSPECTION], [1], [Define to enable GObject Introspection])
enable_introspection=yes
AC_DEFINE([ENABLE_INTROSPECTION], [1], [Define to enable GObject Introspection])
else
have_introspection=no
enable_introspection=no
fi
dnl ================================================================
@ -235,7 +224,6 @@ data/Makefile
docs/Makefile
docs/reference/Makefile
xed/dialogs/Makefile
xed/smclient/Makefile
xed/Makefile
help/Makefile
pixmaps/Makefile
@ -264,5 +252,5 @@ Configuration:
Compiler: ${CC}
Spell Plugin enabled: $enable_enchant
Gvfs metadata enabled: $enable_gvfs_metadata
GObject Introspection: ${have_introspection}
GObject Introspection: ${enable_introspection}
"

View File

@ -13,6 +13,13 @@ gsettings_SCHEMAS = org.x.editor.gschema.xml
@GSETTINGS_RULES@
servicedir = $(datadir)/dbus-1/services
service_in_files = org.x.editor.service.in
service_DATA = $(service_in_files:.service.in=.service)
$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $<> $@
man_MANS = xed.1
pkgconfigdir = $(libdir)/pkgconfig
@ -24,12 +31,14 @@ bugreport_SCRIPTS = xed-bugreport.sh
EXTRA_DIST = \
$(appdata_in_files) \
$(desktop_in_files) \
$(service_in_files) \
$(man_MANS) \
xed.pc.in \
xed-bugreport.sh.in
CLEANFILES = \
$(desktop_DATA) \
$(service_DATA) \
$(gsettings_SCHEMAS) \
$(pkgconfig_DATA) \
$(appdata_DATA)

1
debian/xed.install vendored
View File

@ -4,4 +4,5 @@ usr/lib/xed/xed-bugreport.sh
usr/lib/*/xed/plugins/*.plugin
usr/lib/*/xed/plugins/*.so
usr/share/applications/xed.desktop
usr/share/dbus-1/
usr/share/man/

View File

@ -1,5 +1,3 @@
egg_sm_client_get_type
egg_sm_client_xsmp_get_type
xed_app_activatable_get_type
xed_app_get_type
xed_close_button_get_type

View File

@ -761,13 +761,11 @@ on_rename_cb (XedFileBrowserStore *store,
GFile *newfile,
XedWindow *window)
{
XedApp *app;
GList *documents;
GList *item;
/* Find all documents and set its uri to newuri where it matches olduri */
app = xed_app_get_default ();
documents = xed_app_get_documents (app);
documents = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (item = documents; item; item = item->next)
{

View File

@ -34,7 +34,7 @@
#include <xed/xed-window-activatable.h>
#include <xed/xed-debug.h>
#include <xed/xed-utils.h>
#include <xed/xed-help.h>
#include <xed/xed-app.h>
#define XED_SORT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_SORT_PLUGIN, XedSortPluginPrivate))
@ -110,7 +110,7 @@ sort_dialog_response_handler (GtkDialog *dlg,
break;
case GTK_RESPONSE_HELP:
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-sort-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-sort-plugin");
break;
case GTK_RESPONSE_CANCEL:

View File

@ -34,7 +34,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <xed/xed-utils.h>
#include <xed/xed-help.h>
#include <xed/xed-app.h>
#include "xed-spell-language-dialog.h"
#include "xed-spell-checker-language.h"
@ -70,7 +70,7 @@ dialog_response_handler (GtkDialog *dlg,
{
if (res_id == GTK_RESPONSE_HELP)
{
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");
g_signal_stop_emission_by_name (dlg, "response");
}

View File

@ -32,7 +32,7 @@
#include <time.h>
#include "xed-time-plugin.h"
#include <xed/xed-help.h>
#include <xed/xed-app.h>
#include <glib/gi18n-lib.h>
#include <glib.h>
@ -916,7 +916,7 @@ choose_format_dialog_response_cb (GtkWidget *widget,
case GTK_RESPONSE_HELP:
{
xed_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_HELP");
xed_help_display (GTK_WINDOW (widget), NULL, "xed-insert-date-time-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (widget), NULL, "xed-insert-date-time-plugin");
break;
}
case GTK_RESPONSE_OK:

View File

@ -17,7 +17,6 @@ xed/xed-commands-search.c
xed/xed-debug.c
xed/xed-document.c
xed/xed-documents-panel.c
xed/xed-encodings.c
xed/xed-encodings-combo-box.c
xed/xed-file-chooser-dialog.c
xed/xed-gio-document-loader.c

View File

@ -1,5 +1,5 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = dialogs smclient
SUBDIRS = dialogs
bin_PROGRAMS = xed
@ -8,7 +8,6 @@ noinst_LTLIBRARIES = libxed.la
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(srcdir) \
-I$(srcdir)/smclient \
$(XED_CFLAGS) \
$(WARN_CFLAGS) \
$(INTROSPECTION_CFLAGS) \
@ -22,7 +21,6 @@ xed_SOURCES = \
xed_LDADD = \
libxed.la \
$(XED_LIBS) \
$(EGG_SMCLIENT_LIBS) \
$(INTROSPECTION_LIBS)
xed_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
@ -30,8 +28,7 @@ xed_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
libxed_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
libxed_la_LIBADD = \
dialogs/libdialogs.la \
smclient/libeggsmclient.la
dialogs/libdialogs.la
# XED_LIBS must be the last to ensure correct order on some platforms
libxed_la_LIBADD += $(XED_LIBS) -lICE
@ -52,7 +49,6 @@ NOINST_H_FILES = \
xed-plugins-engine.h \
xed-print-job.h \
xed-print-preview.h \
xed-session.h \
xed-settings.h \
xed-status-combo-box.h \
xed-tab-label.h \
@ -69,7 +65,6 @@ INST_H_FILES = \
xed-document.h \
xed-encodings-combo-box.h \
xed-file-chooser-dialog.h \
xed-help.h \
xed-message-bus.h \
xed-message-type.h \
xed-message.h \
@ -111,7 +106,6 @@ libxed_c_files = \
xed-documents-panel.c \
xed-encodings-combo-box.c \
xed-file-chooser-dialog.c \
xed-help.c \
xed-history-entry.c \
xed-io-error-message-area.c \
xed-message-bus.c \
@ -123,7 +117,6 @@ libxed_c_files = \
xed-print-job.c \
xed-print-preview.c \
xed-progress-message-area.c \
xed-session.c \
xed-settings.c \
xed-searchbar.c \
xed-statusbar.c \
@ -140,7 +133,6 @@ libxed_c_files = \
libxed_la_SOURCES = \
$(BUILT_SOURCES) \
$(libxed_c_files) \
$(BACON_FILES) \
$(POSIXIO_FILES) \
$(NOINST_H_FILES) \
$(INST_H_FILES)
@ -205,10 +197,4 @@ endif
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
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)/xed/update-from-bacon.sh
-include $(top_srcdir)/git.mk

View File

@ -1,396 +0,0 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include "bacon-message-connection.h"
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif
struct BaconMessageConnection {
/* A server accepts connections */
gboolean is_server;
/* The socket path itself */
char *path;
/* File descriptor of the socket */
int fd;
/* Channel to watch */
GIOChannel *chan;
/* Event id returned by g_io_add_watch() */
int conn_id;
/* Connections accepted by this connection */
GSList *accepted_connections;
/* callback */
void (*func) (const char *message, gpointer user_data);
gpointer data;
};
static gboolean
test_is_socket (const char *path)
{
struct stat s;
if (stat (path, &s) == -1)
return FALSE;
if (S_ISSOCK (s.st_mode))
return TRUE;
return FALSE;
}
static gboolean
is_owned_by_user_and_socket (const char *path)
{
struct stat s;
if (stat (path, &s) == -1)
return FALSE;
if (s.st_uid != geteuid ())
return FALSE;
if ((s.st_mode & S_IFSOCK) != S_IFSOCK)
return FALSE;
return TRUE;
}
static gboolean server_cb (GIOChannel *source,
GIOCondition condition, gpointer data);
static gboolean
setup_connection (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn->chan == NULL, FALSE);
conn->chan = g_io_channel_unix_new (conn->fd);
if (!conn->chan) {
return FALSE;
}
g_io_channel_set_line_term (conn->chan, "\n", 1);
conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn);
return TRUE;
}
static void
accept_new_connection (BaconMessageConnection *server_conn)
{
BaconMessageConnection *conn;
int alen;
g_return_if_fail (server_conn->is_server);
conn = g_new0 (BaconMessageConnection, 1);
conn->is_server = FALSE;
conn->func = server_conn->func;
conn->data = server_conn->data;
conn->fd = accept (server_conn->fd, NULL, (guint *)&alen);
server_conn->accepted_connections =
g_slist_prepend (server_conn->accepted_connections, conn);
setup_connection (conn);
}
static gboolean
server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
{
BaconMessageConnection *conn = (BaconMessageConnection *)data;
char *message, *subs, buf;
int cd, rc, offset;
gboolean finished;
offset = 0;
if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) {
accept_new_connection (conn);
return TRUE;
}
message = g_malloc (1);
cd = conn->fd;
rc = read (cd, &buf, 1);
while (rc > 0 && buf != '\n')
{
message = g_realloc (message, rc + offset + 1);
message[offset] = buf;
offset = offset + rc;
rc = read (cd, &buf, 1);
}
if (rc <= 0) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
conn->chan = NULL;
close (conn->fd);
conn->fd = -1;
g_free (message);
conn->conn_id = 0;
return FALSE;
}
message[offset] = '\0';
subs = message;
finished = FALSE;
while (finished == FALSE && *subs != '\0')
{
if (conn->func != NULL)
(*conn->func) (subs, conn->data);
subs += strlen (subs) + 1;
if (subs - message >= offset)
finished = TRUE;
}
g_free (message);
return TRUE;
}
static char *
find_file_with_pattern (const char *dir, const char *pattern)
{
GDir *filedir;
char *found_filename;
const char *filename;
GPatternSpec *pat;
filedir = g_dir_open (dir, 0, NULL);
if (filedir == NULL)
return NULL;
pat = g_pattern_spec_new (pattern);
if (pat == NULL)
{
g_dir_close (filedir);
return NULL;
}
found_filename = NULL;
while ((filename = g_dir_read_name (filedir)))
{
if (g_pattern_match_string (pat, filename))
{
char *tmp = g_build_filename (dir, filename, NULL);
if (is_owned_by_user_and_socket (tmp))
found_filename = g_strdup (filename);
g_free (tmp);
}
if (found_filename != NULL)
break;
}
g_pattern_spec_free (pat);
g_dir_close (filedir);
return found_filename;
}
static char *
socket_filename (const char *prefix)
{
char *pattern, *newfile, *path, *filename;
const char *tmpdir;
pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ());
tmpdir = g_get_tmp_dir ();
filename = find_file_with_pattern (tmpdir, pattern);
if (filename == NULL)
{
newfile = g_strdup_printf ("%s.%s.%u", prefix,
g_get_user_name (), g_random_int ());
path = g_build_filename (tmpdir, newfile, NULL);
g_free (newfile);
} else {
path = g_build_filename (tmpdir, filename, NULL);
g_free (filename);
}
g_free (pattern);
return path;
}
static gboolean
try_server (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;
uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN (strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}
listen (conn->fd, 5);
if (!setup_connection (conn))
return FALSE;
return TRUE;
}
static gboolean
try_client (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;
uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN(strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (connect (conn->fd, (struct sockaddr *) &uaddr,
sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}
return setup_connection (conn);
}
BaconMessageConnection *
bacon_message_connection_new (const char *prefix)
{
BaconMessageConnection *conn;
g_return_val_if_fail (prefix != NULL, NULL);
conn = g_new0 (BaconMessageConnection, 1);
conn->path = socket_filename (prefix);
if (test_is_socket (conn->path) == FALSE)
{
if (!try_server (conn))
{
bacon_message_connection_free (conn);
return NULL;
}
conn->is_server = TRUE;
return conn;
}
if (try_client (conn) == FALSE)
{
unlink (conn->path);
try_server (conn);
if (conn->fd == -1)
{
bacon_message_connection_free (conn);
return NULL;
}
conn->is_server = TRUE;
return conn;
}
conn->is_server = FALSE;
return conn;
}
void
bacon_message_connection_free (BaconMessageConnection *conn)
{
GSList *child_conn;
g_return_if_fail (conn != NULL);
/* Only servers can accept other connections */
g_return_if_fail (conn->is_server != FALSE ||
conn->accepted_connections == NULL);
child_conn = conn->accepted_connections;
while (child_conn != NULL) {
bacon_message_connection_free (child_conn->data);
child_conn = g_slist_next (child_conn);
}
g_slist_free (conn->accepted_connections);
if (conn->conn_id) {
g_source_remove (conn->conn_id);
conn->conn_id = 0;
}
if (conn->chan) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
}
if (conn->is_server != FALSE) {
unlink (conn->path);
}
if (conn->fd != -1) {
close (conn->fd);
}
g_free (conn->path);
g_free (conn);
}
void
bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data)
{
g_return_if_fail (conn != NULL);
conn->func = func;
conn->data = user_data;
}
void
bacon_message_connection_send (BaconMessageConnection *conn,
const char *message)
{
g_return_if_fail (conn != NULL);
g_return_if_fail (message != NULL);
g_io_channel_write_chars (conn->chan, message, strlen (message),
NULL, NULL);
g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL);
g_io_channel_flush (conn->chan, NULL);
}
gboolean
bacon_message_connection_get_is_server (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn != NULL, FALSE);
return conn->is_server;
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef BACON_MESSAGE_CONNECTION_H
#define BACON_MESSAGE_CONNECTION_H
#include <glib.h>
G_BEGIN_DECLS
typedef void (*BaconMessageReceivedFunc) (const char *message,
gpointer user_data);
typedef struct BaconMessageConnection BaconMessageConnection;
BaconMessageConnection *bacon_message_connection_new (const char *prefix);
void bacon_message_connection_free (BaconMessageConnection *conn);
void bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data);
void bacon_message_connection_send (BaconMessageConnection *conn,
const char *message);
gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn);
G_END_DECLS
#endif /* BACON_MESSAGE_CONNECTION_H */

View File

@ -40,7 +40,6 @@
#include "xed-encodings-dialog.h"
#include "xed-utils.h"
#include "xed-debug.h"
#include "xed-help.h"
#include "xed-dirs.h"
#include "xed-settings.h"
@ -271,7 +270,7 @@ response_handler (GtkDialog *dialog,
{
if (response_id == GTK_RESPONSE_HELP)
{
xed_help_display (GTK_WINDOW (dialog), "xed", NULL);
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dialog), "xed", NULL);
g_signal_stop_emission_by_name (dialog, "response");
return;
}

View File

@ -47,7 +47,6 @@
#include "xed-utils.h"
#include "xed-debug.h"
#include "xed-document.h"
#include "xed-help.h"
#include "xed-dirs.h"
#include "xed-settings.h"
#include "xed-utils.h"
@ -172,7 +171,7 @@ dialog_response_handler (GtkDialog *dlg,
switch (res_id)
{
case GTK_RESPONSE_HELP:
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-prefs");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-prefs");
g_signal_stop_emission_by_name (dlg, "response");
break;
default:
@ -308,13 +307,11 @@ setup_view_page (XedPreferencesDialog *dlg)
{
GtkWrapMode wrap_mode;
gboolean display_right_margin;
guint right_margin_position;
xed_debug (DEBUG_PREFS);
/* Get values */
display_right_margin = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_DISPLAY_RIGHT_MARGIN);
right_margin_position = g_settings_get_uint (dlg->priv->editor, XED_SETTINGS_RIGHT_MARGIN_POSITION);
/* Set initial state */
wrap_mode = g_settings_get_enum (dlg->priv->editor, XED_SETTINGS_WRAP_MODE);
@ -400,7 +397,7 @@ setup_font_colors_page_font_section (XedPreferencesDialog *dlg)
ATK_RELATION_CONTROLLER_FOR);
/* Get values */
settings = _xed_app_get_settings (xed_app_get_default ());
settings = _xed_app_get_settings (XED_APP (g_application_get_default ()));
system_font = xed_settings_get_system_font (XED_SETTINGS (settings));
use_default_font = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_USE_DEFAULT_FONT);

View File

@ -1,39 +0,0 @@
platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
platform_libs = libeggdesktopfile.la
platform_ltlibraries = libeggdesktopfile.la
platform_sources = eggsmclient-xsmp.c
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\""EggSMClient"\" \
$(XED_CFLAGS) \
$(platform_defines) \
$(EGG_SMCLIENT_CFLAGS)
noinst_LTLIBRARIES = \
libeggsmclient.la \
$(platform_ltlibraries)
libeggsmclient_la_LIBADD = \
$(EGG_SMCLIENT_LIBS) \
$(platform_libs)
libeggsmclient_la_LDFLAGS = \
$(platform_ldflags)
libeggsmclient_la_SOURCES = \
eggsmclient.c \
eggsmclient.h \
eggsmclient-private.h \
$(platform_sources)
libeggdesktopfile_la_LIBADD = \
$(EGG_LIBS)
libeggdesktopfile_la_SOURCES = \
eggdesktopfile.c \
eggdesktopfile.h
EXTRA_DIST = \
eggsmclient-xsmp.c
-include $(top_srcdir)/git.mk

File diff suppressed because it is too large Load Diff

View File

@ -1,160 +0,0 @@
/* eggdesktopfile.h - Freedesktop.Org Desktop Files
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 151 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_DESKTOP_FILE_H__
#define __EGG_DESKTOP_FILE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct EggDesktopFile EggDesktopFile;
typedef enum {
EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
EGG_DESKTOP_FILE_TYPE_APPLICATION,
EGG_DESKTOP_FILE_TYPE_LINK,
EGG_DESKTOP_FILE_TYPE_DIRECTORY
} EggDesktopFileType;
EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
const char **search_dirs,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
const char *source,
GError **error);
void egg_desktop_file_free (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);
EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
const char *desktop_environment);
gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
GSList *documents,
GError **error);
gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
GSList *documents,
GError **error,
...) G_GNUC_NULL_TERMINATED;
typedef enum {
EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
EGG_DESKTOP_FILE_LAUNCH_PUTENV,
EGG_DESKTOP_FILE_LAUNCH_SCREEN,
EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
EGG_DESKTOP_FILE_LAUNCH_TIME,
EGG_DESKTOP_FILE_LAUNCH_FLAGS,
EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
} EggDesktopFileLaunchOption;
/* Standard Keys */
#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
#define EGG_DESKTOP_FILE_KEY_NAME "Name"
#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
#define EGG_DESKTOP_FILE_KEY_PATH "Path"
#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
#define EGG_DESKTOP_FILE_KEY_URL "URL"
/* Accessors */
gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
const char *key,
GError **error) G_GNUC_MALLOC;
char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
GError **error) G_GNUC_MALLOC;
gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
const char *key,
GError **error);
double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
const char *key,
gsize *length,
GError **error) G_GNUC_MALLOC;
char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
gsize *length,
GError **error) G_GNUC_MALLOC;
/* Errors */
#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
GQuark egg_desktop_file_error_quark (void);
typedef enum {
EGG_DESKTOP_FILE_ERROR_INVALID,
EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
} EggDesktopFileError;
/* Global application desktop file */
void egg_set_desktop_file (const char *desktop_file_path);
void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
EggDesktopFile *egg_get_desktop_file (void);
G_END_DECLS
#endif /* __EGG_DESKTOP_FILE_H__ */

View File

@ -1,39 +0,0 @@
/* eggsmclient-private.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_SM_CLIENT_PRIVATE_H__
#define __EGG_SM_CLIENT_PRIVATE_H__
#include <gtk/gtk.h>
#include "eggsmclient.h"
G_BEGIN_DECLS
GKeyFile *egg_sm_client_save_state (EggSMClient *client);
void egg_sm_client_quit_requested (EggSMClient *client);
void egg_sm_client_quit_cancelled (EggSMClient *client);
void egg_sm_client_quit (EggSMClient *client);
GType egg_sm_client_xsmp_get_type (void);
EggSMClient *egg_sm_client_xsmp_new (void);
G_END_DECLS
#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,573 +0,0 @@
/*
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include <string.h>
#include <glib/gi18n.h>
#include "eggsmclient.h"
#include "eggsmclient-private.h"
static void egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data);
enum {
SAVE_STATE,
QUIT_REQUESTED,
QUIT_CANCELLED,
QUIT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
struct _EggSMClientPrivate {
GKeyFile *state_file;
};
#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
static EggSMClient *global_client;
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
static void
egg_sm_client_init (EggSMClient *client)
{
;
}
static void
egg_sm_client_class_init (EggSMClientClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
/**
* EggSMClient::save_state:
* @client: the client
* @state_file: a #GKeyFile to save state information into
*
* Emitted when the session manager has requested that the
* application save information about its current state. The
* application should save its state into @state_file, and then the
* session manager may then restart the application in a future
* session and tell it to initialize itself from that state.
*
* You should not save any data into @state_file's "start group"
* (ie, the %NULL group). Instead, applications should save their
* data into groups with names that start with the application name,
* and libraries that connect to this signal should save their data
* into groups with names that start with the library name.
*
* Alternatively, rather than (or in addition to) using @state_file,
* the application can save its state by calling
* egg_sm_client_set_restart_command() during the processing of this
* signal (eg, to include a list of files to open).
**/
signals[SAVE_STATE] =
g_signal_new ("save_state",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, save_state),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1, G_TYPE_POINTER);
/**
* EggSMClient::quit_requested:
* @client: the client
*
* Emitted when the session manager requests that the application
* exit (generally because the user is logging out). The application
* should decide whether or not it is willing to quit (perhaps after
* asking the user what to do with documents that have unsaved
* changes) and then call egg_sm_client_will_quit(), passing %TRUE
* or %FALSE to give its answer to the session manager. (It does not
* need to give an answer before returning from the signal handler;
* it can interact with the user asynchronously and then give its
* answer later on.) If the application does not connect to this
* signal, then #EggSMClient will automatically return %TRUE on its
* behalf.
*
* The application should not save its session state as part of
* handling this signal; if the user has requested that the session
* be saved when logging out, then ::save_state will be emitted
* separately.
*
* If the application agrees to quit, it should then wait for either
* the ::quit_cancelled or ::quit signals to be emitted.
**/
signals[QUIT_REQUESTED] =
g_signal_new ("quit_requested",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit_cancelled:
* @client: the client
*
* Emitted when the session manager decides to cancel a logout after
* the application has already agreed to quit. After receiving this
* signal, the application can go back to what it was doing before
* receiving the ::quit_requested signal.
**/
signals[QUIT_CANCELLED] =
g_signal_new ("quit_cancelled",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit:
* @client: the client
*
* Emitted when the session manager wants the application to quit
* (generally because the user is logging out). The application
* should exit as soon as possible after receiving this signal; if
* it does not, the session manager may choose to forcibly kill it.
*
* Normally a GUI application would only be sent a ::quit if it
* agreed to quit in response to a ::quit_requested signal. However,
* this is not guaranteed; in some situations the session manager
* may decide to end the session without giving applications a
* chance to object.
**/
signals[QUIT] =
g_signal_new ("quit",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static gboolean sm_client_disable = FALSE;
static char *sm_client_state_file = NULL;
static char *sm_client_id = NULL;
static char *sm_config_prefix = NULL;
static gboolean
sm_client_post_parse_func (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
EggSMClient *client = egg_sm_client_get ();
if (sm_client_id == NULL)
{
const gchar *desktop_autostart_id;
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
if (desktop_autostart_id != NULL)
sm_client_id = g_strdup (desktop_autostart_id);
}
/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
* use the same client id. */
g_unsetenv ("DESKTOP_AUTOSTART_ID");
if (EGG_SM_CLIENT_GET_CLASS (client)->startup)
EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
return TRUE;
}
/**
* egg_sm_client_get_option_group:
*
* Creates a %GOptionGroup containing the session-management-related
* options. You should add this group to the application's
* %GOptionContext if you want to use #EggSMClient.
*
* Return value: the %GOptionGroup
**/
GOptionGroup *
egg_sm_client_get_option_group (void)
{
const GOptionEntry entries[] = {
{ "sm-client-disable", 0, 0,
G_OPTION_ARG_NONE, &sm_client_disable,
N_("Disable connection to session manager"), NULL },
{ "sm-client-state-file", 0, 0,
G_OPTION_ARG_FILENAME, &sm_client_state_file,
N_("Specify file containing saved configuration"), N_("FILE") },
{ "sm-client-id", 0, 0,
G_OPTION_ARG_STRING, &sm_client_id,
N_("Specify session management ID"), N_("ID") },
/* MateClient compatibility option */
{ "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_NONE, &sm_client_disable,
NULL, NULL },
/* MateClient compatibility option. This is a dummy option that only
* exists so that sessions saved by apps with MateClient can be restored
* later when they've switched to EggSMClient. See bug #575308.
*/
{ "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_STRING, &sm_config_prefix,
NULL, NULL },
{ NULL }
};
GOptionGroup *group;
/* Use our own debug handler for the "EggSMClient" domain. */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
egg_sm_client_debug_handler, NULL);
group = g_option_group_new ("sm-client",
_("Session management options:"),
_("Show session management options"),
NULL, NULL);
g_option_group_add_entries (group, entries);
g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
return group;
}
/**
* egg_sm_client_set_mode:
* @mode: an #EggSMClient mode
*
* Sets the "mode" of #EggSMClient as follows:
*
* %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
* disabled. The application will not even connect to the session
* manager. (egg_sm_client_get() will still return an #EggSMClient,
* but it will just be a dummy object.)
*
* %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
* the session manager (and thus will receive notification when the
* user is logging out, etc), but will request to not be
* automatically restarted with saved state in future sessions.
*
* %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
* function normally.
*
* This must be called before the application's main loop begins.
**/
void
egg_sm_client_set_mode (EggSMClientMode mode)
{
global_client_mode = mode;
}
/**
* egg_sm_client_get_mode:
*
* Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
* for details.
*
* Return value: the global #EggSMClientMode
**/
EggSMClientMode
egg_sm_client_get_mode (void)
{
return global_client_mode;
}
/**
* egg_sm_client_get:
*
* Returns the master #EggSMClient for the application.
*
* On platforms that support saved sessions (ie, POSIX/X11), the
* application will only request to be restarted by the session
* manager if you call egg_set_desktop_file() to set an application
* desktop file. In particular, if the desktop file contains the key
* "X
*
* Return value: the master #EggSMClient.
**/
EggSMClient *
egg_sm_client_get (void)
{
if (!global_client)
{
if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
!sm_client_disable)
{
global_client = egg_sm_client_xsmp_new ();
}
/* Fallback: create a dummy client, so that callers don't have
* to worry about a %NULL return value.
*/
if (!global_client)
global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
}
return global_client;
}
/**
* egg_sm_client_is_resumed:
* @client: the client
*
* Checks whether or not the current session has been resumed from
* a previous saved session. If so, the application should call
* egg_sm_client_get_state_file() and restore its state from the
* returned #GKeyFile.
*
* Return value: %TRUE if the session has been resumed
**/
gboolean
egg_sm_client_is_resumed (EggSMClient *client)
{
g_return_val_if_fail (client == global_client, FALSE);
return sm_client_state_file != NULL;
}
/**
* egg_sm_client_get_state_file:
* @client: the client
*
* If the application was resumed by the session manager, this will
* return the #GKeyFile containing its state from the previous
* session.
*
* Note that other libraries and #EggSMClient itself may also store
* state in the key file, so if you call egg_sm_client_get_groups(),
* on it, the return value will likely include groups that you did not
* put there yourself. (It is also not guaranteed that the first
* group created by the application will still be the "start group"
* when it is resumed.)
*
* Return value: the #GKeyFile containing the application's earlier
* state, or %NULL on error. You should not free this key file; it
* is owned by @client.
**/
GKeyFile *
egg_sm_client_get_state_file (EggSMClient *client)
{
EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
char *state_file_path;
GError *err = NULL;
g_return_val_if_fail (client == global_client, NULL);
if (!sm_client_state_file)
return NULL;
if (priv->state_file)
return priv->state_file;
if (!strncmp (sm_client_state_file, "file://", 7))
state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
else
state_file_path = g_strdup (sm_client_state_file);
priv->state_file = g_key_file_new ();
if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
{
g_warning ("Could not load SM state file '%s': %s",
sm_client_state_file, err->message);
g_clear_error (&err);
g_key_file_free (priv->state_file);
priv->state_file = NULL;
}
g_free (state_file_path);
return priv->state_file;
}
/**
* egg_sm_client_set_restart_command:
* @client: the client
* @argc: the length of @argv
* @argv: argument vector
*
* Sets the command used to restart @client if it does not have a
* .desktop file that can be used to find its restart command.
*
* This can also be used when handling the ::save_state signal, to
* save the current state via an updated command line. (Eg, providing
* a list of filenames to open when the application is resumed.)
**/
void
egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
}
/**
* egg_sm_client_will_quit:
* @client: the client
* @will_quit: whether or not the application is willing to quit
*
* This MUST be called in response to the ::quit_requested signal, to
* indicate whether or not the application is willing to quit. The
* application may call it either directly from the signal handler, or
* at some later point (eg, after asynchronously interacting with the
* user).
*
* If the application does not connect to ::quit_requested,
* #EggSMClient will call this method on its behalf (passing %TRUE
* for @will_quit).
*
* After calling this method, the application should wait to receive
* either ::quit_cancelled or ::quit.
**/
void
egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
}
/**
* egg_sm_client_end_session:
* @style: a hint at how to end the session
* @request_confirmation: whether or not the user should get a chance
* to confirm the action
*
* Requests that the session manager end the current session. @style
* indicates how the session should be ended, and
* @request_confirmation indicates whether or not the user should be
* given a chance to confirm the logout/reboot/shutdown. Both of these
* flags are merely hints though; the session manager may choose to
* ignore them.
*
* Return value: %TRUE if the request was sent; %FALSE if it could not
* be (eg, because it could not connect to the session manager).
**/
gboolean
egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation)
{
EggSMClient *client = egg_sm_client_get ();
g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
{
return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
request_confirmation);
}
else
return FALSE;
}
/* Signal-emitting callbacks from platform-specific code */
GKeyFile *
egg_sm_client_save_state (EggSMClient *client)
{
GKeyFile *state_file;
char *group;
g_return_val_if_fail (client == global_client, NULL);
state_file = g_key_file_new ();
g_debug ("Emitting save_state");
g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
g_debug ("Done emitting save_state");
group = g_key_file_get_start_group (state_file);
if (group)
{
g_free (group);
return state_file;
}
else
{
g_key_file_free (state_file);
return NULL;
}
}
void
egg_sm_client_quit_requested (EggSMClient *client)
{
g_return_if_fail (client == global_client);
if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
{
g_debug ("Not emitting quit_requested because no one is listening");
egg_sm_client_will_quit (client, TRUE);
return;
}
g_debug ("Emitting quit_requested");
g_signal_emit (client, signals[QUIT_REQUESTED], 0);
g_debug ("Done emitting quit_requested");
}
void
egg_sm_client_quit_cancelled (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit_cancelled");
g_signal_emit (client, signals[QUIT_CANCELLED], 0);
g_debug ("Done emitting quit_cancelled");
}
void
egg_sm_client_quit (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit");
g_signal_emit (client, signals[QUIT], 0);
g_debug ("Done emitting quit");
/* FIXME: should we just call gtk_main_quit() here? */
}
static void
egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
static int debug = -1;
if (debug < 0)
debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
if (debug)
g_log_default_handler (log_domain, log_level, message, NULL);
}

View File

@ -1,117 +0,0 @@
/* eggsmclient.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_SM_CLIENT_H__
#define __EGG_SM_CLIENT_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
typedef struct _EggSMClient EggSMClient;
typedef struct _EggSMClientClass EggSMClientClass;
typedef struct _EggSMClientPrivate EggSMClientPrivate;
typedef enum {
EGG_SM_CLIENT_END_SESSION_DEFAULT,
EGG_SM_CLIENT_LOGOUT,
EGG_SM_CLIENT_REBOOT,
EGG_SM_CLIENT_SHUTDOWN
} EggSMClientEndStyle;
typedef enum {
EGG_SM_CLIENT_MODE_DISABLED,
EGG_SM_CLIENT_MODE_NO_RESTART,
EGG_SM_CLIENT_MODE_NORMAL
} EggSMClientMode;
struct _EggSMClient
{
GObject parent;
};
struct _EggSMClientClass
{
GObjectClass parent_class;
/* signals */
void (*save_state) (EggSMClient *client,
GKeyFile *state_file);
void (*quit_requested) (EggSMClient *client);
void (*quit_cancelled) (EggSMClient *client);
void (*quit) (EggSMClient *client);
/* virtual methods */
void (*startup) (EggSMClient *client,
const char *client_id);
void (*set_restart_command) (EggSMClient *client,
int argc,
const char **argv);
void (*will_quit) (EggSMClient *client,
gboolean will_quit);
gboolean (*end_session) (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation);
/* Padding for future expansion */
void (*_egg_reserved1) (void);
void (*_egg_reserved2) (void);
void (*_egg_reserved3) (void);
void (*_egg_reserved4) (void);
};
GType egg_sm_client_get_type (void) G_GNUC_CONST;
GOptionGroup *egg_sm_client_get_option_group (void);
/* Initialization */
void egg_sm_client_set_mode (EggSMClientMode mode);
EggSMClientMode egg_sm_client_get_mode (void);
EggSMClient *egg_sm_client_get (void);
/* Resuming a saved session */
gboolean egg_sm_client_is_resumed (EggSMClient *client);
GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
/* Alternate means of saving state */
void egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv);
/* Handling "quit_requested" signal */
void egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit);
/* Initiate a logout/reboot/shutdown */
gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation);
G_END_DECLS
#endif /* __EGG_SM_CLIENT_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ typedef struct _XedAppClass XedAppClass;
struct _XedApp
{
GObject object;
GtkApplication parent;
/*< private > */
XedAppPrivate *priv;
@ -58,38 +58,49 @@ struct _XedApp
struct _XedAppClass
{
GObjectClass parent_class;
GtkApplicationClass parent_class;
// gboolean (*last_window_destroyed) (XedApp *app);
gboolean (*show_help) (XedApp *app,
GtkWindow *parent,
const gchar *name,
const gchar *link_id);
gchar *(*help_link_id) (XedApp *app,
const gchar *name,
const gchar *link_id);
void (*set_window_title) (XedApp *app,
XedWindow *window,
const gchar *title);
};
/*
* Public methods
*/
/* Public methods */
GType xed_app_get_type (void) G_GNUC_CONST;
XedApp *xed_app_get_default (void);
XedWindow *xed_app_create_window (XedApp *app,
GdkScreen *screen);
const GList *xed_app_get_windows (XedApp *app);
XedWindow *xed_app_get_active_window (XedApp *app);
GList *xed_app_get_main_windows (XedApp *app);
/* Returns a newly allocated list with all the documents */
GList *xed_app_get_documents (XedApp *app);
/* Returns a newly allocated list with all the views */
GList *xed_app_get_views (XedApp *app);
/*
* Non exported functions
*/
gboolean xed_app_show_help (XedApp *app,
GtkWindow *parent,
const gchar *name,
const gchar *link_id);
void xed_app_set_window_title (XedApp *app,
XedWindow *window,
const gchar *title);
/* Non exported functions */
XedWindow *_xed_app_restore_window (XedApp *app,
const gchar *role);
XedWindow *_xed_app_get_window_in_viewport (XedApp *app,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y);
/* global print config */
GtkPageSetup *_xed_app_get_default_page_setup (XedApp *app);

View File

@ -61,6 +61,9 @@ static void tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec,
XedWindow *window);
static void save_as_tab (XedTab *tab,
XedWindow *window);
void
_xed_cmd_file_new (GtkAction *action,
XedWindow *window)
@ -116,7 +119,7 @@ is_duplicated_file (GSList *files,
}
/* File loading */
static gint
static GSList *
load_file_list (XedWindow *window,
const GSList *files,
const GtkSourceEncoding *encoding,
@ -124,11 +127,12 @@ load_file_list (XedWindow *window,
gboolean create)
{
XedTab *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;
xed_debug (DEBUG_COMMANDS);
@ -145,29 +149,25 @@ load_file_list (XedWindow *window,
{
if (l == files)
{
XedDocument *doc;
xed_window_set_active_tab (window, tab);
jump_to = FALSE;
doc = xed_tab_get_document (tab);
if (line_pos > 0)
{
XedDocument *doc;
XedView *view;
doc = xed_tab_get_document (tab);
view = xed_tab_get_view (tab);
/* document counts lines starting from 0 */
xed_document_goto_line (doc, line_pos - 1);
xed_view_scroll_to_cursor (view);
xed_view_scroll_to_cursor (xed_tab_get_view (tab));
}
}
++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_tab_get_document (tab));
}
else
{
files_to_load = g_slist_prepend (files_to_load,
l->data);
files_to_load = g_slist_prepend (files_to_load, l->data);
}
}
}
@ -176,7 +176,7 @@ load_file_list (XedWindow *window,
if (files_to_load == NULL)
{
return loaded_files;
return g_slist_reverse (loaded_files);
}
files_to_load = g_slist_reverse (files_to_load);
@ -196,7 +196,8 @@ load_file_list (XedWindow *window,
l = g_slist_next (l);
jump_to = FALSE;
++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_tab_get_document (tab));
}
}
@ -209,13 +210,16 @@ load_file_list (XedWindow *window,
if (tab != NULL)
{
jump_to = FALSE;
++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_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)
{
XedDocument *doc;
gchar *uri_for_display;
@ -238,8 +242,8 @@ load_file_list (XedWindow *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 */
@ -265,6 +269,7 @@ xed_commands_load_location (XedWindow *window,
{
GSList *locations = NULL;
gchar *uri;
GSList *ret;
g_return_if_fail (XED_IS_WINDOW (window));
g_return_if_fail (G_IS_FILE (location));
@ -276,7 +281,8 @@ xed_commands_load_location (XedWindow *window,
locations = g_slist_prepend (locations, location);
load_file_list (window, locations, encoding, line_pos, FALSE);
ret = load_file_list (window, locations, encoding, line_pos, FALSE);
g_slist_free (ret);
g_slist_free (locations);
}
@ -292,7 +298,7 @@ xed_commands_load_location (XedWindow *window,
*
* Returns:
*/
gint
GSList *
xed_commands_load_locations (XedWindow *window,
const GSList *locations,
const GtkSourceEncoding *encoding,
@ -311,7 +317,7 @@ xed_commands_load_locations (XedWindow *window,
* first doc. Beside specifying a not existing uri creates a
* titled document.
*/
gint
GSList *
_xed_cmd_load_files_from_prompt (XedWindow *window,
GSList *files,
const GtkSourceEncoding *encoding,
@ -338,6 +344,7 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
{
GSList *files;
const GtkSourceEncoding *encoding;
GSList *loaded;
xed_debug (DEBUG_COMMANDS);
@ -358,7 +365,9 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
/* Remember the folder we navigated to */
_xed_window_set_default_location (window, files->data);
xed_commands_load_locations (window, files, encoding, 0);
loaded = xed_commands_load_locations (window, files, encoding, 0);
g_slist_free (loaded);
g_slist_foreach (files, (GFunc) g_object_unref, NULL);
g_slist_free (files);
@ -433,9 +442,6 @@ _xed_cmd_file_open (GtkAction *action,
gtk_widget_show (open_dialog);
}
/* File saving */
static void file_save_as (XedTab *tab, XedWindow *window);
static gboolean
is_read_only (GFile *location)
{
@ -511,6 +517,14 @@ replace_read_only_file (GtkWindow *parent,
return (ret == GTK_RESPONSE_YES);
}
static void
save_finish_cb (XedTab *tab,
GAsyncResult *result,
gpointer user_data)
{
_xed_tab_save_finish (tab, result);
}
static void
save_dialog_response_cb (XedFileChooserDialog *dialog,
gint response_id,
@ -535,13 +549,11 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
{
GFile *location;
XedDocument *doc;
GtkSourceFile *file;
gchar *parse_name;
GtkSourceNewlineType newline_type;
const GtkSourceEncoding *encoding;
doc = xed_tab_get_document (tab);
file = xed_document_get_file (doc);
location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_return_if_fail (location != NULL);
@ -567,7 +579,13 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
* even if the saving fails... */
_xed_window_set_default_location (window, location);
_xed_tab_save_as (tab, location, encoding, newline_type);
_xed_tab_save_as_async (tab,
location,
encoding,
newline_type,
NULL,
(GAsyncReadyCallback) save_finish_cb,
NULL);
g_object_unref (location);
}
@ -602,7 +620,7 @@ save_next_tab:
}
xed_window_set_active_tab (window, tab);
file_save_as (tab, window);
save_as_tab (tab, window);
}
}
@ -643,7 +661,7 @@ confirm_overwrite_callback (GtkFileChooser *dialog,
}
static void
file_save_as (XedTab *tab,
save_as_tab (XedTab *tab,
XedWindow *window)
{
GtkWidget *save_dialog;
@ -715,7 +733,11 @@ file_save_as (XedTab *tab,
/* Set suggested encoding */
encoding = gtk_source_file_get_encoding (file);
g_return_if_fail (encoding != NULL);
if (encoding == NULL)
{
encoding = gtk_source_encoding_get_utf8 ();
}
newline_type = gtk_source_file_get_newline_type (file);
@ -731,7 +753,7 @@ file_save_as (XedTab *tab,
}
static void
file_save (XedTab *tab,
save_tab (XedTab *tab,
XedWindow *window)
{
XedDocument *doc;
@ -750,7 +772,7 @@ file_save (XedTab *tab,
{
xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly");
file_save_as (tab, window);
save_as_tab (tab, window);
return;
}
@ -763,7 +785,10 @@ file_save (XedTab *tab,
g_free (uri_for_display);
_xed_tab_save (tab);
_xed_tab_save_async (tab,
NULL,
(GAsyncReadyCallback) save_finish_cb,
NULL);
}
void
@ -780,7 +805,7 @@ _xed_cmd_file_save (GtkAction *action,
return;
}
file_save (tab, window);
save_tab (tab, window);
}
void
@ -797,14 +822,14 @@ _xed_cmd_file_save_as (GtkAction *action,
return;
}
file_save_as (tab, window);
save_as_tab (tab, window);
}
/*
* The docs in the list must belong to the same XedWindow.
*/
void
_xed_cmd_file_save_documents_list (XedWindow *window,
static void
save_documents_list (XedWindow *window,
GList *docs)
{
GList *l;
@ -846,7 +871,7 @@ _xed_cmd_file_save_documents_list (XedWindow *window,
}
else
{
file_save (t, window);
save_tab (t, window);
}
}
else
@ -898,7 +923,7 @@ _xed_cmd_file_save_documents_list (XedWindow *window,
tab = XED_TAB (tabs_to_save_as->data);
xed_window_set_active_tab (window, tab);
file_save_as (tab, window);
save_as_tab (tab, window);
}
}
@ -913,7 +938,7 @@ xed_commands_save_all_documents (XedWindow *window)
docs = xed_window_get_documents (window);
_xed_cmd_file_save_documents_list (window, docs);
save_documents_list (window, docs);
g_list_free (docs);
}
@ -937,7 +962,7 @@ xed_commands_save_document (XedWindow *window,
xed_debug (DEBUG_COMMANDS);
tab = xed_tab_get_from_document (document);
file_save (tab, window);
save_tab (tab, window);
}
/* File revert */
@ -1213,7 +1238,7 @@ save_and_close (XedTab *tab,
/* Trace tab state changes */
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
file_save (tab, window);
save_tab (tab, window);
}
static void
@ -1228,7 +1253,7 @@ save_as_and_close (XedTab *tab,
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
xed_window_set_active_tab (window, tab);
file_save_as (tab, window);
save_as_tab (tab, window);
}
static void

View File

@ -40,17 +40,19 @@
#include "xed-commands.h"
#include "xed-debug.h"
#include "xed-help.h"
#include "xed-app.h"
#include "xed-dirs.h"
void _xed_cmd_help_contents(GtkAction* action, XedWindow* window)
void _xed_cmd_help_contents (GtkAction *action,
XedWindow *window)
{
xed_debug(DEBUG_COMMANDS);
xed_help_display(GTK_WINDOW(window), NULL, NULL);
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (window), NULL, NULL);
}
void _xed_cmd_help_about(GtkAction* action, XedWindow* window)
void _xed_cmd_help_about (GtkAction *action,
XedWindow *window)
{
static const gchar comments[] = \
N_("A small and lightweight text editor");

View File

@ -25,14 +25,14 @@ void
_xed_cmd_search_find (GtkAction *action,
XedWindow *window)
{
xed_searchbar_show (XED_SEARCHBAR (xed_window_get_searchbar (window)), SEARCH_MODE_SEARCH);
xed_searchbar_show (XED_SEARCHBAR (xed_window_get_searchbar (window)), XED_SEARCH_MODE_SEARCH);
}
void
_xed_cmd_search_replace (GtkAction *action,
XedWindow *window)
{
xed_searchbar_show (XED_SEARCHBAR (xed_window_get_searchbar (window)), SEARCH_MODE_REPLACE);
xed_searchbar_show (XED_SEARCHBAR (xed_window_get_searchbar (window)), XED_SEARCH_MODE_REPLACE);
}
void

View File

@ -10,7 +10,7 @@ G_BEGIN_DECLS
void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSourceEncoding *encoding, gint line_pos);
/* Ignore non-existing URIs */
gint xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos);
GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos);
void xed_commands_save_document (XedWindow *window, XedDocument *document);
void xed_commands_save_all_documents (XedWindow *window);
@ -19,14 +19,13 @@ void xed_commands_save_all_documents (XedWindow *window);
*/
/* Create titled documens for non-existing URIs */
gint _xed_cmd_load_files_from_prompt (XedWindow *window, GSList *files, const GtkSourceEncoding *encoding, gint line_pos);
GSList *_xed_cmd_load_files_from_prompt (XedWindow *window, GSList *files, const GtkSourceEncoding *encoding, gint line_pos);
void _xed_cmd_file_new (GtkAction *action, XedWindow *window);
void _xed_cmd_file_open (GtkAction *action, XedWindow *window);
void _xed_cmd_file_save (GtkAction *action, XedWindow *window);
void _xed_cmd_file_save_as (GtkAction *action, XedWindow *window);
void _xed_cmd_file_save_all (GtkAction *action, XedWindow *window);
void _xed_cmd_file_revert (GtkAction *action, XedWindow *window);
void _xed_cmd_file_open_uri (GtkAction *action, XedWindow *window);
void _xed_cmd_file_print_preview (GtkAction *action, XedWindow *window);
void _xed_cmd_file_print (GtkAction *action, XedWindow *window);
void _xed_cmd_file_close (GtkAction *action, XedWindow *window);
@ -67,8 +66,6 @@ void _xed_cmd_help_about (GtkAction *action, XedWindow *window);
void _xed_cmd_file_close_tab (XedTab *tab, XedWindow *window);
void _xed_cmd_file_save_documents_list (XedWindow *window, GList *docs);
G_END_DECLS
#endif /* __XED_COMMANDS_H__ */

View File

@ -27,115 +27,115 @@
#include "xed-dirs.h"
gchar *
static gchar *user_config_dir = NULL;
static gchar *user_cache_dir = NULL;
static gchar *user_styles_dir = NULL;
static gchar *user_plugins_dir = NULL;
static gchar *xed_data_dir = NULL;
static gchar *xed_locale_dir = NULL;
static gchar *xed_lib_dir = NULL;
static gchar *xed_plugins_dir = NULL;
static gchar *xed_plugins_data_dir = NULL;
void
xed_dirs_init ()
{
if (xed_data_dir == NULL)
{
xed_data_dir = g_build_filename (DATADIR, "xed", NULL);
xed_locale_dir = g_build_filename (DATADIR, "locale", NULL);
xed_lib_dir = g_build_filename (LIBDIR, "xed", NULL);
}
user_cache_dir = g_build_filename (g_get_user_cache_dir (), "xed", NULL);
user_config_dir = g_build_filename (g_get_user_config_dir (), "xed", NULL);
user_styles_dir = g_build_filename (g_get_user_data_dir (), "xed", "styles", NULL);
user_plugins_dir = g_build_filename (g_get_user_data_dir (), "xed", "plugins", NULL);
xed_plugins_dir = g_build_filename (xed_lib_dir, "plugins", NULL);
xed_plugins_data_dir = g_build_filename (xed_data_dir, "plugins", NULL);
}
void
xed_dirs_shutdown ()
{
g_free (user_config_dir);
g_free (user_cache_dir);
g_free (user_plugins_dir);
g_free (xed_data_dir);
g_free (xed_locale_dir);
g_free (xed_lib_dir);
g_free (xed_plugins_dir);
g_free (xed_plugins_data_dir);
}
const gchar *
xed_dirs_get_user_config_dir (void)
{
gchar* config_dir = NULL;
config_dir = g_build_filename(g_get_user_config_dir(), "xed", NULL);
return config_dir;
return user_config_dir;
}
gchar *
const gchar *
xed_dirs_get_user_cache_dir (void)
{
const gchar* cache_dir;
cache_dir = g_get_user_cache_dir();
return g_build_filename(cache_dir, "xed", NULL);
return user_cache_dir;
}
gchar *
const gchar *
xed_dirs_get_user_styles_dir (void)
{
gchar *user_style_dir;
user_style_dir = g_build_filename (g_get_user_data_dir (), "xed", "styles", NULL);
return user_styles_dir;
}
gchar *
const gchar *
xed_dirs_get_user_plugins_dir (void)
{
gchar* plugin_dir;
plugin_dir = g_build_filename(g_get_user_data_dir(), "xed", "plugins", NULL);
return plugin_dir;
return user_plugins_dir;
}
gchar *
xed_dirs_get_user_accels_file (void)
{
gchar* accels = NULL;
gchar *config_dir = NULL;
config_dir = xed_dirs_get_user_config_dir();
accels = g_build_filename(config_dir, "accels", NULL);
g_free(config_dir);
return accels;
}
gchar *
const gchar *
xed_dirs_get_xed_data_dir (void)
{
return g_build_filename(DATADIR, "xed", NULL);
return xed_data_dir;
}
gchar *
const gchar *
xed_dirs_get_xed_locale_dir (void)
{
return g_build_filename(DATADIR, "locale", NULL);
return xed_locale_dir;
}
gchar *
const gchar *
xed_dirs_get_xed_lib_dir (void)
{
return g_build_filename(LIBDIR, "xed", NULL);
return xed_lib_dir;
}
gchar *
const gchar *
xed_dirs_get_xed_plugins_dir (void)
{
gchar* lib_dir;
gchar* plugin_dir;
lib_dir = xed_dirs_get_xed_lib_dir();
plugin_dir = g_build_filename(lib_dir, "plugins", NULL);
g_free(lib_dir);
return plugin_dir;
return xed_plugins_dir;
}
gchar *
const gchar *
xed_dirs_get_xed_plugins_data_dir (void)
{
gchar* data_dir;
gchar* plugin_data_dir;
return xed_plugins_data_dir;
}
data_dir = xed_dirs_get_xed_data_dir ();
plugin_data_dir = g_build_filename (data_dir, "plugins", NULL);
g_free (data_dir);
return plugin_data_dir;
const gchar *
xed_dirs_get_binding_modules_dir (void)
{
return xed_lib_dir;
}
gchar *
xed_dirs_get_ui_file (const gchar *file)
{
gchar* datadir;
gchar *ui_file;
g_return_val_if_fail (file != NULL, NULL);
datadir = xed_dirs_get_xed_data_dir();
ui_file = g_build_filename(datadir, "ui", file, NULL);
g_free(datadir);
ui_file = g_build_filename (xed_dirs_get_xed_data_dir (), "ui", file, NULL);
return ui_file;
}

View File

@ -28,25 +28,30 @@
G_BEGIN_DECLS
gchar *xed_dirs_get_user_config_dir (void);
/* This function must be called before starting xed */
void xed_dirs_init (void);
/* This function must be called before exiting xed */
void xed_dirs_shutdown (void);
gchar *xed_dirs_get_user_cache_dir (void);
const gchar *xed_dirs_get_user_config_dir (void);
gchar *xed_dirs_get_user_styles_dir (void);
const gchar *xed_dirs_get_user_cache_dir (void);
gchar *xed_dirs_get_user_plugins_dir (void);
const gchar *xed_dirs_get_user_styles_dir (void);
gchar *xed_dirs_get_user_accels_file (void);
const gchar *xed_dirs_get_user_plugins_dir (void);
gchar *xed_dirs_get_xed_data_dir (void);
const gchar *xed_dirs_get_xed_data_dir (void);
gchar *xed_dirs_get_xed_locale_dir (void);
const gchar *xed_dirs_get_xed_locale_dir (void);
gchar *xed_dirs_get_xed_lib_dir (void);
const gchar *xed_dirs_get_xed_lib_dir (void);
gchar *xed_dirs_get_xed_plugins_dir (void);
const gchar *xed_dirs_get_xed_plugins_dir (void);
gchar *xed_dirs_get_xed_plugins_data_dir (void);
const gchar *xed_dirs_get_xed_plugins_data_dir (void);
const gchar *xed_dirs_get_binding_modules_dir (void);
gchar *xed_dirs_get_ui_file (const gchar *file);

View File

@ -510,6 +510,12 @@ save_encoding_metadata (XedDocument *doc)
xed_debug (DEBUG_DOCUMENT);
encoding = gtk_source_file_get_encoding (doc->priv->file);
if (encoding == NULL)
{
encoding = gtk_source_encoding_get_utf8 ();
}
charset = gtk_source_encoding_get_charset (encoding);
xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_ENCODING, charset, NULL);
@ -954,8 +960,6 @@ loaded_query_info_cb (GFile *location,
XedDocument *doc)
{
GFileInfo *info;
const gchar *content_type = NULL;
gboolean read_only = FALSE;
GError *error = NULL;
info = g_file_query_info_finish (location, result, &error);
@ -974,18 +978,22 @@ loaded_query_info_cb (GFile *location,
error = NULL;
}
doc->priv->mtime_set = FALSE;
if (info != NULL)
{
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
{
const gchar *content_type;
content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
xed_document_set_content_type (doc, content_type);
}
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
{
gboolean read_only;
read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
set_readonly (doc, read_only);
}
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
@ -993,22 +1001,19 @@ loaded_query_info_cb (GFile *location,
g_file_info_get_modification_time (info, &doc->priv->mtime);
doc->priv->mtime_set = TRUE;
}
}
set_readonly (doc, read_only);
g_get_current_time (&doc->priv->time_of_last_save_or_load);
doc->priv->externally_modified = FALSE;
doc->priv->deleted = FALSE;
xed_document_set_content_type (doc, content_type);
if (info != NULL)
{
g_object_unref (info);
}
/* Async operation finished. */
g_object_unref (doc);
}
static void
xed_document_loaded_real (XedDocument *doc)
{
GFile *location;
if (!doc->priv->language_set_by_user)
{
GtkSourceLanguage *language = guess_language (doc);
@ -1019,15 +1024,20 @@ loaded_query_info_cb (GFile *location,
set_language (doc, language, FALSE);
}
/* Async operation finished. */
g_object_unref (doc);
}
doc->priv->mtime_set = FALSE;
doc->priv->externally_modified = FALSE;
doc->priv->deleted = FALSE;
static void
xed_document_loaded_real (XedDocument *doc)
g_get_current_time (&doc->priv->time_of_last_save_or_load);
set_readonly (doc, FALSE);
xed_document_set_content_type (doc, NULL);
location = gtk_source_file_get_location (doc->priv->file);
if (location != NULL)
{
GFile *location = gtk_source_file_get_location (doc->priv->file);
/* Keep the doc alive during the async operation. */
g_object_ref (doc);
@ -1041,6 +1051,7 @@ xed_document_loaded_real (XedDocument *doc)
(GAsyncReadyCallback) loaded_query_info_cb,
doc);
}
}
static void
saved_query_info_cb (GFile *location,
@ -1191,9 +1202,11 @@ check_file_on_disk (XedDocument *doc)
g_file_info_get_modification_time (info, &timeval);
if (timeval.tv_sec > doc->priv->mtime.tv_sec ||
(timeval.tv_sec == doc->priv->mtime.tv_sec &&
timeval.tv_usec > doc->priv->mtime.tv_usec))
/* Note that mtime can even go backwards if the
* user is copying over a file with an old mtime
*/
if (timeval.tv_sec != doc->priv->mtime.tv_sec ||
timeval.tv_usec != doc->priv->mtime.tv_usec)
{
doc->priv->externally_modified = TRUE;
}

View File

@ -1,99 +0,0 @@
/*
* xed-help.c
* This file is part of xed
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xed-help.h"
#include <glib/gi18n.h>
#include <string.h>
#include <gtk/gtk.h>
gboolean
xed_help_display (GtkWindow *parent,
const gchar *name, /* "xed" if NULL */
const gchar *link_id)
{
GError *error = NULL;
gboolean ret;
gchar *link;
g_return_val_if_fail ((parent == NULL) || GTK_IS_WINDOW (parent), FALSE);
if (name == NULL)
name = "xed";
else if (strcmp (name, "xed.xml") == 0)
{
g_warning ("%s: Using \"xed.xml\" for the help name is deprecated, use \"xed\" or simply NULL instead", G_STRFUNC);
name = "xed";
}
if (link_id)
link = g_strdup_printf ("help:%s/%s", name, link_id);
else
link = g_strdup_printf ("help:%s", name);
ret = gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (parent)),
link,
GDK_CURRENT_TIME,
&error);
g_free (link);
if (error != NULL)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("There was an error displaying the help."));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (G_OBJECT (dialog),
"response",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
gtk_widget_show (dialog);
g_error_free (error);
}
return ret;
}

View File

@ -1,44 +0,0 @@
/*
* xed-help.h
* This file is part of xed
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XED_HELP_H__
#define __XED_HELP_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
gboolean xed_help_display (GtkWindow *parent,
const gchar *name, /* "xed" if NULL */
const gchar *link_id);
G_END_DECLS
#endif /* __XED_HELP_H__ */

View File

@ -27,23 +27,16 @@
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
#include <stdlib.h>
#include <libxml/xmlreader.h>
#include "xed-metadata-manager.h"
#include "xed-debug.h"
#include "xed-dirs.h"
/*
#define XED_METADATA_VERBOSE_DEBUG 1
*/
#define METADATA_FILE "xed-metadata.xml"
#define MAX_ITEMS 50
typedef struct _XedMetadataManager XedMetadataManager;
@ -65,6 +58,8 @@ struct _XedMetadataManager
guint timeout_id;
GHashTable *items;
gchar *metadata_filename;
};
static gboolean xed_metadata_manager_save (gpointer data);
@ -105,13 +100,20 @@ xed_metadata_manager_arm_timeout (void)
}
}
static gboolean
xed_metadata_manager_init (void)
/**
* xed_metadata_manager_init:
* @metadata_filename: the filename where the metadata is.
*
* This function initializes the metadata manager.
* See also xed_metadata_manager_shutdown().
*/
void
xed_metadata_manager_init (const gchar *metadata_filename)
{
xed_debug (DEBUG_METADATA);
if (xed_metadata_manager != NULL)
return TRUE;
return;
xed_metadata_manager = g_new0 (XedMetadataManager, 1);
@ -123,10 +125,17 @@ xed_metadata_manager_init (void)
g_free,
item_free);
return TRUE;
xed_metadata_manager->metadata_filename = g_strdup (metadata_filename);
return;
}
/* This function must be called before exiting xed */
/**
* xed_metadata_manager_shutdown:
*
* This function frees the internal data of the metadata manager.
* See also xed_metadata_manager_init().
*/
void
xed_metadata_manager_shutdown (void)
{
@ -145,6 +154,7 @@ xed_metadata_manager_shutdown (void)
if (xed_metadata_manager->items != NULL)
g_hash_table_destroy (xed_metadata_manager->items);
g_free (gedit_metadata_manager->metadata_filename);
g_free (xed_metadata_manager);
xed_metadata_manager = NULL;
}
@ -218,29 +228,11 @@ parseItem (xmlDocPtr doc, xmlNodePtr cur)
xmlFree (atime);
}
static gchar *
get_metadata_filename (void)
{
gchar *cache_dir;
gchar *metadata;
cache_dir = xed_dirs_get_user_cache_dir ();
metadata = g_build_filename (cache_dir,
METADATA_FILE,
NULL);
g_free (cache_dir);
return metadata;
}
static gboolean
load_values (void)
{
xmlDocPtr doc;
xmlNodePtr cur;
gchar *file_name;
xed_debug (DEBUG_METADATA);
@ -252,16 +244,13 @@ load_values (void)
xmlKeepBlanksDefault (0);
/* FIXME: file locking - Paolo */
file_name = get_metadata_filename ();
if ((file_name == NULL) ||
(!g_file_test (file_name, G_FILE_TEST_EXISTS)))
if ((xed_metadata_manager->metadata_filename == NULL) ||
(!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS)))
{
g_free (file_name);
return FALSE;
}
doc = xmlParseFile (file_name);
g_free (file_name);
doc = xmlParseFile (xed_metadata_manager->metadata_filename);
if (doc == NULL)
{
@ -271,7 +260,7 @@ load_values (void)
cur = xmlDocGetRootElement (doc);
if (cur == NULL)
{
g_message ("The metadata file '%s' is empty", METADATA_FILE);
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc);
return FALSE;
@ -279,7 +268,7 @@ load_values (void)
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
{
g_message ("File '%s' is of the wrong type", METADATA_FILE);
g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc);
return FALSE;
@ -300,6 +289,13 @@ load_values (void)
return TRUE;
}
/**
* xed_metadata_manager_get:
* @location: a #GFile.
* @key: a key.
*
* Gets the value associated with the specified @key for the file @location.
*/
gchar *
xed_metadata_manager_get (GFile *location,
const gchar *key)
@ -315,8 +311,6 @@ xed_metadata_manager_get (GFile *location,
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
xed_metadata_manager_init ();
if (!xed_metadata_manager->values_loaded)
{
gboolean res;
@ -348,6 +342,14 @@ xed_metadata_manager_get (GFile *location,
return g_strdup (value);
}
/**
* xed_metadata_manager_set:
* @location: a #GFile.
* @key: a key.
* @value: the value associated with the @key.
*
* Sets the @key to contain the given @value for the file @location.
*/
void
xed_metadata_manager_set (GFile *location,
const gchar *key,
@ -363,8 +365,6 @@ xed_metadata_manager_set (GFile *location,
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
xed_metadata_manager_init ();
if (!xed_metadata_manager->values_loaded)
{
gboolean res;
@ -523,7 +523,6 @@ xed_metadata_manager_save (gpointer data)
{
xmlDocPtr doc;
xmlNodePtr root;
gchar *file_name;
xed_debug (DEBUG_METADATA);
@ -546,22 +545,20 @@ xed_metadata_manager_save (gpointer data)
root);
/* FIXME: lock file - Paolo */
file_name = get_metadata_filename ();
if (file_name != NULL)
if (xed_metadata_manager->metadata_filename != NULL)
{
gchar *cache_dir;
int res;
/* make sure the cache dir exists */
cache_dir = xed_dirs_get_user_cache_dir ();
cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename);
res = g_mkdir_with_parents (cache_dir, 0755);
if (res != -1)
{
xmlSaveFormatFile (file_name, doc, 1);
xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1);
}
g_free (cache_dir);
g_free (file_name);
}
xmlFreeDoc (doc);

View File

@ -34,13 +34,14 @@
G_BEGIN_DECLS
void xed_metadata_manager_init (const gchar *metadata_filename);
/* This function must be called before exiting xed */
void xed_metadata_manager_shutdown (void);
gchar *xed_metadata_manager_get (GFile *location,
const gchar *key);
void xed_metadata_manager_set (GFile *location,
const gchar *key,
const gchar *value);

View File

@ -54,7 +54,7 @@ struct _XedSearchbarPrivate
GtkWidget *close_button;
GtkSourceSearchSettings *search_settings;
SearchMode search_mode;
XedSearchMode search_mode;
guint update_occurrence_count_id;
};
@ -280,7 +280,7 @@ update_occurrence_count (XedSearchbar *searchbar)
gint count;
gint pos;
if (searchbar->priv->search_mode == SEARCH_MODE_REPLACE)
if (searchbar->priv->search_mode == XED_SEARCH_MODE_REPLACE)
{
return;
}
@ -376,7 +376,7 @@ do_find (XedSearchbar *searchbar,
search_settings = xed_searchbar_get_search_settings (searchbar);
doc = xed_window_get_active_document (searchbar->window);
search_context = xed_document_get_search_context (doc);
searchbar->priv->search_mode = SEARCH_MODE_SEARCH;
searchbar->priv->search_mode = XED_SEARCH_MODE_SEARCH;
if (search_context == NULL || search_settings != gtk_source_search_context_get_settings (search_context))
{
@ -487,7 +487,7 @@ do_replace (XedSearchbar *searchbar)
unescaped_replace_text = gtk_source_utils_unescape_search_text (replace_entry_text);
gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start, &end);
searchbar->priv->search_mode = SEARCH_MODE_REPLACE;
searchbar->priv->search_mode = XED_SEARCH_MODE_REPLACE;
gtk_source_search_context_replace (search_context,
&start,
@ -530,7 +530,7 @@ do_replace_all (XedSearchbar *searchbar)
unescaped_replace_text = gtk_source_utils_unescape_search_text (replace_entry_text);
count = gtk_source_search_context_replace_all (search_context, unescaped_replace_text, -1, NULL);
searchbar->priv->search_mode = SEARCH_MODE_REPLACE;
searchbar->priv->search_mode = XED_SEARCH_MODE_REPLACE;
g_free (unescaped_replace_text);
@ -800,7 +800,7 @@ xed_searchbar_new (GtkWindow *parent)
void
xed_searchbar_show (XedSearchbar *searchbar,
SearchMode search_mode)
XedSearchMode search_mode)
{
XedDocument *doc;
gboolean selection_exists;
@ -835,7 +835,7 @@ xed_searchbar_show (XedSearchbar *searchbar,
gtk_revealer_set_transition_type (GTK_REVEALER (searchbar->priv->revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
gtk_revealer_set_reveal_child (GTK_REVEALER (searchbar->priv->revealer), TRUE);
if (search_mode == SEARCH_MODE_REPLACE)
if (search_mode == XED_SEARCH_MODE_REPLACE)
{
gtk_widget_show (searchbar->priv->replace_label);
gtk_widget_show (searchbar->priv->replace_entry);

View File

@ -39,16 +39,16 @@ struct _XedSearchbarClass
typedef enum
{
SEARCH_MODE_SEARCH,
SEARCH_MODE_REPLACE
} SearchMode;
XED_SEARCH_MODE_SEARCH,
XED_SEARCH_MODE_REPLACE
} XedSearchMode;
GType xed_searchbar_get_type (void) G_GNUC_CONST;
GtkWidget *xed_searchbar_new (GtkWindow *parent);
void xed_searchbar_hide (XedSearchbar *searchbar);
void xed_searchbar_show (XedSearchbar *searchbar, SearchMode search_mode);
void xed_searchbar_show (XedSearchbar *searchbar, XedSearchMode search_mode);
void xed_searchbar_find_again (XedSearchbar *searchbar, gboolean backward);
const gchar *xed_searchbar_get_replace_text (XedSearchbar *searchbar);

View File

@ -1,618 +0,0 @@
/*
* xed-session.c - Basic session management for xed
* This file is part of xed
*
* Copyright (C) 2002 Ximian, Inc.
* Copyright (C) 2005 - Paolo Maggi
*
* Author: Federico Mena-Quintero <federico@ximian.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002-2005. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <unistd.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/xmlwriter.h>
#include "xed-session.h"
#include "xed-debug.h"
#include "xed-plugins-engine.h"
#include "xed-metadata-manager.h"
#include "xed-window.h"
#include "xed-app.h"
#include "xed-commands.h"
#include "dialogs/xed-close-confirmation-dialog.h"
#include "smclient/eggsmclient.h"
/* The master client we use for SM */
static EggSMClient *master_client = NULL;
/* global var used during quit_requested */
static GSList *window_dirty_list;
static void ask_next_confirmation (void);
#define XED_SESSION_LIST_OF_DOCS_TO_SAVE "xed-session-list-of-docs-to-save-key"
static void
save_window_session (GKeyFile *state_file,
const gchar *group_name,
XedWindow *window)
{
const gchar *role;
int width, height;
XedPanel *panel;
GList *docs, *l;
GPtrArray *doc_array;
XedDocument *active_document;
gchar *uri = NULL;
xed_debug (DEBUG_SESSION);
role = gtk_window_get_role (GTK_WINDOW (window));
g_key_file_set_string (state_file, group_name, "role", role);
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
g_key_file_set_integer (state_file, group_name, "width", width);
g_key_file_set_integer (state_file, group_name, "height", height);
panel = xed_window_get_side_panel (window);
g_key_file_set_boolean (state_file, group_name, "side-panel-visible",
gtk_widget_get_visible (GTK_WIDGET (panel)));
panel = xed_window_get_bottom_panel (window);
g_key_file_set_boolean (state_file, group_name, "bottom-panel-visible",
gtk_widget_get_visible (GTK_WIDGET (panel)));
active_document = xed_window_get_active_document (window);
if (active_document)
{
GFile *location;
location = xed_document_get_location (active_document);
if (location)
{
uri = g_file_get_uri (location);
g_object_unref (location);
}
g_key_file_set_string (state_file, group_name, "active-document", uri);
g_free (uri);
}
docs = xed_window_get_documents (window);
doc_array = g_ptr_array_new ();
for (l = docs; l != NULL; l = g_list_next (l))
{
GFile *location;
location = xed_document_get_location (XED_DOCUMENT (l->data));
if (location)
{
uri = g_file_get_uri (location);
g_object_unref (location);
}
if (uri != NULL)
{
g_ptr_array_add (doc_array, uri);
}
}
g_list_free (docs);
if (doc_array->len)
{
g_key_file_set_string_list (state_file, group_name,
"documents",
(const char **)doc_array->pdata,
doc_array->len);
g_ptr_array_foreach (doc_array, (GFunc) g_free, NULL);
}
g_ptr_array_free (doc_array, TRUE);
}
static void
client_save_state_cb (EggSMClient *client,
GKeyFile *state_file,
gpointer user_data)
{
const GList *windows;
gchar *group_name;
int n;
windows = xed_app_get_windows (xed_app_get_default ());
n = 1;
while (windows != NULL)
{
group_name = g_strdup_printf ("xed window %d", n);
save_window_session (state_file,
group_name,
XED_WINDOW (windows->data));
g_free (group_name);
windows = g_list_next (windows);
n++;
}
}
static void
window_handled (XedWindow *window)
{
window_dirty_list = g_slist_remove (window_dirty_list, window);
/* whee... we made it! */
if (window_dirty_list == NULL)
egg_sm_client_will_quit (master_client, TRUE);
else
ask_next_confirmation ();
}
static void
window_state_change (XedWindow *window,
GParamSpec *pspec,
gpointer data)
{
XedWindowState state;
GList *unsaved_docs;
GList *docs_to_save;
GList *l;
gboolean done = TRUE;
state = xed_window_get_state (window);
/* we are still saving */
if (state & XED_WINDOW_STATE_SAVING)
return;
unsaved_docs = xed_window_get_unsaved_documents (window);
docs_to_save = g_object_get_data (G_OBJECT (window),
XED_SESSION_LIST_OF_DOCS_TO_SAVE);
for (l = docs_to_save; l != NULL; l = l->next)
{
if (g_list_find (unsaved_docs, l->data))
{
done = FALSE;
break;
}
}
if (done)
{
g_signal_handlers_disconnect_by_func (window, window_state_change, data);
g_list_free (docs_to_save);
g_object_set_data (G_OBJECT (window),
XED_SESSION_LIST_OF_DOCS_TO_SAVE,
NULL);
window_handled (window);
}
g_list_free (unsaved_docs);
}
static void
close_confirmation_dialog_response_handler (XedCloseConfirmationDialog *dlg,
gint response_id,
XedWindow *window)
{
GList *selected_documents;
GSList *l;
xed_debug (DEBUG_COMMANDS);
switch (response_id)
{
case GTK_RESPONSE_YES:
/* save selected docs */
g_signal_connect (window,
"notify::state",
G_CALLBACK (window_state_change),
NULL);
selected_documents = xed_close_confirmation_dialog_get_selected_documents (dlg);
g_return_if_fail (g_object_get_data (G_OBJECT (window),
XED_SESSION_LIST_OF_DOCS_TO_SAVE) == NULL);
g_object_set_data (G_OBJECT (window),
XED_SESSION_LIST_OF_DOCS_TO_SAVE,
selected_documents);
_xed_cmd_file_save_documents_list (window, selected_documents);
/* FIXME: also need to lock the window to prevent further changes... */
break;
case GTK_RESPONSE_NO:
/* dont save */
window_handled (window);
break;
default:
/* disconnect window_state_changed where needed */
for (l = window_dirty_list; l != NULL; l = l->next)
g_signal_handlers_disconnect_by_func (window,
window_state_change, NULL);
g_slist_free (window_dirty_list);
window_dirty_list = NULL;
/* cancel shutdown */
egg_sm_client_will_quit (master_client, FALSE);
break;
}
gtk_widget_destroy (GTK_WIDGET (dlg));
}
static void
show_confirmation_dialog (XedWindow *window)
{
GList *unsaved_docs;
GtkWidget *dlg;
xed_debug (DEBUG_SESSION);
unsaved_docs = xed_window_get_unsaved_documents (window);
g_return_if_fail (unsaved_docs != NULL);
if (unsaved_docs->next == NULL)
{
/* There is only one unsaved document */
XedTab *tab;
XedDocument *doc;
doc = XED_DOCUMENT (unsaved_docs->data);
tab = xed_tab_get_from_document (doc);
g_return_if_fail (tab != NULL);
xed_window_set_active_tab (window, tab);
dlg = xed_close_confirmation_dialog_new_single (
GTK_WINDOW (window),
doc,
TRUE);
}
else
{
dlg = xed_close_confirmation_dialog_new (GTK_WINDOW (window),
unsaved_docs,
TRUE);
}
g_list_free (unsaved_docs);
g_signal_connect (dlg,
"response",
G_CALLBACK (close_confirmation_dialog_response_handler),
window);
gtk_widget_show (dlg);
}
static void
ask_next_confirmation (void)
{
g_return_if_fail (window_dirty_list != NULL);
/* pop up the confirmation dialog for the first window
* in the dirty list. The next confirmation is asked once
* this one has been handled.
*/
show_confirmation_dialog (XED_WINDOW (window_dirty_list->data));
}
/* quit_requested handler for the master client */
static void
client_quit_requested_cb (EggSMClient *client, gpointer data)
{
XedApp *app;
const GList *l;
xed_debug (DEBUG_SESSION);
app = xed_app_get_default ();
if (window_dirty_list != NULL)
{
g_critical ("global variable window_dirty_list not NULL");
window_dirty_list = NULL;
}
for (l = xed_app_get_windows (app); l != NULL; l = l->next)
{
if (xed_window_get_unsaved_documents (XED_WINDOW (l->data)) != NULL)
{
window_dirty_list = g_slist_prepend (window_dirty_list, l->data);
}
}
/* no modified docs */
if (window_dirty_list == NULL)
{
egg_sm_client_will_quit (client, TRUE);
return;
}
ask_next_confirmation ();
xed_debug_message (DEBUG_SESSION, "END");
}
/* quit handler for the master client */
static void
client_quit_cb (EggSMClient *client, gpointer data)
{
#if 0
xed_debug (DEBUG_SESSION);
if (!client->save_yourself_emitted)
xed_file_close_all ();
xed_debug_message (DEBUG_FILE, "All files closed.");
matecomponent_mdi_destroy (MATECOMPONENT_MDI (xed_mdi));
xed_debug_message (DEBUG_FILE, "Unref xed_mdi.");
g_object_unref (G_OBJECT (xed_mdi));
xed_debug_message (DEBUG_FILE, "Unref xed_mdi: DONE");
xed_debug_message (DEBUG_FILE, "Unref xed_app_server.");
matecomponent_object_unref (xed_app_server);
xed_debug_message (DEBUG_FILE, "Unref xed_app_server: DONE");
#endif
gtk_main_quit ();
}
/**
* xed_session_init:
*
* Initializes session management support. This function should be called near
* the beginning of the program.
**/
void
xed_session_init (void)
{
xed_debug (DEBUG_SESSION);
if (master_client)
return;
master_client = egg_sm_client_get ();
g_signal_connect (master_client,
"save_state",
G_CALLBACK (client_save_state_cb),
NULL);
g_signal_connect (master_client,
"quit_requested",
G_CALLBACK (client_quit_requested_cb),
NULL);
g_signal_connect (master_client,
"quit",
G_CALLBACK (client_quit_cb),
NULL);
}
/**
* xed_session_is_restored:
*
* Returns whether this xed is running from a restarted session.
*
* Return value: TRUE if the session manager restarted us, FALSE otherwise.
* This should be used to determine whether to pay attention to command line
* arguments in case the session was not restored.
**/
gboolean
xed_session_is_restored (void)
{
gboolean restored;
xed_debug (DEBUG_SESSION);
if (!master_client)
return FALSE;
restored = egg_sm_client_is_resumed (master_client);
xed_debug_message (DEBUG_SESSION, restored ? "RESTORED" : "NOT RESTORED");
return restored;
}
static void
parse_window (GKeyFile *state_file, const char *group_name)
{
XedWindow *window;
gchar *role, *active_document, **documents;
int width, height;
gboolean visible;
XedPanel *panel;
GError *error = NULL;
role = g_key_file_get_string (state_file, group_name, "role", NULL);
xed_debug_message (DEBUG_SESSION, "Window role: %s", role);
window = _xed_app_restore_window (xed_app_get_default (), (gchar *) role);
g_free (role);
if (window == NULL)
{
g_warning ("Couldn't restore window");
return;
}
width = g_key_file_get_integer (state_file, group_name,
"width", &error);
if (error)
{
g_clear_error (&error);
width = -1;
}
height = g_key_file_get_integer (state_file, group_name,
"height", &error);
if (error)
{
g_clear_error (&error);
height = -1;
}
gtk_window_set_default_size (GTK_WINDOW (window), width, height);
visible = g_key_file_get_boolean (state_file, group_name,
"side-panel-visible", &error);
if (error)
{
g_clear_error (&error);
visible = FALSE;
}
panel = xed_window_get_side_panel (window);
if (visible)
{
xed_debug_message (DEBUG_SESSION, "Side panel visible");
gtk_widget_show (GTK_WIDGET (panel));
}
else
{
xed_debug_message (DEBUG_SESSION, "Side panel _NOT_ visible");
gtk_widget_hide (GTK_WIDGET (panel));
}
visible = g_key_file_get_boolean (state_file, group_name,
"bottom-panel-visible", &error);
if (error)
{
g_clear_error (&error);
visible = FALSE;
}
panel = xed_window_get_bottom_panel (window);
if (visible)
{
xed_debug_message (DEBUG_SESSION, "Bottom panel visible");
gtk_widget_show (GTK_WIDGET (panel));
}
else
{
xed_debug_message (DEBUG_SESSION, "Bottom panel _NOT_ visible");
gtk_widget_hide (GTK_WIDGET (panel));
}
active_document = g_key_file_get_string (state_file, group_name,
"active-document", NULL);
documents = g_key_file_get_string_list (state_file, group_name,
"documents", NULL, NULL);
if (documents)
{
gint i;
gboolean jump_to = FALSE;
for (i = 0; documents[i]; i++)
{
GFile *location;
if (active_document != NULL)
{
jump_to = strcmp (active_document, documents[i]) == 0;
}
xed_debug_message (DEBUG_SESSION,
"URI: %s (%s)",
documents[i],
jump_to ? "active" : "not active");
location = g_file_new_for_uri (documents[i]);
xed_window_create_tab_from_location (window, location, NULL, 0, FALSE, jump_to);
if (location)
{
g_object_unref (location);
}
}
g_strfreev (documents);
}
g_free (active_document);
gtk_widget_show (GTK_WIDGET (window));
}
/**
* xed_session_load:
*
* Loads the session by fetching the necessary information from the session
* manager and opening files.
*
* Return value: TRUE if the session was loaded successfully, FALSE otherwise.
**/
gboolean
xed_session_load (void)
{
GKeyFile *state_file;
gchar **groups;
int i;
xed_debug (DEBUG_SESSION);
state_file = egg_sm_client_get_state_file (master_client);
if (state_file == NULL)
return FALSE;
groups = g_key_file_get_groups (state_file, NULL);
for (i = 0; groups[i] != NULL; i++)
{
if (g_str_has_prefix (groups[i], "xed window "))
parse_window (state_file, groups[i]);
}
g_strfreev (groups);
g_key_file_free (state_file);
return TRUE;
}

View File

@ -1,47 +0,0 @@
/*
* xed-session.h - Basic session management for xed
* This file is part of xed
*
* Copyright (C) 2002 Ximian, Inc.
* Copyright (C) 2005 - Paolo Maggi
*
* Author: Federico Mena-Quintero <federico@ximian.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002-2005. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id
*/
#ifndef __XED_SESSION_H__
#define __XED_SESSION_H__
#include <glib.h>
G_BEGIN_DECLS
void xed_session_init (void);
gboolean xed_session_is_restored (void);
gboolean xed_session_load (void);
G_END_DECLS
#endif /* __XED_SESSION_H__ */

View File

@ -96,7 +96,7 @@ set_font (XedSettings *xs,
ts = g_settings_get_uint (xs->priv->editor, XED_SETTINGS_TABS_SIZE);
views = xed_app_get_views (xed_app_get_default ());
views = xed_app_get_views (XED_APP (g_application_get_default ()));
for (l = views; l != NULL; l = g_list_next (l))
{
@ -213,7 +213,7 @@ on_scheme_changed (GSettings *settings,
}
}
docs = xed_app_get_documents (xed_app_get_default ());
docs = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (l = docs; l != NULL; l = g_list_next (l))
{
g_return_if_fail (GTK_SOURCE_IS_BUFFER (l->data));
@ -234,7 +234,7 @@ on_auto_save_changed (GSettings *settings,
auto_save = g_settings_get_boolean (settings, key);
docs = xed_app_get_documents (xed_app_get_default ());
docs = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (l = docs; l != NULL; l = g_list_next (l))
{
@ -256,7 +256,7 @@ on_auto_save_interval_changed (GSettings *settings,
g_settings_get (settings, key, "u", &auto_save_interval);
docs = xed_app_get_documents (xed_app_get_default ());
docs = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (l = docs; l != NULL; l = g_list_next (l))
{
@ -278,7 +278,7 @@ on_wrap_mode_changed (GSettings *settings,
wrap_mode = g_settings_get_enum (settings, key);
views = xed_app_get_views (xed_app_get_default ());
views = xed_app_get_views (XED_APP (g_application_get_default ()));
for (l = views; l != NULL; l = g_list_next (l))
{
@ -293,13 +293,12 @@ on_syntax_highlighting_changed (GSettings *settings,
const gchar *key,
XedSettings *xs)
{
const GList *windows;
GList *docs, *l;
GList *docs, *windows, *l;
gboolean enable;
enable = g_settings_get_boolean (settings, key);
docs = xed_app_get_documents (xed_app_get_default ());
docs = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (l = docs; l != NULL; l = g_list_next (l))
{
@ -309,20 +308,20 @@ on_syntax_highlighting_changed (GSettings *settings,
g_list_free (docs);
/* update the sensitivity of the Higlight Mode menu item */
windows = xed_app_get_windows (xed_app_get_default ());
while (windows != NULL)
windows = xed_app_get_main_windows (XED_APP (g_application_get_default ()));
for (l = windows; l != NULL; l = g_list_next (l))
{
GtkUIManager *ui;
GtkAction *a;
ui = xed_window_get_ui_manager (XED_WINDOW (windows->data));
ui = xed_window_get_ui_manager (XED_WINDOW (l->data));
a = gtk_ui_manager_get_action (ui, "/MenuBar/ViewMenu/ViewHighlightModeMenu");
gtk_action_set_sensitive (a, enable);
windows = g_list_next (windows);
}
g_list_free (windows);
}
static void
@ -335,7 +334,7 @@ on_enable_tab_scrolling_changed (GSettings *settings,
enable = g_settings_get_boolean (settings, key);
windows = xed_app_get_windows (xed_app_get_default ());
windows = xed_app_get_main_windows (XED_APP (g_application_get_default ()));
while (windows != NULL)
{
XedNotebook *notebook;

View File

@ -64,7 +64,7 @@ struct _XedTabPrivate
XedPrintJob *print_job;
GtkSourceFileSaver *saver;
GTask *task_saver;
GtkSourceFileSaverFlags save_flags;
/* tmp data for loading */
@ -84,10 +84,20 @@ struct _XedTabPrivate
gint ask_if_externally_modified : 1;
/*tmp data for loading */
guint user_requested_encoding : 1;
};
typedef struct _SaverData SaverData;
struct _SaverData
{
GtkSourceFileSaver *saver;
/* Notes about the create_backup saver flag:
* - At the beginning of a new file saving, force_no_backup is reset to
* FALSE. The create_backup flag is set to the saver if it is enabled
* in GSettings and if it isn't an auto-save.
* - At the beginning of a new file saving, force_no_backup is FALSE.
* The create_backup flag is set to the saver if it is enabled in
* GSettings and if it isn't an auto-save.
* - If creating the backup gives an error, and if the user wants to
* save the file without the backup, force_no_backup is set to TRUE
* and the create_backup flag is removed from the saver.
@ -103,9 +113,6 @@ struct _XedTabPrivate
* button in the info bar to retry the file saving.
*/
guint force_no_backup : 1;
/*tmp data for loading */
guint user_requested_encoding : 1;
};
G_DEFINE_TYPE(XedTab, xed_tab, GTK_TYPE_BOX)
@ -127,6 +134,26 @@ static void load (XedTab *tab,
static void save (XedTab *tab);
static SaverData *
saver_data_new (void)
{
return g_slice_new0 (SaverData);
}
static void
saver_data_free (SaverData *data)
{
if (data != NULL)
{
if (data->saver != NULL)
{
g_object_unref (data->saver);
}
g_slice_free (SaverData, data);
}
}
static void
install_auto_save_timeout (XedTab *tab)
{
@ -235,22 +262,15 @@ clear_loading (XedTab *tab)
g_clear_object (&tab->priv->cancellable);
}
static void
clear_saving (XedTab *tab)
{
g_clear_object (&tab->priv->saver);
tab->priv->force_no_backup = FALSE;
}
static void
xed_tab_dispose (GObject *object)
{
XedTab *tab = XED_TAB (object);
g_clear_object (&tab->priv->editor);
g_clear_object (&tab->priv->task_saver);
clear_loading (tab);
clear_saving (tab);
G_OBJECT_CLASS (xed_tab_parent_class)->dispose (object);
}
@ -734,7 +754,7 @@ show_saving_message_area (XedTab *tab)
gchar *msg = NULL;
gint len;
g_return_if_fail (tab->priv->saver != NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
if (tab->priv->message_area != NULL)
{
@ -761,7 +781,11 @@ show_saving_message_area (XedTab *tab)
else
{
gchar *str;
GFile *location = gtk_source_file_saver_get_location (tab->priv->saver);
SaverData *data;
GFile *location;
data = g_task_get_task_data (tab->priv->task_saver);
location = gtk_source_file_saver_get_location (data->saver);
from = short_name;
to = g_file_get_parse_name (location);
@ -858,10 +882,11 @@ unrecoverable_saving_error_message_area_response (GtkWidget *message_area,
xed_tab_set_state (tab, XED_TAB_STATE_NORMAL);
}
clear_saving (tab);
set_message_area (tab, NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
g_task_return_boolean (tab->priv->task_saver, FALSE);
view = xed_tab_get_view (tab);
gtk_widget_grab_focus (GTK_WIDGET (view));
@ -872,8 +897,11 @@ static void
response_set_save_flags (XedTab *tab,
GtkSourceFileSaverFlags save_flags)
{
SaverData *data;
gboolean create_backup;
data = g_task_get_task_data (tab->priv->task_saver);
create_backup = g_settings_get_boolean (tab->priv->editor, XED_SETTINGS_CREATE_BACKUP_COPY);
/* If we are here, it means that the user expressed his or her willing
@ -881,7 +909,7 @@ response_set_save_flags (XedTab *tab,
* the file saving was initially an auto-save, we set the create_backup
* flag (if the conditions are met).
*/
if (create_backup && !tab->priv->force_no_backup)
if (create_backup && !data->force_no_backup)
{
save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
}
@ -890,7 +918,7 @@ response_set_save_flags (XedTab *tab,
save_flags &= ~GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
}
gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
gtk_source_file_saver_set_flags (data->saver, save_flags);
}
static void
@ -900,16 +928,18 @@ invalid_character_message_area_response (GtkWidget *info_bar,
{
if (response_id == GTK_RESPONSE_YES)
{
SaverData *data;
GtkSourceFileSaverFlags save_flags;
set_message_area (tab, NULL);
g_return_if_fail (tab->priv->saver != NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
data = g_task_get_task_data (tab->priv->task_saver);
/* Don't bug the user again with this... */
tab->priv->save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
save_flags = gtk_source_file_saver_get_flags (tab->priv->saver);
save_flags = gtk_source_file_saver_get_flags (data->saver);
save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
response_set_save_flags (tab, save_flags);
@ -929,14 +959,16 @@ no_backup_error_message_area_response (GtkWidget *message_area,
{
if (response_id == GTK_RESPONSE_YES)
{
SaverData *data;
GtkSourceFileSaverFlags save_flags;
set_message_area (tab, NULL);
g_return_if_fail (tab->priv->saver != NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
data = g_task_get_task_data (tab->priv->task_saver);
tab->priv->force_no_backup = TRUE;
save_flags = gtk_source_file_saver_get_flags (tab->priv->saver);
data->force_no_backup = TRUE;
save_flags = gtk_source_file_saver_get_flags (data->saver);
response_set_save_flags (tab, save_flags);
/* Force saving */
@ -955,17 +987,19 @@ externally_modified_error_message_area_response (GtkWidget *message_area,
{
if (response_id == GTK_RESPONSE_YES)
{
SaverData *data;
GtkSourceFileSaverFlags save_flags;
set_message_area (tab, NULL);
g_return_if_fail (tab->priv->saver != NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
data = g_task_get_task_data (tab->priv->task_saver);
/* ignore_modification_time should not be persisted in save
* flags across saves (i.e. priv->save_flags is not modified).
*/
save_flags = gtk_source_file_saver_get_flags (tab->priv->saver);
save_flags = gtk_source_file_saver_get_flags (data->saver);
save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
response_set_save_flags (tab, save_flags);
@ -985,16 +1019,18 @@ recoverable_saving_error_message_area_response (GtkWidget *message_area,
{
if (response_id == GTK_RESPONSE_OK)
{
SaverData *data;
const GtkSourceEncoding *encoding;
set_message_area (tab, NULL);
g_return_if_fail (tab->priv->saver != NULL);
g_return_if_fail (tab->priv->task_saver != NULL);
data = g_task_get_task_data (tab->priv->task_saver);
encoding = xed_conversion_error_message_area_get_encoding (GTK_WIDGET (message_area));
g_return_if_fail (encoding != NULL);
gtk_source_file_saver_set_encoding (tab->priv->saver, encoding);
gtk_source_file_saver_set_encoding (data->saver, encoding);
save (tab);
}
else
@ -1175,6 +1211,22 @@ _xed_tab_new_from_location (GFile *location,
return GTK_WIDGET (tab);
}
GtkWidget *
_xed_tab_new_from_stream (GInputStream *stream,
const GtkSourceEncoding *encoding,
gint line_pos)
{
GtkWidget *tab;
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
tab = _xed_tab_new ();
_xed_tab_load_stream (XED_TAB (tab), stream, encoding, line_pos);
return tab;
}
/**
* xed_tab_get_view:
* @tab: a #XedTab
@ -1317,12 +1369,10 @@ _xed_tab_get_tooltips (XedTab *tab)
if (enc == NULL)
{
encoding = g_strdup (_("Unicode (UTF-8)"));
enc = gtk_source_encoding_get_utf8 ();
}
else
{
encoding = gtk_source_encoding_to_string (enc);
}
tip = g_markup_printf_escaped ("<b>%s</b> %s\n\n"
"<b>%s</b> %s\n"
@ -1574,6 +1624,7 @@ load_cb (GtkSourceFileLoader *loader,
{
XedDocument *doc = xed_tab_get_document (tab);
GFile *location = gtk_source_file_loader_get_location (loader);
gboolean create_named_new_doc;
GError *error = NULL;
g_return_if_fail (tab->priv->state == XED_TAB_STATE_LOADING ||
@ -1611,10 +1662,13 @@ load_cb (GtkSourceFileLoader *loader,
}
/* Special case creating a named new doc. */
else if (_xed_document_get_create (doc) &&
create_named_new_doc = (_xed_document_get_create (doc) &&
error != NULL &&
error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_NOT_FOUND &&
g_file_has_uri_scheme (location, "file"))
g_file_has_uri_scheme (location, "file"));
if (create_named_new_doc)
{
g_error_free (error);
error = NULL;
@ -1676,7 +1730,7 @@ load_cb (GtkSourceFileLoader *loader,
goto end;
}
if (location != NULL)
if (location != NULL && !create_named_new_doc)
{
gchar *mime = xed_document_get_mime_type (doc);
@ -1725,7 +1779,7 @@ load_cb (GtkSourceFileLoader *loader,
GList *all_documents;
GList *l;
all_documents = xed_app_get_documents (xed_app_get_default ());
all_documents = xed_app_get_documents (XED_APP (g_application_get_default ()));
for (l = all_documents; l != NULL; l = g_list_next (l))
{
@ -1793,6 +1847,8 @@ get_candidate_encodings (XedTab *tab)
GSettings *enc_settings;
gchar **enc_strv;
gchar *metadata_charset;
GtkSourceFile *file;
const GtkSourceEncoding *file_encoding;
GSList *encodings;
enc_settings = g_settings_new ("org.x.editor.preferences.encodings");
@ -1814,12 +1870,19 @@ get_candidate_encodings (XedTab *tab)
{
encodings = g_slist_prepend (encodings, (gpointer)metadata_enc);
}
g_free (metadata_charset);
}
g_strfreev (enc_strv);
file = xed_document_get_file (doc);
file_encoding = gtk_source_file_get_encoding (file);
if (file_encoding != NULL)
{
encodings = g_slist_prepend (encodings, (gpointer)file_encoding);
}
g_object_unref (enc_settings);
g_strfreev (enc_strv);
g_free (metadata_charset);
return encodings;
}
@ -1902,6 +1965,39 @@ _xed_tab_load (XedTab *tab,
load (tab, encoding, line_pos);
}
void
_xed_tab_load_stream (XedTab *tab,
GInputStream *stream,
const GtkSourceEncoding *encoding,
gint line_pos)
{
XedDocument *doc;
GtkSourceFile *file;
g_return_if_fail (XED_IS_TAB (tab));
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail (tab->priv->state == XED_TAB_STATE_NORMAL);
xed_tab_set_state (tab, XED_TAB_STATE_LOADING);
doc = xed_tab_get_document (tab);
file = xed_document_get_file (doc);
if (tab->priv->loader != NULL)
{
g_warning ("XedTab: file loader already exists.");
g_object_unref (tab->priv->loader);
}
gtk_source_file_set_location (file, NULL);
tab->priv->loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (doc), file, stream);
_xed_document_set_create (doc, FALSE);
load (tab, encoding, line_pos);
}
void
_xed_tab_revert (XedTab *tab)
{
@ -1977,7 +2073,7 @@ save_cb (GtkSourceFileSaver *saver,
GFile *location = gtk_source_file_saver_get_location (saver);
GError *error = NULL;
g_return_if_fail (tab->priv->state == XED_TAB_STATE_SAVING);
g_return_if_fail (tab->priv->task_saver != NULL);
gtk_source_file_saver_save_finish (saver, result, &error);
@ -2084,14 +2180,10 @@ save_cb (GtkSourceFileSaver *saver,
tab->priv->ask_if_externally_modified = TRUE;
clear_saving (tab);
g_signal_emit_by_name (doc, "saved");
g_task_return_boolean (tab->priv->task_saver, TRUE);
}
/* Async operation finished. */
g_object_unref (tab);
if (error != NULL)
{
g_error_free (error);
@ -2102,20 +2194,20 @@ static void
save (XedTab *tab)
{
XedDocument *doc;
SaverData *data;
g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (tab->priv->saver));
g_return_if_fail (G_IS_TASK (tab->priv->task_saver));
xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
doc = xed_tab_get_document (tab);
g_signal_emit_by_name (doc, "save");
/* Keep the tab alive during the async operation. */
g_object_ref (tab);
data = g_task_get_task_data (tab->priv->task_saver);
gtk_source_file_saver_save_async (tab->priv->saver,
gtk_source_file_saver_save_async (data->saver,
G_PRIORITY_DEFAULT,
NULL, /* TODO add a cancellable */
g_task_get_cancellable (tab->priv->task_saver),
(GFileProgressCallback) saver_progress_cb,
tab,
NULL,
@ -2133,9 +2225,6 @@ get_initial_save_flags (XedTab *tab,
save_flags = tab->priv->save_flags;
/* force_no_backup must have been reset to FALSE for a new file saving. */
g_return_val_if_fail (!tab->priv->force_no_backup, save_flags);
create_backup = g_settings_get_boolean (tab->priv->editor, XED_SETTINGS_CREATE_BACKUP_COPY);
/* In case of autosaving, we need to preserve the backup that was produced
@ -2151,8 +2240,12 @@ get_initial_save_flags (XedTab *tab,
}
void
_xed_tab_save (XedTab *tab)
_xed_tab_save_async (XedTab *tab,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
SaverData *data;
XedDocument *doc;
GtkSourceFile *file;
GtkSourceFileSaverFlags save_flags;
@ -2162,19 +2255,23 @@ _xed_tab_save (XedTab *tab)
(tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
(tab->priv->state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW));
if (tab->priv->saver != NULL)
if (tab->priv->task_saver != NULL)
{
g_warning ("XedTab: file saver already exists.");
g_object_unref (tab->priv->saver);
tab->priv->saver = NULL;
return;
}
clear_saving (tab);
doc = xed_tab_get_document (tab);
g_return_if_fail (XED_IS_DOCUMENT (doc));
// g_return_if_fail (XED_IS_DOCUMENT (doc));
g_return_if_fail (!xed_document_is_untitled (doc));
tab->priv->task_saver = g_task_new (tab, cancellable, callback, user_data);
data = saver_data_new ();
g_task_set_task_data (tab->priv->task_saver,
data,
(GDestroyNotify) saver_data_free);
save_flags = get_initial_save_flags (tab, FALSE);
if (tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
@ -2189,15 +2286,39 @@ _xed_tab_save (XedTab *tab)
file = xed_document_get_file (doc);
tab->priv->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
gtk_source_file_saver_set_flags (data->saver, save_flags);
save (tab);
}
gboolean
_xed_tab_save_finish (XedTab *tab,
GAsyncResult *result)
{
gboolean success;
g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
g_return_val_if_fail (tab->priv->task_saver == G_TASK (result), FALSE);
success = g_task_propagate_boolean (tab->priv->task_saver, NULL);
g_clear_object (&tab->priv->task_saver);
return success;
}
static void
auto_save_finished_cb (XedTab *tab,
GAsyncResult *result,
gpointer user_data)
{
_xed_tab_save_finish (tab, result);
}
static gboolean
xed_tab_auto_save (XedTab *tab)
{
SaverData *data;
XedDocument *doc;
GtkSourceFile *file;
GtkSourceFileSaverFlags save_flags;
@ -2205,9 +2326,8 @@ xed_tab_auto_save (XedTab *tab)
xed_debug (DEBUG_TAB);
doc = xed_tab_get_document (tab);
g_return_val_if_fail (!xed_document_is_untitled (doc), FALSE);
g_return_val_if_fail (!xed_document_get_readonly (doc), FALSE);
g_return_val_if_fail (!xed_document_is_untitled (doc), G_SOURCE_REMOVE);
g_return_val_if_fail (!xed_document_get_readonly (doc), G_SOURCE_REMOVE);
if (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
{
@ -2229,37 +2349,50 @@ xed_tab_auto_save (XedTab *tab)
/* Set auto_save_timeout to 0 since the timeout is going to be destroyed */
tab->priv->auto_save_timeout = 0;
if (tab->priv->saver != NULL)
if (tab->priv->task_saver != NULL)
{
g_warning ("XedTab: file saver already exists.");
g_object_unref (tab->priv->saver);
tab->priv->saver = NULL;
return G_SOURCE_REMOVE;
}
clear_saving (tab);
tab->priv->task_saver = g_task_new (tab,
NULL,
(GAsyncReadyCallback) auto_save_finished_cb,
NULL);
data = saver_data_new ();
g_task_set_task_data (tab->priv->task_saver,
data,
(GDestroyNotify) saver_data_free);
file = xed_document_get_file (doc);
tab->priv->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
save_flags = get_initial_save_flags (tab, TRUE);
gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
gtk_source_file_saver_set_flags (data->saver, save_flags);
save (tab);
return G_SOURCE_REMOVE;
}
/* Call _xed_tab_save_finish() in @callback, there is no
* _xed_tab_save_as_finish().
*/
void
_xed_tab_save_as (XedTab *tab,
_xed_tab_save_as_async (XedTab *tab,
GFile *location,
const GtkSourceEncoding *encoding,
GtkSourceNewlineType newline_type)
GtkSourceNewlineType newline_type,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
SaverData *data;
XedDocument *doc;
GtkSourceFile *file;
GtkSourceFileSaverFlags save_flags;
GFile *prev_location;
g_return_if_fail (XED_IS_TAB (tab));
g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) ||
@ -2268,14 +2401,18 @@ _xed_tab_save_as (XedTab *tab,
g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (encoding != NULL);
if (tab->priv->saver != NULL)
if (tab->priv->task_saver != NULL)
{
g_warning ("XedTab: file saver already exists.");
g_object_unref (tab->priv->saver);
tab->priv->saver = NULL;
return;
}
clear_saving (tab);
tab->priv->task_saver = g_task_new (tab, cancellable, callback, user_data);
data = saver_data_new ();
g_task_set_task_data (tab->priv->task_saver,
data,
(GDestroyNotify) saver_data_free);
doc = xed_tab_get_document (tab);
g_return_if_fail (XED_IS_DOCUMENT (doc));
@ -2295,20 +2432,12 @@ _xed_tab_save_as (XedTab *tab,
}
file = xed_document_get_file (doc);
prev_location = gtk_source_file_get_location (file);
if (prev_location == NULL || !g_file_equal (prev_location, location))
{
/* Ignore modification time for a save to another location. */
/* TODO do that in GtkSourceFileSaver. */
save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
}
data->saver = gtk_source_file_saver_new_with_target (GTK_SOURCE_BUFFER (doc), file, location);
tab->priv->saver = gtk_source_file_saver_new_with_target (GTK_SOURCE_BUFFER (doc), file, location);
gtk_source_file_saver_set_encoding (tab->priv->saver, encoding);
gtk_source_file_saver_set_newline_type (tab->priv->saver, newline_type);
gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
gtk_source_file_saver_set_encoding (data->saver, encoding);
gtk_source_file_saver_set_newline_type (data->saver, newline_type);
gtk_source_file_saver_set_flags (data->saver, save_flags);
save (tab);
}
@ -2327,7 +2456,7 @@ get_page_setup (XedTab *tab)
if (data == NULL)
{
return _xed_app_get_default_page_setup (xed_app_get_default());
return _xed_app_get_default_page_setup (XED_APP (g_application_get_default ()));
}
else
{
@ -2349,7 +2478,7 @@ get_print_settings (XedTab *tab)
if (data == NULL)
{
settings = _xed_app_get_default_print_settings (xed_app_get_default());
settings = _xed_app_get_default_print_settings (XED_APP (g_application_get_default ()));
}
else
{
@ -2407,7 +2536,7 @@ store_print_settings (XedTab *tab,
g_object_ref (settings), (GDestroyNotify)g_object_unref);
/* make them the default */
_xed_app_set_default_print_settings (xed_app_get_default (), settings);
_xed_app_set_default_print_settings (XED_APP (g_application_get_default ()), settings);
page_setup = xed_print_job_get_page_setup (job);
@ -2416,7 +2545,7 @@ store_print_settings (XedTab *tab,
g_object_ref (page_setup), (GDestroyNotify)g_object_unref);
/* make it the default */
_xed_app_set_default_page_setup (xed_app_get_default (), page_setup);
_xed_app_set_default_page_setup (XED_APP (g_application_get_default ()), page_setup);
}
static void

View File

@ -112,20 +112,46 @@ GtkWidget *_xed_tab_new_from_location (GFile *location,
const GtkSourceEncoding *encoding,
gint line_pos,
gboolean create);
GtkWidget *_xed_tab_new_from_stream (GInputStream *stream,
const GtkSourceEncoding *encoding,
gint line_pos);
gchar *_xed_tab_get_name (XedTab *tab);
gchar *_xed_tab_get_tooltips (XedTab *tab);
GdkPixbuf *_xed_tab_get_icon (XedTab *tab);
void _xed_tab_load (XedTab *tab,
GFile *location,
const GtkSourceEncoding *encoding,
gint line_pos,
gboolean create);
void _xed_tab_load_stream (XedTab *tab,
GInputStream *location,
const GtkSourceEncoding *encoding,
gint line_pos);
void _xed_tab_revert (XedTab *tab);
void _xed_tab_save (XedTab *tab);
void _xed_tab_save_as (XedTab *tab,
void _xed_tab_save_async (XedTab *tab,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean _xed_tab_save_finish (XedTab *tab,
GAsyncResult *result);
void _xed_tab_save_as_async (XedTab *tab,
GFile *location,
const GtkSourceEncoding *encoding,
GtkSourceNewlineType newline_type);
GtkSourceNewlineType newline_type,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void _xed_tab_print (XedTab *tab);
void _xed_tab_print_preview (XedTab *tab);

View File

@ -771,7 +771,7 @@ xed_view_set_font (XedView *view,
GObject *settings;
gchar *font;
settings = _xed_app_get_settings (xed_app_get_default ());
settings = _xed_app_get_settings (XED_APP (g_application_get_default ()));
font = xed_settings_get_system_font (XED_SETTINGS (settings));
font_desc = pango_font_description_from_string (font);

View File

@ -65,7 +65,7 @@ enum
TARGET_URI_LIST = 100
};
G_DEFINE_TYPE(XedWindow, xed_window, GTK_TYPE_WINDOW)
G_DEFINE_TYPE(XedWindow, xed_window, GTK_TYPE_APPLICATION_WINDOW)
static void recent_manager_changed (GtkRecentManager *manager, XedWindow *window);
@ -983,15 +983,19 @@ open_recent_file (GFile *location,
XedWindow *window)
{
GSList *locations = NULL;
GSList *loaded = NULL;
locations = g_slist_prepend (locations, (gpointer) location);
if (xed_commands_load_locations (window, locations, NULL, 0) != 1)
loaded = xed_commands_load_locations (window, locations, NULL, 0);
if (!loaded || loaded->next) /* if it doesn't contain just 1 element */
{
_xed_recent_remove (window, location);
}
g_slist_free (locations);
g_slist_free (loaded);
}
static void
@ -1803,7 +1807,7 @@ clone_window (XedWindow *origin)
xed_debug (DEBUG_WINDOW);
app = xed_app_get_default ();
app = XED_APP (g_application_get_default ());
screen = gtk_window_get_screen (GTK_WINDOW(origin));
window = xed_app_create_window (app, screen);
@ -1940,7 +1944,7 @@ set_title (XedWindow *window)
if (window->priv->active_tab == NULL)
{
gtk_window_set_title (GTK_WINDOW(window), "Xed");
xed_app_set_window_title (XED_APP (g_application_get_default ()), window, "Xed");
return;
}
@ -2012,7 +2016,7 @@ set_title (XedWindow *window)
}
}
gtk_window_set_title (GTK_WINDOW(window), title);
xed_app_set_window_title (XED_APP (g_application_get_default ()), window, title);
g_free (dirname);
g_free (name);
@ -2486,6 +2490,7 @@ load_uris_from_drop (XedWindow *window,
{
GSList *locations = NULL;
gint i;
GSList *loaded;
if (uri_list == NULL)
{
@ -2498,7 +2503,9 @@ load_uris_from_drop (XedWindow *window,
}
locations = g_slist_reverse (locations);
xed_commands_load_locations (window, locations, NULL, 0);
loaded = xed_commands_load_locations (window, locations, NULL, 0);
g_slist_free (loaded);
g_slist_foreach (locations, (GFunc) g_object_unref, NULL);
g_slist_free (locations);
@ -2704,7 +2711,7 @@ fullscreen_controls_build (XedWindow *window)
priv->fullscreen_controls = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_transient_for (GTK_WINDOW(priv->fullscreen_controls), &window->window);
gtk_window_set_transient_for (GTK_WINDOW (priv->fullscreen_controls), GTK_WINDOW (&window->window));
window->priv->fullscreen_controls_container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_set_border_width (GTK_CONTAINER (window->priv->fullscreen_controls_container), 6);
@ -3705,6 +3712,28 @@ xed_window_create_tab (XedWindow *window,
return tab;
}
static XedTab *
process_create_tab (XedWindow *window,
XedTab *tab,
gboolean jump_to)
{
if (tab == NULL)
{
return NULL;
}
gtk_widget_show (GTK_WIDGET (tab));
xed_notebook_add_tab (XED_NOTEBOOK (window->priv->notebook), tab, -1, jump_to);
if (!gtk_widget_get_visible (GTK_WIDGET (window)))
{
gtk_window_present (GTK_WINDOW (window));
}
return tab;
}
/**
* xed_window_create_tab_from_location:
* @window: a #XedWindow
@ -3735,21 +3764,25 @@ xed_window_create_tab_from_location (XedWindow *window,
g_return_val_if_fail(G_IS_FILE (location), NULL);
tab = _xed_tab_new_from_location (location, encoding, line_pos, create);
if (tab == NULL)
{
return NULL;
return process_create_tab (window, XED_TAB (tab), jump_to);
}
gtk_widget_show (tab);
xed_notebook_add_tab (XED_NOTEBOOK(window->priv->notebook), XED_TAB(tab), -1, jump_to);
if (!gtk_widget_get_visible (GTK_WIDGET(window)))
XedTab *
xed_window_create_tab_from_stream (XedWindow *window,
GInputStream *stream,
const GtkSourceEncoding *encoding,
gint line_pos,
gboolean jump_to)
{
gtk_window_present (GTK_WINDOW(window));
}
GtkWidget *tab;
return XED_TAB(tab);
g_return_val_if_fail (XED_IS_WINDOW (window), NULL);
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
tab = _xed_tab_new_from_stream (stream, encoding, line_pos);
return process_create_tab (window, XED_TAB (tab), jump_to);
}
/**
@ -4175,7 +4208,7 @@ _xed_window_fullscreen (XedWindow *window)
}
/* Go to fullscreen mode and hide bars */
gtk_window_fullscreen (&window->window);
gtk_window_fullscreen (GTK_WINDOW (&window->window));
gtk_widget_hide (window->priv->menubar);
@ -4203,7 +4236,7 @@ _xed_window_unfullscreen (XedWindow *window)
}
/* Unfullscreen and show bars */
gtk_window_unfullscreen (&window->window);
gtk_window_unfullscreen (GTK_WINDOW (&window->window));
g_signal_handlers_disconnect_by_func (window->priv->notebook, hide_notebook_tabs_on_fullscreen, window);
gtk_widget_show (window->priv->menubar);

View File

@ -32,7 +32,7 @@ typedef struct _XedWindowClass XedWindowClass;
struct _XedWindow
{
GtkWindow window;
GtkApplicationWindow window;
/*< private > */
XedWindowPrivate *priv;
@ -40,7 +40,7 @@ struct _XedWindow
struct _XedWindowClass
{
GtkWindowClass parent_class;
GtkApplicationWindowClass parent_class;
/* Signals */
void (* tab_added) (XedWindow *window, XedTab *tab);
@ -50,13 +50,13 @@ struct _XedWindowClass
void (* active_tab_state_changed) (XedWindow *window);
};
/*
* Public methods
*/
/* Public methods */
GType xed_window_get_type (void) G_GNUC_CONST;
XedTab *xed_window_create_tab (XedWindow *window, gboolean jump_to);
XedTab *xed_window_create_tab_from_location (XedWindow *window, GFile *location, const GtkSourceEncoding *encoding,
gint line_pos, gboolean create, gboolean jump_to);
XedTab *xed_window_create_tab_from_stream (XedWindow *window, GInputStream *stream, const GtkSourceEncoding *encoding,
gint line_pos, gboolean jump_to);
void xed_window_close_tab (XedWindow *window, XedTab *tab);
void xed_window_close_all_tabs (XedWindow *window);
void xed_window_close_tabs (XedWindow *window, const GList *tabs);

626
xed/xed.c
View File

@ -32,631 +32,25 @@
#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>
#include <gdk/gdkx.h>
#ifdef HAVE_INTROSPECTION
#include <girepository.h>
#endif
#include "xed-app.h"
#include "xed-commands.h"
#include "xed-debug.h"
#include "xed-dirs.h"
#include "xed-plugins-engine.h"
#include "xed-session.h"
#include "xed-utils.h"
#include "xed-window.h"
#include "eggsmclient.h"
#include "eggdesktopfile.h"
#ifndef ENABLE_GVFS_METADATA
#include "xed-metadata-manager.h"
#endif
#include "bacon-message-connection.h"
static guint32 startup_timestamp = 0;
static BaconMessageConnection *connection;
/* 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 XedEncoding *enc;
// while ((enc = xed_encoding_get_from_index (i)) != NULL)
// {
// g_print ("%s\n", xed_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 xed"), NULL },
{ "new-document", '\0', 0, G_OPTION_ARG_NONE, &new_document_option,
N_("Create a new document in an existing instance of xed"), 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
xed_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 &&
// (xed_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;
}
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 XedEncoding *encoding = NULL;
gchar **commands;
gchar **params;
gint workspace;
gint viewport_x;
gint viewport_y;
gchar *display_name;
gint screen_number;
gint i;
XedApp *app;
XedWindow *window;
GdkDisplay *display;
GdkScreen *screen;
g_return_if_fail (message != NULL);
xed_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 = xed_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 = xed_app_get_default ();
if (new_window_option)
{
window = xed_app_create_window (app, screen);
}
else
{
/* get a window in the current workspace (if exists) and raise it */
window = _xed_app_get_window_in_viewport (app,
screen,
workspace,
viewport_x,
viewport_y);
}
if (file_list != NULL)
{
// _xed_cmd_load_files_from_prompt (window,
// file_list,
// encoding,
// line_position);
if (new_document_option)
xed_window_create_tab (window, TRUE);
}
else
{
XedDocument *doc;
doc = xed_window_get_active_document (window);
if (doc == NULL ||
!xed_document_is_untouched (doc) ||
new_document_option)
xed_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));
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);
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.
*/
xed_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);
xed_debug_message (DEBUG_APP, "Display: %s", display_name);
xed_debug_message (DEBUG_APP, "Screen: %d", screen_number);
ws = xed_utils_get_current_workspace (screen);
xed_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);
}
}
xed_debug_message (DEBUG_APP, "Bacon Message: %s", command->str);
bacon_message_connection_send (connection,
command->str);
g_string_free (command, TRUE);
}
int
main (int argc, char *argv[])
{
GOptionContext *context;
XedPluginsEngine *engine;
XedWindow *window;
XedApp *app;
gboolean restored = FALSE;
GError *error = NULL;
gchar *dir;
gchar *icon_dir;
gint status;
/* Setup debugging */
xed_debug_init ();
xed_debug_message (DEBUG_APP, "Startup");
setlocale (LC_ALL, "");
dir = xed_dirs_get_xed_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 HAVE_INTROSPECTION
g_option_context_add_group (context, g_irepository_get_option_group ());
#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_option_context_free (context);
return 1;
}
g_option_context_free (context);
xed_debug_message (DEBUG_APP, "Create bacon connection");
connection = bacon_message_connection_new ("xed");
if (connection != NULL)
{
if (!bacon_message_connection_get_is_server (connection))
{
xed_debug_message (DEBUG_APP, "I'm a client");
xed_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
{
xed_debug_message (DEBUG_APP, "I'm a server");
bacon_message_connection_set_callback (connection,
on_message_received,
app = g_object_new (XED_TYPE_APP,
"application-id", "org.x.editor",
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
NULL);
}
}
else
{
g_warning ("Cannot create the 'xed' connection.");
}
xed_debug_message (DEBUG_APP, "Set icon");
dir = xed_dirs_get_xed_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);
/* Set the associated .desktop file */
egg_set_desktop_file (DATADIR "/applications/xed.desktop");
/* Init plugins engine */
xed_debug_message (DEBUG_APP, "Init plugins");
engine = xed_plugins_engine_get_default ();
/* Initialize session management */
xed_debug_message (DEBUG_APP, "Init session manager");
xed_session_init ();
if (xed_session_is_restored ())
restored = xed_session_load ();
if (!restored)
{
xed_debug_message (DEBUG_APP, "Analyze command line data");
xed_get_command_line_data ();
xed_debug_message (DEBUG_APP, "Get default app");
app = xed_app_get_default ();
xed_debug_message (DEBUG_APP, "Create main window");
window = xed_app_create_window (app, NULL);
// if (file_list != NULL)
// {
// const XedEncoding *encoding = NULL;
// // if (encoding_charset)
// // encoding = xed_encoding_get_from_charset (encoding_charset);
// xed_debug_message (DEBUG_APP, "Load files");
// _xed_cmd_load_files_from_prompt (window,
// file_list,
// encoding,
// line_position);
// }
// else
// {
// xed_debug_message (DEBUG_APP, "Create tab");
// xed_window_create_tab (window, TRUE);
// }
xed_debug_message (DEBUG_APP, "Show window");
gtk_widget_show (GTK_WIDGET (window));
free_command_line_data ();
}
xed_debug_message (DEBUG_APP, "Start gtk-main");
gtk_main();
bacon_message_connection_free (connection);
/* We kept the original engine reference here. So let's unref it to
* finalize it properly.
*/
g_object_unref (engine);
#ifndef ENABLE_GVFS_METADATA
xed_metadata_manager_shutdown ();
#endif
return 0;
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}