initial
This commit is contained in:
254
gedit/Makefile.am
Executable file
254
gedit/Makefile.am
Executable file
@@ -0,0 +1,254 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
SUBDIRS = dialogs smclient
|
||||
|
||||
if OS_OSX
|
||||
SUBDIRS += osx
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = gedit
|
||||
|
||||
noinst_LTLIBRARIES = libgedit.la
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/smclient \
|
||||
$(GEDIT_CFLAGS) \
|
||||
$(IGE_MAC_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(DISABLE_DEPRECATED_CFLAGS) \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\"
|
||||
|
||||
gedit_SOURCES = \
|
||||
gedit.c
|
||||
|
||||
gedit_LDADD = libgedit.la $(GEDIT_LIBS) $(IGE_MAC_LIBS) $(EGG_SMCLIENT_LIBS)
|
||||
|
||||
if PLATFORM_WIN32
|
||||
gedit_LDFLAGS = -Wl,--export-all-symbols -Wl,--out-implib,libgedit-$(GEDIT_API_VERSION).a
|
||||
if OS_WIN32
|
||||
gedit_LDFLAGS += -mwindows
|
||||
endif
|
||||
else
|
||||
gedit_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
|
||||
endif
|
||||
|
||||
libgedit_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
|
||||
|
||||
libgedit_la_LIBADD = \
|
||||
dialogs/libdialogs.la \
|
||||
smclient/libeggsmclient.la
|
||||
|
||||
# GEDIT_LIBS must be the last to ensure correct order on some platforms
|
||||
libgedit_la_LIBADD += $(GEDIT_LIBS)
|
||||
|
||||
if OS_OSX
|
||||
gedit_LDFLAGS += -framework Carbon
|
||||
|
||||
libgedit_la_LIBADD += osx/libosx.la
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = \
|
||||
gedit-enum-types.c \
|
||||
gedit-enum-types.h \
|
||||
gedit-marshal.c \
|
||||
gedit-marshal.h
|
||||
|
||||
if OS_WIN32
|
||||
gedit-res.o: gedit.rc
|
||||
$(WINDRES) -i gedit.rc --input-format=rc -o gedit-res.o -O coff
|
||||
|
||||
gedit_LDADD += gedit-res.o
|
||||
endif
|
||||
|
||||
NOINST_H_FILES = \
|
||||
gedit-close-button.h \
|
||||
gedit-dirs.h \
|
||||
gedit-document-input-stream.h \
|
||||
gedit-document-loader.h \
|
||||
gedit-document-output-stream.h \
|
||||
gedit-document-saver.h \
|
||||
gedit-documents-panel.h \
|
||||
gedit-gio-document-loader.h \
|
||||
gedit-gio-document-saver.h \
|
||||
gedit-history-entry.h \
|
||||
gedit-io-error-message-area.h \
|
||||
gedit-language-manager.h \
|
||||
gedit-object-module.h \
|
||||
gedit-plugin-info.h \
|
||||
gedit-plugin-info-priv.h \
|
||||
gedit-plugin-loader.h \
|
||||
gedit-plugin-manager.h \
|
||||
gedit-plugins-engine.h \
|
||||
gedit-prefs-manager-private.h \
|
||||
gedit-print-job.h \
|
||||
gedit-print-preview.h \
|
||||
gedit-session.h \
|
||||
gedit-smart-charset-converter.h \
|
||||
gedit-style-scheme-manager.h \
|
||||
gedit-tab-label.h \
|
||||
gedittextregion.h \
|
||||
gedit-ui.h \
|
||||
gedit-window-private.h
|
||||
|
||||
INST_H_FILES = \
|
||||
gedit-app.h \
|
||||
gedit-commands.h \
|
||||
gedit-debug.h \
|
||||
gedit-document.h \
|
||||
gedit-encodings.h \
|
||||
gedit-encodings-combo-box.h \
|
||||
gedit-file-chooser-dialog.h \
|
||||
gedit-help.h \
|
||||
gedit-message-bus.h \
|
||||
gedit-message-type.h \
|
||||
gedit-message.h \
|
||||
gedit-notebook.h \
|
||||
gedit-panel.h \
|
||||
gedit-plugin.h \
|
||||
gedit-prefs-manager-app.h \
|
||||
gedit-prefs-manager.h \
|
||||
gedit-progress-message-area.h \
|
||||
gedit-statusbar.h \
|
||||
gedit-status-combo-box.h \
|
||||
gedit-tab.h \
|
||||
gedit-utils.h \
|
||||
gedit-view.h \
|
||||
gedit-window.h
|
||||
|
||||
if !ENABLE_GVFS_METADATA
|
||||
INST_H_FILES += gedit-metadata-manager.h
|
||||
endif
|
||||
|
||||
headerdir = $(prefix)/include/gedit-@GEDIT_API_VERSION@/gedit
|
||||
|
||||
header_DATA = \
|
||||
$(INST_H_FILES)
|
||||
|
||||
|
||||
libgedit_la_SOURCES = \
|
||||
$(BUILT_SOURCES) \
|
||||
$(BACON_FILES) \
|
||||
$(POSIXIO_FILES) \
|
||||
gedit-app.c \
|
||||
gedit-close-button.c \
|
||||
gedit-commands-documents.c \
|
||||
gedit-commands-edit.c \
|
||||
gedit-commands-file.c \
|
||||
gedit-commands-file-print.c \
|
||||
gedit-commands-help.c \
|
||||
gedit-commands-search.c \
|
||||
gedit-commands-view.c \
|
||||
gedit-debug.c \
|
||||
gedit-dirs.c \
|
||||
gedit-document.c \
|
||||
gedit-document-input-stream.c \
|
||||
gedit-document-loader.c \
|
||||
gedit-document-output-stream.c \
|
||||
gedit-gio-document-loader.c \
|
||||
gedit-document-saver.c \
|
||||
gedit-gio-document-saver.c \
|
||||
gedit-documents-panel.c \
|
||||
gedit-encodings.c \
|
||||
gedit-encodings-combo-box.c \
|
||||
gedit-file-chooser-dialog.c \
|
||||
gedit-help.c \
|
||||
gedit-history-entry.c \
|
||||
gedit-io-error-message-area.c \
|
||||
gedit-language-manager.c \
|
||||
gedit-message-bus.c \
|
||||
gedit-message-type.c \
|
||||
gedit-message.c \
|
||||
gedit-object-module.c \
|
||||
gedit-notebook.c \
|
||||
gedit-panel.c \
|
||||
gedit-plugin-info.c \
|
||||
gedit-plugin.c \
|
||||
gedit-plugin-loader.c \
|
||||
gedit-plugin-manager.c \
|
||||
gedit-plugins-engine.c \
|
||||
gedit-prefs-manager-app.c \
|
||||
gedit-prefs-manager.c \
|
||||
gedit-prefs-manager-private.h \
|
||||
gedit-print-job.c \
|
||||
gedit-print-preview.c \
|
||||
gedit-progress-message-area.c \
|
||||
gedit-session.c \
|
||||
gedit-smart-charset-converter.c \
|
||||
gedit-statusbar.c \
|
||||
gedit-status-combo-box.c \
|
||||
gedit-style-scheme-manager.c \
|
||||
gedit-tab.c \
|
||||
gedit-tab-label.c \
|
||||
gedit-utils.c \
|
||||
gedit-view.c \
|
||||
gedit-window.c \
|
||||
gedittextregion.c \
|
||||
$(NOINST_H_FILES) \
|
||||
$(INST_H_FILES)
|
||||
|
||||
if !ENABLE_GVFS_METADATA
|
||||
libgedit_la_SOURCES += gedit-metadata-manager.c
|
||||
endif
|
||||
|
||||
gedit-enum-types.h: gedit-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
|
||||
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template gedit-enum-types.h.template $(INST_H_FILES)) > $@
|
||||
|
||||
gedit-enum-types.c: gedit-enum-types.c.template $(INST_H_FILES) $(GLIB_MKENUMS)
|
||||
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template gedit-enum-types.c.template $(INST_H_FILES)) > $@
|
||||
|
||||
gedit-marshal.h: gedit-marshal.list $(GLIB_GENMARSHAL)
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=gedit_marshal > $@
|
||||
|
||||
gedit-marshal.c: gedit-marshal.list $(GLIB_GENMARSHAL)
|
||||
$(AM_V_GEN) echo "#include \"gedit-marshal.h\"" > $@ && \
|
||||
$(GLIB_GENMARSHAL) $< --body --prefix=gedit_marshal >> $@
|
||||
|
||||
uidir = $(datadir)/gedit-2/ui/
|
||||
ui_DATA = \
|
||||
gedit-ui.xml \
|
||||
gedit-print-preferences.ui
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(ui_DATA) \
|
||||
gedit-enum-types.h.template \
|
||||
gedit-enum-types.c.template \
|
||||
gedit-marshal.list \
|
||||
gedit.rc
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
dist-hook:
|
||||
cd $(distdir); rm -f $(BUILT_SOURCES)
|
||||
|
||||
install-exec-hook:
|
||||
if PLATFORM_WIN32
|
||||
$(mkinstalldirs) "$(DESTDIR)$(libdir)"
|
||||
$(INSTALL_DATA) libgedit-$(GEDIT_API_VERSION).a "$(DESTDIR)$(libdir)"
|
||||
else
|
||||
rm -f $(DESTDIR)$(bindir)/mate-text-editor
|
||||
ln -s gedit $(DESTDIR)$(bindir)/mate-text-editor
|
||||
endif
|
||||
|
||||
if !OS_WIN32
|
||||
BACON_DIR=$(srcdir)/../../libbacon/src/
|
||||
BACON_FILES=bacon-message-connection.h bacon-message-connection.c
|
||||
|
||||
regenerate-built-sources:
|
||||
BACONFILES="$(BACON_FILES)" BACONDIR="$(BACON_DIR)" $(top_srcdir)/gedit/update-from-bacon.sh
|
||||
else
|
||||
BACON_DIR=
|
||||
endif
|
||||
|
||||
if BUILD_MESSAGE_AREA
|
||||
libgedit_la_SOURCES += gedit-message-area.c
|
||||
INST_H_FILES += gedit-message-area.h
|
||||
endif
|
||||
|
||||
if BUILD_SPINNER
|
||||
libgedit_la_SOURCES += gedit-spinner.c
|
||||
NOINST_H_FILES += gedit-spinner.h
|
||||
endif
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
||||
396
gedit/bacon-message-connection.c
Executable file
396
gedit/bacon-message-connection.c
Executable file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
|
||||
}
|
||||
|
||||
43
gedit/bacon-message-connection.h
Executable file
43
gedit/bacon-message-connection.h
Executable file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
|
||||
31
gedit/dialogs/Makefile.am
Executable file
31
gedit/dialogs/Makefile.am
Executable file
@@ -0,0 +1,31 @@
|
||||
uidir = $(datadir)/gedit-2/ui/
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/gedit \
|
||||
-I$(top_builddir)/gedit \
|
||||
$(GEDIT_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(DISABLE_DEPRECATED_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libdialogs.la
|
||||
|
||||
libdialogs_la_SOURCES = \
|
||||
gedit-preferences-dialog.h \
|
||||
gedit-preferences-dialog.c \
|
||||
gedit-close-confirmation-dialog.c \
|
||||
gedit-close-confirmation-dialog.h \
|
||||
gedit-encodings-dialog.c \
|
||||
gedit-encodings-dialog.h \
|
||||
gedit-search-dialog.h \
|
||||
gedit-search-dialog.c
|
||||
|
||||
ui_DATA = \
|
||||
gedit-encodings-dialog.ui \
|
||||
gedit-preferences-dialog.ui \
|
||||
gedit-search-dialog.ui
|
||||
|
||||
EXTRA_DIST = $(ui_DATA)
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
||||
790
gedit/dialogs/gedit-close-confirmation-dialog.c
Executable file
790
gedit/dialogs/gedit-close-confirmation-dialog.c
Executable file
@@ -0,0 +1,790 @@
|
||||
/*
|
||||
* gedit-close-confirmation-dialog.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2004-2005 MATE Foundation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2004-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-close-confirmation-dialog.h"
|
||||
#include <gedit/gedit-app.h>
|
||||
#include <gedit/gedit-utils.h>
|
||||
#include <gedit/gedit-window.h>
|
||||
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_UNSAVED_DOCUMENTS,
|
||||
PROP_LOGOUT_MODE
|
||||
};
|
||||
|
||||
/* Mode */
|
||||
enum
|
||||
{
|
||||
SINGLE_DOC_MODE,
|
||||
MULTIPLE_DOCS_MODE
|
||||
};
|
||||
|
||||
/* Columns */
|
||||
enum
|
||||
{
|
||||
SAVE_COLUMN,
|
||||
NAME_COLUMN,
|
||||
DOC_COLUMN, /* a handy pointer to the document */
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
struct _GeditCloseConfirmationDialogPrivate
|
||||
{
|
||||
gboolean logout_mode;
|
||||
|
||||
GList *unsaved_documents;
|
||||
|
||||
GList *selected_documents;
|
||||
|
||||
GtkTreeModel *list_store;
|
||||
|
||||
gboolean disable_save_to_disk;
|
||||
};
|
||||
|
||||
#define GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
||||
GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, \
|
||||
GeditCloseConfirmationDialogPrivate))
|
||||
|
||||
#define GET_MODE(priv) (((priv->unsaved_documents != NULL) && \
|
||||
(priv->unsaved_documents->next == NULL)) ? \
|
||||
SINGLE_DOC_MODE : MULTIPLE_DOCS_MODE)
|
||||
|
||||
G_DEFINE_TYPE(GeditCloseConfirmationDialog, gedit_close_confirmation_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
static void set_unsaved_document (GeditCloseConfirmationDialog *dlg,
|
||||
const GList *list);
|
||||
|
||||
static GList *get_selected_docs (GtkTreeModel *store);
|
||||
|
||||
/* Since we connect in the costructor we are sure this handler will be called
|
||||
* before the user ones
|
||||
*/
|
||||
static void
|
||||
response_cb (GeditCloseConfirmationDialog *dlg,
|
||||
gint response_id,
|
||||
gpointer data)
|
||||
{
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg));
|
||||
|
||||
priv = dlg->priv;
|
||||
|
||||
if (priv->selected_documents != NULL)
|
||||
g_list_free (priv->selected_documents);
|
||||
|
||||
if (response_id == GTK_RESPONSE_YES)
|
||||
{
|
||||
if (GET_MODE (priv) == SINGLE_DOC_MODE)
|
||||
{
|
||||
priv->selected_documents =
|
||||
g_list_copy (priv->unsaved_documents);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_fail (priv->list_store);
|
||||
|
||||
priv->selected_documents =
|
||||
get_selected_docs (priv->list_store);
|
||||
}
|
||||
}
|
||||
else
|
||||
priv->selected_documents = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_logout_mode (GeditCloseConfirmationDialog *dlg,
|
||||
gboolean logout_mode)
|
||||
{
|
||||
dlg->priv->logout_mode = logout_mode;
|
||||
|
||||
if (logout_mode)
|
||||
{
|
||||
gtk_dialog_add_button (GTK_DIALOG (dlg),
|
||||
_("Log Out _without Saving"),
|
||||
GTK_RESPONSE_NO);
|
||||
|
||||
gedit_dialog_add_button (GTK_DIALOG (dlg),
|
||||
_("_Cancel Logout"),
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_dialog_add_button (GTK_DIALOG (dlg),
|
||||
_("Close _without Saving"),
|
||||
GTK_RESPONSE_NO);
|
||||
|
||||
gtk_dialog_add_button (GTK_DIALOG (dlg),
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
|
||||
if (dlg->priv->disable_save_to_disk)
|
||||
{
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
|
||||
GTK_RESPONSE_NO);
|
||||
}
|
||||
else
|
||||
{
|
||||
const gchar *stock_id = GTK_STOCK_SAVE;
|
||||
|
||||
if (GET_MODE (dlg->priv) == SINGLE_DOC_MODE)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
|
||||
doc = GEDIT_DOCUMENT (dlg->priv->unsaved_documents->data);
|
||||
|
||||
if (gedit_document_get_readonly (doc) ||
|
||||
gedit_document_is_untitled (doc))
|
||||
stock_id = GTK_STOCK_SAVE_AS;
|
||||
}
|
||||
|
||||
gtk_dialog_add_button (GTK_DIALOG (dlg),
|
||||
stock_id,
|
||||
GTK_RESPONSE_YES);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
|
||||
GTK_RESPONSE_YES);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_confirmation_dialog_init (GeditCloseConfirmationDialog *dlg)
|
||||
{
|
||||
AtkObject *atk_obj;
|
||||
|
||||
dlg->priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg);
|
||||
|
||||
dlg->priv->disable_save_to_disk =
|
||||
gedit_app_get_lockdown (gedit_app_get_default ())
|
||||
& GEDIT_LOCKDOWN_SAVE_TO_DISK;
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
14);
|
||||
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
|
||||
gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE);
|
||||
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dlg), TRUE);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), "");
|
||||
|
||||
gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
|
||||
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dlg));
|
||||
atk_object_set_role (atk_obj, ATK_ROLE_ALERT);
|
||||
atk_object_set_name (atk_obj, _("Question"));
|
||||
|
||||
g_signal_connect (dlg,
|
||||
"response",
|
||||
G_CALLBACK (response_cb),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_confirmation_dialog_finalize (GObject *object)
|
||||
{
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
|
||||
priv = GEDIT_CLOSE_CONFIRMATION_DIALOG (object)->priv;
|
||||
|
||||
if (priv->unsaved_documents != NULL)
|
||||
g_list_free (priv->unsaved_documents);
|
||||
|
||||
if (priv->selected_documents != NULL)
|
||||
g_list_free (priv->selected_documents);
|
||||
|
||||
/* Call the parent's destructor */
|
||||
G_OBJECT_CLASS (gedit_close_confirmation_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_confirmation_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditCloseConfirmationDialog *dlg;
|
||||
|
||||
dlg = GEDIT_CLOSE_CONFIRMATION_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_UNSAVED_DOCUMENTS:
|
||||
set_unsaved_document (dlg, g_value_get_pointer (value));
|
||||
break;
|
||||
|
||||
case PROP_LOGOUT_MODE:
|
||||
set_logout_mode (dlg, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_confirmation_dialog_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
|
||||
priv = GEDIT_CLOSE_CONFIRMATION_DIALOG (object)->priv;
|
||||
|
||||
switch( prop_id )
|
||||
{
|
||||
case PROP_UNSAVED_DOCUMENTS:
|
||||
g_value_set_pointer (value, priv->unsaved_documents);
|
||||
break;
|
||||
|
||||
case PROP_LOGOUT_MODE:
|
||||
g_value_set_boolean (value, priv->logout_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_confirmation_dialog_class_init (GeditCloseConfirmationDialogClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gedit_close_confirmation_dialog_set_property;
|
||||
gobject_class->get_property = gedit_close_confirmation_dialog_get_property;
|
||||
gobject_class->finalize = gedit_close_confirmation_dialog_finalize;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditCloseConfirmationDialogPrivate));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_UNSAVED_DOCUMENTS,
|
||||
g_param_spec_pointer ("unsaved_documents",
|
||||
"Unsaved Documents",
|
||||
"List of Unsaved Documents",
|
||||
(G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY)));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LOGOUT_MODE,
|
||||
g_param_spec_boolean ("logout_mode",
|
||||
"Logout Mode",
|
||||
"Whether the dialog is in logout mode",
|
||||
FALSE,
|
||||
(G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY)));
|
||||
}
|
||||
|
||||
static GList *
|
||||
get_selected_docs (GtkTreeModel *store)
|
||||
{
|
||||
GList *list;
|
||||
gboolean valid;
|
||||
GtkTreeIter iter;
|
||||
|
||||
list = NULL;
|
||||
valid = gtk_tree_model_get_iter_first (store, &iter);
|
||||
|
||||
while (valid)
|
||||
{
|
||||
gboolean to_save;
|
||||
GeditDocument *doc;
|
||||
|
||||
gtk_tree_model_get (store, &iter,
|
||||
SAVE_COLUMN, &to_save,
|
||||
DOC_COLUMN, &doc,
|
||||
-1);
|
||||
if (to_save)
|
||||
list = g_list_prepend (list, doc);
|
||||
|
||||
valid = gtk_tree_model_iter_next (store, &iter);
|
||||
}
|
||||
|
||||
list = g_list_reverse (list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList *
|
||||
gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDialog *dlg)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
|
||||
|
||||
return g_list_copy (dlg->priv->selected_documents);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_close_confirmation_dialog_new (GtkWindow *parent,
|
||||
GList *unsaved_documents,
|
||||
gboolean logout_mode)
|
||||
{
|
||||
GtkWidget *dlg;
|
||||
g_return_val_if_fail (unsaved_documents != NULL, NULL);
|
||||
|
||||
dlg = GTK_WIDGET (g_object_new (GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG,
|
||||
"unsaved_documents", unsaved_documents,
|
||||
"logout_mode", logout_mode,
|
||||
NULL));
|
||||
g_return_val_if_fail (dlg != NULL, NULL);
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
gtk_window_group_add_window (gedit_window_get_group (GEDIT_WINDOW (parent)),
|
||||
GTK_WINDOW (dlg));
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
|
||||
}
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_close_confirmation_dialog_new_single (GtkWindow *parent,
|
||||
GeditDocument *doc,
|
||||
gboolean logout_mode)
|
||||
{
|
||||
GtkWidget *dlg;
|
||||
GList *unsaved_documents;
|
||||
g_return_val_if_fail (doc != NULL, NULL);
|
||||
|
||||
unsaved_documents = g_list_prepend (NULL, doc);
|
||||
|
||||
dlg = gedit_close_confirmation_dialog_new (parent,
|
||||
unsaved_documents,
|
||||
logout_mode);
|
||||
|
||||
g_list_free (unsaved_documents);
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_text_secondary_label (GeditDocument *doc)
|
||||
{
|
||||
glong seconds;
|
||||
gchar *secondary_msg;
|
||||
|
||||
seconds = MAX (1, _gedit_document_get_seconds_since_last_save_or_load (doc));
|
||||
|
||||
if (seconds < 55)
|
||||
{
|
||||
secondary_msg = g_strdup_printf (
|
||||
ngettext ("If you don't save, changes from the last %ld second "
|
||||
"will be permanently lost.",
|
||||
"If you don't save, changes from the last %ld seconds "
|
||||
"will be permanently lost.",
|
||||
seconds),
|
||||
seconds);
|
||||
}
|
||||
else if (seconds < 75) /* 55 <= seconds < 75 */
|
||||
{
|
||||
secondary_msg = g_strdup (_("If you don't save, changes from the last minute "
|
||||
"will be permanently lost."));
|
||||
}
|
||||
else if (seconds < 110) /* 75 <= seconds < 110 */
|
||||
{
|
||||
secondary_msg = g_strdup_printf (
|
||||
ngettext ("If you don't save, changes from the last minute and %ld "
|
||||
"second will be permanently lost.",
|
||||
"If you don't save, changes from the last minute and %ld "
|
||||
"seconds will be permanently lost.",
|
||||
seconds - 60 ),
|
||||
seconds - 60);
|
||||
}
|
||||
else if (seconds < 3600)
|
||||
{
|
||||
secondary_msg = g_strdup_printf (
|
||||
ngettext ("If you don't save, changes from the last %ld minute "
|
||||
"will be permanently lost.",
|
||||
"If you don't save, changes from the last %ld minutes "
|
||||
"will be permanently lost.",
|
||||
seconds / 60),
|
||||
seconds / 60);
|
||||
}
|
||||
else if (seconds < 7200)
|
||||
{
|
||||
gint minutes;
|
||||
seconds -= 3600;
|
||||
|
||||
minutes = seconds / 60;
|
||||
if (minutes < 5)
|
||||
{
|
||||
secondary_msg = g_strdup (_("If you don't save, changes from the last hour "
|
||||
"will be permanently lost."));
|
||||
}
|
||||
else
|
||||
{
|
||||
secondary_msg = g_strdup_printf (
|
||||
ngettext ("If you don't save, changes from the last hour and %d "
|
||||
"minute will be permanently lost.",
|
||||
"If you don't save, changes from the last hour and %d "
|
||||
"minutes will be permanently lost.",
|
||||
minutes),
|
||||
minutes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gint hours;
|
||||
|
||||
hours = seconds / 3600;
|
||||
|
||||
secondary_msg = g_strdup_printf (
|
||||
ngettext ("If you don't save, changes from the last %d hour "
|
||||
"will be permanently lost.",
|
||||
"If you don't save, changes from the last %d hours "
|
||||
"will be permanently lost.",
|
||||
hours),
|
||||
hours);
|
||||
}
|
||||
|
||||
return secondary_msg;
|
||||
}
|
||||
|
||||
static void
|
||||
build_single_doc_dialog (GeditCloseConfirmationDialog *dlg)
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *primary_label;
|
||||
GtkWidget *secondary_label;
|
||||
GtkWidget *image;
|
||||
GeditDocument *doc;
|
||||
gchar *doc_name;
|
||||
gchar *str;
|
||||
gchar *markup_str;
|
||||
|
||||
g_return_if_fail (dlg->priv->unsaved_documents->data != NULL);
|
||||
doc = GEDIT_DOCUMENT (dlg->priv->unsaved_documents->data);
|
||||
|
||||
/* Image */
|
||||
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
|
||||
GTK_ICON_SIZE_DIALOG);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
|
||||
|
||||
/* Primary label */
|
||||
primary_label = gtk_label_new (NULL);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
|
||||
gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5);
|
||||
gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
|
||||
|
||||
doc_name = gedit_document_get_short_name_for_display (doc);
|
||||
|
||||
if (dlg->priv->disable_save_to_disk)
|
||||
{
|
||||
str = g_markup_printf_escaped (_("Changes to document \"%s\" will be permanently lost."),
|
||||
doc_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = g_markup_printf_escaped (_("Save changes to document \"%s\" before closing?"),
|
||||
doc_name);
|
||||
}
|
||||
|
||||
g_free (doc_name);
|
||||
|
||||
markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
|
||||
g_free (str);
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
|
||||
g_free (markup_str);
|
||||
|
||||
/* Secondary label */
|
||||
if (dlg->priv->disable_save_to_disk)
|
||||
str = g_strdup (_("Saving has been disabled by the system administrator."));
|
||||
else
|
||||
str = get_text_secondary_label (doc);
|
||||
secondary_label = gtk_label_new (str);
|
||||
g_free (str);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (secondary_label), 0.0, 0.5);
|
||||
gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 12);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), secondary_label, FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
hbox,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
|
||||
gtk_widget_show_all (hbox);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_model (GtkTreeModel *store, GList *docs)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
while (docs != NULL)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
gchar *name;
|
||||
|
||||
doc = GEDIT_DOCUMENT (docs->data);
|
||||
|
||||
name = gedit_document_get_short_name_for_display (doc);
|
||||
|
||||
gtk_list_store_append (GTK_LIST_STORE (store), &iter);
|
||||
gtk_list_store_set (GTK_LIST_STORE (store), &iter,
|
||||
SAVE_COLUMN, TRUE,
|
||||
NAME_COLUMN, name,
|
||||
DOC_COLUMN, doc,
|
||||
-1);
|
||||
|
||||
g_free (name);
|
||||
|
||||
docs = g_list_next (docs);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
save_toggled (GtkCellRendererToggle *renderer, gchar *path_str, GtkTreeModel *store)
|
||||
{
|
||||
GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
|
||||
GtkTreeIter iter;
|
||||
gboolean active;
|
||||
|
||||
gtk_tree_model_get_iter (store, &iter, path);
|
||||
gtk_tree_model_get (store, &iter, SAVE_COLUMN, &active, -1);
|
||||
|
||||
active ^= 1;
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (store), &iter,
|
||||
SAVE_COLUMN, active, -1);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_treeview (GeditCloseConfirmationDialogPrivate *priv)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkWidget *treeview;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
|
||||
treeview = gtk_tree_view_new ();
|
||||
gtk_widget_set_size_request (treeview, 260, 120);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
|
||||
|
||||
/* Create and populate the model */
|
||||
store = gtk_list_store_new (N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
|
||||
populate_model (GTK_TREE_MODEL (store), priv->unsaved_documents);
|
||||
|
||||
/* Set model to the treeview */
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
|
||||
g_object_unref (store);
|
||||
|
||||
priv->list_store = GTK_TREE_MODEL (store);
|
||||
|
||||
/* Add columns */
|
||||
if (!priv->disable_save_to_disk)
|
||||
{
|
||||
renderer = gtk_cell_renderer_toggle_new ();
|
||||
g_signal_connect (renderer, "toggled",
|
||||
G_CALLBACK (save_toggled), store);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes ("Save?",
|
||||
renderer,
|
||||
"active",
|
||||
SAVE_COLUMN,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
}
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Name",
|
||||
renderer,
|
||||
"text",
|
||||
NAME_COLUMN,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
return treeview;
|
||||
}
|
||||
|
||||
static void
|
||||
build_multiple_docs_dialog (GeditCloseConfirmationDialog *dlg)
|
||||
{
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *primary_label;
|
||||
GtkWidget *vbox2;
|
||||
GtkWidget *select_label;
|
||||
GtkWidget *scrolledwindow;
|
||||
GtkWidget *treeview;
|
||||
GtkWidget *secondary_label;
|
||||
gchar *str;
|
||||
gchar *markup_str;
|
||||
|
||||
priv = dlg->priv;
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
hbox, TRUE, TRUE, 0);
|
||||
|
||||
/* Image */
|
||||
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
|
||||
GTK_ICON_SIZE_DIALOG);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 12);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
||||
|
||||
/* Primary label */
|
||||
primary_label = gtk_label_new (NULL);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
|
||||
gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5);
|
||||
gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
|
||||
|
||||
if (priv->disable_save_to_disk)
|
||||
str = g_strdup_printf (
|
||||
ngettext ("Changes to %d document will be permanently lost.",
|
||||
"Changes to %d documents will be permanently lost.",
|
||||
g_list_length (priv->unsaved_documents)),
|
||||
g_list_length (priv->unsaved_documents));
|
||||
else
|
||||
str = g_strdup_printf (
|
||||
ngettext ("There is %d document with unsaved changes. "
|
||||
"Save changes before closing?",
|
||||
"There are %d documents with unsaved changes. "
|
||||
"Save changes before closing?",
|
||||
g_list_length (priv->unsaved_documents)),
|
||||
g_list_length (priv->unsaved_documents));
|
||||
|
||||
markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
|
||||
g_free (str);
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
|
||||
g_free (markup_str);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
|
||||
|
||||
vbox2 = gtk_vbox_new (FALSE, 8);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
|
||||
|
||||
if (priv->disable_save_to_disk)
|
||||
select_label = gtk_label_new_with_mnemonic (_("Docum_ents with unsaved changes:"));
|
||||
else
|
||||
select_label = gtk_label_new_with_mnemonic (_("S_elect the documents you want to save:"));
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), select_label, FALSE, FALSE, 0);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (select_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (select_label), 0.0, 0.5);
|
||||
|
||||
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow, TRUE, TRUE, 0);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_SHADOW_IN);
|
||||
|
||||
treeview = create_treeview (priv);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview);
|
||||
|
||||
/* Secondary label */
|
||||
if (priv->disable_save_to_disk)
|
||||
secondary_label = gtk_label_new (_("Saving has been disabled by the system administrator."));
|
||||
else
|
||||
secondary_label = gtk_label_new (_("If you don't save, "
|
||||
"all your changes will be permanently lost."));
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), secondary_label, FALSE, FALSE, 0);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5);
|
||||
gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (select_label), treeview);
|
||||
|
||||
gtk_widget_show_all (hbox);
|
||||
}
|
||||
|
||||
static void
|
||||
set_unsaved_document (GeditCloseConfirmationDialog *dlg,
|
||||
const GList *list)
|
||||
{
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
|
||||
g_return_if_fail (list != NULL);
|
||||
|
||||
priv = dlg->priv;
|
||||
g_return_if_fail (priv->unsaved_documents == NULL);
|
||||
|
||||
priv->unsaved_documents = g_list_copy ((GList *)list);
|
||||
|
||||
if (GET_MODE (priv) == SINGLE_DOC_MODE)
|
||||
{
|
||||
build_single_doc_dialog (dlg);
|
||||
}
|
||||
else
|
||||
{
|
||||
build_multiple_docs_dialog (dlg);
|
||||
}
|
||||
}
|
||||
|
||||
const GList *
|
||||
gedit_close_confirmation_dialog_get_unsaved_documents (GeditCloseConfirmationDialog *dlg)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
|
||||
|
||||
return dlg->priv->unsaved_documents;
|
||||
}
|
||||
75
gedit/dialogs/gedit-close-confirmation-dialog.h
Executable file
75
gedit/dialogs/gedit-close-confirmation-dialog.h
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* gedit-close-confirmation-dialog.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2004-2005 MATE Foundation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2004-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_CLOSE_CONFIRMATION_DIALOG_H__
|
||||
#define __GEDIT_CLOSE_CONFIRMATION_DIALOG_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gedit/gedit-document.h>
|
||||
|
||||
#define GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG (gedit_close_confirmation_dialog_get_type ())
|
||||
#define GEDIT_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, GeditCloseConfirmationDialog))
|
||||
#define GEDIT_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, GeditCloseConfirmationDialogClass))
|
||||
#define GEDIT_IS_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG))
|
||||
#define GEDIT_IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG))
|
||||
#define GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, GeditCloseConfirmationDialogClass))
|
||||
|
||||
typedef struct _GeditCloseConfirmationDialog GeditCloseConfirmationDialog;
|
||||
typedef struct _GeditCloseConfirmationDialogClass GeditCloseConfirmationDialogClass;
|
||||
typedef struct _GeditCloseConfirmationDialogPrivate GeditCloseConfirmationDialogPrivate;
|
||||
|
||||
struct _GeditCloseConfirmationDialog
|
||||
{
|
||||
GtkDialog parent;
|
||||
|
||||
/*< private > */
|
||||
GeditCloseConfirmationDialogPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditCloseConfirmationDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_close_confirmation_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_close_confirmation_dialog_new (GtkWindow *parent,
|
||||
GList *unsaved_documents,
|
||||
gboolean logout_mode);
|
||||
GtkWidget *gedit_close_confirmation_dialog_new_single (GtkWindow *parent,
|
||||
GeditDocument *doc,
|
||||
gboolean logout_mode);
|
||||
|
||||
const GList *gedit_close_confirmation_dialog_get_unsaved_documents (GeditCloseConfirmationDialog *dlg);
|
||||
|
||||
GList *gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDialog *dlg);
|
||||
|
||||
#endif /* __GEDIT_CLOSE_CONFIRMATION_DIALOG_H__ */
|
||||
|
||||
499
gedit/dialogs/gedit-encodings-dialog.c
Executable file
499
gedit/dialogs/gedit-encodings-dialog.c
Executable file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
* gedit-encodings-dialog.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-encodings-dialog.h"
|
||||
#include "gedit-encodings.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-help.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
#define GEDIT_ENCODINGS_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_ENCODINGS_DIALOG, \
|
||||
GeditEncodingsDialogPrivate))
|
||||
|
||||
struct _GeditEncodingsDialogPrivate
|
||||
{
|
||||
GtkListStore *available_liststore;
|
||||
GtkListStore *displayed_liststore;
|
||||
GtkWidget *available_treeview;
|
||||
GtkWidget *displayed_treeview;
|
||||
GtkWidget *add_button;
|
||||
GtkWidget *remove_button;
|
||||
|
||||
GSList *show_in_menu_list;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditEncodingsDialog, gedit_encodings_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
static void
|
||||
gedit_encodings_dialog_finalize (GObject *object)
|
||||
{
|
||||
GeditEncodingsDialogPrivate *priv = GEDIT_ENCODINGS_DIALOG (object)->priv;
|
||||
|
||||
g_slist_free (priv->show_in_menu_list);
|
||||
|
||||
G_OBJECT_CLASS (gedit_encodings_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_dialog_class_init (GeditEncodingsDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_encodings_dialog_finalize;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditEncodingsDialogPrivate));
|
||||
}
|
||||
|
||||
enum {
|
||||
COLUMN_NAME,
|
||||
COLUMN_CHARSET,
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
static void
|
||||
count_selected_items_func (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
int *count = data;
|
||||
|
||||
*count += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
available_selection_changed_callback (GtkTreeSelection *selection,
|
||||
GeditEncodingsDialog *dialogs)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
gtk_tree_selection_selected_foreach (selection,
|
||||
count_selected_items_func,
|
||||
&count);
|
||||
|
||||
gtk_widget_set_sensitive (dialogs->priv->add_button, count > 0);
|
||||
}
|
||||
|
||||
static void
|
||||
displayed_selection_changed_callback (GtkTreeSelection *selection,
|
||||
GeditEncodingsDialog *dialogs)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
gtk_tree_selection_selected_foreach (selection,
|
||||
count_selected_items_func,
|
||||
&count);
|
||||
|
||||
gtk_widget_set_sensitive (dialogs->priv->remove_button, count > 0);
|
||||
}
|
||||
|
||||
static void
|
||||
get_selected_encodings_func (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GSList **list = data;
|
||||
gchar *charset;
|
||||
const GeditEncoding *enc;
|
||||
|
||||
charset = NULL;
|
||||
gtk_tree_model_get (model, iter, COLUMN_CHARSET, &charset, -1);
|
||||
|
||||
enc = gedit_encoding_get_from_charset (charset);
|
||||
g_free (charset);
|
||||
|
||||
*list = g_slist_prepend (*list, (gpointer)enc);
|
||||
}
|
||||
|
||||
static void
|
||||
update_shown_in_menu_tree_model (GtkListStore *store,
|
||||
GSList *list)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
while (list != NULL)
|
||||
{
|
||||
const GeditEncoding *enc;
|
||||
|
||||
enc = (const GeditEncoding*) list->data;
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
COLUMN_CHARSET,
|
||||
gedit_encoding_get_charset (enc),
|
||||
COLUMN_NAME,
|
||||
gedit_encoding_get_name (enc), -1);
|
||||
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_button_clicked_callback (GtkWidget *button,
|
||||
GeditEncodingsDialog *dialog)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GSList *encodings;
|
||||
GSList *tmp;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->available_treeview));
|
||||
|
||||
encodings = NULL;
|
||||
gtk_tree_selection_selected_foreach (selection,
|
||||
get_selected_encodings_func,
|
||||
&encodings);
|
||||
|
||||
tmp = encodings;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (g_slist_find (dialog->priv->show_in_menu_list, tmp->data) == NULL)
|
||||
dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list,
|
||||
tmp->data);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (encodings);
|
||||
|
||||
update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore),
|
||||
dialog->priv->show_in_menu_list);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_button_clicked_callback (GtkWidget *button,
|
||||
GeditEncodingsDialog *dialog)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GSList *encodings;
|
||||
GSList *tmp;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->displayed_treeview));
|
||||
|
||||
encodings = NULL;
|
||||
gtk_tree_selection_selected_foreach (selection,
|
||||
get_selected_encodings_func,
|
||||
&encodings);
|
||||
|
||||
tmp = encodings;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
dialog->priv->show_in_menu_list = g_slist_remove (dialog->priv->show_in_menu_list,
|
||||
tmp->data);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (encodings);
|
||||
|
||||
update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore),
|
||||
dialog->priv->show_in_menu_list);
|
||||
}
|
||||
|
||||
static void
|
||||
init_shown_in_menu_tree_model (GeditEncodingsDialog *dialog)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GSList *list, *tmp;
|
||||
|
||||
/* add data to the list store */
|
||||
list = gedit_prefs_manager_get_shown_in_menu_encodings ();
|
||||
|
||||
tmp = list;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
const GeditEncoding *enc;
|
||||
|
||||
enc = (const GeditEncoding *) tmp->data;
|
||||
|
||||
dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list,
|
||||
tmp->data);
|
||||
|
||||
gtk_list_store_append (dialog->priv->displayed_liststore,
|
||||
&iter);
|
||||
gtk_list_store_set (dialog->priv->displayed_liststore,
|
||||
&iter,
|
||||
COLUMN_CHARSET,
|
||||
gedit_encoding_get_charset (enc),
|
||||
COLUMN_NAME,
|
||||
gedit_encoding_get_name (enc), -1);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
static void
|
||||
response_handler (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
GeditEncodingsDialog *dlg)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_HELP)
|
||||
{
|
||||
gedit_help_display (GTK_WINDOW (dialog), "gedit", NULL);
|
||||
g_signal_stop_emission_by_name (dialog, "response");
|
||||
return;
|
||||
}
|
||||
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
g_return_if_fail (gedit_prefs_manager_shown_in_menu_encodings_can_set ());
|
||||
gedit_prefs_manager_set_shown_in_menu_encodings (dlg->priv->show_in_menu_list);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_dialog_init (GeditEncodingsDialog *dlg)
|
||||
{
|
||||
GtkWidget *content;
|
||||
GtkCellRenderer *cell_renderer;
|
||||
GtkTreeModel *sort_model;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeIter parent_iter;
|
||||
GtkTreeSelection *selection;
|
||||
const GeditEncoding *enc;
|
||||
GtkWidget *error_widget;
|
||||
int i;
|
||||
gboolean ret;
|
||||
gchar *file;
|
||||
gchar *root_objects[] = {
|
||||
"encodings-dialog-contents",
|
||||
NULL
|
||||
};
|
||||
|
||||
dlg->priv = GEDIT_ENCODINGS_DIALOG_GET_PRIVATE (dlg);
|
||||
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OK,
|
||||
GTK_RESPONSE_OK,
|
||||
GTK_STOCK_HELP,
|
||||
GTK_RESPONSE_HELP,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), _("Character Encodings"));
|
||||
gtk_window_set_default_size (GTK_WINDOW (dlg), 650, 400);
|
||||
gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE);
|
||||
|
||||
/* HIG defaults */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
2); /* 2 * 5 + 2 = 12 */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
|
||||
5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
|
||||
GTK_RESPONSE_OK);
|
||||
|
||||
g_signal_connect (dlg,
|
||||
"response",
|
||||
G_CALLBACK (response_handler),
|
||||
dlg);
|
||||
|
||||
file = gedit_dirs_get_ui_file ("gedit-encodings-dialog.ui");
|
||||
ret = gedit_utils_get_ui_objects (file,
|
||||
root_objects,
|
||||
&error_widget,
|
||||
"encodings-dialog-contents", &content,
|
||||
"add-button", &dlg->priv->add_button,
|
||||
"remove-button", &dlg->priv->remove_button,
|
||||
"available-treeview", &dlg->priv->available_treeview,
|
||||
"displayed-treeview", &dlg->priv->displayed_treeview,
|
||||
NULL);
|
||||
g_free (file);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
gtk_widget_show (error_widget);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
error_widget,
|
||||
TRUE, TRUE, 0);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (error_widget), 5);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
content, TRUE, TRUE, 0);
|
||||
g_object_unref (content);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
|
||||
|
||||
g_signal_connect (dlg->priv->add_button,
|
||||
"clicked",
|
||||
G_CALLBACK (add_button_clicked_callback),
|
||||
dlg);
|
||||
g_signal_connect (dlg->priv->remove_button,
|
||||
"clicked",
|
||||
G_CALLBACK (remove_button_clicked_callback),
|
||||
dlg);
|
||||
|
||||
/* Tree view of available encodings */
|
||||
dlg->priv->available_liststore = gtk_list_store_new (N_COLUMNS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
cell_renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
|
||||
cell_renderer,
|
||||
"text", COLUMN_NAME,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview),
|
||||
column);
|
||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
|
||||
|
||||
cell_renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
|
||||
cell_renderer,
|
||||
"text",
|
||||
COLUMN_CHARSET,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview),
|
||||
column);
|
||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
|
||||
|
||||
/* Add the data */
|
||||
i = 0;
|
||||
while ((enc = gedit_encoding_get_from_index (i)) != NULL)
|
||||
{
|
||||
gtk_list_store_append (dlg->priv->available_liststore,
|
||||
&parent_iter);
|
||||
gtk_list_store_set (dlg->priv->available_liststore,
|
||||
&parent_iter,
|
||||
COLUMN_CHARSET,
|
||||
gedit_encoding_get_charset (enc),
|
||||
COLUMN_NAME,
|
||||
gedit_encoding_get_name (enc), -1);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Sort model */
|
||||
sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->available_liststore));
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
|
||||
COLUMN_NAME,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->available_treeview),
|
||||
sort_model);
|
||||
g_object_unref (G_OBJECT (dlg->priv->available_liststore));
|
||||
g_object_unref (G_OBJECT (sort_model));
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->available_treeview));
|
||||
gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
|
||||
GTK_SELECTION_MULTIPLE);
|
||||
|
||||
available_selection_changed_callback (selection, dlg);
|
||||
g_signal_connect (selection,
|
||||
"changed",
|
||||
G_CALLBACK (available_selection_changed_callback),
|
||||
dlg);
|
||||
|
||||
/* Tree view of selected encodings */
|
||||
dlg->priv->displayed_liststore = gtk_list_store_new (N_COLUMNS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
cell_renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
|
||||
cell_renderer,
|
||||
"text", COLUMN_NAME,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
|
||||
column);
|
||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
|
||||
|
||||
cell_renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
|
||||
cell_renderer,
|
||||
"text",
|
||||
COLUMN_CHARSET,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
|
||||
column);
|
||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
|
||||
|
||||
/* Add the data */
|
||||
init_shown_in_menu_tree_model (dlg);
|
||||
|
||||
/* Sort model */
|
||||
sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->displayed_liststore));
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE
|
||||
(sort_model), COLUMN_NAME,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
|
||||
sort_model);
|
||||
g_object_unref (G_OBJECT (sort_model));
|
||||
g_object_unref (G_OBJECT (dlg->priv->displayed_liststore));
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->displayed_treeview));
|
||||
gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
|
||||
GTK_SELECTION_MULTIPLE);
|
||||
|
||||
displayed_selection_changed_callback (selection, dlg);
|
||||
g_signal_connect (selection,
|
||||
"changed",
|
||||
G_CALLBACK (displayed_selection_changed_callback),
|
||||
dlg);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_encodings_dialog_new (void)
|
||||
{
|
||||
GtkWidget *dlg;
|
||||
|
||||
dlg = GTK_WIDGET (g_object_new (GEDIT_TYPE_ENCODINGS_DIALOG, NULL));
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
86
gedit/dialogs/gedit-encodings-dialog.h
Executable file
86
gedit/dialogs/gedit-encodings-dialog.h
Executable file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* gedit-encodings-dialog.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_ENCODINGS_DIALOG_H__
|
||||
#define __GEDIT_ENCODINGS_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_ENCODINGS_DIALOG (gedit_encodings_dialog_get_type())
|
||||
#define GEDIT_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialog))
|
||||
#define GEDIT_ENCODINGS_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialog const))
|
||||
#define GEDIT_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialogClass))
|
||||
#define GEDIT_IS_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_ENCODINGS_DIALOG))
|
||||
#define GEDIT_IS_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_ENCODINGS_DIALOG))
|
||||
#define GEDIT_ENCODINGS_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialogClass))
|
||||
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditEncodingsDialogPrivate GeditEncodingsDialogPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditEncodingsDialog GeditEncodingsDialog;
|
||||
|
||||
struct _GeditEncodingsDialog
|
||||
{
|
||||
GtkDialog dialog;
|
||||
|
||||
/*< private > */
|
||||
GeditEncodingsDialogPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditEncodingsDialogClass GeditEncodingsDialogClass;
|
||||
|
||||
struct _GeditEncodingsDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_encodings_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_encodings_dialog_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_ENCODINGS_DIALOG_H__ */
|
||||
|
||||
256
gedit/dialogs/gedit-encodings-dialog.ui
Executable file
256
gedit/dialogs/gedit-encodings-dialog.ui
Executable file
@@ -0,0 +1,256 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--*- mode: xml -*-->
|
||||
<interface>
|
||||
<object class="GtkDialog" id="encodings-dialog">
|
||||
<property name="width_request">650</property>
|
||||
<property name="height_request">400</property>
|
||||
<property name="title" translatable="yes">Character encodings</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area3">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="helpbutton1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-help</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="closebutton1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="encodings-dialog-contents">
|
||||
<property name="border_width">6</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="available-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">A_vailable encodings:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">available-treeview</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="available-treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">True</property>
|
||||
<property name="rules_hint">True</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="add-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-add</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="displayed-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">E_ncodings shown in menu:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">displayed-treeview</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="displayed-treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">True</property>
|
||||
<property name="rules_hint">True</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-remove</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-11">helpbutton1</action-widget>
|
||||
<action-widget response="-6">closebutton1</action-widget>
|
||||
<action-widget response="-5">button1</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
1189
gedit/dialogs/gedit-preferences-dialog.c
Executable file
1189
gedit/dialogs/gedit-preferences-dialog.c
Executable file
File diff suppressed because it is too large
Load Diff
87
gedit/dialogs/gedit-preferences-dialog.h
Executable file
87
gedit/dialogs/gedit-preferences-dialog.h
Executable file
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-preferences-dialog.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2001-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PREFERENCES_DIALOG_H__
|
||||
#define __GEDIT_PREFERENCES_DIALOG_H__
|
||||
|
||||
#include "gedit-window.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_PREFERENCES_DIALOG (gedit_preferences_dialog_get_type())
|
||||
#define GEDIT_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialog))
|
||||
#define GEDIT_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialog const))
|
||||
#define GEDIT_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialogClass))
|
||||
#define GEDIT_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PREFERENCES_DIALOG))
|
||||
#define GEDIT_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PREFERENCES_DIALOG))
|
||||
#define GEDIT_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialogClass))
|
||||
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditPreferencesDialogPrivate GeditPreferencesDialogPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditPreferencesDialog GeditPreferencesDialog;
|
||||
|
||||
struct _GeditPreferencesDialog
|
||||
{
|
||||
GtkDialog dialog;
|
||||
|
||||
/*< private > */
|
||||
GeditPreferencesDialogPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditPreferencesDialogClass GeditPreferencesDialogClass;
|
||||
|
||||
struct _GeditPreferencesDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_preferences_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gedit_show_preferences_dialog (GeditWindow *parent);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PREFERENCES_DIALOG_H__ */
|
||||
|
||||
1107
gedit/dialogs/gedit-preferences-dialog.ui
Executable file
1107
gedit/dialogs/gedit-preferences-dialog.ui
Executable file
File diff suppressed because it is too large
Load Diff
634
gedit/dialogs/gedit-search-dialog.c
Executable file
634
gedit/dialogs/gedit-search-dialog.c
Executable file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* gedit-search-dialog.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "gedit-search-dialog.h"
|
||||
#include "gedit-history-entry.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-marshal.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
#define GEDIT_SEARCH_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_SEARCH_DIALOG, \
|
||||
GeditSearchDialogPrivate))
|
||||
|
||||
/* Signals */
|
||||
enum
|
||||
{
|
||||
SHOW_REPLACE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint dialog_signals [LAST_SIGNAL] = { 0 };
|
||||
|
||||
struct _GeditSearchDialogPrivate
|
||||
{
|
||||
gboolean show_replace;
|
||||
|
||||
GtkWidget *table;
|
||||
GtkWidget *search_label;
|
||||
GtkWidget *search_entry;
|
||||
GtkWidget *search_text_entry;
|
||||
GtkWidget *replace_label;
|
||||
GtkWidget *replace_entry;
|
||||
GtkWidget *replace_text_entry;
|
||||
GtkWidget *match_case_checkbutton;
|
||||
GtkWidget *entire_word_checkbutton;
|
||||
GtkWidget *backwards_checkbutton;
|
||||
GtkWidget *wrap_around_checkbutton;
|
||||
GtkWidget *find_button;
|
||||
GtkWidget *replace_button;
|
||||
GtkWidget *replace_all_button;
|
||||
|
||||
gboolean ui_error;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditSearchDialog, gedit_search_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SHOW_REPLACE
|
||||
};
|
||||
|
||||
static void
|
||||
gedit_search_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditSearchDialog *dlg = GEDIT_SEARCH_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHOW_REPLACE:
|
||||
gedit_search_dialog_set_show_replace (dlg,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_search_dialog_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditSearchDialog *dlg = GEDIT_SEARCH_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHOW_REPLACE:
|
||||
g_value_set_boolean (value, dlg->priv->show_replace);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_present_with_time (GeditSearchDialog *dialog,
|
||||
guint32 timestamp)
|
||||
{
|
||||
g_return_if_fail (GEDIT_SEARCH_DIALOG (dialog));
|
||||
|
||||
gtk_window_present_with_time (GTK_WINDOW (dialog), timestamp);
|
||||
|
||||
gtk_widget_grab_focus (dialog->priv->search_text_entry);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_replace (GeditSearchDialog *dlg)
|
||||
{
|
||||
gedit_search_dialog_set_show_replace (dlg, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_search_dialog_class_init (GeditSearchDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkBindingSet *binding_set;
|
||||
|
||||
object_class->set_property = gedit_search_dialog_set_property;
|
||||
object_class->get_property = gedit_search_dialog_get_property;
|
||||
|
||||
klass->show_replace = show_replace;
|
||||
|
||||
dialog_signals[SHOW_REPLACE] =
|
||||
g_signal_new ("show_replace",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GeditSearchDialogClass, show_replace),
|
||||
NULL, NULL,
|
||||
gedit_marshal_BOOLEAN__NONE,
|
||||
G_TYPE_BOOLEAN, 0);
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SHOW_REPLACE,
|
||||
g_param_spec_boolean ("show-replace",
|
||||
"Show Replace",
|
||||
"Whether the dialog is used for Search&Replace",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditSearchDialogPrivate));
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
/* Note: we cannot use the keyval/modifier associated with the
|
||||
* GTK_STOCK_FIND_AND_REPLACE stock item since MATE HIG suggests Ctrl+h
|
||||
* for Replace while gtk+ uses Ctrl+r */
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_h, GDK_CONTROL_MASK, "show_replace", 0);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_H, GDK_CONTROL_MASK, "show_replace", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_text_handler (GtkEditable *editable,
|
||||
const gchar *text,
|
||||
gint length,
|
||||
gint *position,
|
||||
gpointer data)
|
||||
{
|
||||
static gboolean insert_text = FALSE;
|
||||
gchar *escaped_text;
|
||||
gint new_len;
|
||||
|
||||
/* To avoid recursive behavior */
|
||||
if (insert_text)
|
||||
return;
|
||||
|
||||
escaped_text = gedit_utils_escape_search_text (text);
|
||||
|
||||
new_len = strlen (escaped_text);
|
||||
|
||||
if (new_len == length)
|
||||
{
|
||||
g_free (escaped_text);
|
||||
return;
|
||||
}
|
||||
|
||||
insert_text = TRUE;
|
||||
|
||||
g_signal_stop_emission_by_name (editable, "insert_text");
|
||||
|
||||
gtk_editable_insert_text (editable, escaped_text, new_len, position);
|
||||
|
||||
insert_text = FALSE;
|
||||
|
||||
g_free (escaped_text);
|
||||
}
|
||||
|
||||
static void
|
||||
search_text_entry_changed (GtkEditable *editable,
|
||||
GeditSearchDialog *dialog)
|
||||
{
|
||||
const gchar *search_string;
|
||||
|
||||
search_string = gtk_entry_get_text (GTK_ENTRY (editable));
|
||||
g_return_if_fail (search_string != NULL);
|
||||
|
||||
if (*search_string != '\0')
|
||||
{
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE, TRUE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE, FALSE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, FALSE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
response_handler (GeditSearchDialog *dialog,
|
||||
gint response_id,
|
||||
gpointer data)
|
||||
{
|
||||
const gchar *str;
|
||||
|
||||
switch (response_id)
|
||||
{
|
||||
case GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE:
|
||||
case GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE:
|
||||
str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_text_entry));
|
||||
if (*str != '\0')
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
text = gedit_utils_unescape_search_text (str);
|
||||
gedit_history_entry_prepend_text
|
||||
(GEDIT_HISTORY_ENTRY (dialog->priv->replace_entry),
|
||||
text);
|
||||
|
||||
g_free (text);
|
||||
}
|
||||
/* fall through, so that we also save the find entry */
|
||||
case GEDIT_SEARCH_DIALOG_FIND_RESPONSE:
|
||||
str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_text_entry));
|
||||
if (*str != '\0')
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
text = gedit_utils_unescape_search_text (str);
|
||||
gedit_history_entry_prepend_text
|
||||
(GEDIT_HISTORY_ENTRY (dialog->priv->search_entry),
|
||||
text);
|
||||
|
||||
g_free (text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_replace_widgets (GeditSearchDialog *dlg,
|
||||
gboolean show_replace)
|
||||
{
|
||||
if (show_replace)
|
||||
{
|
||||
gtk_widget_show (dlg->priv->replace_label);
|
||||
gtk_widget_show (dlg->priv->replace_entry);
|
||||
gtk_widget_show (dlg->priv->replace_all_button);
|
||||
gtk_widget_show (dlg->priv->replace_button);
|
||||
|
||||
gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 12);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), _("Replace"));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (dlg->priv->replace_label);
|
||||
gtk_widget_hide (dlg->priv->replace_entry);
|
||||
gtk_widget_hide (dlg->priv->replace_all_button);
|
||||
gtk_widget_hide (dlg->priv->replace_button);
|
||||
|
||||
gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 0);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), _("Find"));
|
||||
}
|
||||
|
||||
gtk_widget_show (dlg->priv->find_button);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_search_dialog_init (GeditSearchDialog *dlg)
|
||||
{
|
||||
GtkWidget *content;
|
||||
GtkWidget *error_widget;
|
||||
gboolean ret;
|
||||
gchar *file;
|
||||
gchar *root_objects[] = {
|
||||
"search_dialog_content",
|
||||
NULL
|
||||
};
|
||||
|
||||
dlg->priv = GEDIT_SEARCH_DIALOG_GET_PRIVATE (dlg);
|
||||
|
||||
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
|
||||
gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE);
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
|
||||
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
|
||||
NULL);
|
||||
|
||||
/* HIG defaults */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
2); /* 2 * 5 + 2 = 12 */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
|
||||
5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
|
||||
6);
|
||||
|
||||
file = gedit_dirs_get_ui_file ("gedit-search-dialog.ui");
|
||||
ret = gedit_utils_get_ui_objects (file,
|
||||
root_objects,
|
||||
&error_widget,
|
||||
"search_dialog_content", &content,
|
||||
"table", &dlg->priv->table,
|
||||
"search_label", &dlg->priv->search_label,
|
||||
"replace_with_label", &dlg->priv->replace_label,
|
||||
"match_case_checkbutton", &dlg->priv->match_case_checkbutton,
|
||||
"entire_word_checkbutton", &dlg->priv->entire_word_checkbutton,
|
||||
"search_backwards_checkbutton", &dlg->priv->backwards_checkbutton,
|
||||
"wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton,
|
||||
NULL);
|
||||
g_free (file);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
gtk_widget_show (error_widget);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
error_widget,
|
||||
TRUE, TRUE, 0);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (error_widget),
|
||||
5);
|
||||
|
||||
dlg->priv->ui_error = TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dlg->priv->search_entry = gedit_history_entry_new ("gedit2_search_for_entry",
|
||||
TRUE);
|
||||
gtk_widget_set_size_request (dlg->priv->search_entry, 300, -1);
|
||||
gedit_history_entry_set_escape_func
|
||||
(GEDIT_HISTORY_ENTRY (dlg->priv->search_entry),
|
||||
(GeditHistoryEntryEscapeFunc) gedit_utils_escape_search_text);
|
||||
|
||||
dlg->priv->search_text_entry = gedit_history_entry_get_entry
|
||||
(GEDIT_HISTORY_ENTRY (dlg->priv->search_entry));
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (dlg->priv->search_text_entry),
|
||||
TRUE);
|
||||
gtk_widget_show (dlg->priv->search_entry);
|
||||
gtk_table_attach_defaults (GTK_TABLE (dlg->priv->table),
|
||||
dlg->priv->search_entry,
|
||||
1, 2, 0, 1);
|
||||
|
||||
dlg->priv->replace_entry = gedit_history_entry_new ("gedit2_replace_with_entry",
|
||||
TRUE);
|
||||
gedit_history_entry_set_escape_func
|
||||
(GEDIT_HISTORY_ENTRY (dlg->priv->replace_entry),
|
||||
(GeditHistoryEntryEscapeFunc) gedit_utils_escape_search_text);
|
||||
|
||||
dlg->priv->replace_text_entry = gedit_history_entry_get_entry
|
||||
(GEDIT_HISTORY_ENTRY (dlg->priv->replace_entry));
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (dlg->priv->replace_text_entry),
|
||||
TRUE);
|
||||
gtk_widget_show (dlg->priv->replace_entry);
|
||||
gtk_table_attach_defaults (GTK_TABLE (dlg->priv->table),
|
||||
dlg->priv->replace_entry,
|
||||
1, 2, 1, 2);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->search_label),
|
||||
dlg->priv->search_entry);
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->replace_label),
|
||||
dlg->priv->replace_entry);
|
||||
|
||||
dlg->priv->find_button = gtk_button_new_from_stock (GTK_STOCK_FIND);
|
||||
dlg->priv->replace_all_button = gtk_button_new_with_mnemonic (_("Replace _All"));
|
||||
dlg->priv->replace_button = gedit_gtk_button_new_with_stock_icon (_("_Replace"),
|
||||
GTK_STOCK_FIND_AND_REPLACE);
|
||||
|
||||
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
|
||||
dlg->priv->replace_all_button,
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE);
|
||||
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
|
||||
dlg->priv->replace_button,
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE);
|
||||
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
|
||||
dlg->priv->find_button,
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE);
|
||||
g_object_set (G_OBJECT (dlg->priv->find_button),
|
||||
"can-default", TRUE,
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE);
|
||||
|
||||
/* insensitive by default */
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE,
|
||||
FALSE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
|
||||
FALSE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE,
|
||||
FALSE);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
content, FALSE, FALSE, 0);
|
||||
g_object_unref (content);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
|
||||
|
||||
g_signal_connect (dlg->priv->search_text_entry,
|
||||
"insert_text",
|
||||
G_CALLBACK (insert_text_handler),
|
||||
NULL);
|
||||
g_signal_connect (dlg->priv->replace_text_entry,
|
||||
"insert_text",
|
||||
G_CALLBACK (insert_text_handler),
|
||||
NULL);
|
||||
g_signal_connect (dlg->priv->search_text_entry,
|
||||
"changed",
|
||||
G_CALLBACK (search_text_entry_changed),
|
||||
dlg);
|
||||
|
||||
g_signal_connect (dlg,
|
||||
"response",
|
||||
G_CALLBACK (response_handler),
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_search_dialog_new (GtkWindow *parent,
|
||||
gboolean show_replace)
|
||||
{
|
||||
GeditSearchDialog *dlg;
|
||||
|
||||
dlg = g_object_new (GEDIT_TYPE_SEARCH_DIALOG,
|
||||
"show-replace", show_replace,
|
||||
NULL);
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dlg),
|
||||
parent);
|
||||
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg),
|
||||
TRUE);
|
||||
}
|
||||
|
||||
return GTK_WIDGET (dlg);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_search_dialog_get_show_replace (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
|
||||
|
||||
return dialog->priv->show_replace;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_show_replace (GeditSearchDialog *dialog,
|
||||
gboolean show_replace)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
|
||||
if (dialog->priv->ui_error)
|
||||
return;
|
||||
|
||||
dialog->priv->show_replace = show_replace != FALSE;
|
||||
show_replace_widgets (dialog, dialog->priv->show_replace);
|
||||
|
||||
g_object_notify (G_OBJECT (dialog), "show-replace");
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_search_text (GeditSearchDialog *dialog,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (dialog->priv->search_text_entry),
|
||||
text);
|
||||
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE,
|
||||
(text != '\0'));
|
||||
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE,
|
||||
(text != '\0'));
|
||||
}
|
||||
|
||||
/*
|
||||
* The text must be unescaped before searching.
|
||||
*/
|
||||
const gchar *
|
||||
gedit_search_dialog_get_search_text (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), NULL);
|
||||
|
||||
return gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_text_entry));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_replace_text (GeditSearchDialog *dialog,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (dialog->priv->replace_text_entry),
|
||||
text);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_search_dialog_get_replace_text (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), NULL);
|
||||
|
||||
return gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_text_entry));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_match_case (GeditSearchDialog *dialog,
|
||||
gboolean match_case)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton),
|
||||
match_case);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_search_dialog_get_match_case (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
|
||||
|
||||
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_entire_word (GeditSearchDialog *dialog,
|
||||
gboolean entire_word)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton),
|
||||
entire_word);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_search_dialog_get_entire_word (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
|
||||
|
||||
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_backwards (GeditSearchDialog *dialog,
|
||||
gboolean backwards)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton),
|
||||
backwards);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_search_dialog_get_backwards (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
|
||||
|
||||
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_search_dialog_set_wrap_around (GeditSearchDialog *dialog,
|
||||
gboolean wrap_around)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog));
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton),
|
||||
wrap_around);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_search_dialog_get_wrap_around (GeditSearchDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
|
||||
|
||||
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton));
|
||||
}
|
||||
128
gedit/dialogs/gedit-search-dialog.h
Executable file
128
gedit/dialogs/gedit-search-dialog.h
Executable file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* gedit-search-dialog.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_SEARCH_DIALOG_H__
|
||||
#define __GEDIT_SEARCH_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_SEARCH_DIALOG (gedit_search_dialog_get_type())
|
||||
#define GEDIT_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialog))
|
||||
#define GEDIT_SEARCH_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialog const))
|
||||
#define GEDIT_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialogClass))
|
||||
#define GEDIT_IS_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_SEARCH_DIALOG))
|
||||
#define GEDIT_IS_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_SEARCH_DIALOG))
|
||||
#define GEDIT_SEARCH_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialogClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditSearchDialogPrivate GeditSearchDialogPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditSearchDialog GeditSearchDialog;
|
||||
|
||||
struct _GeditSearchDialog
|
||||
{
|
||||
GtkDialog dialog;
|
||||
|
||||
/*< private > */
|
||||
GeditSearchDialogPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditSearchDialogClass GeditSearchDialogClass;
|
||||
|
||||
struct _GeditSearchDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
|
||||
/* Key bindings */
|
||||
gboolean (* show_replace) (GeditSearchDialog *dlg);
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GEDIT_SEARCH_DIALOG_FIND_RESPONSE = 100,
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_search_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_search_dialog_new (GtkWindow *parent,
|
||||
gboolean show_replace);
|
||||
|
||||
void gedit_search_dialog_present_with_time (GeditSearchDialog *dialog,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean gedit_search_dialog_get_show_replace (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_show_replace (GeditSearchDialog *dialog,
|
||||
gboolean show_replace);
|
||||
|
||||
|
||||
void gedit_search_dialog_set_search_text (GeditSearchDialog *dialog,
|
||||
const gchar *text);
|
||||
const gchar *gedit_search_dialog_get_search_text (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_replace_text (GeditSearchDialog *dialog,
|
||||
const gchar *text);
|
||||
const gchar *gedit_search_dialog_get_replace_text (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_match_case (GeditSearchDialog *dialog,
|
||||
gboolean match_case);
|
||||
gboolean gedit_search_dialog_get_match_case (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_entire_word (GeditSearchDialog *dialog,
|
||||
gboolean entire_word);
|
||||
gboolean gedit_search_dialog_get_entire_word (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_backwards (GeditSearchDialog *dialog,
|
||||
gboolean backwards);
|
||||
gboolean gedit_search_dialog_get_backwards (GeditSearchDialog *dialog);
|
||||
|
||||
void gedit_search_dialog_set_wrap_around (GeditSearchDialog *dialog,
|
||||
gboolean wrap_around);
|
||||
gboolean gedit_search_dialog_get_wrap_around (GeditSearchDialog *dialog);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_SEARCH_DIALOG_H__ */
|
||||
255
gedit/dialogs/gedit-search-dialog.ui
Executable file
255
gedit/dialogs/gedit-search-dialog.ui
Executable file
@@ -0,0 +1,255 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--*- mode: xml -*-->
|
||||
<interface>
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="title" translatable="yes">Replace</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||
<property name="modal">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="destroy_with_parent">False</property>
|
||||
<property name="decorated">True</property>
|
||||
<property name="skip_taskbar_hint">False</property>
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="urgency_hint">False</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">8</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="replace_all_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Replace All</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="replace_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Replace</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="find_next_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-find</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="search_dialog_content">
|
||||
<property name="border_width">5</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="row_spacing">12</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="search_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Search for: </property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="replace_with_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Replace _with: </property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="match_case_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_Match case</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="entire_word_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Match _entire word only</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="search_backwards_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Search _backwards</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wrap_around_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_Wrap around</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">True</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="0">close_button</action-widget>
|
||||
<action-widget response="0">replace_all_button</action-widget>
|
||||
<action-widget response="0">replace_button</action-widget>
|
||||
<action-widget response="0">find_next_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
911
gedit/gedit-app.c
Executable file
911
gedit/gedit-app.c
Executable file
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* gedit-app.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005-2006 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-app.h"
|
||||
#include "gedit-prefs-manager-app.h"
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-notebook.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-enum-types.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
#ifdef OS_OSX
|
||||
#include <ige-mac-integration.h>
|
||||
#endif
|
||||
|
||||
#define GEDIT_PAGE_SETUP_FILE "gedit-page-setup"
|
||||
#define GEDIT_PRINT_SETTINGS_FILE "gedit-print-settings"
|
||||
|
||||
#define GEDIT_APP_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_APP, GeditAppPrivate))
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_LOCKDOWN
|
||||
};
|
||||
|
||||
struct _GeditAppPrivate
|
||||
{
|
||||
GList *windows;
|
||||
GeditWindow *active_window;
|
||||
|
||||
GeditLockdownMask lockdown;
|
||||
|
||||
GtkPageSetup *page_setup;
|
||||
GtkPrintSettings *print_settings;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditApp, gedit_app, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gedit_app_finalize (GObject *object)
|
||||
{
|
||||
GeditApp *app = GEDIT_APP (object);
|
||||
|
||||
g_list_free (app->priv->windows);
|
||||
|
||||
if (app->priv->page_setup)
|
||||
g_object_unref (app->priv->page_setup);
|
||||
if (app->priv->print_settings)
|
||||
g_object_unref (app->priv->print_settings);
|
||||
|
||||
G_OBJECT_CLASS (gedit_app_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_app_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditApp *app = GEDIT_APP (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LOCKDOWN:
|
||||
g_value_set_flags (value, gedit_app_get_lockdown (app));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_app_class_init (GeditAppClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_app_finalize;
|
||||
object_class->get_property = gedit_app_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LOCKDOWN,
|
||||
g_param_spec_flags ("lockdown",
|
||||
"Lockdown",
|
||||
"The lockdown mask",
|
||||
GEDIT_TYPE_LOCKDOWN_MASK,
|
||||
0,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditAppPrivate));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_user_config_dir (void)
|
||||
{
|
||||
gchar *config_dir;
|
||||
gboolean ret = TRUE;
|
||||
gint res;
|
||||
|
||||
config_dir = gedit_dirs_get_user_config_dir ();
|
||||
if (config_dir == NULL)
|
||||
{
|
||||
g_warning ("Could not get config directory\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = g_mkdir_with_parents (config_dir, 0755);
|
||||
if (res < 0)
|
||||
{
|
||||
g_warning ("Could not create config directory\n");
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
g_free (config_dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
load_accels (void)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
filename = gedit_dirs_get_user_accels_file ();
|
||||
if (filename != NULL)
|
||||
{
|
||||
gedit_debug_message (DEBUG_APP, "Loading keybindings from %s\n", filename);
|
||||
gtk_accel_map_load (filename);
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
save_accels (void)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
filename = gedit_dirs_get_user_accels_file ();
|
||||
if (filename != NULL)
|
||||
{
|
||||
gedit_debug_message (DEBUG_APP, "Saving keybindings in %s\n", filename);
|
||||
gtk_accel_map_save (filename);
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_page_setup_file (void)
|
||||
{
|
||||
gchar *config_dir;
|
||||
gchar *setup = NULL;
|
||||
|
||||
config_dir = gedit_dirs_get_user_config_dir ();
|
||||
|
||||
if (config_dir != NULL)
|
||||
{
|
||||
setup = g_build_filename (config_dir,
|
||||
GEDIT_PAGE_SETUP_FILE,
|
||||
NULL);
|
||||
g_free (config_dir);
|
||||
}
|
||||
|
||||
return setup;
|
||||
}
|
||||
|
||||
static void
|
||||
load_page_setup (GeditApp *app)
|
||||
{
|
||||
gchar *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (app->priv->page_setup == NULL);
|
||||
|
||||
filename = get_page_setup_file ();
|
||||
|
||||
app->priv->page_setup = gtk_page_setup_new_from_file (filename,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
/* Ignore file not found error */
|
||||
if (error->domain != G_FILE_ERROR ||
|
||||
error->code != G_FILE_ERROR_NOENT)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
}
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
|
||||
/* fall back to default settings */
|
||||
if (app->priv->page_setup == NULL)
|
||||
app->priv->page_setup = gtk_page_setup_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
save_page_setup (GeditApp *app)
|
||||
{
|
||||
gchar *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
if (app->priv->page_setup == NULL)
|
||||
return;
|
||||
|
||||
filename = get_page_setup_file ();
|
||||
|
||||
gtk_page_setup_to_file (app->priv->page_setup,
|
||||
filename,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_print_settings_file (void)
|
||||
{
|
||||
gchar *config_dir;
|
||||
gchar *settings = NULL;
|
||||
|
||||
config_dir = gedit_dirs_get_user_config_dir ();
|
||||
|
||||
if (config_dir != NULL)
|
||||
{
|
||||
settings = g_build_filename (config_dir,
|
||||
GEDIT_PRINT_SETTINGS_FILE,
|
||||
NULL);
|
||||
g_free (config_dir);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static void
|
||||
load_print_settings (GeditApp *app)
|
||||
{
|
||||
gchar *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (app->priv->print_settings == NULL);
|
||||
|
||||
filename = get_print_settings_file ();
|
||||
|
||||
app->priv->print_settings = gtk_print_settings_new_from_file (filename,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
/* Ignore file not found error */
|
||||
if (error->domain != G_FILE_ERROR ||
|
||||
error->code != G_FILE_ERROR_NOENT)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
}
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
|
||||
/* fall back to default settings */
|
||||
if (app->priv->print_settings == NULL)
|
||||
app->priv->print_settings = gtk_print_settings_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
save_print_settings (GeditApp *app)
|
||||
{
|
||||
gchar *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
if (app->priv->print_settings == NULL)
|
||||
return;
|
||||
|
||||
filename = get_print_settings_file ();
|
||||
|
||||
gtk_print_settings_to_file (app->priv->print_settings,
|
||||
filename,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_app_init (GeditApp *app)
|
||||
{
|
||||
app->priv = GEDIT_APP_GET_PRIVATE (app);
|
||||
|
||||
load_accels ();
|
||||
|
||||
/* initial lockdown state */
|
||||
app->priv->lockdown = gedit_prefs_manager_get_lockdown ();
|
||||
}
|
||||
|
||||
static void
|
||||
app_weak_notify (gpointer data,
|
||||
GObject *where_the_app_was)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_default:
|
||||
*
|
||||
* Returns the #GeditApp object. This object is a singleton and
|
||||
* represents the running gedit instance.
|
||||
*
|
||||
* Return value: the #GeditApp pointer
|
||||
*/
|
||||
GeditApp *
|
||||
gedit_app_get_default (void)
|
||||
{
|
||||
static GeditApp *app = NULL;
|
||||
|
||||
if (app != NULL)
|
||||
return app;
|
||||
|
||||
app = GEDIT_APP (g_object_new (GEDIT_TYPE_APP, NULL));
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (app),
|
||||
(gpointer) &app);
|
||||
g_object_weak_ref (G_OBJECT (app),
|
||||
app_weak_notify,
|
||||
NULL);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
static void
|
||||
set_active_window (GeditApp *app,
|
||||
GeditWindow *window)
|
||||
{
|
||||
app->priv->active_window = window;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_focus_in_event (GeditWindow *window,
|
||||
GdkEventFocus *event,
|
||||
GeditApp *app)
|
||||
{
|
||||
/* updates active_view and active_child when a new toplevel receives focus */
|
||||
g_return_val_if_fail (GEDIT_IS_WINDOW (window), FALSE);
|
||||
|
||||
set_active_window (app, window);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_delete_event (GeditWindow *window,
|
||||
GdkEvent *event,
|
||||
GeditApp *app)
|
||||
{
|
||||
GeditWindowState ws;
|
||||
|
||||
ws = gedit_window_get_state (window);
|
||||
|
||||
if (ws &
|
||||
(GEDIT_WINDOW_STATE_SAVING |
|
||||
GEDIT_WINDOW_STATE_PRINTING |
|
||||
GEDIT_WINDOW_STATE_SAVING_SESSION))
|
||||
return TRUE;
|
||||
|
||||
_gedit_cmd_file_quit (NULL, window);
|
||||
|
||||
/* Do not destroy the window */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
window_destroy (GeditWindow *window,
|
||||
GeditApp *app)
|
||||
{
|
||||
app->priv->windows = g_list_remove (app->priv->windows,
|
||||
window);
|
||||
|
||||
if (window == app->priv->active_window)
|
||||
{
|
||||
set_active_window (app, app->priv->windows != NULL ? app->priv->windows->data : NULL);
|
||||
}
|
||||
|
||||
/* CHECK: I don't think we have to disconnect this function, since windows
|
||||
is being destroyed */
|
||||
/*
|
||||
g_signal_handlers_disconnect_by_func (window,
|
||||
G_CALLBACK (window_focus_in_event),
|
||||
app);
|
||||
g_signal_handlers_disconnect_by_func (window,
|
||||
G_CALLBACK (window_destroy),
|
||||
app);
|
||||
*/
|
||||
if (app->priv->windows == NULL)
|
||||
{
|
||||
#ifdef OS_OSX
|
||||
if (!GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "gedit-is-quitting-all")))
|
||||
{
|
||||
/* Create hidden proxy window on OS X to handle the menu */
|
||||
gedit_app_create_window (app, NULL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* Last window is gone... save some settings and exit */
|
||||
ensure_user_config_dir ();
|
||||
|
||||
save_accels ();
|
||||
save_page_setup (app);
|
||||
save_print_settings (app);
|
||||
|
||||
g_object_unref (app);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates a unique string for a window role */
|
||||
static gchar *
|
||||
gen_role (void)
|
||||
{
|
||||
GTimeVal result;
|
||||
static gint serial;
|
||||
|
||||
g_get_current_time (&result);
|
||||
|
||||
return g_strdup_printf ("gedit-window-%ld-%ld-%d-%s",
|
||||
result.tv_sec,
|
||||
result.tv_usec,
|
||||
serial++,
|
||||
g_get_host_name ());
|
||||
}
|
||||
|
||||
static GeditWindow *
|
||||
gedit_app_create_window_real (GeditApp *app,
|
||||
gboolean set_geometry,
|
||||
const gchar *role)
|
||||
{
|
||||
GeditWindow *window;
|
||||
|
||||
gedit_debug (DEBUG_APP);
|
||||
|
||||
/*
|
||||
* We need to be careful here, there is a race condition:
|
||||
* when another gedit is launched it checks active_window,
|
||||
* so we must do our best to ensure that active_window
|
||||
* is never NULL when at least a window exists.
|
||||
*/
|
||||
if (app->priv->windows == NULL)
|
||||
{
|
||||
window = g_object_new (GEDIT_TYPE_WINDOW, NULL);
|
||||
set_active_window (app, window);
|
||||
}
|
||||
else
|
||||
{
|
||||
window = g_object_new (GEDIT_TYPE_WINDOW, NULL);
|
||||
}
|
||||
|
||||
app->priv->windows = g_list_prepend (app->priv->windows,
|
||||
window);
|
||||
|
||||
gedit_debug_message (DEBUG_APP, "Window created");
|
||||
|
||||
if (role != NULL)
|
||||
{
|
||||
gtk_window_set_role (GTK_WINDOW (window), role);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *newrole;
|
||||
|
||||
newrole = gen_role ();
|
||||
gtk_window_set_role (GTK_WINDOW (window), newrole);
|
||||
g_free (newrole);
|
||||
}
|
||||
|
||||
if (set_geometry)
|
||||
{
|
||||
GdkWindowState state;
|
||||
gint w, h;
|
||||
|
||||
state = gedit_prefs_manager_get_window_state ();
|
||||
|
||||
if ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
|
||||
{
|
||||
gedit_prefs_manager_get_default_window_size (&w, &h);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), w, h);
|
||||
gtk_window_maximize (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
gedit_prefs_manager_get_window_size (&w, &h);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), w, h);
|
||||
gtk_window_unmaximize (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
if ((state & GDK_WINDOW_STATE_STICKY ) != 0)
|
||||
gtk_window_stick (GTK_WINDOW (window));
|
||||
else
|
||||
gtk_window_unstick (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
g_signal_connect (window,
|
||||
"focus_in_event",
|
||||
G_CALLBACK (window_focus_in_event),
|
||||
app);
|
||||
g_signal_connect (window,
|
||||
"delete_event",
|
||||
G_CALLBACK (window_delete_event),
|
||||
app);
|
||||
g_signal_connect (window,
|
||||
"destroy",
|
||||
G_CALLBACK (window_destroy),
|
||||
app);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_create_window:
|
||||
* @app: the #GeditApp
|
||||
*
|
||||
* Create a new #GeditWindow part of @app.
|
||||
*
|
||||
* Return value: the new #GeditWindow
|
||||
*/
|
||||
GeditWindow *
|
||||
gedit_app_create_window (GeditApp *app,
|
||||
GdkScreen *screen)
|
||||
{
|
||||
GeditWindow *window;
|
||||
|
||||
window = gedit_app_create_window_real (app, TRUE, NULL);
|
||||
|
||||
if (screen != NULL)
|
||||
gtk_window_set_screen (GTK_WINDOW (window), screen);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as _create_window, but doesn't set the geometry.
|
||||
* The session manager takes care of it. Used in mate-session.
|
||||
*/
|
||||
GeditWindow *
|
||||
_gedit_app_restore_window (GeditApp *app,
|
||||
const gchar *role)
|
||||
{
|
||||
GeditWindow *window;
|
||||
|
||||
window = gedit_app_create_window_real (app, FALSE, role);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_windows:
|
||||
* @app: the #GeditApp
|
||||
*
|
||||
* Returns all the windows currently present in #GeditApp.
|
||||
*
|
||||
* Return value: the list of #GeditWindows objects. The list
|
||||
* should not be freed
|
||||
*/
|
||||
const GList *
|
||||
gedit_app_get_windows (GeditApp *app)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
return app->priv->windows;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_active_window:
|
||||
* @app: the #GeditApp
|
||||
*
|
||||
* Retrives the #GeditWindow currently active.
|
||||
*
|
||||
* Return value: the active #GeditWindow
|
||||
*/
|
||||
GeditWindow *
|
||||
gedit_app_get_active_window (GeditApp *app)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
/* make sure our active window is always realized:
|
||||
* this is needed on startup if we launch two gedit fast
|
||||
* enough that the second instance comes up before the
|
||||
* first one shows its window.
|
||||
*/
|
||||
if (!GTK_WIDGET_REALIZED (GTK_WIDGET (app->priv->active_window)))
|
||||
gtk_widget_realize (GTK_WIDGET (app->priv->active_window));
|
||||
|
||||
return app->priv->active_window;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_in_viewport (GeditWindow *window,
|
||||
GdkScreen *screen,
|
||||
gint workspace,
|
||||
gint viewport_x,
|
||||
gint viewport_y)
|
||||
{
|
||||
GdkScreen *s;
|
||||
GdkDisplay *display;
|
||||
GdkWindow *gdkwindow;
|
||||
const gchar *cur_name;
|
||||
const gchar *name;
|
||||
gint cur_n;
|
||||
gint n;
|
||||
gint ws;
|
||||
gint sc_width, sc_height;
|
||||
gint x, y, width, height;
|
||||
gint vp_x, vp_y;
|
||||
|
||||
/* Check for screen and display match */
|
||||
display = gdk_screen_get_display (screen);
|
||||
cur_name = gdk_display_get_name (display);
|
||||
cur_n = gdk_screen_get_number (screen);
|
||||
|
||||
s = gtk_window_get_screen (GTK_WINDOW (window));
|
||||
display = gdk_screen_get_display (s);
|
||||
name = gdk_display_get_name (display);
|
||||
n = gdk_screen_get_number (s);
|
||||
|
||||
if (strcmp (cur_name, name) != 0 || cur_n != n)
|
||||
return FALSE;
|
||||
|
||||
/* Check for workspace match */
|
||||
ws = gedit_utils_get_window_workspace (GTK_WINDOW (window));
|
||||
if (ws != workspace && ws != GEDIT_ALL_WORKSPACES)
|
||||
return FALSE;
|
||||
|
||||
/* Check for viewport match */
|
||||
gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
|
||||
gdk_window_get_position (gdkwindow, &x, &y);
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
width = gdk_window_get_width(gdkwindow);
|
||||
height = gdk_window_get_height(gdkwindow);
|
||||
#else
|
||||
gdk_drawable_get_size(gdkwindow, &width, &height);
|
||||
#endif
|
||||
|
||||
gedit_utils_get_current_viewport (screen, &vp_x, &vp_y);
|
||||
x += vp_x;
|
||||
y += vp_y;
|
||||
|
||||
sc_width = gdk_screen_get_width (screen);
|
||||
sc_height = gdk_screen_get_height (screen);
|
||||
|
||||
return x + width * .25 >= viewport_x &&
|
||||
x + width * .75 <= viewport_x + sc_width &&
|
||||
y >= viewport_y &&
|
||||
y + height <= viewport_y + sc_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gedit_app_get_window_in_viewport
|
||||
* @app: the #GeditApp
|
||||
* @screen: the #GdkScreen
|
||||
* @workspace: the workspace number
|
||||
* @viewport_x: the viewport horizontal origin
|
||||
* @viewport_y: the viewport vertical origin
|
||||
*
|
||||
* Since a workspace can be larger than the screen, it is divided into several
|
||||
* equal parts called viewports. This function retrives the #GeditWindow in
|
||||
* the given viewport of the given workspace.
|
||||
*
|
||||
* Return value: the #GeditWindow in the given viewport of the given workspace.
|
||||
*/
|
||||
GeditWindow *
|
||||
_gedit_app_get_window_in_viewport (GeditApp *app,
|
||||
GdkScreen *screen,
|
||||
gint workspace,
|
||||
gint viewport_x,
|
||||
gint viewport_y)
|
||||
{
|
||||
GeditWindow *window;
|
||||
|
||||
GList *l;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
/* first try if the active window */
|
||||
window = app->priv->active_window;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
|
||||
|
||||
if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
|
||||
return window;
|
||||
|
||||
/* otherwise try to see if there is a window on this workspace */
|
||||
for (l = app->priv->windows; l != NULL; l = l->next)
|
||||
{
|
||||
window = l->data;
|
||||
|
||||
if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
|
||||
return window;
|
||||
}
|
||||
|
||||
/* no window on this workspace... create a new one */
|
||||
return gedit_app_create_window (app, screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_documents:
|
||||
* @app: the #GeditApp
|
||||
*
|
||||
* Returns all the documents currently open in #GeditApp.
|
||||
*
|
||||
* Return value: a newly allocated list of #GeditDocument objects
|
||||
*/
|
||||
GList *
|
||||
gedit_app_get_documents (GeditApp *app)
|
||||
{
|
||||
GList *res = NULL;
|
||||
GList *windows;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
windows = app->priv->windows;
|
||||
|
||||
while (windows != NULL)
|
||||
{
|
||||
res = g_list_concat (res,
|
||||
gedit_window_get_documents (GEDIT_WINDOW (windows->data)));
|
||||
|
||||
windows = g_list_next (windows);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_views:
|
||||
* @app: the #GeditApp
|
||||
*
|
||||
* Returns all the views currently present in #GeditApp.
|
||||
*
|
||||
* Return value: a newly allocated list of #GeditView objects
|
||||
*/
|
||||
GList *
|
||||
gedit_app_get_views (GeditApp *app)
|
||||
{
|
||||
GList *res = NULL;
|
||||
GList *windows;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
windows = app->priv->windows;
|
||||
|
||||
while (windows != NULL)
|
||||
{
|
||||
res = g_list_concat (res,
|
||||
gedit_window_get_views (GEDIT_WINDOW (windows->data)));
|
||||
|
||||
windows = g_list_next (windows);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_app_get_lockdown:
|
||||
* @app: a #GeditApp
|
||||
*
|
||||
* Gets the lockdown mask (see #GeditLockdownMask) for the application.
|
||||
* The lockdown mask determines which functions are locked down using
|
||||
* the MATE-wise lockdown MateConf keys.
|
||||
**/
|
||||
GeditLockdownMask
|
||||
gedit_app_get_lockdown (GeditApp *app)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), GEDIT_LOCKDOWN_ALL);
|
||||
|
||||
return app->priv->lockdown;
|
||||
}
|
||||
|
||||
static void
|
||||
app_lockdown_changed (GeditApp *app)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = app->priv->windows; l != NULL; l = l->next)
|
||||
_gedit_window_set_lockdown (GEDIT_WINDOW (l->data),
|
||||
app->priv->lockdown);
|
||||
|
||||
g_object_notify (G_OBJECT (app), "lockdown");
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_app_set_lockdown (GeditApp *app,
|
||||
GeditLockdownMask lockdown)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_APP (app));
|
||||
|
||||
app->priv->lockdown = lockdown;
|
||||
|
||||
app_lockdown_changed (app);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_app_set_lockdown_bit (GeditApp *app,
|
||||
GeditLockdownMask bit,
|
||||
gboolean value)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_APP (app));
|
||||
|
||||
if (value)
|
||||
app->priv->lockdown |= bit;
|
||||
else
|
||||
app->priv->lockdown &= ~bit;
|
||||
|
||||
app_lockdown_changed (app);
|
||||
}
|
||||
|
||||
/* Returns a copy */
|
||||
GtkPageSetup *
|
||||
_gedit_app_get_default_page_setup (GeditApp *app)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
if (app->priv->page_setup == NULL)
|
||||
load_page_setup (app);
|
||||
|
||||
return gtk_page_setup_copy (app->priv->page_setup);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_app_set_default_page_setup (GeditApp *app,
|
||||
GtkPageSetup *page_setup)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_APP (app));
|
||||
g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
|
||||
|
||||
if (app->priv->page_setup != NULL)
|
||||
g_object_unref (app->priv->page_setup);
|
||||
|
||||
app->priv->page_setup = g_object_ref (page_setup);
|
||||
}
|
||||
|
||||
/* Returns a copy */
|
||||
GtkPrintSettings *
|
||||
_gedit_app_get_default_print_settings (GeditApp *app)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
|
||||
|
||||
if (app->priv->print_settings == NULL)
|
||||
load_print_settings (app);
|
||||
|
||||
return gtk_print_settings_copy (app->priv->print_settings);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_app_set_default_print_settings (GeditApp *app,
|
||||
GtkPrintSettings *settings)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_APP (app));
|
||||
g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
|
||||
|
||||
if (app->priv->print_settings != NULL)
|
||||
g_object_unref (app->priv->print_settings);
|
||||
|
||||
app->priv->print_settings = g_object_ref (settings);
|
||||
}
|
||||
|
||||
142
gedit/gedit-app.h
Executable file
142
gedit/gedit-app.h
Executable file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* gedit-app.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_APP_H__
|
||||
#define __GEDIT_APP_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gedit/gedit-window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_APP (gedit_app_get_type())
|
||||
#define GEDIT_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_APP, GeditApp))
|
||||
#define GEDIT_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_APP, GeditAppClass))
|
||||
#define GEDIT_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_APP))
|
||||
#define GEDIT_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_APP))
|
||||
#define GEDIT_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_APP, GeditAppClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditAppPrivate GeditAppPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditApp GeditApp;
|
||||
|
||||
struct _GeditApp
|
||||
{
|
||||
GObject object;
|
||||
|
||||
/*< private > */
|
||||
GeditAppPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditAppClass GeditAppClass;
|
||||
|
||||
struct _GeditAppClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Lockdown mask definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_LOCKDOWN_COMMAND_LINE = 1 << 0,
|
||||
GEDIT_LOCKDOWN_PRINTING = 1 << 1,
|
||||
GEDIT_LOCKDOWN_PRINT_SETUP = 1 << 2,
|
||||
GEDIT_LOCKDOWN_SAVE_TO_DISK = 1 << 3,
|
||||
GEDIT_LOCKDOWN_ALL = 0xF
|
||||
} GeditLockdownMask;
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_app_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditApp *gedit_app_get_default (void);
|
||||
|
||||
GeditWindow *gedit_app_create_window (GeditApp *app,
|
||||
GdkScreen *screen);
|
||||
|
||||
const GList *gedit_app_get_windows (GeditApp *app);
|
||||
GeditWindow *gedit_app_get_active_window (GeditApp *app);
|
||||
|
||||
/* Returns a newly allocated list with all the documents */
|
||||
GList *gedit_app_get_documents (GeditApp *app);
|
||||
|
||||
/* Returns a newly allocated list with all the views */
|
||||
GList *gedit_app_get_views (GeditApp *app);
|
||||
|
||||
/* Lockdown state */
|
||||
GeditLockdownMask gedit_app_get_lockdown (GeditApp *app);
|
||||
|
||||
/*
|
||||
* Non exported functions
|
||||
*/
|
||||
GeditWindow *_gedit_app_restore_window (GeditApp *app,
|
||||
const gchar *role);
|
||||
GeditWindow *_gedit_app_get_window_in_viewport (GeditApp *app,
|
||||
GdkScreen *screen,
|
||||
gint workspace,
|
||||
gint viewport_x,
|
||||
gint viewport_y);
|
||||
void _gedit_app_set_lockdown (GeditApp *app,
|
||||
GeditLockdownMask lockdown);
|
||||
void _gedit_app_set_lockdown_bit (GeditApp *app,
|
||||
GeditLockdownMask bit,
|
||||
gboolean value);
|
||||
/*
|
||||
* This one is a gedit-window function, but we declare it here to avoid
|
||||
* #include headaches since it needs the GeditLockdownMask declaration.
|
||||
*/
|
||||
void _gedit_window_set_lockdown (GeditWindow *window,
|
||||
GeditLockdownMask lockdown);
|
||||
|
||||
/* global print config */
|
||||
GtkPageSetup *_gedit_app_get_default_page_setup (GeditApp *app);
|
||||
void _gedit_app_set_default_page_setup (GeditApp *app,
|
||||
GtkPageSetup *page_setup);
|
||||
GtkPrintSettings *_gedit_app_get_default_print_settings (GeditApp *app);
|
||||
void _gedit_app_set_default_print_settings (GeditApp *app,
|
||||
GtkPrintSettings *settings);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_APP_H__ */
|
||||
80
gedit/gedit-close-button.c
Executable file
80
gedit/gedit-close-button.c
Executable file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* gedit-close-button.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Paolo Borelli
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gedit-close-button.h"
|
||||
|
||||
G_DEFINE_TYPE (GeditCloseButton, gedit_close_button, GTK_TYPE_BUTTON)
|
||||
|
||||
static void
|
||||
gedit_close_button_style_set (GtkWidget *button,
|
||||
GtkStyle *previous_style)
|
||||
{
|
||||
gint h, w;
|
||||
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &w, &h);
|
||||
|
||||
gtk_widget_set_size_request (button, w + 2, h + 2);
|
||||
|
||||
GTK_WIDGET_CLASS (gedit_close_button_parent_class)->style_set (button, previous_style);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_button_class_init (GeditCloseButtonClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->style_set = gedit_close_button_style_set;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_close_button_init (GeditCloseButton *button)
|
||||
{
|
||||
GtkRcStyle *rcstyle;
|
||||
GtkWidget *image;
|
||||
|
||||
/* make it as small as possible */
|
||||
rcstyle = gtk_rc_style_new ();
|
||||
rcstyle->xthickness = rcstyle->ythickness = 0;
|
||||
gtk_widget_modify_style (GTK_WIDGET (button), rcstyle);
|
||||
g_object_unref (rcstyle);
|
||||
|
||||
image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
gtk_widget_show (image);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_close_button_new ()
|
||||
{
|
||||
GeditCloseButton *button;
|
||||
|
||||
button = g_object_new (GEDIT_TYPE_CLOSE_BUTTON,
|
||||
"relief", GTK_RELIEF_NONE,
|
||||
"focus-on-click", FALSE,
|
||||
NULL);
|
||||
|
||||
return GTK_WIDGET (button);
|
||||
}
|
||||
|
||||
56
gedit/gedit-close-button.h
Executable file
56
gedit/gedit-close-button.h
Executable file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* gedit-close-button.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Paolo Borelli
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_CLOSE_BUTTON_H__
|
||||
#define __GEDIT_CLOSE_BUTTON_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_CLOSE_BUTTON (gedit_close_button_get_type ())
|
||||
#define GEDIT_CLOSE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_CLOSE_BUTTON, GeditCloseButton))
|
||||
#define GEDIT_CLOSE_BUTTON_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_CLOSE_BUTTON, GeditCloseButton const))
|
||||
#define GEDIT_CLOSE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_CLOSE_BUTTON, GeditCloseButtonClass))
|
||||
#define GEDIT_IS_CLOSE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_CLOSE_BUTTON))
|
||||
#define GEDIT_IS_CLOSE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_CLOSE_BUTTON))
|
||||
#define GEDIT_CLOSE_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_CLOSE_BUTTON, GeditCloseButtonClass))
|
||||
|
||||
typedef struct _GeditCloseButton GeditCloseButton;
|
||||
typedef struct _GeditCloseButtonClass GeditCloseButtonClass;
|
||||
typedef struct _GeditCloseButtonPrivate GeditCloseButtonPrivate;
|
||||
|
||||
struct _GeditCloseButton {
|
||||
GtkButton parent;
|
||||
};
|
||||
|
||||
struct _GeditCloseButtonClass {
|
||||
GtkButtonClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_close_button_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_close_button_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_CLOSE_BUTTON_H__ */
|
||||
87
gedit/gedit-commands-documents.c
Executable file
87
gedit/gedit-commands-documents.c
Executable file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* gedit-documents-commands.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-notebook.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
void
|
||||
_gedit_cmd_documents_previous_document (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GtkNotebook *notebook;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
notebook = GTK_NOTEBOOK (_gedit_window_get_notebook (window));
|
||||
gtk_notebook_prev_page (notebook);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_documents_next_document (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GtkNotebook *notebook;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
notebook = GTK_NOTEBOOK (_gedit_window_get_notebook (window));
|
||||
gtk_notebook_next_page (notebook);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_documents_move_to_new_window (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditNotebook *old_notebook;
|
||||
GeditTab *tab;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = gedit_window_get_active_tab (window);
|
||||
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
old_notebook = GEDIT_NOTEBOOK (_gedit_window_get_notebook (window));
|
||||
|
||||
g_return_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (old_notebook)) > 1);
|
||||
|
||||
_gedit_window_move_tab_to_new_window (window, tab);
|
||||
}
|
||||
174
gedit/gedit-commands-edit.c
Executable file
174
gedit/gedit-commands-edit.c
Executable file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* gedit-commands-edit.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-view.h"
|
||||
#include "dialogs/gedit-preferences-dialog.h"
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_undo (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
GtkSourceBuffer *active_document;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
|
||||
|
||||
gtk_source_buffer_undo (active_document);
|
||||
|
||||
gedit_view_scroll_to_cursor (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_redo (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
GtkSourceBuffer *active_document;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
|
||||
|
||||
gtk_source_buffer_redo (active_document);
|
||||
|
||||
gedit_view_scroll_to_cursor (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_cut (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
gedit_view_cut_clipboard (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_copy (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
gedit_view_copy_clipboard (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_paste (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
gedit_view_paste_clipboard (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_delete (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
gedit_view_delete_selection (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_select_all (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view);
|
||||
|
||||
gedit_view_select_all (active_view);
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_edit_preferences (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
gedit_show_preferences_dialog (window);
|
||||
}
|
||||
91
gedit/gedit-commands-file-print.c
Executable file
91
gedit/gedit-commands-file-print.c
Executable file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* gedit-commands-file-print.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-tab.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
#if !GTK_CHECK_VERSION (2, 17, 4)
|
||||
void
|
||||
_gedit_cmd_file_page_setup (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditTab *tab;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = gedit_window_get_active_tab (window);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
_gedit_tab_page_setup (tab);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
_gedit_cmd_file_print_preview (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditTab *tab;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = gedit_window_get_active_tab (window);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
_gedit_tab_print_preview (tab);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_file_print (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditTab *tab;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = gedit_window_get_active_tab (window);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
_gedit_tab_print (tab);
|
||||
}
|
||||
|
||||
1885
gedit/gedit-commands-file.c
Executable file
1885
gedit/gedit-commands-file.c
Executable file
File diff suppressed because it is too large
Load Diff
115
gedit/gedit-commands-help.c
Executable file
115
gedit/gedit-commands-help.c
Executable file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* gedit-help-commands.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-help.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
void
|
||||
_gedit_cmd_help_contents (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
gedit_help_display (GTK_WINDOW (window), NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_help_about (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
static const gchar * const authors[] = {
|
||||
"Paolo Maggi <paolo@gnome.org>",
|
||||
"Paolo Borelli <pborelli@katamail.com>",
|
||||
"Steve Fr\303\251cinaux <steve@istique.net>",
|
||||
"Jesse van den Kieboom <jessevdk@gnome.org>",
|
||||
"Ignacio Casal Quinteiro <icq@gnome.org>",
|
||||
"James Willcox <jwillcox@gnome.org>",
|
||||
"Chema Celorio",
|
||||
"Federico Mena Quintero <federico@novell.com>",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const gchar * const documenters[] = {
|
||||
"Sun MATE Documentation Team <gdocteam@sun.com>",
|
||||
"Eric Baudais <baudais@okstate.edu>",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const gchar copyright[] = \
|
||||
"Copyright \xc2\xa9 1998-2000 Evan Lawrence, Alex Robert\n"
|
||||
"Copyright \xc2\xa9 2000-2002 Chema Celorio, Paolo Maggi\n"
|
||||
"Copyright \xc2\xa9 2003-2006 Paolo Maggi\n"
|
||||
"Copyright \xc2\xa9 2004-2010 Paolo Borelli, Jesse van den Kieboom\nSteve Fr\303\251cinaux, Ignacio Casal Quinteiro";
|
||||
|
||||
static const gchar comments[] = \
|
||||
N_("gedit is a small and lightweight text editor for the "
|
||||
"MATE Desktop");
|
||||
|
||||
GdkPixbuf *logo;
|
||||
gchar *data_dir;
|
||||
gchar *logo_file;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
data_dir = gedit_dirs_get_gedit_data_dir ();
|
||||
logo_file = g_build_filename (data_dir,
|
||||
"logo",
|
||||
"gedit-logo.png",
|
||||
NULL);
|
||||
g_free (data_dir);
|
||||
logo = gdk_pixbuf_new_from_file (logo_file, NULL);
|
||||
g_free (logo_file);
|
||||
|
||||
gtk_show_about_dialog (GTK_WINDOW (window),
|
||||
"program-name", "gedit",
|
||||
"authors", authors,
|
||||
"comments", _(comments),
|
||||
"copyright", copyright,
|
||||
"documenters", documenters,
|
||||
"logo", logo,
|
||||
"translator-credits", _("translator-credits"),
|
||||
"version", VERSION,
|
||||
"website", "http://www.gedit.org",
|
||||
NULL);
|
||||
|
||||
if (logo)
|
||||
g_object_unref (logo);
|
||||
}
|
||||
716
gedit/gedit-commands-search.c
Executable file
716
gedit/gedit-commands-search.c
Executable file
@@ -0,0 +1,716 @@
|
||||
/*
|
||||
* gedit-search-commands.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2006 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-statusbar.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-window-private.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "dialogs/gedit-search-dialog.h"
|
||||
|
||||
#define GEDIT_SEARCH_DIALOG_KEY "gedit-search-dialog-key"
|
||||
#define GEDIT_LAST_SEARCH_DATA_KEY "gedit-last-search-data-key"
|
||||
|
||||
typedef struct _LastSearchData LastSearchData;
|
||||
struct _LastSearchData
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
};
|
||||
|
||||
static void
|
||||
last_search_data_free (LastSearchData *data)
|
||||
{
|
||||
g_slice_free (LastSearchData, data);
|
||||
}
|
||||
|
||||
static void
|
||||
last_search_data_restore_position (GeditSearchDialog *dlg)
|
||||
{
|
||||
LastSearchData *data;
|
||||
|
||||
data = g_object_get_data (G_OBJECT (dlg), GEDIT_LAST_SEARCH_DATA_KEY);
|
||||
|
||||
if (data != NULL)
|
||||
{
|
||||
gtk_window_move (GTK_WINDOW (dlg),
|
||||
data->x,
|
||||
data->y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
last_search_data_store_position (GeditSearchDialog *dlg)
|
||||
{
|
||||
LastSearchData *data;
|
||||
|
||||
data = g_object_get_data (G_OBJECT (dlg), GEDIT_LAST_SEARCH_DATA_KEY);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
data = g_slice_new (LastSearchData);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (dlg),
|
||||
GEDIT_LAST_SEARCH_DATA_KEY,
|
||||
data,
|
||||
(GDestroyNotify) last_search_data_free);
|
||||
}
|
||||
|
||||
gtk_window_get_position (GTK_WINDOW (dlg),
|
||||
&data->x,
|
||||
&data->y);
|
||||
}
|
||||
|
||||
/* Use occurences only for Replace All */
|
||||
static void
|
||||
text_found (GeditWindow *window,
|
||||
gint occurrences)
|
||||
{
|
||||
if (occurrences > 1)
|
||||
{
|
||||
gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
ngettext("Found and replaced %d occurrence",
|
||||
"Found and replaced %d occurrences",
|
||||
occurrences),
|
||||
occurrences);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (occurrences == 1)
|
||||
gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
_("Found and replaced one occurrence"));
|
||||
else
|
||||
gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
" ");
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_MSG_LENGTH 40
|
||||
static void
|
||||
text_not_found (GeditWindow *window,
|
||||
const gchar *text)
|
||||
{
|
||||
gchar *searched;
|
||||
|
||||
searched = gedit_utils_str_end_truncate (text, MAX_MSG_LENGTH);
|
||||
|
||||
gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
/* Translators: %s is replaced by the text
|
||||
entered by the user in the search box */
|
||||
_("\"%s\" not found"), searched);
|
||||
g_free (searched);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_search (GeditView *view,
|
||||
gboolean wrap_around,
|
||||
gboolean search_backwards)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
GtkTextIter start_iter;
|
||||
GtkTextIter match_start;
|
||||
GtkTextIter match_end;
|
||||
gboolean found = FALSE;
|
||||
|
||||
doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
|
||||
|
||||
if (!search_backwards)
|
||||
{
|
||||
gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
|
||||
NULL,
|
||||
&start_iter);
|
||||
|
||||
found = gedit_document_search_forward (doc,
|
||||
&start_iter,
|
||||
NULL,
|
||||
&match_start,
|
||||
&match_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
|
||||
&start_iter,
|
||||
NULL);
|
||||
|
||||
found = gedit_document_search_backward (doc,
|
||||
NULL,
|
||||
&start_iter,
|
||||
&match_start,
|
||||
&match_end);
|
||||
}
|
||||
|
||||
if (!found && wrap_around)
|
||||
{
|
||||
if (!search_backwards)
|
||||
found = gedit_document_search_forward (doc,
|
||||
NULL,
|
||||
NULL, /* FIXME: set the end_inter */
|
||||
&match_start,
|
||||
&match_end);
|
||||
else
|
||||
found = gedit_document_search_backward (doc,
|
||||
NULL, /* FIXME: set the start_inter */
|
||||
NULL,
|
||||
&match_start,
|
||||
&match_end);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc),
|
||||
&match_start);
|
||||
|
||||
gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc),
|
||||
"selection_bound",
|
||||
&match_end);
|
||||
|
||||
gedit_view_scroll_to_cursor (view);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc),
|
||||
&start_iter);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void
|
||||
do_find (GeditSearchDialog *dialog,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
GeditDocument *doc;
|
||||
gchar *search_text;
|
||||
const gchar *entry_text;
|
||||
gboolean match_case;
|
||||
gboolean entire_word;
|
||||
gboolean wrap_around;
|
||||
gboolean search_backwards;
|
||||
guint flags = 0;
|
||||
guint old_flags = 0;
|
||||
gboolean found;
|
||||
|
||||
/* TODO: make the dialog insensitive when all the tabs are closed
|
||||
* and assert here that the view is not NULL */
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
if (active_view == NULL)
|
||||
return;
|
||||
|
||||
doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
|
||||
|
||||
entry_text = gedit_search_dialog_get_search_text (dialog);
|
||||
|
||||
match_case = gedit_search_dialog_get_match_case (dialog);
|
||||
entire_word = gedit_search_dialog_get_entire_word (dialog);
|
||||
search_backwards = gedit_search_dialog_get_backwards (dialog);
|
||||
wrap_around = gedit_search_dialog_get_wrap_around (dialog);
|
||||
|
||||
GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case);
|
||||
GEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word);
|
||||
|
||||
search_text = gedit_document_get_search_text (doc, &old_flags);
|
||||
|
||||
if ((search_text == NULL) ||
|
||||
(strcmp (search_text, entry_text) != 0) ||
|
||||
(flags != old_flags))
|
||||
{
|
||||
gedit_document_set_search_text (doc, entry_text, flags);
|
||||
}
|
||||
|
||||
g_free (search_text);
|
||||
|
||||
found = run_search (active_view,
|
||||
wrap_around,
|
||||
search_backwards);
|
||||
|
||||
if (found)
|
||||
text_found (window, 0);
|
||||
else
|
||||
text_not_found (window, entry_text);
|
||||
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
|
||||
found);
|
||||
}
|
||||
|
||||
/* FIXME: move in gedit-document.c and share it with gedit-view */
|
||||
static gboolean
|
||||
get_selected_text (GtkTextBuffer *doc,
|
||||
gchar **selected_text,
|
||||
gint *len)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
|
||||
g_return_val_if_fail (selected_text != NULL, FALSE);
|
||||
g_return_val_if_fail (*selected_text == NULL, FALSE);
|
||||
|
||||
if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end))
|
||||
{
|
||||
if (len != NULL)
|
||||
len = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE);
|
||||
|
||||
if (len != NULL)
|
||||
*len = g_utf8_strlen (*selected_text, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
replace_selected_text (GtkTextBuffer *buffer,
|
||||
const gchar *replace)
|
||||
{
|
||||
g_return_if_fail (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL));
|
||||
g_return_if_fail (replace != NULL);
|
||||
|
||||
gtk_text_buffer_begin_user_action (buffer);
|
||||
|
||||
gtk_text_buffer_delete_selection (buffer, FALSE, TRUE);
|
||||
|
||||
gtk_text_buffer_insert_at_cursor (buffer, replace, strlen (replace));
|
||||
|
||||
gtk_text_buffer_end_user_action (buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
do_replace (GeditSearchDialog *dialog,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
const gchar *search_entry_text;
|
||||
const gchar *replace_entry_text;
|
||||
gchar *unescaped_search_text;
|
||||
gchar *unescaped_replace_text;
|
||||
gchar *selected_text = NULL;
|
||||
gboolean match_case;
|
||||
|
||||
doc = gedit_window_get_active_document (window);
|
||||
if (doc == NULL)
|
||||
return;
|
||||
|
||||
search_entry_text = gedit_search_dialog_get_search_text (dialog);
|
||||
g_return_if_fail ((search_entry_text) != NULL);
|
||||
g_return_if_fail ((*search_entry_text) != '\0');
|
||||
|
||||
/* replace text may be "", we just delete */
|
||||
replace_entry_text = gedit_search_dialog_get_replace_text (dialog);
|
||||
g_return_if_fail ((replace_entry_text) != NULL);
|
||||
|
||||
unescaped_search_text = gedit_utils_unescape_search_text (search_entry_text);
|
||||
|
||||
get_selected_text (GTK_TEXT_BUFFER (doc),
|
||||
&selected_text,
|
||||
NULL);
|
||||
|
||||
match_case = gedit_search_dialog_get_match_case (dialog);
|
||||
|
||||
if ((selected_text == NULL) ||
|
||||
(match_case && (strcmp (selected_text, unescaped_search_text) != 0)) ||
|
||||
(!match_case && !g_utf8_caselessnmatch (selected_text,
|
||||
unescaped_search_text,
|
||||
strlen (selected_text),
|
||||
strlen (unescaped_search_text)) != 0))
|
||||
{
|
||||
do_find (dialog, window);
|
||||
g_free (unescaped_search_text);
|
||||
g_free (selected_text);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
unescaped_replace_text = gedit_utils_unescape_search_text (replace_entry_text);
|
||||
replace_selected_text (GTK_TEXT_BUFFER (doc), unescaped_replace_text);
|
||||
|
||||
g_free (unescaped_search_text);
|
||||
g_free (selected_text);
|
||||
g_free (unescaped_replace_text);
|
||||
|
||||
do_find (dialog, window);
|
||||
}
|
||||
|
||||
static void
|
||||
do_replace_all (GeditSearchDialog *dialog,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
GeditDocument *doc;
|
||||
const gchar *search_entry_text;
|
||||
const gchar *replace_entry_text;
|
||||
gboolean match_case;
|
||||
gboolean entire_word;
|
||||
guint flags = 0;
|
||||
gint count;
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
if (active_view == NULL)
|
||||
return;
|
||||
|
||||
doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
|
||||
|
||||
search_entry_text = gedit_search_dialog_get_search_text (dialog);
|
||||
g_return_if_fail ((search_entry_text) != NULL);
|
||||
g_return_if_fail ((*search_entry_text) != '\0');
|
||||
|
||||
/* replace text may be "", we just delete all occurrencies */
|
||||
replace_entry_text = gedit_search_dialog_get_replace_text (dialog);
|
||||
g_return_if_fail ((replace_entry_text) != NULL);
|
||||
|
||||
match_case = gedit_search_dialog_get_match_case (dialog);
|
||||
entire_word = gedit_search_dialog_get_entire_word (dialog);
|
||||
|
||||
GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case);
|
||||
GEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word);
|
||||
|
||||
count = gedit_document_replace_all (doc,
|
||||
search_entry_text,
|
||||
replace_entry_text,
|
||||
flags);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
text_found (window, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
text_not_found (window, search_entry_text);
|
||||
}
|
||||
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
search_dialog_response_cb (GeditSearchDialog *dialog,
|
||||
gint response_id,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
switch (response_id)
|
||||
{
|
||||
case GEDIT_SEARCH_DIALOG_FIND_RESPONSE:
|
||||
do_find (dialog, window);
|
||||
break;
|
||||
case GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE:
|
||||
do_replace (dialog, window);
|
||||
break;
|
||||
case GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE:
|
||||
do_replace_all (dialog, window);
|
||||
break;
|
||||
default:
|
||||
last_search_data_store_position (dialog);
|
||||
gtk_widget_hide (GTK_WIDGET (dialog));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
search_dialog_delete_event_cb (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
/* prevent destruction */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
search_dialog_destroyed (GeditWindow *window,
|
||||
GeditSearchDialog *dialog)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
g_object_set_data (G_OBJECT (window),
|
||||
GEDIT_SEARCH_DIALOG_KEY,
|
||||
NULL);
|
||||
g_object_set_data (G_OBJECT (dialog),
|
||||
GEDIT_LAST_SEARCH_DATA_KEY,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_dialog (GeditWindow *window, gboolean show_replace)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gedit_search_dialog_new (GTK_WINDOW (window), show_replace);
|
||||
|
||||
g_signal_connect (dialog,
|
||||
"response",
|
||||
G_CALLBACK (search_dialog_response_cb),
|
||||
window);
|
||||
g_signal_connect (dialog,
|
||||
"delete-event",
|
||||
G_CALLBACK (search_dialog_delete_event_cb),
|
||||
NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (window),
|
||||
GEDIT_SEARCH_DIALOG_KEY,
|
||||
dialog);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (dialog),
|
||||
(GWeakNotify) search_dialog_destroyed,
|
||||
window);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_find (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gpointer data;
|
||||
GtkWidget *search_dialog;
|
||||
GeditDocument *doc;
|
||||
gboolean selection_exists;
|
||||
gchar *find_text = NULL;
|
||||
gint sel_len;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
data = g_object_get_data (G_OBJECT (window), GEDIT_SEARCH_DIALOG_KEY);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
search_dialog = create_dialog (window, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (data));
|
||||
|
||||
search_dialog = GTK_WIDGET (data);
|
||||
|
||||
/* turn the dialog into a find dialog if needed */
|
||||
if (gedit_search_dialog_get_show_replace (GEDIT_SEARCH_DIALOG (search_dialog)))
|
||||
gedit_search_dialog_set_show_replace (GEDIT_SEARCH_DIALOG (search_dialog),
|
||||
FALSE);
|
||||
}
|
||||
|
||||
doc = gedit_window_get_active_document (window);
|
||||
g_return_if_fail (doc != NULL);
|
||||
|
||||
selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc),
|
||||
&find_text,
|
||||
&sel_len);
|
||||
|
||||
if (selection_exists && find_text != NULL && sel_len < 80)
|
||||
{
|
||||
gedit_search_dialog_set_search_text (GEDIT_SEARCH_DIALOG (search_dialog),
|
||||
find_text);
|
||||
g_free (find_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (find_text);
|
||||
}
|
||||
|
||||
gtk_widget_show (search_dialog);
|
||||
last_search_data_restore_position (GEDIT_SEARCH_DIALOG (search_dialog));
|
||||
gedit_search_dialog_present_with_time (GEDIT_SEARCH_DIALOG (search_dialog),
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_replace (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gpointer data;
|
||||
GtkWidget *replace_dialog;
|
||||
GeditDocument *doc;
|
||||
gboolean selection_exists;
|
||||
gchar *find_text = NULL;
|
||||
gint sel_len;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
data = g_object_get_data (G_OBJECT (window), GEDIT_SEARCH_DIALOG_KEY);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
replace_dialog = create_dialog (window, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (data));
|
||||
|
||||
replace_dialog = GTK_WIDGET (data);
|
||||
|
||||
/* turn the dialog into a find dialog if needed */
|
||||
if (!gedit_search_dialog_get_show_replace (GEDIT_SEARCH_DIALOG (replace_dialog)))
|
||||
gedit_search_dialog_set_show_replace (GEDIT_SEARCH_DIALOG (replace_dialog),
|
||||
TRUE);
|
||||
}
|
||||
|
||||
doc = gedit_window_get_active_document (window);
|
||||
g_return_if_fail (doc != NULL);
|
||||
|
||||
selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc),
|
||||
&find_text,
|
||||
&sel_len);
|
||||
|
||||
if (selection_exists && find_text != NULL && sel_len < 80)
|
||||
{
|
||||
gedit_search_dialog_set_search_text (GEDIT_SEARCH_DIALOG (replace_dialog),
|
||||
find_text);
|
||||
g_free (find_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (find_text);
|
||||
}
|
||||
|
||||
gtk_widget_show (replace_dialog);
|
||||
last_search_data_restore_position (GEDIT_SEARCH_DIALOG (replace_dialog));
|
||||
gedit_search_dialog_present_with_time (GEDIT_SEARCH_DIALOG (replace_dialog),
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
do_find_again (GeditWindow *window,
|
||||
gboolean backward)
|
||||
{
|
||||
GeditView *active_view;
|
||||
gboolean wrap_around = TRUE;
|
||||
gpointer data;
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
g_return_if_fail (active_view != NULL);
|
||||
|
||||
data = g_object_get_data (G_OBJECT (window), GEDIT_SEARCH_DIALOG_KEY);
|
||||
|
||||
if (data != NULL)
|
||||
wrap_around = gedit_search_dialog_get_wrap_around (GEDIT_SEARCH_DIALOG (data));
|
||||
|
||||
run_search (active_view,
|
||||
wrap_around,
|
||||
backward);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_find_next (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
do_find_again (window, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_find_prev (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
do_find_again (window, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_clear_highlight (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
doc = gedit_window_get_active_document (window);
|
||||
gedit_document_set_search_text (GEDIT_DOCUMENT (doc),
|
||||
"",
|
||||
GEDIT_SEARCH_DONT_SET_FLAGS);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_goto_line (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
if (active_view == NULL)
|
||||
return;
|
||||
|
||||
/* Focus the view if needed: we need to focus the view otherwise
|
||||
activating the binding for goto line has no effect */
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
|
||||
|
||||
/* goto line is builtin in GeditView, just activate
|
||||
* the corrisponding binding.
|
||||
*/
|
||||
gtk_bindings_activate (GTK_OBJECT (active_view),
|
||||
GDK_i,
|
||||
GDK_CONTROL_MASK);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_search_incremental_search (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GeditView *active_view;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
active_view = gedit_window_get_active_view (window);
|
||||
if (active_view == NULL)
|
||||
return;
|
||||
|
||||
/* Focus the view if needed: we need to focus the view otherwise
|
||||
activating the binding for incremental search has no effect */
|
||||
gtk_widget_grab_focus (GTK_WIDGET (active_view));
|
||||
|
||||
/* incremental search is builtin in GeditView, just activate
|
||||
* the corrisponding binding.
|
||||
*/
|
||||
gtk_bindings_activate (GTK_OBJECT (active_view),
|
||||
GDK_k,
|
||||
GDK_CONTROL_MASK);
|
||||
}
|
||||
154
gedit/gedit-commands-view.c
Executable file
154
gedit/gedit-commands-view.c
Executable file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* gedit-view-commands.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-commands.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-window-private.h"
|
||||
|
||||
|
||||
void
|
||||
_gedit_cmd_view_show_toolbar (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gboolean visible;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
if (visible)
|
||||
gtk_widget_show (window->priv->toolbar);
|
||||
else
|
||||
gtk_widget_hide (window->priv->toolbar);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_view_show_statusbar (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gboolean visible;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
if (visible)
|
||||
gtk_widget_show (window->priv->statusbar);
|
||||
else
|
||||
gtk_widget_hide (window->priv->statusbar);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_view_show_side_pane (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gboolean visible;
|
||||
GeditPanel *panel;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
panel = gedit_window_get_side_panel (window);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
gtk_widget_show (GTK_WIDGET (panel));
|
||||
gtk_widget_grab_focus (GTK_WIDGET (panel));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET (panel));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_view_show_bottom_pane (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gboolean visible;
|
||||
GeditPanel *panel;
|
||||
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
panel = gedit_window_get_bottom_panel (window);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
gtk_widget_show (GTK_WIDGET (panel));
|
||||
gtk_widget_grab_focus (GTK_WIDGET (panel));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET (panel));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_view_toggle_fullscreen_mode (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_debug (DEBUG_COMMANDS);
|
||||
|
||||
if (_gedit_window_is_fullscreen (window))
|
||||
_gedit_window_unfullscreen (window);
|
||||
else
|
||||
_gedit_window_fullscreen (window);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_cmd_view_leave_fullscreen_mode (GtkAction *action,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GtkAction *view_action;
|
||||
|
||||
view_action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
|
||||
"ViewFullscreen");
|
||||
g_signal_handlers_block_by_func
|
||||
(view_action, G_CALLBACK (_gedit_cmd_view_toggle_fullscreen_mode),
|
||||
window);
|
||||
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_action),
|
||||
FALSE);
|
||||
_gedit_window_unfullscreen (window);
|
||||
g_signal_handlers_unblock_by_func
|
||||
(view_action, G_CALLBACK (_gedit_cmd_view_toggle_fullscreen_mode),
|
||||
window);
|
||||
}
|
||||
166
gedit/gedit-commands.h
Executable file
166
gedit/gedit-commands.h
Executable file
@@ -0,0 +1,166 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-commands.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_COMMANDS_H__
|
||||
#define __GEDIT_COMMANDS_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gedit/gedit-window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Do nothing if URI does not exist */
|
||||
void gedit_commands_load_uri (GeditWindow *window,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
gint line_pos);
|
||||
|
||||
/* Ignore non-existing URIs */
|
||||
gint gedit_commands_load_uris (GeditWindow *window,
|
||||
const GSList *uris,
|
||||
const GeditEncoding *encoding,
|
||||
gint line_pos);
|
||||
|
||||
void gedit_commands_save_document (GeditWindow *window,
|
||||
GeditDocument *document);
|
||||
|
||||
void gedit_commands_save_all_documents (GeditWindow *window);
|
||||
|
||||
/*
|
||||
* Non-exported functions
|
||||
*/
|
||||
|
||||
/* Create titled documens for non-existing URIs */
|
||||
gint _gedit_cmd_load_files_from_prompt (GeditWindow *window,
|
||||
GSList *files,
|
||||
const GeditEncoding *encoding,
|
||||
gint line_pos);
|
||||
|
||||
void _gedit_cmd_file_new (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_open (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_save (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_save_as (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_save_all (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_revert (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_open_uri (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_print_preview (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_print (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_close (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_close_all (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_file_quit (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_edit_undo (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_redo (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_cut (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_copy (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_paste (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_delete (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_select_all (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_edit_preferences (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_view_show_toolbar (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_view_show_statusbar (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_view_show_side_pane (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_view_show_bottom_pane (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_view_toggle_fullscreen_mode (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_view_leave_fullscreen_mode (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_search_find (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_find_next (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_find_prev (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_replace (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_clear_highlight (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_goto_line (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_search_incremental_search (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_documents_previous_document (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_documents_next_document (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_documents_move_to_new_window (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_help_contents (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
void _gedit_cmd_help_about (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_file_close_tab (GeditTab *tab,
|
||||
GeditWindow *window);
|
||||
|
||||
void _gedit_cmd_file_save_documents_list (GeditWindow *window,
|
||||
GList *docs);
|
||||
|
||||
|
||||
#if !GTK_CHECK_VERSION (2, 17, 4)
|
||||
void _gedit_cmd_file_page_setup (GtkAction *action,
|
||||
GeditWindow *window);
|
||||
#endif
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_COMMANDS_H__ */
|
||||
159
gedit/gedit-debug.c
Executable file
159
gedit/gedit-debug.c
Executable file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* gedit-debug.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002 - 2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "gedit-debug.h"
|
||||
|
||||
#define ENABLE_PROFILING
|
||||
|
||||
#ifdef ENABLE_PROFILING
|
||||
static GTimer *timer = NULL;
|
||||
static gdouble last = 0.0;
|
||||
#endif
|
||||
|
||||
static GeditDebugSection debug = GEDIT_NO_DEBUG;
|
||||
|
||||
void
|
||||
gedit_debug_init (void)
|
||||
{
|
||||
if (g_getenv ("GEDIT_DEBUG") != NULL)
|
||||
{
|
||||
/* enable all debugging */
|
||||
debug = ~GEDIT_NO_DEBUG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_getenv ("GEDIT_DEBUG_VIEW") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_VIEW;
|
||||
if (g_getenv ("GEDIT_DEBUG_SEARCH") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_SEARCH;
|
||||
if (g_getenv ("GEDIT_DEBUG_PREFS") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_PREFS;
|
||||
if (g_getenv ("GEDIT_DEBUG_PRINT") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_PRINT;
|
||||
if (g_getenv ("GEDIT_DEBUG_PLUGINS") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_PLUGINS;
|
||||
if (g_getenv ("GEDIT_DEBUG_TAB") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_TAB;
|
||||
if (g_getenv ("GEDIT_DEBUG_DOCUMENT") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_DOCUMENT;
|
||||
if (g_getenv ("GEDIT_DEBUG_COMMANDS") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_COMMANDS;
|
||||
if (g_getenv ("GEDIT_DEBUG_APP") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_APP;
|
||||
if (g_getenv ("GEDIT_DEBUG_SESSION") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_SESSION;
|
||||
if (g_getenv ("GEDIT_DEBUG_UTILS") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_UTILS;
|
||||
if (g_getenv ("GEDIT_DEBUG_METADATA") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_METADATA;
|
||||
if (g_getenv ("GEDIT_DEBUG_WINDOW") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_WINDOW;
|
||||
if (g_getenv ("GEDIT_DEBUG_LOADER") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_LOADER;
|
||||
if (g_getenv ("GEDIT_DEBUG_SAVER") != NULL)
|
||||
debug = debug | GEDIT_DEBUG_SAVER;
|
||||
|
||||
out:
|
||||
|
||||
#ifdef ENABLE_PROFILING
|
||||
if (debug != GEDIT_NO_DEBUG)
|
||||
timer = g_timer_new ();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_debug_message (GeditDebugSection section,
|
||||
const gchar *file,
|
||||
gint line,
|
||||
const gchar *function,
|
||||
const gchar *format, ...)
|
||||
{
|
||||
if (G_UNLIKELY (debug & section))
|
||||
{
|
||||
#ifdef ENABLE_PROFILING
|
||||
gdouble seconds;
|
||||
#endif
|
||||
|
||||
va_list args;
|
||||
gchar *msg;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
msg = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
#ifdef ENABLE_PROFILING
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
seconds = g_timer_elapsed (timer, NULL);
|
||||
g_print ("[%f (%f)] %s:%d (%s) %s\n",
|
||||
seconds, seconds - last, file, line, function, msg);
|
||||
last = seconds;
|
||||
#else
|
||||
g_print ("%s:%d (%s) %s\n", file, line, function, msg);
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
|
||||
g_free (msg);
|
||||
}
|
||||
}
|
||||
|
||||
void gedit_debug (GeditDebugSection section,
|
||||
const gchar *file,
|
||||
gint line,
|
||||
const gchar *function)
|
||||
{
|
||||
if (G_UNLIKELY (debug & section))
|
||||
{
|
||||
#ifdef ENABLE_PROFILING
|
||||
gdouble seconds;
|
||||
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
seconds = g_timer_elapsed (timer, NULL);
|
||||
g_print ("[%f (%f)] %s:%d (%s)\n",
|
||||
seconds, seconds - last, file, line, function);
|
||||
last = seconds;
|
||||
#else
|
||||
g_print ("%s:%d (%s)\n", file, line, function);
|
||||
#endif
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
93
gedit/gedit-debug.h
Executable file
93
gedit/gedit-debug.h
Executable file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* gedit-debug.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002 - 2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DEBUG_H__
|
||||
#define __GEDIT_DEBUG_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/*
|
||||
* Set an environmental var of the same name to turn on
|
||||
* debugging output. Setting GEDIT_DEBUG will turn on all
|
||||
* sections.
|
||||
*/
|
||||
typedef enum {
|
||||
GEDIT_NO_DEBUG = 0,
|
||||
GEDIT_DEBUG_VIEW = 1 << 0,
|
||||
GEDIT_DEBUG_SEARCH = 1 << 1,
|
||||
GEDIT_DEBUG_PRINT = 1 << 2,
|
||||
GEDIT_DEBUG_PREFS = 1 << 3,
|
||||
GEDIT_DEBUG_PLUGINS = 1 << 4,
|
||||
GEDIT_DEBUG_TAB = 1 << 5,
|
||||
GEDIT_DEBUG_DOCUMENT = 1 << 6,
|
||||
GEDIT_DEBUG_COMMANDS = 1 << 7,
|
||||
GEDIT_DEBUG_APP = 1 << 8,
|
||||
GEDIT_DEBUG_SESSION = 1 << 9,
|
||||
GEDIT_DEBUG_UTILS = 1 << 10,
|
||||
GEDIT_DEBUG_METADATA = 1 << 11,
|
||||
GEDIT_DEBUG_WINDOW = 1 << 12,
|
||||
GEDIT_DEBUG_LOADER = 1 << 13,
|
||||
GEDIT_DEBUG_SAVER = 1 << 14
|
||||
} GeditDebugSection;
|
||||
|
||||
|
||||
#define DEBUG_VIEW GEDIT_DEBUG_VIEW, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_SEARCH GEDIT_DEBUG_SEARCH, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_PRINT GEDIT_DEBUG_PRINT, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_PREFS GEDIT_DEBUG_PREFS, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_PLUGINS GEDIT_DEBUG_PLUGINS, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_TAB GEDIT_DEBUG_TAB, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_DOCUMENT GEDIT_DEBUG_DOCUMENT,__FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_COMMANDS GEDIT_DEBUG_COMMANDS,__FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_APP GEDIT_DEBUG_APP, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_SESSION GEDIT_DEBUG_SESSION, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_UTILS GEDIT_DEBUG_UTILS, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_METADATA GEDIT_DEBUG_METADATA,__FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_WINDOW GEDIT_DEBUG_WINDOW, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_LOADER GEDIT_DEBUG_LOADER, __FILE__, __LINE__, G_STRFUNC
|
||||
#define DEBUG_SAVER GEDIT_DEBUG_SAVER, __FILE__, __LINE__, G_STRFUNC
|
||||
|
||||
void gedit_debug_init (void);
|
||||
|
||||
void gedit_debug (GeditDebugSection section,
|
||||
const gchar *file,
|
||||
gint line,
|
||||
const gchar *function);
|
||||
|
||||
void gedit_debug_message (GeditDebugSection section,
|
||||
const gchar *file,
|
||||
gint line,
|
||||
const gchar *function,
|
||||
const gchar *format, ...) G_GNUC_PRINTF(5, 6);
|
||||
|
||||
|
||||
#endif /* __GEDIT_DEBUG_H__ */
|
||||
320
gedit/gedit-dirs.c
Executable file
320
gedit/gedit-dirs.c
Executable file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* gedit-dirs.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2008 Ignacio Casal Quinteiro
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
#ifdef OS_OSX
|
||||
#include <ige-mac-bundle.h>
|
||||
#endif
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_user_config_dir (void)
|
||||
{
|
||||
gchar *config_dir = NULL;
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
const gchar *envvar;
|
||||
const gchar *home;
|
||||
|
||||
/* Support old libmate env var */
|
||||
envvar = g_getenv ("MATE22_USER_DIR");
|
||||
if (envvar != NULL)
|
||||
{
|
||||
config_dir = g_build_filename (envvar,
|
||||
"gedit",
|
||||
NULL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
home = g_get_home_dir ();
|
||||
|
||||
if (home != NULL)
|
||||
{
|
||||
config_dir = g_build_filename (home,
|
||||
".mate2",
|
||||
"gedit",
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
#else
|
||||
config_dir = g_build_filename (g_get_user_config_dir (),
|
||||
"gedit",
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
return config_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_user_cache_dir (void)
|
||||
{
|
||||
const gchar *cache_dir;
|
||||
|
||||
cache_dir = g_get_user_cache_dir ();
|
||||
|
||||
return g_build_filename (cache_dir,
|
||||
"gedit",
|
||||
NULL);
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_user_plugins_dir (void)
|
||||
{
|
||||
gchar *config_dir;
|
||||
gchar *plugin_dir;
|
||||
|
||||
config_dir = gedit_dirs_get_user_config_dir ();
|
||||
|
||||
plugin_dir = g_build_filename (config_dir,
|
||||
"plugins",
|
||||
NULL);
|
||||
g_free (config_dir);
|
||||
|
||||
return plugin_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_user_accels_file (void)
|
||||
{
|
||||
gchar *accels = NULL;
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
const gchar *envvar;
|
||||
const gchar *home;
|
||||
|
||||
/* on linux accels are stored in .mate2/accels
|
||||
* for historic reasons (backward compat with the
|
||||
* old libmate that took care of saving them */
|
||||
|
||||
/* Support old libmate env var */
|
||||
envvar = g_getenv ("MATE22_USER_DIR");
|
||||
if (envvar != NULL)
|
||||
{
|
||||
accels = g_build_filename (envvar,
|
||||
"accels",
|
||||
"gedit",
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
home = g_get_home_dir ();
|
||||
|
||||
if (home != NULL)
|
||||
{
|
||||
accels = g_build_filename (home,
|
||||
".mate2",
|
||||
"accels",
|
||||
"gedit",
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
gchar *config_dir = NULL;
|
||||
|
||||
config_dir = gedit_dirs_get_user_config_dir ();
|
||||
accels = g_build_filename (config_dir,
|
||||
"accels",
|
||||
"gedit",
|
||||
NULL);
|
||||
|
||||
g_free (config_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
return accels;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_gedit_data_dir (void)
|
||||
{
|
||||
gchar *data_dir;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *win32_dir;
|
||||
|
||||
win32_dir = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
|
||||
data_dir = g_build_filename (win32_dir,
|
||||
"share",
|
||||
"gedit-2",
|
||||
NULL);
|
||||
|
||||
g_free (win32_dir);
|
||||
#elif defined (OS_OSX)
|
||||
IgeMacBundle *bundle = ige_mac_bundle_get_default ();
|
||||
|
||||
if (ige_mac_bundle_get_is_app_bundle (bundle))
|
||||
{
|
||||
const gchar *bundle_data_dir = ige_mac_bundle_get_datadir (bundle);
|
||||
|
||||
data_dir = g_build_filename (bundle_data_dir,
|
||||
"gedit-2",
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_dir = g_build_filename (DATADIR, "gedit-2", NULL);
|
||||
}
|
||||
#else
|
||||
data_dir = g_build_filename (DATADIR,
|
||||
"gedit-2",
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
return data_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_gedit_locale_dir (void)
|
||||
{
|
||||
gchar *locale_dir;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *win32_dir;
|
||||
|
||||
win32_dir = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
|
||||
locale_dir = g_build_filename (win32_dir,
|
||||
"share",
|
||||
"locale",
|
||||
NULL);
|
||||
|
||||
g_free (win32_dir);
|
||||
#elif defined (OS_OSX)
|
||||
IgeMacBundle *bundle = ige_mac_bundle_get_default ();
|
||||
|
||||
if (ige_mac_bundle_get_is_app_bundle (bundle))
|
||||
{
|
||||
locale_dir = g_strdup (ige_mac_bundle_get_localedir (bundle));
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_dir = g_build_filename (DATADIR,
|
||||
"locale",
|
||||
NULL);
|
||||
}
|
||||
#else
|
||||
locale_dir = g_build_filename (DATADIR,
|
||||
"locale",
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
return locale_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_gedit_lib_dir (void)
|
||||
{
|
||||
gchar *lib_dir;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *win32_dir;
|
||||
|
||||
win32_dir = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
|
||||
lib_dir = g_build_filename (win32_dir,
|
||||
"lib",
|
||||
"gedit-2",
|
||||
NULL);
|
||||
|
||||
g_free (win32_dir);
|
||||
#elif defined (OS_OSX)
|
||||
IgeMacBundle *bundle = ige_mac_bundle_get_default ();
|
||||
|
||||
if (ige_mac_bundle_get_is_app_bundle (bundle))
|
||||
{
|
||||
const gchar *path = ige_mac_bundle_get_resourcesdir (bundle);
|
||||
lib_dir = g_build_filename (path,
|
||||
"lib",
|
||||
"gedit-2",
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
lib_dir = g_build_filename (LIBDIR,
|
||||
"gedit-2",
|
||||
NULL);
|
||||
}
|
||||
#else
|
||||
lib_dir = g_build_filename (LIBDIR,
|
||||
"gedit-2",
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
return lib_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_gedit_plugins_dir (void)
|
||||
{
|
||||
gchar *lib_dir;
|
||||
gchar *plugin_dir;
|
||||
|
||||
lib_dir = gedit_dirs_get_gedit_lib_dir ();
|
||||
|
||||
plugin_dir = g_build_filename (lib_dir,
|
||||
"plugins",
|
||||
NULL);
|
||||
g_free (lib_dir);
|
||||
|
||||
return plugin_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_gedit_plugin_loaders_dir (void)
|
||||
{
|
||||
gchar *lib_dir;
|
||||
gchar *loader_dir;
|
||||
|
||||
lib_dir = gedit_dirs_get_gedit_lib_dir ();
|
||||
|
||||
loader_dir = g_build_filename (lib_dir,
|
||||
"plugin-loaders",
|
||||
NULL);
|
||||
g_free (lib_dir);
|
||||
|
||||
return loader_dir;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_dirs_get_ui_file (const gchar *file)
|
||||
{
|
||||
gchar *datadir;
|
||||
gchar *ui_file;
|
||||
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
|
||||
datadir = gedit_dirs_get_gedit_data_dir ();
|
||||
ui_file = g_build_filename (datadir,
|
||||
"ui",
|
||||
file,
|
||||
NULL);
|
||||
g_free (datadir);
|
||||
|
||||
return ui_file;
|
||||
}
|
||||
54
gedit/gedit-dirs.h
Executable file
54
gedit/gedit-dirs.h
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* gedit-dirs.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2008 Ignacio Casal Quinteiro
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GEDIT_DIRS_H__
|
||||
#define __GEDIT_DIRS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gchar *gedit_dirs_get_user_config_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_user_cache_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_user_plugins_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_user_accels_file (void);
|
||||
|
||||
gchar *gedit_dirs_get_gedit_data_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_gedit_locale_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_gedit_lib_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_gedit_plugins_dir (void);
|
||||
|
||||
gchar *gedit_dirs_get_gedit_plugin_loaders_dir
|
||||
(void);
|
||||
|
||||
gchar *gedit_dirs_get_ui_file (const gchar *file);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DIRS_H__ */
|
||||
479
gedit/gedit-document-input-stream.c
Executable file
479
gedit/gedit-document-input-stream.c
Executable file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* gedit-document-input-stream.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Ignacio Casal Quinteiro
|
||||
*
|
||||
* gedit is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gedit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gedit; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
#include "gedit-document-input-stream.h"
|
||||
#include "gedit-enum-types.h"
|
||||
|
||||
/* NOTE: never use async methods on this stream, the stream is just
|
||||
* a wrapper around GtkTextBuffer api so that we can use GIO Stream
|
||||
* methods, but the undelying code operates on a GtkTextBuffer, so
|
||||
* there is no I/O involved and should be accessed only by the main
|
||||
* thread */
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GeditDocumentInputStream, gedit_document_input_stream, G_TYPE_INPUT_STREAM);
|
||||
|
||||
struct _GeditDocumentInputStreamPrivate
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextMark *pos;
|
||||
gint bytes_partial;
|
||||
|
||||
GeditDocumentNewlineType newline_type;
|
||||
|
||||
guint newline_added : 1;
|
||||
guint is_initialized : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_BUFFER,
|
||||
PROP_NEWLINE_TYPE
|
||||
};
|
||||
|
||||
static gssize gedit_document_input_stream_read (GInputStream *stream,
|
||||
void *buffer,
|
||||
gsize count,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
static gboolean gedit_document_input_stream_close (GInputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
static void
|
||||
gedit_document_input_stream_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentInputStream *stream = GEDIT_DOCUMENT_INPUT_STREAM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_BUFFER:
|
||||
stream->priv->buffer = GTK_TEXT_BUFFER (g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_NEWLINE_TYPE:
|
||||
stream->priv->newline_type = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_input_stream_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentInputStream *stream = GEDIT_DOCUMENT_INPUT_STREAM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_BUFFER:
|
||||
g_value_set_object (value, stream->priv->buffer);
|
||||
break;
|
||||
|
||||
case PROP_NEWLINE_TYPE:
|
||||
g_value_set_enum (value, stream->priv->newline_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_input_stream_class_init (GeditDocumentInputStreamClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditDocumentInputStreamPrivate));
|
||||
|
||||
gobject_class->get_property = gedit_document_input_stream_get_property;
|
||||
gobject_class->set_property = gedit_document_input_stream_set_property;
|
||||
|
||||
stream_class->read_fn = gedit_document_input_stream_read;
|
||||
stream_class->close_fn = gedit_document_input_stream_close;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_BUFFER,
|
||||
g_param_spec_object ("buffer",
|
||||
"Buffer",
|
||||
"The buffer which is read",
|
||||
GTK_TYPE_TEXT_BUFFER,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* GeditDocumentInputStream:newline-type:
|
||||
*
|
||||
* The :newline-type property determines what is considered
|
||||
* as a line ending when reading complete lines from the stream.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NEWLINE_TYPE,
|
||||
g_param_spec_enum ("newline-type",
|
||||
"Newline type",
|
||||
"The accepted types of line ending",
|
||||
GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_NAME |
|
||||
G_PARAM_STATIC_BLURB |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_input_stream_init (GeditDocumentInputStream *stream)
|
||||
{
|
||||
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
|
||||
GEDIT_TYPE_DOCUMENT_INPUT_STREAM,
|
||||
GeditDocumentInputStreamPrivate);
|
||||
}
|
||||
|
||||
static gsize
|
||||
get_new_line_size (GeditDocumentInputStream *stream)
|
||||
{
|
||||
gsize ret;
|
||||
|
||||
switch (stream->priv->newline_type)
|
||||
{
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_CR:
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_LF:
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
|
||||
ret = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_document_input_stream_new:
|
||||
* @buffer: a #GtkTextBuffer
|
||||
*
|
||||
* Reads the data from @buffer.
|
||||
*
|
||||
* Returns: a new #GInputStream to read @buffer
|
||||
*/
|
||||
GInputStream *
|
||||
gedit_document_input_stream_new (GtkTextBuffer *buffer,
|
||||
GeditDocumentNewlineType type)
|
||||
{
|
||||
GeditDocumentInputStream *stream;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
|
||||
|
||||
stream = g_object_new (GEDIT_TYPE_DOCUMENT_INPUT_STREAM,
|
||||
"buffer", buffer,
|
||||
"newline-type", type,
|
||||
NULL);
|
||||
|
||||
return G_INPUT_STREAM (stream);
|
||||
}
|
||||
|
||||
gsize
|
||||
gedit_document_input_stream_get_total_size (GeditDocumentInputStream *stream)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_INPUT_STREAM (stream), 0);
|
||||
|
||||
return gtk_text_buffer_get_char_count (stream->priv->buffer);
|
||||
}
|
||||
|
||||
gsize
|
||||
gedit_document_input_stream_tell (GeditDocumentInputStream *stream)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_INPUT_STREAM (stream), 0);
|
||||
|
||||
/* FIXME: is this potentially inefficient? If yes, we could keep
|
||||
track of the offset internally, assuming the mark doesn't move
|
||||
during the operation */
|
||||
if (!stream->priv->is_initialized)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkTextIter iter;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
|
||||
&iter,
|
||||
stream->priv->pos);
|
||||
return gtk_text_iter_get_offset (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
get_new_line (GeditDocumentInputStream *stream)
|
||||
{
|
||||
const gchar *ret;
|
||||
|
||||
switch (stream->priv->newline_type)
|
||||
{
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_CR:
|
||||
ret = "\r";
|
||||
break;
|
||||
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_LF:
|
||||
ret = "\n";
|
||||
break;
|
||||
|
||||
case GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
|
||||
ret = "\r\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
ret = "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gsize
|
||||
read_line (GeditDocumentInputStream *stream,
|
||||
gchar *outbuf,
|
||||
gsize space_left)
|
||||
{
|
||||
GtkTextIter start, next, end;
|
||||
gchar *buf;
|
||||
gint bytes; /* int since it's what iter_get_offset returns */
|
||||
gsize bytes_to_write, newline_size, read;
|
||||
const gchar *newline;
|
||||
gboolean is_last;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
|
||||
&start,
|
||||
stream->priv->pos);
|
||||
|
||||
if (gtk_text_iter_is_end (&start))
|
||||
return 0;
|
||||
|
||||
end = next = start;
|
||||
newline = get_new_line (stream);
|
||||
|
||||
/* Check needed for empty lines */
|
||||
if (!gtk_text_iter_ends_line (&end))
|
||||
gtk_text_iter_forward_to_line_end (&end);
|
||||
|
||||
gtk_text_iter_forward_line (&next);
|
||||
|
||||
buf = gtk_text_iter_get_slice (&start, &end);
|
||||
|
||||
/* the bytes of a line includes also the newline, so with the
|
||||
offsets we remove the newline and we add the new newline size */
|
||||
bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;
|
||||
|
||||
/* bytes_in_line includes the newlines, so we remove that assuming that
|
||||
they are single byte characters */
|
||||
bytes = bytes - (gtk_text_iter_get_offset (&next) - gtk_text_iter_get_offset (&end));
|
||||
is_last = gtk_text_iter_is_end (&end);
|
||||
|
||||
/* bytes_to_write contains the amount of bytes we would like to write.
|
||||
This means its the amount of bytes in the line (without the newline
|
||||
in the buffer) + the amount of bytes for the newline we want to
|
||||
write (newline_size) */
|
||||
bytes_to_write = bytes;
|
||||
|
||||
/* do not add the new newline_size for the last line */
|
||||
newline_size = get_new_line_size (stream);
|
||||
if (!is_last)
|
||||
bytes_to_write += newline_size;
|
||||
|
||||
if (bytes_to_write > space_left)
|
||||
{
|
||||
gchar *ptr;
|
||||
gint char_offset;
|
||||
gint written;
|
||||
gsize to_write;
|
||||
|
||||
/* Here the line does not fit in the buffer, we thus write
|
||||
the amount of bytes we can still fit, storing the position
|
||||
for the next read with the mark. Do not try to write the
|
||||
new newline in this case, it will be handled in the next
|
||||
iteration */
|
||||
to_write = MIN (space_left, bytes);
|
||||
ptr = buf;
|
||||
written = 0;
|
||||
char_offset = 0;
|
||||
|
||||
while (written < to_write)
|
||||
{
|
||||
gint w;
|
||||
|
||||
ptr = g_utf8_next_char (ptr);
|
||||
w = (ptr - buf);
|
||||
if (w > to_write)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
written = w;
|
||||
++char_offset;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (outbuf, buf, written);
|
||||
|
||||
/* Note: offset is one past what we wrote */
|
||||
gtk_text_iter_forward_chars (&start, char_offset);
|
||||
stream->priv->bytes_partial += written;
|
||||
read = written;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First just copy the bytes without the newline */
|
||||
memcpy (outbuf, buf, bytes);
|
||||
|
||||
/* Then add the newline, but not for the last line */
|
||||
if (!is_last)
|
||||
{
|
||||
memcpy (outbuf + bytes, newline, newline_size);
|
||||
}
|
||||
|
||||
start = next;
|
||||
stream->priv->bytes_partial = 0;
|
||||
read = bytes_to_write;
|
||||
}
|
||||
|
||||
gtk_text_buffer_move_mark (stream->priv->buffer,
|
||||
stream->priv->pos,
|
||||
&start);
|
||||
|
||||
g_free (buf);
|
||||
return read;
|
||||
}
|
||||
|
||||
static gssize
|
||||
gedit_document_input_stream_read (GInputStream *stream,
|
||||
void *buffer,
|
||||
gsize count,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GeditDocumentInputStream *dstream;
|
||||
GtkTextIter iter;
|
||||
gssize space_left, read, n;
|
||||
|
||||
dstream = GEDIT_DOCUMENT_INPUT_STREAM (stream);
|
||||
|
||||
if (count < 6)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
|
||||
"Not enougth space in destination");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||
return -1;
|
||||
|
||||
/* Initialize the mark to the first char in the text buffer */
|
||||
if (!dstream->priv->is_initialized)
|
||||
{
|
||||
gtk_text_buffer_get_start_iter (dstream->priv->buffer, &iter);
|
||||
dstream->priv->pos = gtk_text_buffer_create_mark (dstream->priv->buffer,
|
||||
NULL,
|
||||
&iter,
|
||||
FALSE);
|
||||
|
||||
dstream->priv->is_initialized = TRUE;
|
||||
}
|
||||
|
||||
space_left = count;
|
||||
read = 0;
|
||||
|
||||
do
|
||||
{
|
||||
n = read_line (dstream, buffer + read, space_left);
|
||||
read += n;
|
||||
space_left -= n;
|
||||
} while (space_left > 0 && n != 0 && dstream->priv->bytes_partial == 0);
|
||||
|
||||
/* Make sure that non-empty files are always terminated with \n (see bug #95676).
|
||||
* Note that we strip the trailing \n when loading the file */
|
||||
gtk_text_buffer_get_iter_at_mark (dstream->priv->buffer,
|
||||
&iter,
|
||||
dstream->priv->pos);
|
||||
|
||||
if (gtk_text_iter_is_end (&iter) &&
|
||||
!gtk_text_iter_is_start (&iter))
|
||||
{
|
||||
gssize newline_size;
|
||||
|
||||
newline_size = get_new_line_size (dstream);
|
||||
|
||||
if (space_left >= newline_size &&
|
||||
!dstream->priv->newline_added)
|
||||
{
|
||||
const gchar *newline;
|
||||
|
||||
newline = get_new_line (dstream);
|
||||
|
||||
memcpy (buffer + read, newline, newline_size);
|
||||
|
||||
read += newline_size;
|
||||
dstream->priv->newline_added = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gedit_document_input_stream_close (GInputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GeditDocumentInputStream *dstream = GEDIT_DOCUMENT_INPUT_STREAM (stream);
|
||||
|
||||
dstream->priv->newline_added = FALSE;
|
||||
|
||||
if (dstream->priv->is_initialized)
|
||||
{
|
||||
gtk_text_buffer_delete_mark (dstream->priv->buffer, dstream->priv->pos);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
68
gedit/gedit-document-input-stream.h
Executable file
68
gedit/gedit-document-input-stream.h
Executable file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* gedit-document-input-stream.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Ignacio Casal Quinteiro
|
||||
*
|
||||
* gedit is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gedit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gedit; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DOCUMENT_INPUT_STREAM_H__
|
||||
#define __GEDIT_DOCUMENT_INPUT_STREAM_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-document.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_DOCUMENT_INPUT_STREAM (gedit_document_input_stream_get_type ())
|
||||
#define GEDIT_DOCUMENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_INPUT_STREAM, GeditDocumentInputStream))
|
||||
#define GEDIT_DOCUMENT_INPUT_STREAM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_INPUT_STREAM, GeditDocumentInputStream const))
|
||||
#define GEDIT_DOCUMENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENT_INPUT_STREAM, GeditDocumentInputStreamClass))
|
||||
#define GEDIT_IS_DOCUMENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DOCUMENT_INPUT_STREAM))
|
||||
#define GEDIT_IS_DOCUMENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_INPUT_STREAM))
|
||||
#define GEDIT_DOCUMENT_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENT_INPUT_STREAM, GeditDocumentInputStreamClass))
|
||||
|
||||
typedef struct _GeditDocumentInputStream GeditDocumentInputStream;
|
||||
typedef struct _GeditDocumentInputStreamClass GeditDocumentInputStreamClass;
|
||||
typedef struct _GeditDocumentInputStreamPrivate GeditDocumentInputStreamPrivate;
|
||||
|
||||
struct _GeditDocumentInputStream
|
||||
{
|
||||
GInputStream parent;
|
||||
|
||||
GeditDocumentInputStreamPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditDocumentInputStreamClass
|
||||
{
|
||||
GInputStreamClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_document_input_stream_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GInputStream *gedit_document_input_stream_new (GtkTextBuffer *buffer,
|
||||
GeditDocumentNewlineType type);
|
||||
|
||||
gsize gedit_document_input_stream_get_total_size (GeditDocumentInputStream *stream);
|
||||
|
||||
gsize gedit_document_input_stream_tell (GeditDocumentInputStream *stream);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENT_INPUT_STREAM_H__ */
|
||||
357
gedit/gedit-document-loader.c
Executable file
357
gedit/gedit-document-loader.c
Executable file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* gedit-document-loader.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-document-loader.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-metadata-manager.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-marshal.h"
|
||||
#include "gedit-enum-types.h"
|
||||
|
||||
/* Those are for the the gedit_document_loader_new() factory */
|
||||
#include "gedit-gio-document-loader.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(GeditDocumentLoader, gedit_document_loader, G_TYPE_OBJECT)
|
||||
|
||||
/* Signals */
|
||||
|
||||
enum {
|
||||
LOADING,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
/* Properties */
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DOCUMENT,
|
||||
PROP_URI,
|
||||
PROP_ENCODING,
|
||||
PROP_NEWLINE_TYPE
|
||||
};
|
||||
|
||||
static void
|
||||
gedit_document_loader_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_return_if_fail (loader->document == NULL);
|
||||
loader->document = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_return_if_fail (loader->uri == NULL);
|
||||
loader->uri = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_return_if_fail (loader->encoding == NULL);
|
||||
loader->encoding = g_value_get_boxed (value);
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
loader->auto_detected_newline_type = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_loader_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, loader->document);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, loader->uri);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_value_set_boxed (value, gedit_document_loader_get_encoding (loader));
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
g_value_set_enum (value, loader->auto_detected_newline_type);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_loader_finalize (GObject *object)
|
||||
{
|
||||
GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (object);
|
||||
|
||||
g_free (loader->uri);
|
||||
|
||||
if (loader->info)
|
||||
g_object_unref (loader->info);
|
||||
|
||||
G_OBJECT_CLASS (gedit_document_loader_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_loader_dispose (GObject *object)
|
||||
{
|
||||
GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (object);
|
||||
|
||||
if (loader->info != NULL)
|
||||
{
|
||||
g_object_unref (loader->info);
|
||||
loader->info = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_document_loader_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_loader_class_init (GeditDocumentLoaderClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_document_loader_finalize;
|
||||
object_class->dispose = gedit_document_loader_dispose;
|
||||
object_class->get_property = gedit_document_loader_get_property;
|
||||
object_class->set_property = gedit_document_loader_set_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DOCUMENT,
|
||||
g_param_spec_object ("document",
|
||||
"Document",
|
||||
"The GeditDocument this GeditDocumentLoader is associated with",
|
||||
GEDIT_TYPE_DOCUMENT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_URI,
|
||||
g_param_spec_string ("uri",
|
||||
"URI",
|
||||
"The URI this GeditDocumentLoader loads the document from",
|
||||
"",
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ENCODING,
|
||||
g_param_spec_boxed ("encoding",
|
||||
"Encoding",
|
||||
"The encoding of the saved file",
|
||||
GEDIT_TYPE_ENCODING,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_NEWLINE_TYPE,
|
||||
g_param_spec_enum ("newline-type",
|
||||
"Newline type",
|
||||
"The accepted types of line ending",
|
||||
GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_NAME |
|
||||
G_PARAM_STATIC_BLURB));
|
||||
|
||||
signals[LOADING] =
|
||||
g_signal_new ("loading",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditDocumentLoaderClass, loading),
|
||||
NULL, NULL,
|
||||
gedit_marshal_VOID__BOOLEAN_POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_loader_init (GeditDocumentLoader *loader)
|
||||
{
|
||||
loader->used = FALSE;
|
||||
loader->auto_detected_newline_type = GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_document_loader_loading (GeditDocumentLoader *loader,
|
||||
gboolean completed,
|
||||
GError *error)
|
||||
{
|
||||
/* the object will be unrefed in the callback of the loading signal
|
||||
* (when completed == TRUE), so we need to prevent finalization.
|
||||
*/
|
||||
if (completed)
|
||||
{
|
||||
g_object_ref (loader);
|
||||
}
|
||||
|
||||
g_signal_emit (loader, signals[LOADING], 0, completed, error);
|
||||
|
||||
if (completed)
|
||||
{
|
||||
if (error == NULL)
|
||||
gedit_debug_message (DEBUG_LOADER, "load completed");
|
||||
else
|
||||
gedit_debug_message (DEBUG_LOADER, "load failed");
|
||||
|
||||
g_object_unref (loader);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a factory method that returns an appopriate loader
|
||||
* for the given uri.
|
||||
*/
|
||||
GeditDocumentLoader *
|
||||
gedit_document_loader_new (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding)
|
||||
{
|
||||
GeditDocumentLoader *loader;
|
||||
GType loader_type;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
/* At the moment we just use gio loader in all cases...
|
||||
* In the future it would be great to have a PolicyKit
|
||||
* loader to get permission to save systen files etc */
|
||||
loader_type = GEDIT_TYPE_GIO_DOCUMENT_LOADER;
|
||||
|
||||
loader = GEDIT_DOCUMENT_LOADER (g_object_new (loader_type,
|
||||
"document", doc,
|
||||
"uri", uri,
|
||||
"encoding", encoding,
|
||||
NULL));
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
/* If enconding == NULL, the encoding will be autodetected */
|
||||
void
|
||||
gedit_document_loader_load (GeditDocumentLoader *loader)
|
||||
{
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
g_return_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader));
|
||||
|
||||
/* the loader can be used just once, then it must be thrown away */
|
||||
g_return_if_fail (loader->used == FALSE);
|
||||
loader->used = TRUE;
|
||||
|
||||
GEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->load (loader);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_document_loader_cancel (GeditDocumentLoader *loader)
|
||||
{
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), FALSE);
|
||||
|
||||
return GEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->cancel (loader);
|
||||
}
|
||||
|
||||
GeditDocument *
|
||||
gedit_document_loader_get_document (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
return loader->document;
|
||||
}
|
||||
|
||||
/* Returns STDIN_URI if loading from stdin */
|
||||
const gchar *
|
||||
gedit_document_loader_get_uri (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
return loader->uri;
|
||||
}
|
||||
|
||||
goffset
|
||||
gedit_document_loader_get_bytes_read (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), 0);
|
||||
|
||||
return GEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->get_bytes_read (loader);
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_document_loader_get_encoding (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
if (loader->encoding != NULL)
|
||||
return loader->encoding;
|
||||
|
||||
g_return_val_if_fail (loader->auto_detected_encoding != NULL,
|
||||
gedit_encoding_get_current ());
|
||||
|
||||
return loader->auto_detected_encoding;
|
||||
}
|
||||
|
||||
GeditDocumentNewlineType
|
||||
gedit_document_loader_get_newline_type (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader),
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF);
|
||||
|
||||
return loader->auto_detected_newline_type;
|
||||
}
|
||||
|
||||
GFileInfo *
|
||||
gedit_document_loader_get_info (GeditDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
return loader->info;
|
||||
}
|
||||
130
gedit/gedit-document-loader.h
Executable file
130
gedit/gedit-document-loader.h
Executable file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* gedit-document-loader.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DOCUMENT_LOADER_H__
|
||||
#define __GEDIT_DOCUMENT_LOADER_H__
|
||||
|
||||
#include <gedit/gedit-document.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_DOCUMENT_LOADER (gedit_document_loader_get_type())
|
||||
#define GEDIT_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoader))
|
||||
#define GEDIT_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoaderClass))
|
||||
#define GEDIT_IS_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT_LOADER))
|
||||
#define GEDIT_IS_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_LOADER))
|
||||
#define GEDIT_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoaderClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditDocumentLoaderPrivate GeditDocumentLoaderPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditDocumentLoader GeditDocumentLoader;
|
||||
|
||||
struct _GeditDocumentLoader
|
||||
{
|
||||
GObject object;
|
||||
|
||||
GeditDocument *document;
|
||||
gboolean used;
|
||||
|
||||
/* Info on the current file */
|
||||
GFileInfo *info;
|
||||
gchar *uri;
|
||||
const GeditEncoding *encoding;
|
||||
const GeditEncoding *auto_detected_encoding;
|
||||
GeditDocumentNewlineType auto_detected_newline_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditDocumentLoaderClass GeditDocumentLoaderClass;
|
||||
|
||||
struct _GeditDocumentLoaderClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* loading) (GeditDocumentLoader *loader,
|
||||
gboolean completed,
|
||||
const GError *error);
|
||||
|
||||
/* VTable */
|
||||
void (* load) (GeditDocumentLoader *loader);
|
||||
gboolean (* cancel) (GeditDocumentLoader *loader);
|
||||
goffset (* get_bytes_read) (GeditDocumentLoader *loader);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_document_loader_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* If enconding == NULL, the encoding will be autodetected */
|
||||
GeditDocumentLoader *gedit_document_loader_new (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding);
|
||||
|
||||
void gedit_document_loader_loading (GeditDocumentLoader *loader,
|
||||
gboolean completed,
|
||||
GError *error);
|
||||
|
||||
void gedit_document_loader_load (GeditDocumentLoader *loader);
|
||||
#if 0
|
||||
gboolean gedit_document_loader_load_from_stdin (GeditDocumentLoader *loader);
|
||||
#endif
|
||||
gboolean gedit_document_loader_cancel (GeditDocumentLoader *loader);
|
||||
|
||||
GeditDocument *gedit_document_loader_get_document (GeditDocumentLoader *loader);
|
||||
|
||||
/* Returns STDIN_URI if loading from stdin */
|
||||
#define STDIN_URI "stdin:"
|
||||
const gchar *gedit_document_loader_get_uri (GeditDocumentLoader *loader);
|
||||
|
||||
const GeditEncoding *gedit_document_loader_get_encoding (GeditDocumentLoader *loader);
|
||||
|
||||
GeditDocumentNewlineType gedit_document_loader_get_newline_type (GeditDocumentLoader *loader);
|
||||
|
||||
goffset gedit_document_loader_get_bytes_read (GeditDocumentLoader *loader);
|
||||
|
||||
/* You can get from the info: content_type, time_modified, standard_size, access_can_write
|
||||
and also the metadata*/
|
||||
GFileInfo *gedit_document_loader_get_info (GeditDocumentLoader *loader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENT_LOADER_H__ */
|
||||
391
gedit/gedit-document-output-stream.c
Executable file
391
gedit/gedit-document-output-stream.c
Executable file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* gedit-document-output-stream.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Ignacio Casal Quinteiro
|
||||
*
|
||||
* gedit is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gedit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gedit; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gio/gio.h>
|
||||
#include "gedit-document-output-stream.h"
|
||||
|
||||
/* NOTE: never use async methods on this stream, the stream is just
|
||||
* a wrapper around GtkTextBuffer api so that we can use GIO Stream
|
||||
* methods, but the undelying code operates on a GtkTextBuffer, so
|
||||
* there is no I/O involved and should be accessed only by the main
|
||||
* thread */
|
||||
|
||||
#define GEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object),\
|
||||
GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM,\
|
||||
GeditDocumentOutputStreamPrivate))
|
||||
|
||||
#define MAX_UNICHAR_LEN 6
|
||||
|
||||
struct _GeditDocumentOutputStreamPrivate
|
||||
{
|
||||
GeditDocument *doc;
|
||||
GtkTextIter pos;
|
||||
|
||||
gchar *buffer;
|
||||
gsize buflen;
|
||||
|
||||
guint is_initialized : 1;
|
||||
guint is_closed : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DOCUMENT
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GeditDocumentOutputStream, gedit_document_output_stream, G_TYPE_OUTPUT_STREAM)
|
||||
|
||||
static gssize gedit_document_output_stream_write (GOutputStream *stream,
|
||||
const void *buffer,
|
||||
gsize count,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
static gboolean gedit_document_output_stream_close (GOutputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
stream->priv->doc = GEDIT_DOCUMENT (g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, stream->priv->doc);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_finalize (GObject *object)
|
||||
{
|
||||
GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
|
||||
|
||||
g_free (stream->priv->buffer);
|
||||
|
||||
G_OBJECT_CLASS (gedit_document_output_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_constructed (GObject *object)
|
||||
{
|
||||
GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
|
||||
|
||||
if (!stream->priv->doc)
|
||||
{
|
||||
g_critical ("This should never happen, a problem happened constructing the Document Output Stream!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init the undoable action */
|
||||
gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
|
||||
/* clear the buffer */
|
||||
gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->doc),
|
||||
"", 0);
|
||||
gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
|
||||
FALSE);
|
||||
|
||||
gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_class_init (GeditDocumentOutputStreamClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->get_property = gedit_document_output_stream_get_property;
|
||||
object_class->set_property = gedit_document_output_stream_set_property;
|
||||
object_class->finalize = gedit_document_output_stream_finalize;
|
||||
object_class->constructed = gedit_document_output_stream_constructed;
|
||||
|
||||
stream_class->write_fn = gedit_document_output_stream_write;
|
||||
stream_class->close_fn = gedit_document_output_stream_close;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DOCUMENT,
|
||||
g_param_spec_object ("document",
|
||||
"Document",
|
||||
"The document which is written",
|
||||
GEDIT_TYPE_DOCUMENT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditDocumentOutputStreamPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_output_stream_init (GeditDocumentOutputStream *stream)
|
||||
{
|
||||
stream->priv = GEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE (stream);
|
||||
|
||||
stream->priv->buffer = NULL;
|
||||
stream->priv->buflen = 0;
|
||||
|
||||
stream->priv->is_initialized = FALSE;
|
||||
stream->priv->is_closed = FALSE;
|
||||
}
|
||||
|
||||
static GeditDocumentNewlineType
|
||||
get_newline_type (GtkTextIter *end)
|
||||
{
|
||||
GeditDocumentNewlineType res;
|
||||
GtkTextIter copy;
|
||||
gunichar c;
|
||||
|
||||
copy = *end;
|
||||
c = gtk_text_iter_get_char (©);
|
||||
|
||||
if (g_unichar_break_type (c) == G_UNICODE_BREAK_CARRIAGE_RETURN)
|
||||
{
|
||||
if (gtk_text_iter_forward_char (©) &&
|
||||
g_unichar_break_type (gtk_text_iter_get_char (©)) == G_UNICODE_BREAK_LINE_FEED)
|
||||
{
|
||||
res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = GEDIT_DOCUMENT_NEWLINE_TYPE_LF;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GOutputStream *
|
||||
gedit_document_output_stream_new (GeditDocument *doc)
|
||||
{
|
||||
return G_OUTPUT_STREAM (g_object_new (GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM,
|
||||
"document", doc, NULL));
|
||||
}
|
||||
|
||||
GeditDocumentNewlineType
|
||||
gedit_document_output_stream_detect_newline_type (GeditDocumentOutputStream *stream)
|
||||
{
|
||||
GeditDocumentNewlineType type;
|
||||
GtkTextIter iter;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_OUTPUT_STREAM (stream),
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
|
||||
|
||||
type = GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
|
||||
|
||||
gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->doc),
|
||||
&iter);
|
||||
|
||||
if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
|
||||
{
|
||||
type = get_newline_type (&iter);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* If the last char is a newline, remove it from the buffer (otherwise
|
||||
GtkTextView shows it as an empty line). See bug #324942. */
|
||||
static void
|
||||
remove_ending_newline (GeditDocumentOutputStream *stream)
|
||||
{
|
||||
GtkTextIter end;
|
||||
GtkTextIter start;
|
||||
|
||||
gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc), &end);
|
||||
start = end;
|
||||
|
||||
gtk_text_iter_set_line_offset (&start, 0);
|
||||
|
||||
if (gtk_text_iter_ends_line (&start) &&
|
||||
gtk_text_iter_backward_line (&start))
|
||||
{
|
||||
if (!gtk_text_iter_ends_line (&start))
|
||||
{
|
||||
gtk_text_iter_forward_to_line_end (&start);
|
||||
}
|
||||
|
||||
/* Delete the empty line which is from 'start' to 'end' */
|
||||
gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->doc),
|
||||
&start,
|
||||
&end);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
end_append_text_to_document (GeditDocumentOutputStream *stream)
|
||||
{
|
||||
remove_ending_newline (stream);
|
||||
|
||||
gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
|
||||
FALSE);
|
||||
|
||||
gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
|
||||
}
|
||||
|
||||
static gssize
|
||||
gedit_document_output_stream_write (GOutputStream *stream,
|
||||
const void *buffer,
|
||||
gsize count,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GeditDocumentOutputStream *ostream;
|
||||
gchar *text;
|
||||
gsize len;
|
||||
gboolean freetext = FALSE;
|
||||
const gchar *end;
|
||||
gsize nvalid;
|
||||
gboolean valid;
|
||||
|
||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||
return -1;
|
||||
|
||||
ostream = GEDIT_DOCUMENT_OUTPUT_STREAM (stream);
|
||||
|
||||
if (!ostream->priv->is_initialized)
|
||||
{
|
||||
/* Init the undoable action */
|
||||
gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (ostream->priv->doc));
|
||||
|
||||
gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->doc),
|
||||
&ostream->priv->pos);
|
||||
ostream->priv->is_initialized = TRUE;
|
||||
}
|
||||
|
||||
if (ostream->priv->buflen > 0)
|
||||
{
|
||||
len = ostream->priv->buflen + count;
|
||||
text = g_new (gchar , len + 1);
|
||||
memcpy (text, ostream->priv->buffer, ostream->priv->buflen);
|
||||
memcpy (text + ostream->priv->buflen, buffer, count);
|
||||
text[len] = '\0';
|
||||
g_free (ostream->priv->buffer);
|
||||
ostream->priv->buffer = NULL;
|
||||
ostream->priv->buflen = 0;
|
||||
freetext = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = (gchar *) buffer;
|
||||
len = count;
|
||||
}
|
||||
|
||||
/* validate */
|
||||
valid = g_utf8_validate (text, len, &end);
|
||||
nvalid = end - text;
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
gsize remainder;
|
||||
|
||||
remainder = len - nvalid;
|
||||
|
||||
if ((remainder < MAX_UNICHAR_LEN) &&
|
||||
(g_utf8_get_char_validated (text + nvalid, remainder) == (gunichar)-2))
|
||||
{
|
||||
ostream->priv->buffer = g_strndup (end, remainder);
|
||||
ostream->priv->buflen = remainder;
|
||||
len -= remainder;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: we cuould escape invalid text and tag it in red
|
||||
* and make the doc readonly.
|
||||
*/
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||
_("Invalid UTF-8 sequence in input"));
|
||||
|
||||
if (freetext)
|
||||
g_free (text);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc),
|
||||
&ostream->priv->pos, text, len);
|
||||
|
||||
if (freetext)
|
||||
g_free (text);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gedit_document_output_stream_close (GOutputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GeditDocumentOutputStream *ostream = GEDIT_DOCUMENT_OUTPUT_STREAM (stream);
|
||||
|
||||
if (!ostream->priv->is_closed && ostream->priv->is_initialized)
|
||||
{
|
||||
end_append_text_to_document (ostream);
|
||||
ostream->priv->is_closed = TRUE;
|
||||
}
|
||||
|
||||
if (ostream->priv->buflen > 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||
_("Incomplete UTF-8 sequence in input"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
64
gedit/gedit-document-output-stream.h
Executable file
64
gedit/gedit-document-output-stream.h
Executable file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* gedit-document-output-stream.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2010 - Ignacio Casal Quinteiro
|
||||
*
|
||||
* gedit is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gedit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with gedit; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GEDIT_DOCUMENT_OUTPUT_STREAM_H__
|
||||
#define __GEDIT_DOCUMENT_OUTPUT_STREAM_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "gedit-document.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM (gedit_document_output_stream_get_type ())
|
||||
#define GEDIT_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStream))
|
||||
#define GEDIT_DOCUMENT_OUTPUT_STREAM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStream const))
|
||||
#define GEDIT_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStreamClass))
|
||||
#define GEDIT_IS_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
|
||||
#define GEDIT_IS_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
|
||||
#define GEDIT_DOCUMENT_OUTPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStreamClass))
|
||||
|
||||
typedef struct _GeditDocumentOutputStream GeditDocumentOutputStream;
|
||||
typedef struct _GeditDocumentOutputStreamClass GeditDocumentOutputStreamClass;
|
||||
typedef struct _GeditDocumentOutputStreamPrivate GeditDocumentOutputStreamPrivate;
|
||||
|
||||
struct _GeditDocumentOutputStream
|
||||
{
|
||||
GOutputStream parent;
|
||||
|
||||
GeditDocumentOutputStreamPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditDocumentOutputStreamClass
|
||||
{
|
||||
GOutputStreamClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_document_output_stream_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GOutputStream *gedit_document_output_stream_new (GeditDocument *doc);
|
||||
|
||||
GeditDocumentNewlineType gedit_document_output_stream_detect_newline_type (GeditDocumentOutputStream *stream);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENT_OUTPUT_STREAM_H__ */
|
||||
359
gedit/gedit-document-saver.c
Executable file
359
gedit/gedit-document-saver.c
Executable file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* gedit-document-saver.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005-2006 - Paolo Borelli and Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Borelli, Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-document-saver.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-marshal.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-enum-types.h"
|
||||
#include "gedit-gio-document-saver.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(GeditDocumentSaver, gedit_document_saver, G_TYPE_OBJECT)
|
||||
|
||||
/* Signals */
|
||||
|
||||
enum {
|
||||
SAVING,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
/* Properties */
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DOCUMENT,
|
||||
PROP_URI,
|
||||
PROP_ENCODING,
|
||||
PROP_NEWLINE_TYPE,
|
||||
PROP_FLAGS
|
||||
};
|
||||
|
||||
static void
|
||||
gedit_document_saver_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_return_if_fail (saver->document == NULL);
|
||||
saver->document = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_return_if_fail (saver->uri == NULL);
|
||||
saver->uri = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_return_if_fail (saver->encoding == NULL);
|
||||
saver->encoding = g_value_get_boxed (value);
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
saver->newline_type = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
saver->flags = g_value_get_flags (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_saver_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, saver->document);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, saver->uri);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_value_set_boxed (value, saver->encoding);
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
g_value_set_enum (value, saver->newline_type);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
g_value_set_flags (value, saver->flags);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_saver_finalize (GObject *object)
|
||||
{
|
||||
GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (object);
|
||||
|
||||
g_free (saver->uri);
|
||||
|
||||
G_OBJECT_CLASS (gedit_document_saver_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_saver_dispose (GObject *object)
|
||||
{
|
||||
GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (object);
|
||||
|
||||
if (saver->info != NULL)
|
||||
{
|
||||
g_object_unref (saver->info);
|
||||
saver->info = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_document_saver_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_saver_class_init (GeditDocumentSaverClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_document_saver_finalize;
|
||||
object_class->dispose = gedit_document_saver_dispose;
|
||||
object_class->set_property = gedit_document_saver_set_property;
|
||||
object_class->get_property = gedit_document_saver_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DOCUMENT,
|
||||
g_param_spec_object ("document",
|
||||
"Document",
|
||||
"The GeditDocument this GeditDocumentSaver is associated with",
|
||||
GEDIT_TYPE_DOCUMENT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_URI,
|
||||
g_param_spec_string ("uri",
|
||||
"URI",
|
||||
"The URI this GeditDocumentSaver saves the document to",
|
||||
"",
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ENCODING,
|
||||
g_param_spec_boxed ("encoding",
|
||||
"URI",
|
||||
"The encoding of the saved file",
|
||||
GEDIT_TYPE_ENCODING,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_NEWLINE_TYPE,
|
||||
g_param_spec_enum ("newline-type",
|
||||
"Newline type",
|
||||
"The accepted types of line ending",
|
||||
GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_NAME |
|
||||
G_PARAM_STATIC_BLURB |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FLAGS,
|
||||
g_param_spec_flags ("flags",
|
||||
"Flags",
|
||||
"The flags for the saving operation",
|
||||
GEDIT_TYPE_DOCUMENT_SAVE_FLAGS,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
signals[SAVING] =
|
||||
g_signal_new ("saving",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditDocumentSaverClass, saving),
|
||||
NULL, NULL,
|
||||
gedit_marshal_VOID__BOOLEAN_POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_document_saver_init (GeditDocumentSaver *saver)
|
||||
{
|
||||
saver->used = FALSE;
|
||||
}
|
||||
|
||||
GeditDocumentSaver *
|
||||
gedit_document_saver_new (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
GeditDocumentNewlineType newline_type,
|
||||
GeditDocumentSaveFlags flags)
|
||||
{
|
||||
GeditDocumentSaver *saver;
|
||||
GType saver_type;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
saver_type = GEDIT_TYPE_GIO_DOCUMENT_SAVER;
|
||||
|
||||
if (encoding == NULL)
|
||||
encoding = gedit_encoding_get_utf8 ();
|
||||
|
||||
saver = GEDIT_DOCUMENT_SAVER (g_object_new (saver_type,
|
||||
"document", doc,
|
||||
"uri", uri,
|
||||
"encoding", encoding,
|
||||
"newline_type", newline_type,
|
||||
"flags", flags,
|
||||
NULL));
|
||||
|
||||
return saver;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_document_saver_saving (GeditDocumentSaver *saver,
|
||||
gboolean completed,
|
||||
GError *error)
|
||||
{
|
||||
/* the object will be unrefed in the callback of the saving
|
||||
* signal, so we need to prevent finalization.
|
||||
*/
|
||||
if (completed)
|
||||
{
|
||||
g_object_ref (saver);
|
||||
}
|
||||
|
||||
g_signal_emit (saver, signals[SAVING], 0, completed, error);
|
||||
|
||||
if (completed)
|
||||
{
|
||||
if (error == NULL)
|
||||
gedit_debug_message (DEBUG_SAVER, "save completed");
|
||||
else
|
||||
gedit_debug_message (DEBUG_SAVER, "save failed");
|
||||
|
||||
g_object_unref (saver);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gedit_document_saver_save (GeditDocumentSaver *saver,
|
||||
GTimeVal *old_mtime)
|
||||
{
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
g_return_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver));
|
||||
g_return_if_fail (saver->uri != NULL && strlen (saver->uri) > 0);
|
||||
|
||||
g_return_if_fail (saver->used == FALSE);
|
||||
saver->used = TRUE;
|
||||
|
||||
// CHECK:
|
||||
// - sanity check a max len for the uri?
|
||||
// report async (in an idle handler) or sync (bool ret)
|
||||
// async is extra work here, sync is special casing in the caller
|
||||
|
||||
/* never keep backup of autosaves */
|
||||
if ((saver->flags & GEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP) != 0)
|
||||
saver->keep_backup = FALSE;
|
||||
else
|
||||
saver->keep_backup = gedit_prefs_manager_get_create_backup_copy ();
|
||||
|
||||
GEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->save (saver, old_mtime);
|
||||
}
|
||||
|
||||
GeditDocument *
|
||||
gedit_document_saver_get_document (GeditDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), NULL);
|
||||
|
||||
return saver->document;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_document_saver_get_uri (GeditDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), NULL);
|
||||
|
||||
return saver->uri;
|
||||
}
|
||||
|
||||
/* Returns 0 if file size is unknown */
|
||||
goffset
|
||||
gedit_document_saver_get_file_size (GeditDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), 0);
|
||||
|
||||
return GEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->get_file_size (saver);
|
||||
}
|
||||
|
||||
goffset
|
||||
gedit_document_saver_get_bytes_written (GeditDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), 0);
|
||||
|
||||
return GEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->get_bytes_written (saver);
|
||||
}
|
||||
|
||||
GFileInfo *
|
||||
gedit_document_saver_get_info (GeditDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), NULL);
|
||||
|
||||
return saver->info;
|
||||
}
|
||||
133
gedit/gedit-document-saver.h
Executable file
133
gedit/gedit-document-saver.h
Executable file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* gedit-document-saver.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyrhing (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DOCUMENT_SAVER_H__
|
||||
#define __GEDIT_DOCUMENT_SAVER_H__
|
||||
|
||||
#include <gedit/gedit-document.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_DOCUMENT_SAVER (gedit_document_saver_get_type())
|
||||
#define GEDIT_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaver))
|
||||
#define GEDIT_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaverClass))
|
||||
#define GEDIT_IS_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT_SAVER))
|
||||
#define GEDIT_IS_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_SAVER))
|
||||
#define GEDIT_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaverClass))
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditDocumentSaver GeditDocumentSaver;
|
||||
|
||||
struct _GeditDocumentSaver
|
||||
{
|
||||
GObject object;
|
||||
|
||||
/*< private >*/
|
||||
GFileInfo *info;
|
||||
GeditDocument *document;
|
||||
gboolean used;
|
||||
|
||||
gchar *uri;
|
||||
const GeditEncoding *encoding;
|
||||
GeditDocumentNewlineType newline_type;
|
||||
|
||||
GeditDocumentSaveFlags flags;
|
||||
|
||||
gboolean keep_backup;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditDocumentSaverClass GeditDocumentSaverClass;
|
||||
|
||||
struct _GeditDocumentSaverClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* saving) (GeditDocumentSaver *saver,
|
||||
gboolean completed,
|
||||
const GError *error);
|
||||
|
||||
/* VTable */
|
||||
void (* save) (GeditDocumentSaver *saver,
|
||||
GTimeVal *old_mtime);
|
||||
goffset (* get_file_size) (GeditDocumentSaver *saver);
|
||||
goffset (* get_bytes_written) (GeditDocumentSaver *saver);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_document_saver_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* If enconding == NULL, the encoding will be autodetected */
|
||||
GeditDocumentSaver *gedit_document_saver_new (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
GeditDocumentNewlineType newline_type,
|
||||
GeditDocumentSaveFlags flags);
|
||||
|
||||
void gedit_document_saver_saving (GeditDocumentSaver *saver,
|
||||
gboolean completed,
|
||||
GError *error);
|
||||
void gedit_document_saver_save (GeditDocumentSaver *saver,
|
||||
GTimeVal *old_mtime);
|
||||
|
||||
#if 0
|
||||
void gedit_document_saver_cancel (GeditDocumentSaver *saver);
|
||||
#endif
|
||||
|
||||
GeditDocument *gedit_document_saver_get_document (GeditDocumentSaver *saver);
|
||||
|
||||
const gchar *gedit_document_saver_get_uri (GeditDocumentSaver *saver);
|
||||
|
||||
/* If backup_uri is NULL no backup will be made */
|
||||
const gchar *gedit_document_saver_get_backup_uri (GeditDocumentSaver *saver);
|
||||
void *gedit_document_saver_set_backup_uri (GeditDocumentSaver *saver,
|
||||
const gchar *backup_uri);
|
||||
|
||||
/* Returns 0 if file size is unknown */
|
||||
goffset gedit_document_saver_get_file_size (GeditDocumentSaver *saver);
|
||||
|
||||
goffset gedit_document_saver_get_bytes_written (GeditDocumentSaver *saver);
|
||||
|
||||
GFileInfo *gedit_document_saver_get_info (GeditDocumentSaver *saver);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENT_SAVER_H__ */
|
||||
2732
gedit/gedit-document.c
Executable file
2732
gedit/gedit-document.c
Executable file
File diff suppressed because it is too large
Load Diff
338
gedit/gedit-document.h
Executable file
338
gedit/gedit-document.h
Executable file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* gedit-document.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
|
||||
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DOCUMENT_H__
|
||||
#define __GEDIT_DOCUMENT_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtksourceview/gtksourcebuffer.h>
|
||||
|
||||
#include <gedit/gedit-encodings.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_DOCUMENT (gedit_document_get_type())
|
||||
#define GEDIT_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT, GeditDocument))
|
||||
#define GEDIT_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT, GeditDocumentClass))
|
||||
#define GEDIT_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT))
|
||||
#define GEDIT_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT))
|
||||
#define GEDIT_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT, GeditDocumentClass))
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#define GEDIT_METADATA_ATTRIBUTE_POSITION "position"
|
||||
#define GEDIT_METADATA_ATTRIBUTE_ENCODING "encoding"
|
||||
#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "language"
|
||||
#else
|
||||
#define GEDIT_METADATA_ATTRIBUTE_POSITION "metadata::gedit-position"
|
||||
#define GEDIT_METADATA_ATTRIBUTE_ENCODING "metadata::gedit-encoding"
|
||||
#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "metadata::gedit-language"
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_CR,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF
|
||||
} GeditDocumentNewlineType;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#define GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF
|
||||
#else
|
||||
#define GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT GEDIT_DOCUMENT_NEWLINE_TYPE_LF
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_SEARCH_DONT_SET_FLAGS = 1 << 0,
|
||||
GEDIT_SEARCH_ENTIRE_WORD = 1 << 1,
|
||||
GEDIT_SEARCH_CASE_SENSITIVE = 1 << 2
|
||||
|
||||
} GeditSearchFlags;
|
||||
|
||||
/**
|
||||
* GeditDocumentSaveFlags:
|
||||
* @GEDIT_DOCUMENT_SAVE_IGNORE_MTIME: save file despite external modifications.
|
||||
* @GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP: write the file directly without attempting to backup.
|
||||
* @GEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP: preserve previous backup file, needed to support autosaving.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_DOCUMENT_SAVE_IGNORE_MTIME = 1 << 0,
|
||||
GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP = 1 << 1,
|
||||
GEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP = 1 << 2
|
||||
} GeditDocumentSaveFlags;
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditDocumentPrivate GeditDocumentPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditDocument GeditDocument;
|
||||
|
||||
struct _GeditDocument
|
||||
{
|
||||
GtkSourceBuffer buffer;
|
||||
|
||||
/*< private > */
|
||||
GeditDocumentPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditDocumentClass GeditDocumentClass;
|
||||
|
||||
struct _GeditDocumentClass
|
||||
{
|
||||
GtkSourceBufferClass parent_class;
|
||||
|
||||
/* Signals */ // CHECK: ancora da rivedere
|
||||
|
||||
void (* cursor_moved) (GeditDocument *document);
|
||||
|
||||
/* Document load */
|
||||
void (* load) (GeditDocument *document,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
|
||||
void (* loading) (GeditDocument *document,
|
||||
goffset size,
|
||||
goffset total_size);
|
||||
|
||||
void (* loaded) (GeditDocument *document,
|
||||
const GError *error);
|
||||
|
||||
/* Document save */
|
||||
void (* save) (GeditDocument *document,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
GeditDocumentSaveFlags flags);
|
||||
|
||||
void (* saving) (GeditDocument *document,
|
||||
goffset size,
|
||||
goffset total_size);
|
||||
|
||||
void (* saved) (GeditDocument *document,
|
||||
const GError *error);
|
||||
|
||||
void (* search_highlight_updated)
|
||||
(GeditDocument *document,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end);
|
||||
};
|
||||
|
||||
|
||||
#define GEDIT_DOCUMENT_ERROR gedit_document_error_quark ()
|
||||
|
||||
enum
|
||||
{
|
||||
GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
|
||||
GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP,
|
||||
GEDIT_DOCUMENT_ERROR_TOO_BIG,
|
||||
GEDIT_DOCUMENT_ERROR_ENCODING_AUTO_DETECTION_FAILED,
|
||||
GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
|
||||
GEDIT_DOCUMENT_NUM_ERRORS
|
||||
};
|
||||
|
||||
GQuark gedit_document_error_quark (void);
|
||||
|
||||
GType gedit_document_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditDocument *gedit_document_new (void);
|
||||
|
||||
GFile *gedit_document_get_location (GeditDocument *doc);
|
||||
|
||||
gchar *gedit_document_get_uri (GeditDocument *doc);
|
||||
void gedit_document_set_uri (GeditDocument *doc,
|
||||
const gchar *uri);
|
||||
|
||||
gchar *gedit_document_get_uri_for_display
|
||||
(GeditDocument *doc);
|
||||
gchar *gedit_document_get_short_name_for_display
|
||||
(GeditDocument *doc);
|
||||
|
||||
void gedit_document_set_short_name_for_display
|
||||
(GeditDocument *doc,
|
||||
const gchar *name);
|
||||
|
||||
gchar *gedit_document_get_content_type
|
||||
(GeditDocument *doc);
|
||||
|
||||
void gedit_document_set_content_type
|
||||
(GeditDocument *doc,
|
||||
const gchar *content_type);
|
||||
|
||||
gchar *gedit_document_get_mime_type (GeditDocument *doc);
|
||||
|
||||
gboolean gedit_document_get_readonly (GeditDocument *doc);
|
||||
|
||||
void gedit_document_load (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
|
||||
gboolean gedit_document_insert_file (GeditDocument *doc,
|
||||
GtkTextIter *iter,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding);
|
||||
|
||||
gboolean gedit_document_load_cancel (GeditDocument *doc);
|
||||
|
||||
void gedit_document_save (GeditDocument *doc,
|
||||
GeditDocumentSaveFlags flags);
|
||||
|
||||
void gedit_document_save_as (GeditDocument *doc,
|
||||
const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
GeditDocumentSaveFlags flags);
|
||||
|
||||
gboolean gedit_document_is_untouched (GeditDocument *doc);
|
||||
gboolean gedit_document_is_untitled (GeditDocument *doc);
|
||||
|
||||
gboolean gedit_document_is_local (GeditDocument *doc);
|
||||
|
||||
gboolean gedit_document_get_deleted (GeditDocument *doc);
|
||||
|
||||
gboolean gedit_document_goto_line (GeditDocument *doc,
|
||||
gint line);
|
||||
|
||||
gboolean gedit_document_goto_line_offset(GeditDocument *doc,
|
||||
gint line,
|
||||
gint line_offset);
|
||||
|
||||
void gedit_document_set_search_text (GeditDocument *doc,
|
||||
const gchar *text,
|
||||
guint flags);
|
||||
|
||||
gchar *gedit_document_get_search_text (GeditDocument *doc,
|
||||
guint *flags);
|
||||
|
||||
gboolean gedit_document_get_can_search_again
|
||||
(GeditDocument *doc);
|
||||
|
||||
gboolean gedit_document_search_forward (GeditDocument *doc,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end);
|
||||
|
||||
gboolean gedit_document_search_backward (GeditDocument *doc,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end);
|
||||
|
||||
gint gedit_document_replace_all (GeditDocument *doc,
|
||||
const gchar *find,
|
||||
const gchar *replace,
|
||||
guint flags);
|
||||
|
||||
void gedit_document_set_language (GeditDocument *doc,
|
||||
GtkSourceLanguage *lang);
|
||||
GtkSourceLanguage
|
||||
*gedit_document_get_language (GeditDocument *doc);
|
||||
|
||||
const GeditEncoding
|
||||
*gedit_document_get_encoding (GeditDocument *doc);
|
||||
|
||||
void gedit_document_set_enable_search_highlighting
|
||||
(GeditDocument *doc,
|
||||
gboolean enable);
|
||||
|
||||
gboolean gedit_document_get_enable_search_highlighting
|
||||
(GeditDocument *doc);
|
||||
|
||||
void gedit_document_set_newline_type (GeditDocument *doc,
|
||||
GeditDocumentNewlineType newline_type);
|
||||
|
||||
GeditDocumentNewlineType
|
||||
gedit_document_get_newline_type (GeditDocument *doc);
|
||||
|
||||
gchar *gedit_document_get_metadata (GeditDocument *doc,
|
||||
const gchar *key);
|
||||
|
||||
void gedit_document_set_metadata (GeditDocument *doc,
|
||||
const gchar *first_key,
|
||||
...);
|
||||
|
||||
/*
|
||||
* Non exported functions
|
||||
*/
|
||||
void _gedit_document_set_readonly (GeditDocument *doc,
|
||||
gboolean readonly);
|
||||
|
||||
glong _gedit_document_get_seconds_since_last_save_or_load
|
||||
(GeditDocument *doc);
|
||||
|
||||
/* Note: this is a sync stat: use only on local files */
|
||||
gboolean _gedit_document_check_externally_modified
|
||||
(GeditDocument *doc);
|
||||
|
||||
void _gedit_document_search_region (GeditDocument *doc,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
|
||||
/* Search macros */
|
||||
#define GEDIT_SEARCH_IS_DONT_SET_FLAGS(sflags) ((sflags & GEDIT_SEARCH_DONT_SET_FLAGS) != 0)
|
||||
#define GEDIT_SEARCH_SET_DONT_SET_FLAGS(sflags,state) ((state == TRUE) ? \
|
||||
(sflags |= GEDIT_SEARCH_DONT_SET_FLAGS) : (sflags &= ~GEDIT_SEARCH_DONT_SET_FLAGS))
|
||||
|
||||
#define GEDIT_SEARCH_IS_ENTIRE_WORD(sflags) ((sflags & GEDIT_SEARCH_ENTIRE_WORD) != 0)
|
||||
#define GEDIT_SEARCH_SET_ENTIRE_WORD(sflags,state) ((state == TRUE) ? \
|
||||
(sflags |= GEDIT_SEARCH_ENTIRE_WORD) : (sflags &= ~GEDIT_SEARCH_ENTIRE_WORD))
|
||||
|
||||
#define GEDIT_SEARCH_IS_CASE_SENSITIVE(sflags) ((sflags & GEDIT_SEARCH_CASE_SENSITIVE) != 0)
|
||||
#define GEDIT_SEARCH_SET_CASE_SENSITIVE(sflags,state) ((state == TRUE) ? \
|
||||
(sflags |= GEDIT_SEARCH_CASE_SENSITIVE) : (sflags &= ~GEDIT_SEARCH_CASE_SENSITIVE))
|
||||
|
||||
typedef GMountOperation *(*GeditMountOperationFactory)(GeditDocument *doc,
|
||||
gpointer userdata);
|
||||
|
||||
void _gedit_document_set_mount_operation_factory
|
||||
(GeditDocument *doc,
|
||||
GeditMountOperationFactory callback,
|
||||
gpointer userdata);
|
||||
GMountOperation
|
||||
*_gedit_document_create_mount_operation
|
||||
(GeditDocument *doc);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENT_H__ */
|
||||
828
gedit/gedit-documents-panel.c
Executable file
828
gedit/gedit-documents-panel.c
Executable file
@@ -0,0 +1,828 @@
|
||||
/*
|
||||
* gedit-documents-panel.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "gedit-documents-panel.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-notebook.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#define GEDIT_DOCUMENTS_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_DOCUMENTS_PANEL, \
|
||||
GeditDocumentsPanelPrivate))
|
||||
|
||||
struct _GeditDocumentsPanelPrivate
|
||||
{
|
||||
GeditWindow *window;
|
||||
|
||||
GtkWidget *treeview;
|
||||
GtkTreeModel *model;
|
||||
|
||||
guint adding_tab : 1;
|
||||
guint is_reodering : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditDocumentsPanel, gedit_documents_panel, GTK_TYPE_VBOX)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WINDOW
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PIXBUF_COLUMN,
|
||||
NAME_COLUMN,
|
||||
TAB_COLUMN,
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
#define MAX_DOC_NAME_LENGTH 60
|
||||
|
||||
static gchar *
|
||||
tab_get_name (GeditTab *tab)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
gchar *name;
|
||||
gchar *docname;
|
||||
gchar *tab_name;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
|
||||
|
||||
doc = gedit_tab_get_document (tab);
|
||||
|
||||
name = gedit_document_get_short_name_for_display (doc);
|
||||
|
||||
/* Truncate the name so it doesn't get insanely wide. */
|
||||
docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
|
||||
|
||||
if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
|
||||
{
|
||||
if (gedit_document_get_readonly (doc))
|
||||
{
|
||||
tab_name = g_markup_printf_escaped ("<i>%s</i> [<i>%s</i>]",
|
||||
docname,
|
||||
_("Read-Only"));
|
||||
}
|
||||
else
|
||||
{
|
||||
tab_name = g_markup_printf_escaped ("<i>%s</i>",
|
||||
docname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gedit_document_get_readonly (doc))
|
||||
{
|
||||
tab_name = g_markup_printf_escaped ("%s [<i>%s</i>]",
|
||||
docname,
|
||||
_("Read-Only"));
|
||||
}
|
||||
else
|
||||
{
|
||||
tab_name = g_markup_escape_text (docname, -1);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (docname);
|
||||
g_free (name);
|
||||
|
||||
return tab_name;
|
||||
}
|
||||
|
||||
static void
|
||||
get_iter_from_tab (GeditDocumentsPanel *panel, GeditTab *tab, GtkTreeIter *iter)
|
||||
{
|
||||
gint num;
|
||||
GtkWidget *nb;
|
||||
GtkTreePath *path;
|
||||
|
||||
nb = _gedit_window_get_notebook (panel->priv->window);
|
||||
num = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
|
||||
GTK_WIDGET (tab));
|
||||
|
||||
path = gtk_tree_path_new_from_indices (num, -1);
|
||||
gtk_tree_model_get_iter (panel->priv->model,
|
||||
iter,
|
||||
path);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
window_active_tab_changed (GeditWindow *window,
|
||||
GeditTab *tab,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
g_return_if_fail (tab != NULL);
|
||||
|
||||
if (!_gedit_window_is_removing_tabs (window))
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
get_iter_from_tab (panel, tab, &iter);
|
||||
|
||||
if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model),
|
||||
&iter))
|
||||
{
|
||||
selection = gtk_tree_view_get_selection (
|
||||
GTK_TREE_VIEW (panel->priv->treeview));
|
||||
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_list (GeditDocumentsPanel *panel)
|
||||
{
|
||||
/* TODO: refresh the list only if the panel is visible */
|
||||
|
||||
GList *tabs;
|
||||
GList *l;
|
||||
GtkWidget *nb;
|
||||
GtkListStore *list_store;
|
||||
GeditTab *active_tab;
|
||||
|
||||
/* g_debug ("refresh_list"); */
|
||||
|
||||
list_store = GTK_LIST_STORE (panel->priv->model);
|
||||
|
||||
gtk_list_store_clear (list_store);
|
||||
|
||||
active_tab = gedit_window_get_active_tab (panel->priv->window);
|
||||
|
||||
nb = _gedit_window_get_notebook (panel->priv->window);
|
||||
|
||||
tabs = gtk_container_get_children (GTK_CONTAINER (nb));
|
||||
l = tabs;
|
||||
|
||||
panel->priv->adding_tab = TRUE;
|
||||
|
||||
while (l != NULL)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
gchar *name;
|
||||
GtkTreeIter iter;
|
||||
|
||||
name = tab_get_name (GEDIT_TAB (l->data));
|
||||
pixbuf = _gedit_tab_get_icon (GEDIT_TAB (l->data));
|
||||
|
||||
/* Add a new row to the model */
|
||||
gtk_list_store_append (list_store, &iter);
|
||||
gtk_list_store_set (list_store,
|
||||
&iter,
|
||||
PIXBUF_COLUMN, pixbuf,
|
||||
NAME_COLUMN, name,
|
||||
TAB_COLUMN, l->data,
|
||||
-1);
|
||||
|
||||
g_free (name);
|
||||
if (pixbuf != NULL)
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
if (l->data == active_tab)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (
|
||||
GTK_TREE_VIEW (panel->priv->treeview));
|
||||
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
}
|
||||
|
||||
l = g_list_next (l);
|
||||
}
|
||||
|
||||
panel->priv->adding_tab = FALSE;
|
||||
|
||||
g_list_free (tabs);
|
||||
}
|
||||
|
||||
static void
|
||||
sync_name_and_icon (GeditTab *tab,
|
||||
GParamSpec *pspec,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
gchar *name;
|
||||
GtkTreeIter iter;
|
||||
|
||||
get_iter_from_tab (panel, tab, &iter);
|
||||
|
||||
name = tab_get_name (tab);
|
||||
pixbuf = _gedit_tab_get_icon (tab);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (panel->priv->model),
|
||||
&iter,
|
||||
PIXBUF_COLUMN, pixbuf,
|
||||
NAME_COLUMN, name,
|
||||
TAB_COLUMN, tab,
|
||||
-1);
|
||||
|
||||
g_free (name);
|
||||
if (pixbuf != NULL)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tab_removed (GeditWindow *window,
|
||||
GeditTab *tab,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (tab,
|
||||
G_CALLBACK (sync_name_and_icon),
|
||||
panel);
|
||||
|
||||
if (_gedit_window_is_removing_tabs (window))
|
||||
gtk_list_store_clear (GTK_LIST_STORE (panel->priv->model));
|
||||
else
|
||||
refresh_list (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tab_added (GeditWindow *window,
|
||||
GeditTab *tab,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter sibling;
|
||||
GdkPixbuf *pixbuf;
|
||||
gchar *name;
|
||||
|
||||
g_signal_connect (tab,
|
||||
"notify::name",
|
||||
G_CALLBACK (sync_name_and_icon),
|
||||
panel);
|
||||
|
||||
g_signal_connect (tab,
|
||||
"notify::state",
|
||||
G_CALLBACK (sync_name_and_icon),
|
||||
panel);
|
||||
|
||||
get_iter_from_tab (panel, tab, &sibling);
|
||||
|
||||
panel->priv->adding_tab = TRUE;
|
||||
|
||||
if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model),
|
||||
&sibling))
|
||||
{
|
||||
gtk_list_store_insert_after (GTK_LIST_STORE (panel->priv->model),
|
||||
&iter,
|
||||
&sibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeditTab *active_tab;
|
||||
|
||||
gtk_list_store_append (GTK_LIST_STORE (panel->priv->model),
|
||||
&iter);
|
||||
|
||||
active_tab = gedit_window_get_active_tab (panel->priv->window);
|
||||
|
||||
if (tab == active_tab)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (
|
||||
GTK_TREE_VIEW (panel->priv->treeview));
|
||||
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
name = tab_get_name (tab);
|
||||
pixbuf = _gedit_tab_get_icon (tab);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (panel->priv->model),
|
||||
&iter,
|
||||
PIXBUF_COLUMN, pixbuf,
|
||||
NAME_COLUMN, name,
|
||||
TAB_COLUMN, tab,
|
||||
-1);
|
||||
|
||||
g_free (name);
|
||||
if (pixbuf != NULL)
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
panel->priv->adding_tab = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
window_tabs_reordered (GeditWindow *window,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
if (panel->priv->is_reodering)
|
||||
return;
|
||||
|
||||
refresh_list (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
set_window (GeditDocumentsPanel *panel,
|
||||
GeditWindow *window)
|
||||
{
|
||||
g_return_if_fail (panel->priv->window == NULL);
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
panel->priv->window = g_object_ref (window);
|
||||
|
||||
g_signal_connect (window,
|
||||
"tab_added",
|
||||
G_CALLBACK (window_tab_added),
|
||||
panel);
|
||||
g_signal_connect (window,
|
||||
"tab_removed",
|
||||
G_CALLBACK (window_tab_removed),
|
||||
panel);
|
||||
g_signal_connect (window,
|
||||
"tabs_reordered",
|
||||
G_CALLBACK (window_tabs_reordered),
|
||||
panel);
|
||||
g_signal_connect (window,
|
||||
"active_tab_changed",
|
||||
G_CALLBACK (window_active_tab_changed),
|
||||
panel);
|
||||
}
|
||||
|
||||
static void
|
||||
treeview_cursor_changed (GtkTreeView *view,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
gpointer tab;
|
||||
|
||||
selection = gtk_tree_view_get_selection (
|
||||
GTK_TREE_VIEW (panel->priv->treeview));
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
{
|
||||
gtk_tree_model_get (panel->priv->model,
|
||||
&iter,
|
||||
TAB_COLUMN,
|
||||
&tab,
|
||||
-1);
|
||||
|
||||
if (gedit_window_get_active_tab (panel->priv->window) != tab)
|
||||
{
|
||||
gedit_window_set_active_tab (panel->priv->window,
|
||||
GEDIT_TAB (tab));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WINDOW:
|
||||
set_window (panel, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WINDOW:
|
||||
g_value_set_object (value,
|
||||
GEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel)->window);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_finalize (GObject *object)
|
||||
{
|
||||
/* GeditDocumentsPanel *tab = GEDIT_DOCUMENTS_PANEL (object); */
|
||||
|
||||
/* TODO: disconnect signal with window */
|
||||
|
||||
G_OBJECT_CLASS (gedit_documents_panel_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_dispose (GObject *object)
|
||||
{
|
||||
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
|
||||
|
||||
if (panel->priv->window != NULL)
|
||||
{
|
||||
g_object_unref (panel->priv->window);
|
||||
panel->priv->window = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_documents_panel_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_class_init (GeditDocumentsPanelClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_documents_panel_finalize;
|
||||
object_class->dispose = gedit_documents_panel_dispose;
|
||||
object_class->get_property = gedit_documents_panel_get_property;
|
||||
object_class->set_property = gedit_documents_panel_set_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WINDOW,
|
||||
g_param_spec_object ("window",
|
||||
"Window",
|
||||
"The GeditWindow this GeditDocumentsPanel is associated with",
|
||||
GEDIT_TYPE_WINDOW,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditDocumentsPanelPrivate));
|
||||
}
|
||||
|
||||
static GtkTreePath *
|
||||
get_current_path (GeditDocumentsPanel *panel)
|
||||
{
|
||||
gint num;
|
||||
GtkWidget *nb;
|
||||
GtkTreePath *path;
|
||||
|
||||
nb = _gedit_window_get_notebook (panel->priv->window);
|
||||
num = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
|
||||
|
||||
path = gtk_tree_path_new_from_indices (num, -1);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_position (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GdkRectangle rect;
|
||||
gint wx, wy;
|
||||
GtkRequisition requisition;
|
||||
GtkWidget *w;
|
||||
|
||||
w = panel->priv->treeview;
|
||||
|
||||
path = get_current_path (panel);
|
||||
|
||||
gtk_tree_view_get_cell_area (GTK_TREE_VIEW (w),
|
||||
path,
|
||||
NULL,
|
||||
&rect);
|
||||
|
||||
wx = rect.x;
|
||||
wy = rect.y;
|
||||
|
||||
gdk_window_get_origin (w->window, x, y);
|
||||
|
||||
gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
|
||||
|
||||
if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
|
||||
{
|
||||
*x += w->allocation.x + w->allocation.width - requisition.width - 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
*x += w->allocation.x + 10;
|
||||
}
|
||||
|
||||
wy = MAX (*y + 5, *y + wy + 5);
|
||||
wy = MIN (wy, *y + w->allocation.height - requisition.height - 5);
|
||||
|
||||
*y = wy;
|
||||
|
||||
*push_in = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_popup_menu (GeditDocumentsPanel *panel,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
|
||||
menu = gtk_ui_manager_get_widget (gedit_window_get_ui_manager (panel->priv->window),
|
||||
"/NotebookPopup");
|
||||
g_return_val_if_fail (menu != NULL, FALSE);
|
||||
|
||||
if (event != NULL)
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (menu),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
event->button,
|
||||
event->time);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (menu),
|
||||
NULL,
|
||||
NULL,
|
||||
(GtkMenuPositionFunc) menu_position,
|
||||
panel,
|
||||
0,
|
||||
gtk_get_current_event_time ());
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
panel_button_press_event (GtkTreeView *treeview,
|
||||
GdkEventButton *event,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
if ((GDK_BUTTON_PRESS == event->type) && (3 == event->button))
|
||||
{
|
||||
GtkTreePath* path = NULL;
|
||||
|
||||
if (event->window == gtk_tree_view_get_bin_window (treeview))
|
||||
{
|
||||
/* Change the cursor position */
|
||||
if (gtk_tree_view_get_path_at_pos (treeview,
|
||||
event->x,
|
||||
event->y,
|
||||
&path,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
|
||||
gtk_tree_view_set_cursor (treeview,
|
||||
path,
|
||||
NULL,
|
||||
FALSE);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
/* A row exists at mouse position */
|
||||
return show_popup_menu (panel, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
panel_popup_menu (GtkWidget *treeview,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
/* Only respond if the treeview is the actual focus */
|
||||
if (gtk_window_get_focus (GTK_WINDOW (panel->priv->window)) == treeview)
|
||||
{
|
||||
return show_popup_menu (panel, NULL);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
treeview_query_tooltip (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_tip,
|
||||
GtkTooltip *tooltip,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
|
||||
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
|
||||
GtkTreePath *path = NULL;
|
||||
gpointer *tab;
|
||||
gchar *tip;
|
||||
|
||||
if (keyboard_tip)
|
||||
{
|
||||
gtk_tree_view_get_cursor (tree_view, &path, NULL);
|
||||
|
||||
if (path == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gint bin_x, bin_y;
|
||||
|
||||
gtk_tree_view_convert_widget_to_bin_window_coords (tree_view,
|
||||
x, y,
|
||||
&bin_x, &bin_y);
|
||||
|
||||
if (!gtk_tree_view_get_path_at_pos (tree_view,
|
||||
bin_x, bin_y,
|
||||
&path,
|
||||
NULL, NULL, NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
gtk_tree_model_get (model,
|
||||
&iter,
|
||||
TAB_COLUMN,
|
||||
&tab,
|
||||
-1);
|
||||
|
||||
tip = _gedit_tab_get_tooltips (GEDIT_TAB (tab));
|
||||
gtk_tooltip_set_markup (tooltip, tip);
|
||||
|
||||
g_free (tip);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
treeview_row_inserted (GtkTreeModel *tree_model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
GeditDocumentsPanel *panel)
|
||||
{
|
||||
GeditTab *tab;
|
||||
gint *indeces;
|
||||
GtkWidget *nb;
|
||||
gint old_position;
|
||||
gint new_position;
|
||||
|
||||
if (panel->priv->adding_tab)
|
||||
return;
|
||||
|
||||
tab = gedit_window_get_active_tab (panel->priv->window);
|
||||
g_return_if_fail (tab != NULL);
|
||||
|
||||
panel->priv->is_reodering = TRUE;
|
||||
|
||||
indeces = gtk_tree_path_get_indices (path);
|
||||
|
||||
/* g_debug ("New Index: %d (path: %s)", indeces[0], gtk_tree_path_to_string (path));*/
|
||||
|
||||
nb = _gedit_window_get_notebook (panel->priv->window);
|
||||
|
||||
new_position = indeces[0];
|
||||
old_position = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
|
||||
GTK_WIDGET (tab));
|
||||
if (new_position > old_position)
|
||||
new_position = MAX (0, new_position - 1);
|
||||
|
||||
gedit_notebook_reorder_tab (GEDIT_NOTEBOOK (nb),
|
||||
tab,
|
||||
new_position);
|
||||
|
||||
panel->priv->is_reodering = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_documents_panel_init (GeditDocumentsPanel *panel)
|
||||
{
|
||||
GtkWidget *sw;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *cell;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
panel->priv = GEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel);
|
||||
|
||||
panel->priv->adding_tab = FALSE;
|
||||
panel->priv->is_reodering = FALSE;
|
||||
|
||||
/* Create the scrolled window */
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
g_return_if_fail (sw != NULL);
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_widget_show (sw);
|
||||
gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0);
|
||||
|
||||
/* Create the empty model */
|
||||
panel->priv->model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
|
||||
GDK_TYPE_PIXBUF,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_POINTER));
|
||||
|
||||
/* Create the treeview */
|
||||
panel->priv->treeview = gtk_tree_view_new_with_model (panel->priv->model);
|
||||
g_object_unref (G_OBJECT (panel->priv->model));
|
||||
gtk_container_add (GTK_CONTAINER (sw), panel->priv->treeview);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (panel->priv->treeview), FALSE);
|
||||
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (panel->priv->treeview), TRUE);
|
||||
|
||||
g_object_set (panel->priv->treeview, "has-tooltip", TRUE, NULL);
|
||||
|
||||
gtk_widget_show (panel->priv->treeview);
|
||||
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (column, _("Documents"));
|
||||
|
||||
cell = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, cell, FALSE);
|
||||
gtk_tree_view_column_add_attribute (column, cell, "pixbuf", PIXBUF_COLUMN);
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, cell, TRUE);
|
||||
gtk_tree_view_column_add_attribute (column, cell, "markup", NAME_COLUMN);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (panel->priv->treeview),
|
||||
column);
|
||||
|
||||
selection = gtk_tree_view_get_selection (
|
||||
GTK_TREE_VIEW (panel->priv->treeview));
|
||||
|
||||
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
|
||||
|
||||
g_signal_connect (panel->priv->treeview,
|
||||
"cursor_changed",
|
||||
G_CALLBACK (treeview_cursor_changed),
|
||||
panel);
|
||||
g_signal_connect (panel->priv->treeview,
|
||||
"button-press-event",
|
||||
G_CALLBACK (panel_button_press_event),
|
||||
panel);
|
||||
g_signal_connect (panel->priv->treeview,
|
||||
"popup-menu",
|
||||
G_CALLBACK (panel_popup_menu),
|
||||
panel);
|
||||
g_signal_connect (panel->priv->treeview,
|
||||
"query-tooltip",
|
||||
G_CALLBACK (treeview_query_tooltip),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (panel->priv->model,
|
||||
"row-inserted",
|
||||
G_CALLBACK (treeview_row_inserted),
|
||||
panel);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_documents_panel_new (GeditWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
|
||||
|
||||
return GTK_WIDGET (g_object_new (GEDIT_TYPE_DOCUMENTS_PANEL,
|
||||
"window", window,
|
||||
NULL));
|
||||
}
|
||||
85
gedit/gedit-documents-panel.h
Executable file
85
gedit/gedit-documents-panel.h
Executable file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* gedit-documents-panel.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_DOCUMENTS_PANEL_H__
|
||||
#define __GEDIT_DOCUMENTS_PANEL_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gedit/gedit-window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_DOCUMENTS_PANEL (gedit_documents_panel_get_type())
|
||||
#define GEDIT_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanel))
|
||||
#define GEDIT_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanelClass))
|
||||
#define GEDIT_IS_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENTS_PANEL))
|
||||
#define GEDIT_IS_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENTS_PANEL))
|
||||
#define GEDIT_DOCUMENTS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanelClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditDocumentsPanelPrivate GeditDocumentsPanelPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditDocumentsPanel GeditDocumentsPanel;
|
||||
|
||||
struct _GeditDocumentsPanel
|
||||
{
|
||||
GtkVBox vbox;
|
||||
|
||||
/*< private > */
|
||||
GeditDocumentsPanelPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditDocumentsPanelClass GeditDocumentsPanelClass;
|
||||
|
||||
struct _GeditDocumentsPanelClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_documents_panel_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_documents_panel_new (GeditWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_DOCUMENTS_PANEL_H__ */
|
||||
468
gedit/gedit-encodings-combo-box.c
Executable file
468
gedit/gedit-encodings-combo-box.c
Executable file
@@ -0,0 +1,468 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-encodings-combo-box.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id: gedit-encodings-combo-box.c 6112 2008-01-23 08:26:24Z sfre $
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gedit/gedit-encodings-combo-box.h>
|
||||
#include <gedit/gedit-prefs-manager.h>
|
||||
#include <gedit/dialogs/gedit-encodings-dialog.h>
|
||||
|
||||
#define ENCODING_KEY "Enconding"
|
||||
|
||||
#define GEDIT_ENCODINGS_COMBO_BOX_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_ENCODINGS_COMBO_BOX, \
|
||||
GeditEncodingsComboBoxPrivate))
|
||||
|
||||
struct _GeditEncodingsComboBoxPrivate
|
||||
{
|
||||
GtkListStore *store;
|
||||
glong changed_id;
|
||||
|
||||
guint activated_item;
|
||||
|
||||
guint save_mode : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NAME_COLUMN,
|
||||
ENCODING_COLUMN,
|
||||
ADD_COLUMN,
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SAVE_MODE
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE(GeditEncodingsComboBox, gedit_encodings_combo_box, GTK_TYPE_COMBO_BOX)
|
||||
|
||||
static void update_menu (GeditEncodingsComboBox *combo_box);
|
||||
|
||||
static void
|
||||
gedit_encodings_combo_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditEncodingsComboBox *combo;
|
||||
|
||||
combo = GEDIT_ENCODINGS_COMBO_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SAVE_MODE:
|
||||
combo->priv->save_mode = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_combo_box_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditEncodingsComboBox *combo;
|
||||
|
||||
combo = GEDIT_ENCODINGS_COMBO_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SAVE_MODE:
|
||||
g_value_set_boolean (value, combo->priv->save_mode);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_combo_box_dispose (GObject *object)
|
||||
{
|
||||
GeditEncodingsComboBox *combo = GEDIT_ENCODINGS_COMBO_BOX (object);
|
||||
|
||||
if (combo->priv->store != NULL)
|
||||
{
|
||||
g_object_unref (combo->priv->store);
|
||||
combo->priv->store = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_encodings_combo_box_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_combo_box_class_init (GeditEncodingsComboBoxClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gedit_encodings_combo_box_set_property;
|
||||
object_class->get_property = gedit_encodings_combo_box_get_property;
|
||||
object_class->dispose = gedit_encodings_combo_box_dispose;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SAVE_MODE,
|
||||
g_param_spec_boolean ("save-mode",
|
||||
"Save Mode",
|
||||
"Save Mode",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditEncodingsComboBoxPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_response_cb (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
GeditEncodingsComboBox *menu)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
update_menu (menu);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
add_or_remove (GeditEncodingsComboBox *menu,
|
||||
GtkTreeModel *model)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gboolean add_item = FALSE;
|
||||
|
||||
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter,
|
||||
ADD_COLUMN, &add_item,
|
||||
-1);
|
||||
}
|
||||
|
||||
if (!add_item)
|
||||
{
|
||||
menu->priv->activated_item = gtk_combo_box_get_active (GTK_COMBO_BOX (menu));
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu));
|
||||
|
||||
#if !GTK_CHECK_VERSION (2, 18, 0)
|
||||
if (!GTK_WIDGET_TOPLEVEL (toplevel))
|
||||
#else
|
||||
if (!gtk_widget_is_toplevel (toplevel))
|
||||
#endif
|
||||
toplevel = NULL;
|
||||
|
||||
g_signal_handler_block (menu, menu->priv->changed_id);
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (menu),
|
||||
menu->priv->activated_item);
|
||||
g_signal_handler_unblock (menu, menu->priv->changed_id);
|
||||
|
||||
dialog = gedit_encodings_dialog_new();
|
||||
|
||||
if (toplevel != NULL)
|
||||
{
|
||||
GtkWindowGroup *wg;
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dialog),
|
||||
GTK_WINDOW (toplevel));
|
||||
|
||||
wg = GTK_WINDOW (toplevel)->group;
|
||||
if (wg == NULL)
|
||||
{
|
||||
wg = gtk_window_group_new ();
|
||||
gtk_window_group_add_window (wg,
|
||||
GTK_WINDOW (toplevel));
|
||||
}
|
||||
|
||||
gtk_window_group_add_window (wg,
|
||||
GTK_WINDOW (dialog));
|
||||
}
|
||||
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
|
||||
g_signal_connect (dialog,
|
||||
"response",
|
||||
G_CALLBACK (dialog_response_cb),
|
||||
menu);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
gchar *str;
|
||||
gboolean ret;
|
||||
|
||||
gtk_tree_model_get (model, iter, NAME_COLUMN, &str, -1);
|
||||
ret = (str == NULL || *str == '\0');
|
||||
g_free (str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu (GeditEncodingsComboBox *menu)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
GSList *encodings, *l;
|
||||
gchar *str;
|
||||
const GeditEncoding *utf8_encoding;
|
||||
const GeditEncoding *current_encoding;
|
||||
|
||||
store = menu->priv->store;
|
||||
|
||||
/* Unset the previous model */
|
||||
g_signal_handler_block (menu, menu->priv->changed_id);
|
||||
gtk_list_store_clear (store);
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (menu),
|
||||
NULL);
|
||||
|
||||
utf8_encoding = gedit_encoding_get_utf8 ();
|
||||
current_encoding = gedit_encoding_get_current ();
|
||||
|
||||
if (!menu->priv->save_mode)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, _("Automatically Detected"),
|
||||
ENCODING_COLUMN, NULL,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, "",
|
||||
ENCODING_COLUMN, NULL,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
}
|
||||
|
||||
if (current_encoding != utf8_encoding)
|
||||
str = gedit_encoding_to_string (utf8_encoding);
|
||||
else
|
||||
str = g_strdup_printf (_("Current Locale (%s)"),
|
||||
gedit_encoding_get_charset (utf8_encoding));
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, str,
|
||||
ENCODING_COLUMN, utf8_encoding,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
|
||||
g_free (str);
|
||||
|
||||
if ((utf8_encoding != current_encoding) &&
|
||||
(current_encoding != NULL))
|
||||
{
|
||||
str = g_strdup_printf (_("Current Locale (%s)"),
|
||||
gedit_encoding_get_charset (current_encoding));
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, str,
|
||||
ENCODING_COLUMN, current_encoding,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
encodings = gedit_prefs_manager_get_shown_in_menu_encodings ();
|
||||
|
||||
for (l = encodings; l != NULL; l = g_slist_next (l))
|
||||
{
|
||||
const GeditEncoding *enc = (const GeditEncoding *)l->data;
|
||||
|
||||
if ((enc != current_encoding) &&
|
||||
(enc != utf8_encoding) &&
|
||||
(enc != NULL))
|
||||
{
|
||||
str = gedit_encoding_to_string (enc);
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, str,
|
||||
ENCODING_COLUMN, enc,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (encodings);
|
||||
|
||||
if (gedit_prefs_manager_shown_in_menu_encodings_can_set ())
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
/* separator */
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, "",
|
||||
ENCODING_COLUMN, NULL,
|
||||
ADD_COLUMN, FALSE,
|
||||
-1);
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
NAME_COLUMN, _("Add or Remove..."),
|
||||
ENCODING_COLUMN, NULL,
|
||||
ADD_COLUMN, TRUE,
|
||||
-1);
|
||||
}
|
||||
|
||||
/* set the model back */
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (menu),
|
||||
GTK_TREE_MODEL (menu->priv->store));
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0);
|
||||
|
||||
g_signal_handler_unblock (menu, menu->priv->changed_id);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_encodings_combo_box_init (GeditEncodingsComboBox *menu)
|
||||
{
|
||||
GtkCellRenderer *text_renderer;
|
||||
|
||||
menu->priv = GEDIT_ENCODINGS_COMBO_BOX_GET_PRIVATE (menu);
|
||||
|
||||
menu->priv->store = gtk_list_store_new (N_COLUMNS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_POINTER,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
/* Setup up the cells */
|
||||
text_renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (menu),
|
||||
text_renderer, TRUE);
|
||||
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (menu),
|
||||
text_renderer,
|
||||
"text",
|
||||
NAME_COLUMN,
|
||||
NULL);
|
||||
|
||||
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu),
|
||||
separator_func, NULL,
|
||||
NULL);
|
||||
|
||||
menu->priv->changed_id = g_signal_connect (menu, "changed",
|
||||
G_CALLBACK (add_or_remove),
|
||||
menu->priv->store);
|
||||
|
||||
update_menu (menu);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_encodings_combo_box_new (gboolean save_mode)
|
||||
{
|
||||
return g_object_new (GEDIT_TYPE_ENCODINGS_COMBO_BOX,
|
||||
"save_mode", save_mode,
|
||||
NULL);
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_encodings_combo_box_get_selected_encoding (GeditEncodingsComboBox *menu)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (menu), NULL);
|
||||
|
||||
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter))
|
||||
{
|
||||
const GeditEncoding *ret;
|
||||
GtkTreeModel *model;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu));
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
ENCODING_COLUMN, &ret,
|
||||
-1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_encodings_combo_box_set_selected_encoding (GeditEncodingsComboBox *menu,
|
||||
const GeditEncoding *encoding)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
gboolean b;
|
||||
g_return_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (menu));
|
||||
g_return_if_fail (GTK_IS_COMBO_BOX (menu));
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu));
|
||||
b = gtk_tree_model_get_iter_first (model, &iter);
|
||||
|
||||
while (b)
|
||||
{
|
||||
const GeditEncoding *enc;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
ENCODING_COLUMN, &enc,
|
||||
-1);
|
||||
|
||||
if (enc == encoding)
|
||||
{
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (menu),
|
||||
&iter);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
b = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
}
|
||||
78
gedit/gedit-encodings-combo-box.h
Executable file
78
gedit/gedit-encodings-combo-box.h
Executable file
@@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-encodings-combo-box.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id: gedit-encodings-option-menu.h 4429 2005-12-12 17:28:04Z pborelli $
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_ENCODINGS_COMBO_BOX_H__
|
||||
#define __GEDIT_ENCODINGS_COMBO_BOX_H__
|
||||
|
||||
#include <gtk/gtkoptionmenu.h>
|
||||
#include <gedit/gedit-encodings.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_ENCODINGS_COMBO_BOX (gedit_encodings_combo_box_get_type ())
|
||||
#define GEDIT_ENCODINGS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_ENCODINGS_COMBO_BOX, GeditEncodingsComboBox))
|
||||
#define GEDIT_ENCODINGS_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_ENCODINGS_COMBO_BOX, GeditEncodingsComboBoxClass))
|
||||
#define GEDIT_IS_ENCODINGS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_ENCODINGS_COMBO_BOX))
|
||||
#define GEDIT_IS_ENCODINGS_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_ENCODINGS_COMBO_BOX))
|
||||
#define GEDIT_ENCODINGS_COMBO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_ENCODINGS_COMBO_BOX, GeditEncodingsComboBoxClass))
|
||||
|
||||
|
||||
typedef struct _GeditEncodingsComboBox GeditEncodingsComboBox;
|
||||
typedef struct _GeditEncodingsComboBoxClass GeditEncodingsComboBoxClass;
|
||||
|
||||
typedef struct _GeditEncodingsComboBoxPrivate GeditEncodingsComboBoxPrivate;
|
||||
|
||||
struct _GeditEncodingsComboBox
|
||||
{
|
||||
GtkComboBox parent;
|
||||
|
||||
GeditEncodingsComboBoxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditEncodingsComboBoxClass
|
||||
{
|
||||
GtkComboBoxClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_encodings_combo_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* Constructor */
|
||||
GtkWidget *gedit_encodings_combo_box_new (gboolean save_mode);
|
||||
|
||||
const GeditEncoding *gedit_encodings_combo_box_get_selected_encoding (GeditEncodingsComboBox *menu);
|
||||
void gedit_encodings_combo_box_set_selected_encoding (GeditEncodingsComboBox *menu,
|
||||
const GeditEncoding *encoding);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_ENCODINGS_COMBO_BOX_H__ */
|
||||
|
||||
|
||||
473
gedit/gedit-encodings.c
Executable file
473
gedit/gedit-encodings.c
Executable file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* gedit-encodings.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-encodings.h"
|
||||
|
||||
|
||||
struct _GeditEncoding
|
||||
{
|
||||
gint index;
|
||||
const gchar *charset;
|
||||
const gchar *name;
|
||||
};
|
||||
|
||||
/*
|
||||
* The original versions of the following tables are taken from profterm
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
GEDIT_ENCODING_ISO_8859_1,
|
||||
GEDIT_ENCODING_ISO_8859_2,
|
||||
GEDIT_ENCODING_ISO_8859_3,
|
||||
GEDIT_ENCODING_ISO_8859_4,
|
||||
GEDIT_ENCODING_ISO_8859_5,
|
||||
GEDIT_ENCODING_ISO_8859_6,
|
||||
GEDIT_ENCODING_ISO_8859_7,
|
||||
GEDIT_ENCODING_ISO_8859_8,
|
||||
GEDIT_ENCODING_ISO_8859_9,
|
||||
GEDIT_ENCODING_ISO_8859_10,
|
||||
GEDIT_ENCODING_ISO_8859_13,
|
||||
GEDIT_ENCODING_ISO_8859_14,
|
||||
GEDIT_ENCODING_ISO_8859_15,
|
||||
GEDIT_ENCODING_ISO_8859_16,
|
||||
|
||||
GEDIT_ENCODING_UTF_7,
|
||||
GEDIT_ENCODING_UTF_16,
|
||||
GEDIT_ENCODING_UTF_16_BE,
|
||||
GEDIT_ENCODING_UTF_16_LE,
|
||||
GEDIT_ENCODING_UTF_32,
|
||||
GEDIT_ENCODING_UCS_2,
|
||||
GEDIT_ENCODING_UCS_4,
|
||||
|
||||
GEDIT_ENCODING_ARMSCII_8,
|
||||
GEDIT_ENCODING_BIG5,
|
||||
GEDIT_ENCODING_BIG5_HKSCS,
|
||||
GEDIT_ENCODING_CP_866,
|
||||
|
||||
GEDIT_ENCODING_EUC_JP,
|
||||
GEDIT_ENCODING_EUC_JP_MS,
|
||||
GEDIT_ENCODING_CP932,
|
||||
GEDIT_ENCODING_EUC_KR,
|
||||
GEDIT_ENCODING_EUC_TW,
|
||||
|
||||
GEDIT_ENCODING_GB18030,
|
||||
GEDIT_ENCODING_GB2312,
|
||||
GEDIT_ENCODING_GBK,
|
||||
GEDIT_ENCODING_GEOSTD8,
|
||||
|
||||
GEDIT_ENCODING_IBM_850,
|
||||
GEDIT_ENCODING_IBM_852,
|
||||
GEDIT_ENCODING_IBM_855,
|
||||
GEDIT_ENCODING_IBM_857,
|
||||
GEDIT_ENCODING_IBM_862,
|
||||
GEDIT_ENCODING_IBM_864,
|
||||
|
||||
GEDIT_ENCODING_ISO_2022_JP,
|
||||
GEDIT_ENCODING_ISO_2022_KR,
|
||||
GEDIT_ENCODING_ISO_IR_111,
|
||||
GEDIT_ENCODING_JOHAB,
|
||||
GEDIT_ENCODING_KOI8_R,
|
||||
GEDIT_ENCODING_KOI8__R,
|
||||
GEDIT_ENCODING_KOI8_U,
|
||||
|
||||
GEDIT_ENCODING_SHIFT_JIS,
|
||||
GEDIT_ENCODING_TCVN,
|
||||
GEDIT_ENCODING_TIS_620,
|
||||
GEDIT_ENCODING_UHC,
|
||||
GEDIT_ENCODING_VISCII,
|
||||
|
||||
GEDIT_ENCODING_WINDOWS_1250,
|
||||
GEDIT_ENCODING_WINDOWS_1251,
|
||||
GEDIT_ENCODING_WINDOWS_1252,
|
||||
GEDIT_ENCODING_WINDOWS_1253,
|
||||
GEDIT_ENCODING_WINDOWS_1254,
|
||||
GEDIT_ENCODING_WINDOWS_1255,
|
||||
GEDIT_ENCODING_WINDOWS_1256,
|
||||
GEDIT_ENCODING_WINDOWS_1257,
|
||||
GEDIT_ENCODING_WINDOWS_1258,
|
||||
|
||||
GEDIT_ENCODING_LAST,
|
||||
|
||||
GEDIT_ENCODING_UTF_8,
|
||||
GEDIT_ENCODING_UNKNOWN
|
||||
|
||||
} GeditEncodingIndex;
|
||||
|
||||
static const GeditEncoding utf8_encoding = {
|
||||
GEDIT_ENCODING_UTF_8,
|
||||
"UTF-8",
|
||||
N_("Unicode")
|
||||
};
|
||||
|
||||
/* initialized in gedit_encoding_lazy_init() */
|
||||
static GeditEncoding unknown_encoding = {
|
||||
GEDIT_ENCODING_UNKNOWN,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const GeditEncoding encodings [] = {
|
||||
|
||||
{ GEDIT_ENCODING_ISO_8859_1,
|
||||
"ISO-8859-1", N_("Western") },
|
||||
{ GEDIT_ENCODING_ISO_8859_2,
|
||||
"ISO-8859-2", N_("Central European") },
|
||||
{ GEDIT_ENCODING_ISO_8859_3,
|
||||
"ISO-8859-3", N_("South European") },
|
||||
{ GEDIT_ENCODING_ISO_8859_4,
|
||||
"ISO-8859-4", N_("Baltic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_5,
|
||||
"ISO-8859-5", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_6,
|
||||
"ISO-8859-6", N_("Arabic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_7,
|
||||
"ISO-8859-7", N_("Greek") },
|
||||
{ GEDIT_ENCODING_ISO_8859_8,
|
||||
"ISO-8859-8", N_("Hebrew Visual") },
|
||||
{ GEDIT_ENCODING_ISO_8859_9,
|
||||
"ISO-8859-9", N_("Turkish") },
|
||||
{ GEDIT_ENCODING_ISO_8859_10,
|
||||
"ISO-8859-10", N_("Nordic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_13,
|
||||
"ISO-8859-13", N_("Baltic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_14,
|
||||
"ISO-8859-14", N_("Celtic") },
|
||||
{ GEDIT_ENCODING_ISO_8859_15,
|
||||
"ISO-8859-15", N_("Western") },
|
||||
{ GEDIT_ENCODING_ISO_8859_16,
|
||||
"ISO-8859-16", N_("Romanian") },
|
||||
|
||||
{ GEDIT_ENCODING_UTF_7,
|
||||
"UTF-7", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UTF_16,
|
||||
"UTF-16", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UTF_16_BE,
|
||||
"UTF-16BE", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UTF_16_LE,
|
||||
"UTF-16LE", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UTF_32,
|
||||
"UTF-32", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UCS_2,
|
||||
"UCS-2", N_("Unicode") },
|
||||
{ GEDIT_ENCODING_UCS_4,
|
||||
"UCS-4", N_("Unicode") },
|
||||
|
||||
{ GEDIT_ENCODING_ARMSCII_8,
|
||||
"ARMSCII-8", N_("Armenian") },
|
||||
{ GEDIT_ENCODING_BIG5,
|
||||
"BIG5", N_("Chinese Traditional") },
|
||||
{ GEDIT_ENCODING_BIG5_HKSCS,
|
||||
"BIG5-HKSCS", N_("Chinese Traditional") },
|
||||
{ GEDIT_ENCODING_CP_866,
|
||||
"CP866", N_("Cyrillic/Russian") },
|
||||
|
||||
{ GEDIT_ENCODING_EUC_JP,
|
||||
"EUC-JP", N_("Japanese") },
|
||||
{ GEDIT_ENCODING_EUC_JP_MS,
|
||||
"EUC-JP-MS", N_("Japanese") },
|
||||
{ GEDIT_ENCODING_CP932,
|
||||
"CP932", N_("Japanese") },
|
||||
|
||||
{ GEDIT_ENCODING_EUC_KR,
|
||||
"EUC-KR", N_("Korean") },
|
||||
{ GEDIT_ENCODING_EUC_TW,
|
||||
"EUC-TW", N_("Chinese Traditional") },
|
||||
|
||||
{ GEDIT_ENCODING_GB18030,
|
||||
"GB18030", N_("Chinese Simplified") },
|
||||
{ GEDIT_ENCODING_GB2312,
|
||||
"GB2312", N_("Chinese Simplified") },
|
||||
{ GEDIT_ENCODING_GBK,
|
||||
"GBK", N_("Chinese Simplified") },
|
||||
{ GEDIT_ENCODING_GEOSTD8,
|
||||
"GEORGIAN-ACADEMY", N_("Georgian") }, /* FIXME GEOSTD8 ? */
|
||||
|
||||
{ GEDIT_ENCODING_IBM_850,
|
||||
"IBM850", N_("Western") },
|
||||
{ GEDIT_ENCODING_IBM_852,
|
||||
"IBM852", N_("Central European") },
|
||||
{ GEDIT_ENCODING_IBM_855,
|
||||
"IBM855", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_IBM_857,
|
||||
"IBM857", N_("Turkish") },
|
||||
{ GEDIT_ENCODING_IBM_862,
|
||||
"IBM862", N_("Hebrew") },
|
||||
{ GEDIT_ENCODING_IBM_864,
|
||||
"IBM864", N_("Arabic") },
|
||||
|
||||
{ GEDIT_ENCODING_ISO_2022_JP,
|
||||
"ISO-2022-JP", N_("Japanese") },
|
||||
{ GEDIT_ENCODING_ISO_2022_KR,
|
||||
"ISO-2022-KR", N_("Korean") },
|
||||
{ GEDIT_ENCODING_ISO_IR_111,
|
||||
"ISO-IR-111", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_JOHAB,
|
||||
"JOHAB", N_("Korean") },
|
||||
{ GEDIT_ENCODING_KOI8_R,
|
||||
"KOI8R", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_KOI8__R,
|
||||
"KOI8-R", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_KOI8_U,
|
||||
"KOI8U", N_("Cyrillic/Ukrainian") },
|
||||
|
||||
{ GEDIT_ENCODING_SHIFT_JIS,
|
||||
"SHIFT_JIS", N_("Japanese") },
|
||||
{ GEDIT_ENCODING_TCVN,
|
||||
"TCVN", N_("Vietnamese") },
|
||||
{ GEDIT_ENCODING_TIS_620,
|
||||
"TIS-620", N_("Thai") },
|
||||
{ GEDIT_ENCODING_UHC,
|
||||
"UHC", N_("Korean") },
|
||||
{ GEDIT_ENCODING_VISCII,
|
||||
"VISCII", N_("Vietnamese") },
|
||||
|
||||
{ GEDIT_ENCODING_WINDOWS_1250,
|
||||
"WINDOWS-1250", N_("Central European") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1251,
|
||||
"WINDOWS-1251", N_("Cyrillic") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1252,
|
||||
"WINDOWS-1252", N_("Western") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1253,
|
||||
"WINDOWS-1253", N_("Greek") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1254,
|
||||
"WINDOWS-1254", N_("Turkish") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1255,
|
||||
"WINDOWS-1255", N_("Hebrew") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1256,
|
||||
"WINDOWS-1256", N_("Arabic") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1257,
|
||||
"WINDOWS-1257", N_("Baltic") },
|
||||
{ GEDIT_ENCODING_WINDOWS_1258,
|
||||
"WINDOWS-1258", N_("Vietnamese") }
|
||||
};
|
||||
|
||||
static void
|
||||
gedit_encoding_lazy_init (void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
const gchar *locale_charset;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
if (g_get_charset (&locale_charset) == FALSE)
|
||||
{
|
||||
unknown_encoding.charset = g_strdup (locale_charset);
|
||||
}
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_encoding_get_from_charset (const gchar *charset)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (charset != NULL, NULL);
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
if (charset == NULL)
|
||||
return NULL;
|
||||
|
||||
if (g_ascii_strcasecmp (charset, "UTF-8") == 0)
|
||||
return gedit_encoding_get_utf8 ();
|
||||
|
||||
i = 0;
|
||||
while (i < GEDIT_ENCODING_LAST)
|
||||
{
|
||||
if (g_ascii_strcasecmp (charset, encodings[i].charset) == 0)
|
||||
return &encodings[i];
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (unknown_encoding.charset != NULL)
|
||||
{
|
||||
if (g_ascii_strcasecmp (charset, unknown_encoding.charset) == 0)
|
||||
return &unknown_encoding;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_encoding_get_from_index (gint idx)
|
||||
{
|
||||
g_return_val_if_fail (idx >= 0, NULL);
|
||||
|
||||
if (idx >= GEDIT_ENCODING_LAST)
|
||||
return NULL;
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
return &encodings[idx];
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_encoding_get_utf8 (void)
|
||||
{
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
return &utf8_encoding;
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_encoding_get_current (void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
static const GeditEncoding *locale_encoding = NULL;
|
||||
|
||||
const gchar *locale_charset;
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
if (initialized != FALSE)
|
||||
return locale_encoding;
|
||||
|
||||
if (g_get_charset (&locale_charset) == FALSE)
|
||||
{
|
||||
g_return_val_if_fail (locale_charset != NULL, &utf8_encoding);
|
||||
|
||||
locale_encoding = gedit_encoding_get_from_charset (locale_charset);
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_encoding = &utf8_encoding;
|
||||
}
|
||||
|
||||
if (locale_encoding == NULL)
|
||||
{
|
||||
locale_encoding = &unknown_encoding;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (locale_encoding != NULL, NULL);
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
return locale_encoding;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_encoding_to_string (const GeditEncoding* enc)
|
||||
{
|
||||
g_return_val_if_fail (enc != NULL, NULL);
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
g_return_val_if_fail (enc->charset != NULL, NULL);
|
||||
|
||||
if (enc->name != NULL)
|
||||
{
|
||||
return g_strdup_printf ("%s (%s)", _(enc->name), enc->charset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_ascii_strcasecmp (enc->charset, "ANSI_X3.4-1968") == 0)
|
||||
return g_strdup_printf ("US-ASCII (%s)", enc->charset);
|
||||
else
|
||||
return g_strdup (enc->charset);
|
||||
}
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_encoding_get_charset (const GeditEncoding* enc)
|
||||
{
|
||||
g_return_val_if_fail (enc != NULL, NULL);
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
g_return_val_if_fail (enc->charset != NULL, NULL);
|
||||
|
||||
return enc->charset;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_encoding_get_name (const GeditEncoding* enc)
|
||||
{
|
||||
g_return_val_if_fail (enc != NULL, NULL);
|
||||
|
||||
gedit_encoding_lazy_init ();
|
||||
|
||||
return (enc->name == NULL) ? _("Unknown") : _(enc->name);
|
||||
}
|
||||
|
||||
/* These are to make language bindings happy. Since Encodings are
|
||||
* const, copy() just returns the same pointer and fres() doesn't
|
||||
* do nothing */
|
||||
|
||||
GeditEncoding *
|
||||
gedit_encoding_copy (const GeditEncoding *enc)
|
||||
{
|
||||
g_return_val_if_fail (enc != NULL, NULL);
|
||||
|
||||
return (GeditEncoding *) enc;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_encoding_free (GeditEncoding *enc)
|
||||
{
|
||||
g_return_if_fail (enc != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_encoding_get_type:
|
||||
*
|
||||
* Retrieves the GType object which is associated with the
|
||||
* #GeditEncoding class.
|
||||
*
|
||||
* Return value: the GType associated with #GeditEncoding.
|
||||
**/
|
||||
GType
|
||||
gedit_encoding_get_type (void)
|
||||
{
|
||||
static GType our_type = 0;
|
||||
|
||||
if (!our_type)
|
||||
our_type = g_boxed_type_register_static (
|
||||
"GeditEncoding",
|
||||
(GBoxedCopyFunc) gedit_encoding_copy,
|
||||
(GBoxedFreeFunc) gedit_encoding_free);
|
||||
|
||||
return our_type;
|
||||
}
|
||||
|
||||
62
gedit/gedit-encodings.h
Executable file
62
gedit/gedit-encodings.h
Executable file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* gedit-encodings.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_ENCODINGS_H__
|
||||
#define __GEDIT_ENCODINGS_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GeditEncoding GeditEncoding;
|
||||
|
||||
#define GEDIT_TYPE_ENCODING (gedit_encoding_get_type ())
|
||||
|
||||
GType gedit_encoding_get_type (void) G_GNUC_CONST;
|
||||
|
||||
const GeditEncoding *gedit_encoding_get_from_charset (const gchar *charset);
|
||||
const GeditEncoding *gedit_encoding_get_from_index (gint index);
|
||||
|
||||
gchar *gedit_encoding_to_string (const GeditEncoding *enc);
|
||||
|
||||
const gchar *gedit_encoding_get_name (const GeditEncoding *enc);
|
||||
const gchar *gedit_encoding_get_charset (const GeditEncoding *enc);
|
||||
|
||||
const GeditEncoding *gedit_encoding_get_utf8 (void);
|
||||
const GeditEncoding *gedit_encoding_get_current (void);
|
||||
|
||||
/* These should not be used, they are just to make python bindings happy */
|
||||
GeditEncoding *gedit_encoding_copy (const GeditEncoding *enc);
|
||||
void gedit_encoding_free (GeditEncoding *enc);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_ENCODINGS_H__ */
|
||||
39
gedit/gedit-enum-types.c.template
Executable file
39
gedit/gedit-enum-types.c.template
Executable file
@@ -0,0 +1,39 @@
|
||||
/*** BEGIN file-header ***/
|
||||
#include "gedit-enum-types.h"
|
||||
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
/* enumerations from "@filename@" */
|
||||
#include "@filename@"
|
||||
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN value-header ***/
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static GType the_type = 0;
|
||||
|
||||
if (the_type == 0)
|
||||
{
|
||||
static const G@Type@Value values[] = {
|
||||
/*** END value-header ***/
|
||||
|
||||
/*** BEGIN value-production ***/
|
||||
{ @VALUENAME@,
|
||||
"@VALUENAME@",
|
||||
"@valuenick@" },
|
||||
/*** END value-production ***/
|
||||
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
the_type = g_@type@_register_static (
|
||||
g_intern_static_string ("@EnumName@"),
|
||||
values);
|
||||
}
|
||||
return the_type;
|
||||
}
|
||||
|
||||
/*** END value-tail ***/
|
||||
27
gedit/gedit-enum-types.h.template
Executable file
27
gedit/gedit-enum-types.h.template
Executable file
@@ -0,0 +1,27 @@
|
||||
/*** BEGIN file-header ***/
|
||||
#ifndef __GEDIT_ENUM_TYPES_H__
|
||||
#define __GEDIT_ENUM_TYPES_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
/* Enumerations from "@filename@" */
|
||||
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN enumeration-production ***/
|
||||
#define GEDIT_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
|
||||
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/*** END enumeration-production ***/
|
||||
|
||||
/*** BEGIN file-tail ***/
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_ENUM_TYPES_H__ */
|
||||
/*** END file-tail ***/
|
||||
|
||||
560
gedit/gedit-file-chooser-dialog.c
Executable file
560
gedit/gedit-file-chooser-dialog.c
Executable file
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
* gedit-file-chooser-dialog.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005-2007 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* TODO: Override set_extra_widget */
|
||||
/* TODO: add encoding property */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gedit-file-chooser-dialog.h"
|
||||
#include "gedit-encodings-combo-box.h"
|
||||
#include "gedit-language-manager.h"
|
||||
#include "gedit-prefs-manager-app.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-enum-types.h"
|
||||
|
||||
#define GEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogPrivate))
|
||||
|
||||
#define ALL_FILES _("All Files")
|
||||
#define ALL_TEXT_FILES _("All Text Files")
|
||||
|
||||
struct _GeditFileChooserDialogPrivate
|
||||
{
|
||||
GtkWidget *option_menu;
|
||||
GtkWidget *extra_widget;
|
||||
|
||||
GtkWidget *newline_label;
|
||||
GtkWidget *newline_combo;
|
||||
GtkListStore *newline_store;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditFileChooserDialog, gedit_file_chooser_dialog, GTK_TYPE_FILE_CHOOSER_DIALOG)
|
||||
|
||||
static void
|
||||
gedit_file_chooser_dialog_class_init (GeditFileChooserDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditFileChooserDialogPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
create_option_menu (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
GtkWidget *label;
|
||||
GtkWidget *menu;
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
||||
|
||||
menu = gedit_encodings_combo_box_new (
|
||||
gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
|
||||
label,
|
||||
FALSE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
|
||||
menu,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (menu);
|
||||
|
||||
dialog->priv->option_menu = menu;
|
||||
}
|
||||
|
||||
static void
|
||||
update_newline_visibility (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE)
|
||||
{
|
||||
gtk_widget_show (dialog->priv->newline_label);
|
||||
gtk_widget_show (dialog->priv->newline_combo);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (dialog->priv->newline_label);
|
||||
gtk_widget_hide (dialog->priv->newline_combo);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
newline_combo_append (GtkComboBox *combo,
|
||||
GtkListStore *store,
|
||||
GtkTreeIter *iter,
|
||||
const gchar *label,
|
||||
GeditDocumentNewlineType newline_type)
|
||||
{
|
||||
gtk_list_store_append (store, iter);
|
||||
gtk_list_store_set (store, iter, 0, label, 1, newline_type, -1);
|
||||
|
||||
if (newline_type == GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT)
|
||||
{
|
||||
gtk_combo_box_set_active_iter (combo, iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_newline_combo (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
GtkWidget *label, *combo;
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeIter iter;
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("L_ine Ending:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
||||
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE);
|
||||
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo),
|
||||
renderer,
|
||||
TRUE);
|
||||
|
||||
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo),
|
||||
renderer,
|
||||
"text",
|
||||
0);
|
||||
|
||||
newline_combo_append (GTK_COMBO_BOX (combo),
|
||||
store,
|
||||
&iter,
|
||||
_("Unix/Linux"),
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_LF);
|
||||
|
||||
newline_combo_append (GTK_COMBO_BOX (combo),
|
||||
store,
|
||||
&iter,
|
||||
_("Mac OS Classic"),
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_CR);
|
||||
|
||||
newline_combo_append (GTK_COMBO_BOX (combo),
|
||||
store,
|
||||
&iter,
|
||||
_("Windows"),
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
|
||||
label,
|
||||
FALSE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
|
||||
combo,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
dialog->priv->newline_combo = combo;
|
||||
dialog->priv->newline_label = label;
|
||||
dialog->priv->newline_store = store;
|
||||
|
||||
update_newline_visibility (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
create_extra_widget (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
dialog->priv->extra_widget = gtk_hbox_new (FALSE, 6);
|
||||
|
||||
gtk_widget_show (dialog->priv->extra_widget);
|
||||
|
||||
create_option_menu (dialog);
|
||||
create_newline_combo (dialog);
|
||||
|
||||
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
|
||||
dialog->priv->extra_widget);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
action_changed (GeditFileChooserDialog *dialog,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileChooserAction action;
|
||||
|
||||
action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case GTK_FILE_CHOOSER_ACTION_OPEN:
|
||||
g_object_set (dialog->priv->option_menu,
|
||||
"save_mode", FALSE,
|
||||
NULL);
|
||||
gtk_widget_show (dialog->priv->option_menu);
|
||||
break;
|
||||
case GTK_FILE_CHOOSER_ACTION_SAVE:
|
||||
g_object_set (dialog->priv->option_menu,
|
||||
"save_mode", TRUE,
|
||||
NULL);
|
||||
gtk_widget_show (dialog->priv->option_menu);
|
||||
break;
|
||||
default:
|
||||
gtk_widget_hide (dialog->priv->option_menu);
|
||||
}
|
||||
|
||||
update_newline_visibility (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
filter_changed (GeditFileChooserDialog *dialog,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileFilter *filter;
|
||||
|
||||
if (!gedit_prefs_manager_active_file_filter_can_set ())
|
||||
return;
|
||||
|
||||
filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
|
||||
if (filter != NULL)
|
||||
{
|
||||
const gchar *name;
|
||||
gint id = 0;
|
||||
|
||||
name = gtk_file_filter_get_name (filter);
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
if (strcmp (name, ALL_TEXT_FILES) == 0)
|
||||
id = 1;
|
||||
|
||||
gedit_debug_message (DEBUG_COMMANDS, "Active filter: %s (%d)", name, id);
|
||||
|
||||
gedit_prefs_manager_set_active_file_filter (id);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: use globs too - Paolo (Aug. 27, 2007) */
|
||||
static gboolean
|
||||
all_text_files_filter (const GtkFileFilterInfo *filter_info,
|
||||
gpointer data)
|
||||
{
|
||||
static GSList *known_mime_types = NULL;
|
||||
GSList *mime_types;
|
||||
|
||||
if (known_mime_types == NULL)
|
||||
{
|
||||
GtkSourceLanguageManager *lm;
|
||||
const gchar * const *languages;
|
||||
|
||||
lm = gedit_get_language_manager ();
|
||||
languages = gtk_source_language_manager_get_language_ids (lm);
|
||||
|
||||
while ((languages != NULL) && (*languages != NULL))
|
||||
{
|
||||
gchar **mime_types;
|
||||
gint i;
|
||||
GtkSourceLanguage *lang;
|
||||
|
||||
lang = gtk_source_language_manager_get_language (lm, *languages);
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), FALSE);
|
||||
++languages;
|
||||
|
||||
mime_types = gtk_source_language_get_mime_types (lang);
|
||||
if (mime_types == NULL)
|
||||
continue;
|
||||
|
||||
for (i = 0; mime_types[i] != NULL; i++)
|
||||
{
|
||||
if (!g_content_type_is_a (mime_types[i], "text/plain"))
|
||||
{
|
||||
gedit_debug_message (DEBUG_COMMANDS,
|
||||
"Mime-type %s is not related to text/plain",
|
||||
mime_types[i]);
|
||||
|
||||
known_mime_types = g_slist_prepend (known_mime_types,
|
||||
g_strdup (mime_types[i]));
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (mime_types);
|
||||
}
|
||||
|
||||
/* known_mime_types always has "text/plain" as first item" */
|
||||
known_mime_types = g_slist_prepend (known_mime_types, g_strdup ("text/plain"));
|
||||
}
|
||||
|
||||
/* known mime_types contains "text/plain" and then the list of mime-types unrelated to "text/plain"
|
||||
* that gedit recognizes */
|
||||
|
||||
if (filter_info->mime_type == NULL)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* The filter is matching:
|
||||
* - the mime-types beginning with "text/"
|
||||
* - the mime-types inheriting from a known mime-type (note the text/plain is
|
||||
* the first known mime-type)
|
||||
*/
|
||||
|
||||
if (strncmp (filter_info->mime_type, "text/", 5) == 0)
|
||||
return TRUE;
|
||||
|
||||
mime_types = known_mime_types;
|
||||
while (mime_types != NULL)
|
||||
{
|
||||
if (g_content_type_is_a (filter_info->mime_type, (const gchar*)mime_types->data))
|
||||
return TRUE;
|
||||
|
||||
mime_types = g_slist_next (mime_types);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_file_chooser_dialog_init (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
dialog->priv = GEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gedit_file_chooser_dialog_new_valist (const gchar *title,
|
||||
GtkWindow *parent,
|
||||
GtkFileChooserAction action,
|
||||
const GeditEncoding *encoding,
|
||||
const gchar *first_button_text,
|
||||
va_list varargs)
|
||||
{
|
||||
GtkWidget *result;
|
||||
const char *button_text = first_button_text;
|
||||
gint response_id;
|
||||
GtkFileFilter *filter;
|
||||
gint active_filter;
|
||||
|
||||
g_return_val_if_fail (parent != NULL, NULL);
|
||||
|
||||
result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG,
|
||||
"title", title,
|
||||
"file-system-backend", NULL,
|
||||
"local-only", FALSE,
|
||||
"action", action,
|
||||
"select-multiple", action == GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
NULL);
|
||||
|
||||
create_extra_widget (GEDIT_FILE_CHOOSER_DIALOG (result));
|
||||
|
||||
g_signal_connect (result,
|
||||
"notify::action",
|
||||
G_CALLBACK (action_changed),
|
||||
NULL);
|
||||
|
||||
if (encoding != NULL)
|
||||
gedit_encodings_combo_box_set_selected_encoding (
|
||||
GEDIT_ENCODINGS_COMBO_BOX (GEDIT_FILE_CHOOSER_DIALOG (result)->priv->option_menu),
|
||||
encoding);
|
||||
|
||||
active_filter = gedit_prefs_manager_get_active_file_filter ();
|
||||
gedit_debug_message (DEBUG_COMMANDS, "Active filter: %d", active_filter);
|
||||
|
||||
/* Filters */
|
||||
filter = gtk_file_filter_new ();
|
||||
|
||||
gtk_file_filter_set_name (filter, ALL_FILES);
|
||||
gtk_file_filter_add_pattern (filter, "*");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
|
||||
|
||||
if (active_filter != 1)
|
||||
{
|
||||
/* Make this filter the default */
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
|
||||
}
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, ALL_TEXT_FILES);
|
||||
gtk_file_filter_add_custom (filter,
|
||||
GTK_FILE_FILTER_MIME_TYPE,
|
||||
all_text_files_filter,
|
||||
NULL,
|
||||
NULL);
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
|
||||
|
||||
if (active_filter == 1)
|
||||
{
|
||||
/* Make this filter the default */
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
|
||||
}
|
||||
|
||||
g_signal_connect (result,
|
||||
"notify::filter",
|
||||
G_CALLBACK (filter_changed),
|
||||
NULL);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (result), parent);
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE);
|
||||
|
||||
while (button_text)
|
||||
{
|
||||
response_id = va_arg (varargs, gint);
|
||||
|
||||
gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
|
||||
if ((response_id == GTK_RESPONSE_OK) ||
|
||||
(response_id == GTK_RESPONSE_ACCEPT) ||
|
||||
(response_id == GTK_RESPONSE_YES) ||
|
||||
(response_id == GTK_RESPONSE_APPLY))
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (result), response_id);
|
||||
|
||||
button_text = va_arg (varargs, const gchar *);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_file_chooser_dialog_new:
|
||||
* @title: Title of the dialog, or %NULL
|
||||
* @parent: Transient parent of the dialog, or %NULL
|
||||
* @action: Open or save mode for the dialog
|
||||
* @first_button_text: stock ID or text to go in the first button, or %NULL
|
||||
* @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
|
||||
*
|
||||
* Creates a new #GeditFileChooserDialog. This function is analogous to
|
||||
* gtk_dialog_new_with_buttons().
|
||||
*
|
||||
* Return value: a new #GeditFileChooserDialog
|
||||
*
|
||||
**/
|
||||
GtkWidget *
|
||||
gedit_file_chooser_dialog_new (const gchar *title,
|
||||
GtkWindow *parent,
|
||||
GtkFileChooserAction action,
|
||||
const GeditEncoding *encoding,
|
||||
const gchar *first_button_text,
|
||||
...)
|
||||
{
|
||||
GtkWidget *result;
|
||||
va_list varargs;
|
||||
|
||||
va_start (varargs, first_button_text);
|
||||
result = gedit_file_chooser_dialog_new_valist (title, parent, action,
|
||||
encoding, first_button_text,
|
||||
varargs);
|
||||
va_end (varargs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog *dialog,
|
||||
const GeditEncoding *encoding)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
|
||||
g_return_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
|
||||
|
||||
gedit_encodings_combo_box_set_selected_encoding (
|
||||
GEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu),
|
||||
encoding);
|
||||
}
|
||||
|
||||
const GeditEncoding *
|
||||
gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
|
||||
g_return_val_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu), NULL);
|
||||
g_return_val_if_fail ((gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_OPEN ||
|
||||
gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE), NULL);
|
||||
|
||||
return gedit_encodings_combo_box_get_selected_encoding (
|
||||
GEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
|
||||
}
|
||||
|
||||
void
|
||||
gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog *dialog,
|
||||
GeditDocumentNewlineType newline_type)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
|
||||
g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
|
||||
model = GTK_TREE_MODEL (dialog->priv->newline_store);
|
||||
|
||||
if (!gtk_tree_model_get_iter_first (model, &iter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
GeditDocumentNewlineType nt;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &nt, -1);
|
||||
|
||||
if (newline_type == nt)
|
||||
{
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
|
||||
&iter);
|
||||
break;
|
||||
}
|
||||
} while (gtk_tree_model_iter_next (model, &iter));
|
||||
}
|
||||
|
||||
GeditDocumentNewlineType
|
||||
gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GeditDocumentNewlineType newline_type;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
|
||||
g_return_val_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
|
||||
|
||||
gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
|
||||
&iter);
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->newline_store),
|
||||
&iter,
|
||||
1,
|
||||
&newline_type,
|
||||
-1);
|
||||
|
||||
return newline_type;
|
||||
}
|
||||
89
gedit/gedit-file-chooser-dialog.h
Executable file
89
gedit/gedit-file-chooser-dialog.h
Executable file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* gedit-file-chooser-dialog.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_FILE_CHOOSER_DIALOG_H__
|
||||
#define __GEDIT_FILE_CHOOSER_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gedit/gedit-encodings.h>
|
||||
#include <gedit/gedit-enum-types.h>
|
||||
#include <gedit/gedit-document.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_FILE_CHOOSER_DIALOG (gedit_file_chooser_dialog_get_type ())
|
||||
#define GEDIT_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialog))
|
||||
#define GEDIT_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass))
|
||||
#define GEDIT_IS_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG))
|
||||
#define GEDIT_IS_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_CHOOSER_DIALOG))
|
||||
#define GEDIT_FILE_CHOOSER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass))
|
||||
|
||||
typedef struct _GeditFileChooserDialog GeditFileChooserDialog;
|
||||
typedef struct _GeditFileChooserDialogClass GeditFileChooserDialogClass;
|
||||
|
||||
typedef struct _GeditFileChooserDialogPrivate GeditFileChooserDialogPrivate;
|
||||
|
||||
struct _GeditFileChooserDialogClass
|
||||
{
|
||||
GtkFileChooserDialogClass parent_class;
|
||||
};
|
||||
|
||||
struct _GeditFileChooserDialog
|
||||
{
|
||||
GtkFileChooserDialog parent_instance;
|
||||
|
||||
GeditFileChooserDialogPrivate *priv;
|
||||
};
|
||||
|
||||
GType gedit_file_chooser_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_file_chooser_dialog_new (const gchar *title,
|
||||
GtkWindow *parent,
|
||||
GtkFileChooserAction action,
|
||||
const GeditEncoding *encoding,
|
||||
const gchar *first_button_text,
|
||||
...);
|
||||
|
||||
void gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog *dialog,
|
||||
const GeditEncoding *encoding);
|
||||
|
||||
const GeditEncoding
|
||||
*gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog);
|
||||
|
||||
void gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog *dialog,
|
||||
GeditDocumentNewlineType newline_type);
|
||||
|
||||
GeditDocumentNewlineType
|
||||
gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_FILE_CHOOSER_DIALOG_H__ */
|
||||
708
gedit/gedit-gio-document-loader.c
Executable file
708
gedit/gedit-gio-document-loader.c
Executable file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
* gedit-gio-document-loader.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2008. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "gedit-gio-document-loader.h"
|
||||
#include "gedit-document-output-stream.h"
|
||||
#include "gedit-smart-charset-converter.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-utils.h"
|
||||
|
||||
#ifndef ENABLE_GVFS_METADATA
|
||||
#include "gedit-metadata-manager.h"
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeditGioDocumentLoader *loader;
|
||||
GCancellable *cancellable;
|
||||
|
||||
gssize read;
|
||||
gboolean tried_mount;
|
||||
} AsyncData;
|
||||
|
||||
#define READ_CHUNK_SIZE 8192
|
||||
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
|
||||
G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
|
||||
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," \
|
||||
GEDIT_METADATA_ATTRIBUTE_ENCODING
|
||||
|
||||
#define GEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE(object) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_GIO_DOCUMENT_LOADER, \
|
||||
GeditGioDocumentLoaderPrivate))
|
||||
|
||||
static void gedit_gio_document_loader_load (GeditDocumentLoader *loader);
|
||||
static gboolean gedit_gio_document_loader_cancel (GeditDocumentLoader *loader);
|
||||
static goffset gedit_gio_document_loader_get_bytes_read (GeditDocumentLoader *loader);
|
||||
|
||||
static void open_async_read (AsyncData *async);
|
||||
|
||||
struct _GeditGioDocumentLoaderPrivate
|
||||
{
|
||||
/* Info on the current file */
|
||||
GFile *gfile;
|
||||
|
||||
goffset bytes_read;
|
||||
|
||||
/* Handle for remote files */
|
||||
GCancellable *cancellable;
|
||||
GInputStream *stream;
|
||||
GOutputStream *output;
|
||||
GeditSmartCharsetConverter *converter;
|
||||
|
||||
gchar buffer[READ_CHUNK_SIZE];
|
||||
|
||||
GError *error;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditGioDocumentLoader, gedit_gio_document_loader, GEDIT_TYPE_DOCUMENT_LOADER)
|
||||
|
||||
static void
|
||||
gedit_gio_document_loader_dispose (GObject *object)
|
||||
{
|
||||
GeditGioDocumentLoaderPrivate *priv;
|
||||
|
||||
priv = GEDIT_GIO_DOCUMENT_LOADER (object)->priv;
|
||||
|
||||
if (priv->cancellable != NULL)
|
||||
{
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_object_unref (priv->cancellable);
|
||||
priv->cancellable = NULL;
|
||||
}
|
||||
|
||||
if (priv->stream != NULL)
|
||||
{
|
||||
g_object_unref (priv->stream);
|
||||
priv->stream = NULL;
|
||||
}
|
||||
|
||||
if (priv->output != NULL)
|
||||
{
|
||||
g_object_unref (priv->output);
|
||||
priv->output = NULL;
|
||||
}
|
||||
|
||||
if (priv->converter != NULL)
|
||||
{
|
||||
g_object_unref (priv->converter);
|
||||
priv->converter = NULL;
|
||||
}
|
||||
|
||||
if (priv->gfile != NULL)
|
||||
{
|
||||
g_object_unref (priv->gfile);
|
||||
priv->gfile = NULL;
|
||||
}
|
||||
|
||||
if (priv->error != NULL)
|
||||
{
|
||||
g_error_free (priv->error);
|
||||
priv->error = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_gio_document_loader_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_loader_class_init (GeditGioDocumentLoaderClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GeditDocumentLoaderClass *loader_class = GEDIT_DOCUMENT_LOADER_CLASS (klass);
|
||||
|
||||
object_class->dispose = gedit_gio_document_loader_dispose;
|
||||
|
||||
loader_class->load = gedit_gio_document_loader_load;
|
||||
loader_class->cancel = gedit_gio_document_loader_cancel;
|
||||
loader_class->get_bytes_read = gedit_gio_document_loader_get_bytes_read;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditGioDocumentLoaderPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_loader_init (GeditGioDocumentLoader *gvloader)
|
||||
{
|
||||
gvloader->priv = GEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE (gvloader);
|
||||
|
||||
gvloader->priv->converter = NULL;
|
||||
gvloader->priv->error = NULL;
|
||||
}
|
||||
|
||||
static AsyncData *
|
||||
async_data_new (GeditGioDocumentLoader *gvloader)
|
||||
{
|
||||
AsyncData *async;
|
||||
|
||||
async = g_slice_new (AsyncData);
|
||||
async->loader = gvloader;
|
||||
async->cancellable = g_object_ref (gvloader->priv->cancellable);
|
||||
async->tried_mount = FALSE;
|
||||
|
||||
return async;
|
||||
}
|
||||
|
||||
static void
|
||||
async_data_free (AsyncData *async)
|
||||
{
|
||||
g_object_unref (async->cancellable);
|
||||
g_slice_free (AsyncData, async);
|
||||
}
|
||||
|
||||
static const GeditEncoding *
|
||||
get_metadata_encoding (GeditDocumentLoader *loader)
|
||||
{
|
||||
const GeditEncoding *enc = NULL;
|
||||
|
||||
#ifndef ENABLE_GVFS_METADATA
|
||||
gchar *charset;
|
||||
const gchar *uri;
|
||||
|
||||
uri = gedit_document_loader_get_uri (loader);
|
||||
|
||||
charset = gedit_metadata_manager_get (uri, "encoding");
|
||||
|
||||
if (charset == NULL)
|
||||
return NULL;
|
||||
|
||||
enc = gedit_encoding_get_from_charset (charset);
|
||||
|
||||
g_free (charset);
|
||||
#else
|
||||
GFileInfo *info;
|
||||
|
||||
info = gedit_document_loader_get_info (loader);
|
||||
|
||||
/* check if the encoding was set in the metadata */
|
||||
if (g_file_info_has_attribute (info, GEDIT_METADATA_ATTRIBUTE_ENCODING))
|
||||
{
|
||||
const gchar *charset;
|
||||
|
||||
charset = g_file_info_get_attribute_string (info,
|
||||
GEDIT_METADATA_ATTRIBUTE_ENCODING);
|
||||
|
||||
if (charset == NULL)
|
||||
return NULL;
|
||||
|
||||
enc = gedit_encoding_get_from_charset (charset);
|
||||
}
|
||||
#endif
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_load_completed_or_failed (GeditGioDocumentLoader *loader, AsyncData *async)
|
||||
{
|
||||
gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (loader),
|
||||
TRUE,
|
||||
loader->priv->error);
|
||||
|
||||
if (async)
|
||||
async_data_free (async);
|
||||
}
|
||||
|
||||
static void
|
||||
async_failed (AsyncData *async, GError *error)
|
||||
{
|
||||
g_propagate_error (&async->loader->priv->error, error);
|
||||
remote_load_completed_or_failed (async->loader, async);
|
||||
}
|
||||
|
||||
static void
|
||||
close_input_stream_ready_cb (GInputStream *stream,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Finished closing input stream");
|
||||
|
||||
if (!g_input_stream_close_finish (stream, res, &error))
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
|
||||
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Close output stream");
|
||||
if (!g_output_stream_close (async->loader->priv->output,
|
||||
async->cancellable, &error))
|
||||
{
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
remote_load_completed_or_failed (async->loader, async);
|
||||
}
|
||||
|
||||
static void
|
||||
write_complete (AsyncData *async)
|
||||
{
|
||||
GeditDocumentLoader *loader;
|
||||
|
||||
loader = GEDIT_DOCUMENT_LOADER (async->loader);
|
||||
|
||||
if (async->loader->priv->stream)
|
||||
g_input_stream_close_async (G_INPUT_STREAM (async->loader->priv->stream),
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback)close_input_stream_ready_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
/* prototype, because they call each other... isn't C lovely */
|
||||
static void read_file_chunk (AsyncData *async);
|
||||
|
||||
static void
|
||||
write_file_chunk (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
gssize bytes_written;
|
||||
GError *error = NULL;
|
||||
|
||||
gvloader = async->loader;
|
||||
|
||||
/* we use sync methods on doc stream since it is in memory. Using async
|
||||
would be racy and we can endup with invalidated iters */
|
||||
bytes_written = g_output_stream_write (G_OUTPUT_STREAM (gvloader->priv->output),
|
||||
gvloader->priv->buffer,
|
||||
async->read,
|
||||
async->cancellable,
|
||||
&error);
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
|
||||
if (bytes_written == -1)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* note that this signal blocks the read... check if it isn't
|
||||
* a performance problem
|
||||
*/
|
||||
gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
read_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
async_read_cb (GInputStream *stream,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* manually check cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gvloader = async->loader;
|
||||
|
||||
async->read = g_input_stream_read_finish (stream, res, &error);
|
||||
|
||||
/* error occurred */
|
||||
if (async->read == -1)
|
||||
{
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for the extremely unlikely case where the file size overflows. */
|
||||
if (gvloader->priv->bytes_read + async->read < gvloader->priv->bytes_read)
|
||||
{
|
||||
g_set_error (&gvloader->priv->error,
|
||||
GEDIT_DOCUMENT_ERROR,
|
||||
GEDIT_DOCUMENT_ERROR_TOO_BIG,
|
||||
"File too big");
|
||||
|
||||
async_failed (async, gvloader->priv->error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Bump the size. */
|
||||
gvloader->priv->bytes_read += async->read;
|
||||
|
||||
/* end of the file, we are done! */
|
||||
if (async->read == 0)
|
||||
{
|
||||
GeditDocumentLoader *loader;
|
||||
|
||||
loader = GEDIT_DOCUMENT_LOADER (gvloader);
|
||||
|
||||
loader->auto_detected_encoding =
|
||||
gedit_smart_charset_converter_get_guessed (gvloader->priv->converter);
|
||||
|
||||
loader->auto_detected_newline_type =
|
||||
gedit_document_output_stream_detect_newline_type (GEDIT_DOCUMENT_OUTPUT_STREAM (gvloader->priv->output));
|
||||
|
||||
/* Check if we needed some fallback char, if so, check if there was
|
||||
a previous error and if not set a fallback used error */
|
||||
/* FIXME Uncomment this when we want to manage conversion fallback */
|
||||
/*if ((gedit_smart_charset_converter_get_num_fallbacks (gvloader->priv->converter) != 0) &&
|
||||
gvloader->priv->error == NULL)
|
||||
{
|
||||
g_set_error_literal (&gvloader->priv->error,
|
||||
GEDIT_DOCUMENT_ERROR,
|
||||
GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
|
||||
"There was a conversion error and it was "
|
||||
"needed to use a fallback char");
|
||||
}*/
|
||||
|
||||
write_complete (async);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
write_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
read_file_chunk (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
|
||||
gvloader = async->loader;
|
||||
|
||||
g_input_stream_read_async (G_INPUT_STREAM (gvloader->priv->stream),
|
||||
gvloader->priv->buffer,
|
||||
READ_CHUNK_SIZE,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) async_read_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_candidate_encodings (GeditGioDocumentLoader *gvloader)
|
||||
{
|
||||
const GeditEncoding *metadata;
|
||||
GSList *encodings = NULL;
|
||||
|
||||
encodings = gedit_prefs_manager_get_auto_detected_encodings ();
|
||||
|
||||
metadata = get_metadata_encoding (GEDIT_DOCUMENT_LOADER (gvloader));
|
||||
if (metadata != NULL)
|
||||
{
|
||||
encodings = g_slist_prepend (encodings, (gpointer)metadata);
|
||||
}
|
||||
|
||||
return encodings;
|
||||
}
|
||||
|
||||
static void
|
||||
finish_query_info (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
GeditDocumentLoader *loader;
|
||||
GInputStream *conv_stream;
|
||||
GFileInfo *info;
|
||||
GSList *candidate_encodings;
|
||||
|
||||
gvloader = async->loader;
|
||||
loader = GEDIT_DOCUMENT_LOADER (gvloader);
|
||||
info = loader->info;
|
||||
|
||||
/* if it's not a regular file, error out... */
|
||||
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
|
||||
g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
|
||||
{
|
||||
g_set_error (&gvloader->priv->error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_REGULAR_FILE,
|
||||
"Not a regular file");
|
||||
|
||||
remote_load_completed_or_failed (gvloader, async);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the candidate encodings */
|
||||
if (loader->encoding == NULL)
|
||||
{
|
||||
candidate_encodings = get_candidate_encodings (gvloader);
|
||||
}
|
||||
else
|
||||
{
|
||||
candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->encoding);
|
||||
}
|
||||
|
||||
gvloader->priv->converter = gedit_smart_charset_converter_new (candidate_encodings);
|
||||
g_slist_free (candidate_encodings);
|
||||
|
||||
conv_stream = g_converter_input_stream_new (gvloader->priv->stream,
|
||||
G_CONVERTER (gvloader->priv->converter));
|
||||
g_object_unref (gvloader->priv->stream);
|
||||
|
||||
gvloader->priv->stream = conv_stream;
|
||||
|
||||
/* Output stream */
|
||||
gvloader->priv->output = gedit_document_output_stream_new (loader->document);
|
||||
|
||||
/* start reading */
|
||||
read_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
query_info_cb (GFile *source,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
GFileInfo *info;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* manually check the cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gvloader = async->loader;
|
||||
|
||||
/* finish the info query */
|
||||
info = g_file_query_info_finish (gvloader->priv->gfile,
|
||||
res,
|
||||
&error);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
/* propagate the error and clean up */
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
GEDIT_DOCUMENT_LOADER (gvloader)->info = info;
|
||||
|
||||
finish_query_info (async);
|
||||
}
|
||||
|
||||
static void
|
||||
mount_ready_callback (GFile *file,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean mounted;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* manual check for cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
|
||||
|
||||
if (!mounted)
|
||||
{
|
||||
async_failed (async, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* try again to open the file for reading */
|
||||
open_async_read (async);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
recover_not_mounted (AsyncData *async)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
GMountOperation *mount_operation;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
doc = gedit_document_loader_get_document (GEDIT_DOCUMENT_LOADER (async->loader));
|
||||
mount_operation = _gedit_document_create_mount_operation (doc);
|
||||
|
||||
async->tried_mount = TRUE;
|
||||
g_file_mount_enclosing_volume (async->loader->priv->gfile,
|
||||
G_MOUNT_MOUNT_NONE,
|
||||
mount_operation,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) mount_ready_callback,
|
||||
async);
|
||||
|
||||
g_object_unref (mount_operation);
|
||||
}
|
||||
|
||||
static void
|
||||
async_read_ready_callback (GObject *source,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GeditGioDocumentLoader *gvloader;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* manual check for cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gvloader = async->loader;
|
||||
|
||||
gvloader->priv->stream = G_INPUT_STREAM (g_file_read_finish (gvloader->priv->gfile,
|
||||
res, &error));
|
||||
|
||||
if (!gvloader->priv->stream)
|
||||
{
|
||||
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
|
||||
{
|
||||
recover_not_mounted (async);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Propagate error */
|
||||
g_propagate_error (&gvloader->priv->error, error);
|
||||
gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
|
||||
TRUE,
|
||||
gvloader->priv->error);
|
||||
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the file info: note we cannot use
|
||||
* g_file_input_stream_query_info_async since it is not able to get the
|
||||
* content type etc, beside it is not supported by gvfs.
|
||||
* Using the file instead of the stream is slightly racy, but for
|
||||
* loading this is not too bad...
|
||||
*/
|
||||
g_file_query_info_async (gvloader->priv->gfile,
|
||||
REMOTE_QUERY_ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) query_info_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
static void
|
||||
open_async_read (AsyncData *async)
|
||||
{
|
||||
g_file_read_async (async->loader->priv->gfile,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) async_read_ready_callback,
|
||||
async);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_loader_load (GeditDocumentLoader *loader)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader = GEDIT_GIO_DOCUMENT_LOADER (loader);
|
||||
AsyncData *async;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
/* make sure no load operation is currently running */
|
||||
g_return_if_fail (gvloader->priv->cancellable == NULL);
|
||||
|
||||
gvloader->priv->gfile = g_file_new_for_uri (loader->uri);
|
||||
|
||||
/* loading start */
|
||||
gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
gvloader->priv->cancellable = g_cancellable_new ();
|
||||
async = async_data_new (gvloader);
|
||||
|
||||
open_async_read (async);
|
||||
}
|
||||
|
||||
static goffset
|
||||
gedit_gio_document_loader_get_bytes_read (GeditDocumentLoader *loader)
|
||||
{
|
||||
return GEDIT_GIO_DOCUMENT_LOADER (loader)->priv->bytes_read;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gedit_gio_document_loader_cancel (GeditDocumentLoader *loader)
|
||||
{
|
||||
GeditGioDocumentLoader *gvloader = GEDIT_GIO_DOCUMENT_LOADER (loader);
|
||||
|
||||
if (gvloader->priv->cancellable == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_cancellable_cancel (gvloader->priv->cancellable);
|
||||
|
||||
g_set_error (&gvloader->priv->error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_CANCELLED,
|
||||
"Operation cancelled");
|
||||
|
||||
remote_load_completed_or_failed (gvloader, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
79
gedit/gedit-gio-document-loader.h
Executable file
79
gedit/gedit-gio-document-loader.h
Executable file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* gedit-gio-document-loader.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2008. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_GIO_DOCUMENT_LOADER_H__
|
||||
#define __GEDIT_GIO_DOCUMENT_LOADER_H__
|
||||
|
||||
#include <gedit/gedit-document.h>
|
||||
#include "gedit-document-loader.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_GIO_DOCUMENT_LOADER (gedit_gio_document_loader_get_type())
|
||||
#define GEDIT_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_GIO_DOCUMENT_LOADER, GeditGioDocumentLoader))
|
||||
#define GEDIT_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_GIO_DOCUMENT_LOADER, GeditGioDocumentLoaderClass))
|
||||
#define GEDIT_IS_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_GIO_DOCUMENT_LOADER))
|
||||
#define GEDIT_IS_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_GIO_DOCUMENT_LOADER))
|
||||
#define GEDIT_GIO_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_GIO_DOCUMENT_LOADER, GeditGioDocumentLoaderClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditGioDocumentLoaderPrivate GeditGioDocumentLoaderPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditGioDocumentLoader GeditGioDocumentLoader;
|
||||
|
||||
struct _GeditGioDocumentLoader
|
||||
{
|
||||
GeditDocumentLoader loader;
|
||||
|
||||
/*< private > */
|
||||
GeditGioDocumentLoaderPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef GeditDocumentLoaderClass GeditGioDocumentLoaderClass;
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_gio_document_loader_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_GIO_DOCUMENT_LOADER_H__ */
|
||||
775
gedit/gedit-gio-document-saver.c
Executable file
775
gedit/gedit-gio-document-saver.c
Executable file
@@ -0,0 +1,775 @@
|
||||
/*
|
||||
* gedit-gio-document-saver.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005-2006 - Paolo Borelli and Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Borelli, Paolo Maggi, Steve Frécinaux
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gedit-gio-document-saver.h"
|
||||
#include "gedit-document-input-stream.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
#define WRITE_CHUNK_SIZE 8192
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeditGioDocumentSaver *saver;
|
||||
gchar buffer[WRITE_CHUNK_SIZE];
|
||||
GCancellable *cancellable;
|
||||
gboolean tried_mount;
|
||||
gssize written;
|
||||
gssize read;
|
||||
GError *error;
|
||||
} AsyncData;
|
||||
|
||||
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED
|
||||
|
||||
#define GEDIT_GIO_DOCUMENT_SAVER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_GIO_DOCUMENT_SAVER, \
|
||||
GeditGioDocumentSaverPrivate))
|
||||
|
||||
static void gedit_gio_document_saver_save (GeditDocumentSaver *saver,
|
||||
GTimeVal *old_mtime);
|
||||
static goffset gedit_gio_document_saver_get_file_size (GeditDocumentSaver *saver);
|
||||
static goffset gedit_gio_document_saver_get_bytes_written (GeditDocumentSaver *saver);
|
||||
|
||||
|
||||
static void check_modified_async (AsyncData *async);
|
||||
|
||||
struct _GeditGioDocumentSaverPrivate
|
||||
{
|
||||
GTimeVal old_mtime;
|
||||
|
||||
goffset size;
|
||||
goffset bytes_written;
|
||||
|
||||
GFile *gfile;
|
||||
GCancellable *cancellable;
|
||||
GOutputStream *stream;
|
||||
GInputStream *input;
|
||||
|
||||
GError *error;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditGioDocumentSaver, gedit_gio_document_saver, GEDIT_TYPE_DOCUMENT_SAVER)
|
||||
|
||||
static void
|
||||
gedit_gio_document_saver_dispose (GObject *object)
|
||||
{
|
||||
GeditGioDocumentSaverPrivate *priv = GEDIT_GIO_DOCUMENT_SAVER (object)->priv;
|
||||
|
||||
if (priv->cancellable != NULL)
|
||||
{
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_object_unref (priv->cancellable);
|
||||
priv->cancellable = NULL;
|
||||
}
|
||||
|
||||
if (priv->gfile != NULL)
|
||||
{
|
||||
g_object_unref (priv->gfile);
|
||||
priv->gfile = NULL;
|
||||
}
|
||||
|
||||
if (priv->error != NULL)
|
||||
{
|
||||
g_error_free (priv->error);
|
||||
priv->error = NULL;
|
||||
}
|
||||
|
||||
if (priv->stream != NULL)
|
||||
{
|
||||
g_object_unref (priv->stream);
|
||||
priv->stream = NULL;
|
||||
}
|
||||
|
||||
if (priv->input != NULL)
|
||||
{
|
||||
g_object_unref (priv->input);
|
||||
priv->input = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_gio_document_saver_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static AsyncData *
|
||||
async_data_new (GeditGioDocumentSaver *gvsaver)
|
||||
{
|
||||
AsyncData *async;
|
||||
|
||||
async = g_slice_new (AsyncData);
|
||||
async->saver = gvsaver;
|
||||
async->cancellable = g_object_ref (gvsaver->priv->cancellable);
|
||||
|
||||
async->tried_mount = FALSE;
|
||||
async->written = 0;
|
||||
async->read = 0;
|
||||
|
||||
async->error = NULL;
|
||||
|
||||
return async;
|
||||
}
|
||||
|
||||
static void
|
||||
async_data_free (AsyncData *async)
|
||||
{
|
||||
g_object_unref (async->cancellable);
|
||||
|
||||
if (async->error)
|
||||
{
|
||||
g_error_free (async->error);
|
||||
}
|
||||
|
||||
g_slice_free (AsyncData, async);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_saver_class_init (GeditGioDocumentSaverClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GeditDocumentSaverClass *saver_class = GEDIT_DOCUMENT_SAVER_CLASS (klass);
|
||||
|
||||
object_class->dispose = gedit_gio_document_saver_dispose;
|
||||
|
||||
saver_class->save = gedit_gio_document_saver_save;
|
||||
saver_class->get_file_size = gedit_gio_document_saver_get_file_size;
|
||||
saver_class->get_bytes_written = gedit_gio_document_saver_get_bytes_written;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditGioDocumentSaverPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_saver_init (GeditGioDocumentSaver *gvsaver)
|
||||
{
|
||||
gvsaver->priv = GEDIT_GIO_DOCUMENT_SAVER_GET_PRIVATE (gvsaver);
|
||||
|
||||
gvsaver->priv->cancellable = g_cancellable_new ();
|
||||
gvsaver->priv->error = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_save_completed_or_failed (GeditGioDocumentSaver *gvsaver,
|
||||
AsyncData *async)
|
||||
{
|
||||
gedit_document_saver_saving (GEDIT_DOCUMENT_SAVER (gvsaver),
|
||||
TRUE,
|
||||
gvsaver->priv->error);
|
||||
|
||||
if (async)
|
||||
async_data_free (async);
|
||||
}
|
||||
|
||||
static void
|
||||
async_failed (AsyncData *async,
|
||||
GError *error)
|
||||
{
|
||||
g_propagate_error (&async->saver->priv->error, error);
|
||||
remote_save_completed_or_failed (async->saver, async);
|
||||
}
|
||||
|
||||
/* BEGIN NOTE:
|
||||
*
|
||||
* This fixes an issue in GOutputStream that applies the atomic replace
|
||||
* save strategy. The stream moves the written file to the original file
|
||||
* when the stream is closed. However, there is no way currently to tell
|
||||
* the stream that the save should be aborted (there could be a
|
||||
* conversion error). The patch explicitly closes the output stream
|
||||
* in all these cases with a GCancellable in the cancelled state, causing
|
||||
* the output stream to close, but not move the file. This makes use
|
||||
* of an implementation detail in the local gio file stream and should be
|
||||
* properly fixed by adding the appropriate API in gio. Until then, at least
|
||||
* we prevent data corruption for now.
|
||||
*
|
||||
* Relevant bug reports:
|
||||
*
|
||||
* Bug 615110 - write file ignore encoding errors (gedit)
|
||||
* https://bugzilla.mate.org/show_bug.cgi?id=615110
|
||||
*
|
||||
* Bug 602412 - g_file_replace does not restore original file when there is
|
||||
* errors while writing (glib/gio)
|
||||
* https://bugzilla.mate.org/show_bug.cgi?id=602412
|
||||
*/
|
||||
static void
|
||||
cancel_output_stream_ready_cb (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
g_output_stream_close_finish (stream, result, NULL);
|
||||
|
||||
/* check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable) || async->error == NULL)
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
error = async->error;
|
||||
async->error = NULL;
|
||||
|
||||
async_failed (async, error);
|
||||
}
|
||||
|
||||
static void
|
||||
cancel_output_stream (AsyncData *async)
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Cancel output stream");
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
g_cancellable_cancel (cancellable);
|
||||
|
||||
g_output_stream_close_async (async->saver->priv->stream,
|
||||
G_PRIORITY_HIGH,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)cancel_output_stream_ready_cb,
|
||||
async);
|
||||
|
||||
g_object_unref (cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
cancel_output_stream_and_fail (AsyncData *async,
|
||||
GError *error)
|
||||
{
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Cancel output stream and fail");
|
||||
|
||||
g_propagate_error (&async->error, error);
|
||||
cancel_output_stream (async);
|
||||
}
|
||||
|
||||
/*
|
||||
* END NOTE
|
||||
*/
|
||||
|
||||
static void
|
||||
remote_get_info_cb (GFile *source,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *saver;
|
||||
GFileInfo *info;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
saver = async->saver;
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Finished query info on file");
|
||||
info = g_file_query_info_finish (source, res, &error);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
if (GEDIT_DOCUMENT_SAVER (saver)->info != NULL)
|
||||
g_object_unref (GEDIT_DOCUMENT_SAVER (saver)->info);
|
||||
|
||||
GEDIT_DOCUMENT_SAVER (saver)->info = info;
|
||||
}
|
||||
else
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Query info failed: %s", error->message);
|
||||
g_propagate_error (&saver->priv->error, error);
|
||||
}
|
||||
|
||||
remote_save_completed_or_failed (saver, async);
|
||||
}
|
||||
|
||||
static void
|
||||
close_async_ready_get_info_cb (GOutputStream *stream,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Finished closing stream");
|
||||
|
||||
if (!g_output_stream_close_finish (stream, res, &error))
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Closing stream error: %s", error->message);
|
||||
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the file info: note we cannot use
|
||||
* g_file_output_stream_query_info_async since it is not able to get the
|
||||
* content type etc, beside it is not supported by gvfs.
|
||||
* I'm not sure this is actually necessary, can't we just use
|
||||
* g_content_type_guess (since we have the file name and the data)
|
||||
*/
|
||||
gedit_debug_message (DEBUG_SAVER, "Query info on file");
|
||||
g_file_query_info_async (async->saver->priv->gfile,
|
||||
REMOTE_QUERY_ATTRIBUTES,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) remote_get_info_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
static void
|
||||
write_complete (AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
/* first we close the input stream */
|
||||
gedit_debug_message (DEBUG_SAVER, "Close input stream");
|
||||
if (!g_input_stream_close (async->saver->priv->input,
|
||||
async->cancellable, &error))
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
|
||||
cancel_output_stream_and_fail (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* now we close the output stream */
|
||||
gedit_debug_message (DEBUG_SAVER, "Close output stream");
|
||||
g_output_stream_close_async (async->saver->priv->stream,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback)close_async_ready_get_info_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
/* prototype, because they call each other... isn't C lovely */
|
||||
static void read_file_chunk (AsyncData *async);
|
||||
static void write_file_chunk (AsyncData *async);
|
||||
|
||||
static void
|
||||
async_write_cb (GOutputStream *stream,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
gssize bytes_written;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* Check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
cancel_output_stream (async);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written = g_output_stream_write_finish (stream, res, &error);
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
|
||||
|
||||
if (bytes_written == -1)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
|
||||
cancel_output_stream_and_fail (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
gvsaver = async->saver;
|
||||
async->written += bytes_written;
|
||||
|
||||
/* write again */
|
||||
if (async->written != async->read)
|
||||
{
|
||||
write_file_chunk (async);
|
||||
return;
|
||||
}
|
||||
|
||||
/* note that this signal blocks the write... check if it isn't
|
||||
* a performance problem
|
||||
*/
|
||||
gedit_document_saver_saving (GEDIT_DOCUMENT_SAVER (gvsaver),
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
read_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
write_file_chunk (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
gvsaver = async->saver;
|
||||
|
||||
g_output_stream_write_async (G_OUTPUT_STREAM (gvsaver->priv->stream),
|
||||
async->buffer + async->written,
|
||||
async->read - async->written,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) async_write_cb,
|
||||
async);
|
||||
}
|
||||
|
||||
static void
|
||||
read_file_chunk (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
GeditDocumentInputStream *dstream;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
gvsaver = async->saver;
|
||||
async->written = 0;
|
||||
|
||||
/* we use sync methods on doc stream since it is in memory. Using async
|
||||
would be racy and we can endup with invalidated iters */
|
||||
async->read = g_input_stream_read (gvsaver->priv->input,
|
||||
async->buffer,
|
||||
WRITE_CHUNK_SIZE,
|
||||
async->cancellable,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
cancel_output_stream_and_fail (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we finished reading and writing */
|
||||
if (async->read == 0)
|
||||
{
|
||||
write_complete (async);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get how many chars have been read */
|
||||
dstream = GEDIT_DOCUMENT_INPUT_STREAM (gvsaver->priv->input);
|
||||
gvsaver->priv->bytes_written = gedit_document_input_stream_tell (dstream);
|
||||
|
||||
write_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
async_replace_ready_callback (GFile *source,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
GeditDocumentSaver *saver;
|
||||
GCharsetConverter *converter;
|
||||
GFileOutputStream *file_stream;
|
||||
GError *error = NULL;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* Check cancelled state manually */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gvsaver = async->saver;
|
||||
saver = GEDIT_DOCUMENT_SAVER (gvsaver);
|
||||
file_stream = g_file_replace_finish (source, res, &error);
|
||||
|
||||
/* handle any error that might occur */
|
||||
if (!file_stream)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Opening file failed: %s", error->message);
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: manage converter error? */
|
||||
gedit_debug_message (DEBUG_SAVER, "Encoding charset: %s",
|
||||
gedit_encoding_get_charset (saver->encoding));
|
||||
|
||||
if (saver->encoding != gedit_encoding_get_utf8 ())
|
||||
{
|
||||
converter = g_charset_converter_new (gedit_encoding_get_charset (saver->encoding),
|
||||
"UTF-8",
|
||||
NULL);
|
||||
gvsaver->priv->stream = g_converter_output_stream_new (G_OUTPUT_STREAM (file_stream),
|
||||
G_CONVERTER (converter));
|
||||
|
||||
g_object_unref (file_stream);
|
||||
g_object_unref (converter);
|
||||
}
|
||||
else
|
||||
{
|
||||
gvsaver->priv->stream = G_OUTPUT_STREAM (file_stream);
|
||||
}
|
||||
|
||||
gvsaver->priv->input = gedit_document_input_stream_new (GTK_TEXT_BUFFER (saver->document),
|
||||
saver->newline_type);
|
||||
|
||||
gvsaver->priv->size = gedit_document_input_stream_get_total_size (GEDIT_DOCUMENT_INPUT_STREAM (gvsaver->priv->input));
|
||||
|
||||
read_file_chunk (async);
|
||||
}
|
||||
|
||||
static void
|
||||
begin_write (AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
GeditDocumentSaver *saver;
|
||||
gboolean backup;
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Start replacing file contents");
|
||||
|
||||
/* For remote files we simply use g_file_replace_async. There is no
|
||||
* backup as of yet
|
||||
*/
|
||||
gvsaver = async->saver;
|
||||
saver = GEDIT_DOCUMENT_SAVER (gvsaver);
|
||||
|
||||
/* Do not make backups for remote files so they do not clutter remote systems */
|
||||
backup = (saver->keep_backup && gedit_document_is_local (saver->document));
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "File contents size: %" G_GINT64_FORMAT, gvsaver->priv->size);
|
||||
gedit_debug_message (DEBUG_SAVER, "Calling replace_async");
|
||||
gedit_debug_message (DEBUG_SAVER, backup ? "Keep backup" : "Discard backup");
|
||||
|
||||
g_file_replace_async (gvsaver->priv->gfile,
|
||||
NULL,
|
||||
backup,
|
||||
G_FILE_CREATE_NONE,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) async_replace_ready_callback,
|
||||
async);
|
||||
}
|
||||
|
||||
static void
|
||||
mount_ready_callback (GFile *file,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean mounted;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* manual check for cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
|
||||
|
||||
if (!mounted)
|
||||
{
|
||||
async_failed (async, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* try again to get the modified state */
|
||||
check_modified_async (async);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
recover_not_mounted (AsyncData *async)
|
||||
{
|
||||
GeditDocument *doc;
|
||||
GMountOperation *mount_operation;
|
||||
|
||||
gedit_debug (DEBUG_LOADER);
|
||||
|
||||
doc = gedit_document_saver_get_document (GEDIT_DOCUMENT_SAVER (async->saver));
|
||||
mount_operation = _gedit_document_create_mount_operation (doc);
|
||||
|
||||
async->tried_mount = TRUE;
|
||||
g_file_mount_enclosing_volume (async->saver->priv->gfile,
|
||||
G_MOUNT_MOUNT_NONE,
|
||||
mount_operation,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) mount_ready_callback,
|
||||
async);
|
||||
|
||||
g_object_unref (mount_operation);
|
||||
}
|
||||
|
||||
static void
|
||||
check_modification_callback (GFile *source,
|
||||
GAsyncResult *res,
|
||||
AsyncData *async)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
|
||||
gedit_debug (DEBUG_SAVER);
|
||||
|
||||
/* manually check cancelled state */
|
||||
if (g_cancellable_is_cancelled (async->cancellable))
|
||||
{
|
||||
async_data_free (async);
|
||||
return;
|
||||
}
|
||||
|
||||
gvsaver = async->saver;
|
||||
info = g_file_query_info_finish (source, res, &error);
|
||||
if (info == NULL)
|
||||
{
|
||||
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
|
||||
{
|
||||
recover_not_mounted (async);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* it's perfectly fine if the file doesn't exist yet */
|
||||
if (error->code != G_IO_ERROR_NOT_FOUND)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Error getting modification: %s", error->message);
|
||||
|
||||
async_failed (async, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the mtime is > what we know about it (if we have it) */
|
||||
if (info != NULL && g_file_info_has_attribute (info,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED))
|
||||
{
|
||||
GTimeVal mtime;
|
||||
GTimeVal old_mtime;
|
||||
|
||||
g_file_info_get_modification_time (info, &mtime);
|
||||
old_mtime = gvsaver->priv->old_mtime;
|
||||
|
||||
if ((old_mtime.tv_sec > 0 || old_mtime.tv_usec > 0) &&
|
||||
(mtime.tv_sec != old_mtime.tv_sec || mtime.tv_usec != old_mtime.tv_usec) &&
|
||||
(GEDIT_DOCUMENT_SAVER (gvsaver)->flags & GEDIT_DOCUMENT_SAVE_IGNORE_MTIME) == 0)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "File is externally modified");
|
||||
g_set_error (&gvsaver->priv->error,
|
||||
GEDIT_DOCUMENT_ERROR,
|
||||
GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
|
||||
"Externally modified");
|
||||
|
||||
remote_save_completed_or_failed (gvsaver, async);
|
||||
g_object_unref (info);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (info != NULL)
|
||||
g_object_unref (info);
|
||||
|
||||
/* modification check passed, start write */
|
||||
begin_write (async);
|
||||
}
|
||||
|
||||
static void
|
||||
check_modified_async (AsyncData *async)
|
||||
{
|
||||
gedit_debug_message (DEBUG_SAVER, "Check externally modified");
|
||||
|
||||
g_file_query_info_async (async->saver->priv->gfile,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_HIGH,
|
||||
async->cancellable,
|
||||
(GAsyncReadyCallback) check_modification_callback,
|
||||
async);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
save_remote_file_real (GeditGioDocumentSaver *gvsaver)
|
||||
{
|
||||
AsyncData *async;
|
||||
|
||||
gedit_debug_message (DEBUG_SAVER, "Starting gio save");
|
||||
|
||||
/* First find out if the file is modified externally. This requires
|
||||
* a stat, but I don't think we can do this any other way
|
||||
*/
|
||||
async = async_data_new (gvsaver);
|
||||
|
||||
check_modified_async (async);
|
||||
|
||||
/* return false to stop timeout */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_gio_document_saver_save (GeditDocumentSaver *saver,
|
||||
GTimeVal *old_mtime)
|
||||
{
|
||||
GeditGioDocumentSaver *gvsaver = GEDIT_GIO_DOCUMENT_SAVER (saver);
|
||||
|
||||
gvsaver->priv->old_mtime = *old_mtime;
|
||||
gvsaver->priv->gfile = g_file_new_for_uri (saver->uri);
|
||||
|
||||
/* saving start */
|
||||
gedit_document_saver_saving (saver, FALSE, NULL);
|
||||
|
||||
g_timeout_add_full (G_PRIORITY_HIGH,
|
||||
0,
|
||||
(GSourceFunc) save_remote_file_real,
|
||||
gvsaver,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static goffset
|
||||
gedit_gio_document_saver_get_file_size (GeditDocumentSaver *saver)
|
||||
{
|
||||
return GEDIT_GIO_DOCUMENT_SAVER (saver)->priv->size;
|
||||
}
|
||||
|
||||
static goffset
|
||||
gedit_gio_document_saver_get_bytes_written (GeditDocumentSaver *saver)
|
||||
{
|
||||
return GEDIT_GIO_DOCUMENT_SAVER (saver)->priv->bytes_written;
|
||||
}
|
||||
76
gedit/gedit-gio-document-saver.h
Executable file
76
gedit/gedit-gio-document-saver.h
Executable file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* gedit-gio-document-saver.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyrhing (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_GIO_DOCUMENT_SAVER_H__
|
||||
#define __GEDIT_GIO_DOCUMENT_SAVER_H__
|
||||
|
||||
#include <gedit/gedit-document-saver.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_GIO_DOCUMENT_SAVER (gedit_gio_document_saver_get_type())
|
||||
#define GEDIT_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_GIO_DOCUMENT_SAVER, GeditGioDocumentSaver))
|
||||
#define GEDIT_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_GIO_DOCUMENT_SAVER, GeditGioDocumentSaverClass))
|
||||
#define GEDIT_IS_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_GIO_DOCUMENT_SAVER))
|
||||
#define GEDIT_IS_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_GIO_DOCUMENT_SAVER))
|
||||
#define GEDIT_GIO_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_GIO_DOCUMENT_SAVER, GeditGioDocumentSaverClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditGioDocumentSaverPrivate GeditGioDocumentSaverPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditGioDocumentSaver GeditGioDocumentSaver;
|
||||
|
||||
struct _GeditGioDocumentSaver
|
||||
{
|
||||
GeditDocumentSaver saver;
|
||||
|
||||
/*< private > */
|
||||
GeditGioDocumentSaverPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef GeditDocumentSaverClass GeditGioDocumentSaverClass;
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_gio_document_saver_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_GIO_DOCUMENT_SAVER_H__ */
|
||||
122
gedit/gedit-help.c
Executable file
122
gedit/gedit-help.c
Executable file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* gedit-help.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "gedit-help.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef OS_OSX
|
||||
#include "osx/gedit-osx.h"
|
||||
#endif
|
||||
|
||||
gboolean
|
||||
gedit_help_display (GtkWindow *parent,
|
||||
const gchar *name, /* "gedit" 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);
|
||||
|
||||
#ifdef OS_OSX
|
||||
if (name == NULL || strcmp(name, "gedit.xml") == NULL || strcmp(name, "gedit") == 0)
|
||||
{
|
||||
return gedit_osx_show_help (link_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name == NULL)
|
||||
name = "gedit";
|
||||
else if (strcmp (name, "gedit.xml") == 0)
|
||||
{
|
||||
g_warning ("%s: Using \"gedit.xml\" for the help name is deprecated, use \"gedit\" or simply NULL instead", G_STRFUNC);
|
||||
|
||||
name = "gedit";
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (link_id)
|
||||
link = g_strdup_printf ("ghelp:%s?%s", name, link_id);
|
||||
else
|
||||
link = g_strdup_printf ("ghelp:%s", name);
|
||||
#else
|
||||
if (link_id)
|
||||
link = g_strdup_printf ("http://library.mate.org/users/gedit/stable/%s",
|
||||
link_id);
|
||||
else
|
||||
link = g_strdup ("http://library.mate.org/users/gedit/stable/");
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
44
gedit/gedit-help.h
Executable file
44
gedit/gedit-help.h
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* gedit-help.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_HELP_H__
|
||||
#define __GEDIT_HELP_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean gedit_help_display (GtkWindow *parent,
|
||||
const gchar *name, /* "gedit" if NULL */
|
||||
const gchar *link_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_HELP_H__ */
|
||||
632
gedit/gedit-history-entry.c
Executable file
632
gedit/gedit-history-entry.c
Executable file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* gedit-history-entry.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2006 - Paolo Borelli
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <mateconf/mateconf-client.h>
|
||||
|
||||
#include "gedit-history-entry.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_HISTORY_ID,
|
||||
PROP_HISTORY_LENGTH
|
||||
};
|
||||
|
||||
#define MIN_ITEM_LEN 3
|
||||
|
||||
#define GEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT 10
|
||||
|
||||
#define GEDIT_HISTORY_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_HISTORY_ENTRY, \
|
||||
GeditHistoryEntryPrivate))
|
||||
|
||||
struct _GeditHistoryEntryPrivate
|
||||
{
|
||||
gchar *history_id;
|
||||
guint history_length;
|
||||
|
||||
GtkEntryCompletion *completion;
|
||||
|
||||
MateConfClient *mateconf_client;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditHistoryEntry, gedit_history_entry, GTK_TYPE_COMBO_BOX_ENTRY)
|
||||
|
||||
static void
|
||||
gedit_history_entry_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *spec)
|
||||
{
|
||||
GeditHistoryEntry *entry;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (object));
|
||||
|
||||
entry = GEDIT_HISTORY_ENTRY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HISTORY_ID:
|
||||
entry->priv->history_id = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_HISTORY_LENGTH:
|
||||
gedit_history_entry_set_history_length (entry,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *spec)
|
||||
{
|
||||
GeditHistoryEntryPrivate *priv;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (object));
|
||||
|
||||
priv = GEDIT_HISTORY_ENTRY (object)->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HISTORY_ID:
|
||||
g_value_set_string (value, priv->history_id);
|
||||
break;
|
||||
case PROP_HISTORY_LENGTH:
|
||||
g_value_set_uint (value, priv->history_length);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_destroy (GtkObject *object)
|
||||
{
|
||||
gedit_history_entry_set_enable_completion (GEDIT_HISTORY_ENTRY (object),
|
||||
FALSE);
|
||||
|
||||
GTK_OBJECT_CLASS (gedit_history_entry_parent_class)->destroy (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_finalize (GObject *object)
|
||||
{
|
||||
GeditHistoryEntryPrivate *priv;
|
||||
|
||||
priv = GEDIT_HISTORY_ENTRY (object)->priv;
|
||||
|
||||
g_free (priv->history_id);
|
||||
|
||||
if (priv->mateconf_client != NULL)
|
||||
{
|
||||
g_object_unref (G_OBJECT (priv->mateconf_client));
|
||||
priv->mateconf_client = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gedit_history_entry_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_class_init (GeditHistoryEntryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gedit_history_entry_set_property;
|
||||
object_class->get_property = gedit_history_entry_get_property;
|
||||
object_class->finalize = gedit_history_entry_finalize;
|
||||
gtkobject_class->destroy = gedit_history_entry_destroy;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_HISTORY_ID,
|
||||
g_param_spec_string ("history-id",
|
||||
"History ID",
|
||||
"History ID",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_HISTORY_LENGTH,
|
||||
g_param_spec_uint ("history-length",
|
||||
"Max History Length",
|
||||
"Max History Length",
|
||||
0,
|
||||
G_MAXUINT,
|
||||
GEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* TODO: Add enable-completion property */
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditHistoryEntryPrivate));
|
||||
}
|
||||
|
||||
static GtkListStore *
|
||||
get_history_store (GeditHistoryEntry *entry)
|
||||
{
|
||||
GtkTreeModel *store;
|
||||
|
||||
store = gtk_combo_box_get_model (GTK_COMBO_BOX (entry));
|
||||
g_return_val_if_fail (GTK_IS_LIST_STORE (store), NULL);
|
||||
|
||||
return (GtkListStore *) store;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_history_key (GeditHistoryEntry *entry)
|
||||
{
|
||||
gchar *tmp;
|
||||
gchar *key;
|
||||
|
||||
/*
|
||||
* We store the data under /apps/mate-settings/
|
||||
* like the old MateEntry did. Maybe we should
|
||||
* consider moving it to the /gedit MateConf prefix...
|
||||
* Or maybe we should just switch away from MateConf.
|
||||
*/
|
||||
|
||||
tmp = mateconf_escape_key (entry->priv->history_id, -1);
|
||||
key = g_strconcat ("/apps/mate-settings/",
|
||||
"gedit",
|
||||
"/history-",
|
||||
tmp,
|
||||
NULL);
|
||||
g_free (tmp);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_history_list (GeditHistoryEntry *entry)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
gboolean valid;
|
||||
GSList *list = NULL;
|
||||
|
||||
store = get_history_store (entry);
|
||||
|
||||
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store),
|
||||
&iter);
|
||||
|
||||
while (valid)
|
||||
{
|
||||
gchar *str;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (store),
|
||||
&iter,
|
||||
0, &str,
|
||||
-1);
|
||||
|
||||
list = g_slist_prepend (list, str);
|
||||
|
||||
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store),
|
||||
&iter);
|
||||
}
|
||||
|
||||
return g_slist_reverse (list);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_save_history (GeditHistoryEntry *entry)
|
||||
{
|
||||
GSList *mateconf_items;
|
||||
gchar *key;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
|
||||
mateconf_items = get_history_list (entry);
|
||||
key = get_history_key (entry);
|
||||
|
||||
mateconf_client_set_list (entry->priv->mateconf_client,
|
||||
key,
|
||||
MATECONF_VALUE_STRING,
|
||||
mateconf_items,
|
||||
NULL);
|
||||
|
||||
g_slist_foreach (mateconf_items, (GFunc) g_free, NULL);
|
||||
g_slist_free (mateconf_items);
|
||||
g_free (key);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remove_item (GtkListStore *store,
|
||||
const gchar *text)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_val_if_fail (text != NULL, FALSE);
|
||||
|
||||
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
|
||||
return FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
gchar *item_text;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (store),
|
||||
&iter,
|
||||
0,
|
||||
&item_text,
|
||||
-1);
|
||||
|
||||
if (item_text != NULL &&
|
||||
strcmp (item_text, text) == 0)
|
||||
{
|
||||
gtk_list_store_remove (store, &iter);
|
||||
g_free (item_text);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_free (item_text);
|
||||
|
||||
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clamp_list_store (GtkListStore *store,
|
||||
guint max)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
/* -1 because TreePath counts from 0 */
|
||||
path = gtk_tree_path_new_from_indices (max - 1, -1);
|
||||
|
||||
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!gtk_list_store_remove (store, &iter))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_history_item (GeditHistoryEntry *entry,
|
||||
const gchar *text,
|
||||
gboolean prepend)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (g_utf8_strlen (text, -1) <= MIN_ITEM_LEN)
|
||||
return;
|
||||
|
||||
store = get_history_store (entry);
|
||||
|
||||
/* remove the text from the store if it was already
|
||||
* present. If it wasn't, clamp to max history - 1
|
||||
* before inserting the new row, otherwise appending
|
||||
* would not work */
|
||||
|
||||
if (!remove_item (store, text))
|
||||
clamp_list_store (store,
|
||||
entry->priv->history_length - 1);
|
||||
|
||||
if (prepend)
|
||||
gtk_list_store_insert (store, &iter, 0);
|
||||
else
|
||||
gtk_list_store_append (store, &iter);
|
||||
|
||||
gtk_list_store_set (store,
|
||||
&iter,
|
||||
0,
|
||||
text,
|
||||
-1);
|
||||
|
||||
gedit_history_entry_save_history (entry);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_prepend_text (GeditHistoryEntry *entry,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
insert_history_item (entry, text, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_append_text (GeditHistoryEntry *entry,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
insert_history_item (entry, text, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_load_history (GeditHistoryEntry *entry)
|
||||
{
|
||||
GSList *mateconf_items, *l;
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
gchar *key;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
|
||||
store = get_history_store (entry);
|
||||
key = get_history_key (entry);
|
||||
|
||||
mateconf_items = mateconf_client_get_list (entry->priv->mateconf_client,
|
||||
key,
|
||||
MATECONF_VALUE_STRING,
|
||||
NULL);
|
||||
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
for (l = mateconf_items, i = 0;
|
||||
l != NULL && i < entry->priv->history_length;
|
||||
l = l->next, i++)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store,
|
||||
&iter,
|
||||
0,
|
||||
l->data,
|
||||
-1);
|
||||
}
|
||||
|
||||
g_slist_foreach (mateconf_items, (GFunc) g_free, NULL);
|
||||
g_slist_free (mateconf_items);
|
||||
g_free (key);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_clear (GeditHistoryEntry *entry)
|
||||
{
|
||||
GtkListStore *store;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
|
||||
store = get_history_store (entry);
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
gedit_history_entry_save_history (entry);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_history_entry_init (GeditHistoryEntry *entry)
|
||||
{
|
||||
GeditHistoryEntryPrivate *priv;
|
||||
|
||||
priv = GEDIT_HISTORY_ENTRY_GET_PRIVATE (entry);
|
||||
entry->priv = priv;
|
||||
|
||||
priv->history_id = NULL;
|
||||
priv->history_length = GEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT;
|
||||
|
||||
priv->completion = NULL;
|
||||
|
||||
priv->mateconf_client = mateconf_client_get_default ();
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_set_history_length (GeditHistoryEntry *entry,
|
||||
guint history_length)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
g_return_if_fail (history_length > 0);
|
||||
|
||||
entry->priv->history_length = history_length;
|
||||
|
||||
/* TODO: update if we currently have more items than max */
|
||||
}
|
||||
|
||||
guint
|
||||
gedit_history_entry_get_history_length (GeditHistoryEntry *entry)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_HISTORY_ENTRY (entry), 0);
|
||||
|
||||
return entry->priv->history_length;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_history_entry_get_history_id (GeditHistoryEntry *entry)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_HISTORY_ENTRY (entry), NULL);
|
||||
|
||||
return g_strdup (entry->priv->history_id);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_set_enable_completion (GeditHistoryEntry *entry,
|
||||
gboolean enable)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (entry->priv->completion != NULL)
|
||||
return;
|
||||
|
||||
entry->priv->completion = gtk_entry_completion_new ();
|
||||
gtk_entry_completion_set_model (entry->priv->completion,
|
||||
GTK_TREE_MODEL (get_history_store (entry)));
|
||||
|
||||
/* Use model column 0 as the text column */
|
||||
gtk_entry_completion_set_text_column (entry->priv->completion, 0);
|
||||
|
||||
gtk_entry_completion_set_minimum_key_length (entry->priv->completion,
|
||||
MIN_ITEM_LEN);
|
||||
|
||||
gtk_entry_completion_set_popup_completion (entry->priv->completion, FALSE);
|
||||
gtk_entry_completion_set_inline_completion (entry->priv->completion, TRUE);
|
||||
|
||||
/* Assign the completion to the entry */
|
||||
gtk_entry_set_completion (GTK_ENTRY (gedit_history_entry_get_entry(entry)),
|
||||
entry->priv->completion);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry->priv->completion == NULL)
|
||||
return;
|
||||
|
||||
gtk_entry_set_completion (GTK_ENTRY (gedit_history_entry_get_entry (entry)),
|
||||
NULL);
|
||||
|
||||
g_object_unref (entry->priv->completion);
|
||||
|
||||
entry->priv->completion = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_history_entry_get_enable_completion (GeditHistoryEntry *entry)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_HISTORY_ENTRY (entry), FALSE);
|
||||
|
||||
return entry->priv->completion != NULL;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gedit_history_entry_new (const gchar *history_id,
|
||||
gboolean enable_completion)
|
||||
{
|
||||
GtkWidget *ret;
|
||||
GtkListStore *store;
|
||||
|
||||
g_return_val_if_fail (history_id != NULL, NULL);
|
||||
|
||||
/* Note that we are setting the model, so
|
||||
* user must be careful to always manipulate
|
||||
* data in the history through gedit_history_entry_
|
||||
* functions.
|
||||
*/
|
||||
|
||||
store = gtk_list_store_new (1, G_TYPE_STRING);
|
||||
|
||||
ret = g_object_new (GEDIT_TYPE_HISTORY_ENTRY,
|
||||
"history-id", history_id,
|
||||
"model", store,
|
||||
"text-column", 0,
|
||||
NULL);
|
||||
|
||||
g_object_unref (store);
|
||||
|
||||
/* loading has to happen after the model
|
||||
* has been set. However the model is not a
|
||||
* G_PARAM_CONSTRUCT property of GtkComboBox
|
||||
* so we cannot do this in the constructor.
|
||||
* For now we simply do here since this widget is
|
||||
* not bound to other programming languages.
|
||||
* A maybe better alternative is to override the
|
||||
* model property of combobox and mark CONTRUCT_ONLY.
|
||||
* This would also ensure that the model cannot be
|
||||
* set explicitely at a later time.
|
||||
*/
|
||||
gedit_history_entry_load_history (GEDIT_HISTORY_ENTRY (ret));
|
||||
|
||||
gedit_history_entry_set_enable_completion (GEDIT_HISTORY_ENTRY (ret),
|
||||
enable_completion);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to get the editable text entry internal widget.
|
||||
* I would prefer to not expose this implementation detail and
|
||||
* simply make the GeditHistoryEntry widget implement the
|
||||
* GtkEditable interface. Unfortunately both GtkEditable and
|
||||
* GtkComboBox have a "changed" signal and I am not sure how to
|
||||
* handle the conflict.
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_history_entry_get_entry (GeditHistoryEntry *entry)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_HISTORY_ENTRY (entry), NULL);
|
||||
|
||||
return gtk_bin_get_child (GTK_BIN (entry));
|
||||
}
|
||||
|
||||
static void
|
||||
escape_cell_data_func (GtkTreeViewColumn *col,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
GeditHistoryEntryEscapeFunc escape_func)
|
||||
{
|
||||
gchar *str;
|
||||
gchar *escaped;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &str, -1);
|
||||
escaped = escape_func (str);
|
||||
g_object_set (renderer, "text", escaped, NULL);
|
||||
|
||||
g_free (str);
|
||||
g_free (escaped);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_history_entry_set_escape_func (GeditHistoryEntry *entry,
|
||||
GeditHistoryEntryEscapeFunc escape_func)
|
||||
{
|
||||
GList *cells;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_HISTORY_ENTRY (entry));
|
||||
|
||||
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (entry));
|
||||
|
||||
/* We only have one cell renderer */
|
||||
g_return_if_fail (cells->data != NULL && cells->next == NULL);
|
||||
|
||||
if (escape_func != NULL)
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
|
||||
GTK_CELL_RENDERER (cells->data),
|
||||
(GtkCellLayoutDataFunc) escape_cell_data_func,
|
||||
escape_func,
|
||||
NULL);
|
||||
else
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
|
||||
GTK_CELL_RENDERER (cells->data),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_list_free (cells);
|
||||
}
|
||||
96
gedit/gedit-history-entry.h
Executable file
96
gedit/gedit-history-entry.h
Executable file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* gedit-history-entry.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2006 - Paolo Borelli
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_HISTORY_ENTRY_H__
|
||||
#define __GEDIT_HISTORY_ENTRY_H__
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_HISTORY_ENTRY (gedit_history_entry_get_type ())
|
||||
#define GEDIT_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_HISTORY_ENTRY, GeditHistoryEntry))
|
||||
#define GEDIT_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_HISTORY_ENTRY, GeditHistoryEntryClass))
|
||||
#define GEDIT_IS_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_HISTORY_ENTRY))
|
||||
#define GEDIT_IS_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_HISTORY_ENTRY))
|
||||
#define GEDIT_HISTORY_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_HISTORY_ENTRY, GeditHistoryEntryClass))
|
||||
|
||||
|
||||
typedef struct _GeditHistoryEntry GeditHistoryEntry;
|
||||
typedef struct _GeditHistoryEntryClass GeditHistoryEntryClass;
|
||||
typedef struct _GeditHistoryEntryPrivate GeditHistoryEntryPrivate;
|
||||
|
||||
struct _GeditHistoryEntryClass
|
||||
{
|
||||
GtkComboBoxEntryClass parent_class;
|
||||
};
|
||||
|
||||
struct _GeditHistoryEntry
|
||||
{
|
||||
GtkComboBoxEntry parent_instance;
|
||||
|
||||
GeditHistoryEntryPrivate *priv;
|
||||
};
|
||||
|
||||
GType gedit_history_entry_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_history_entry_new (const gchar *history_id,
|
||||
gboolean enable_completion);
|
||||
|
||||
void gedit_history_entry_prepend_text (GeditHistoryEntry *entry,
|
||||
const gchar *text);
|
||||
|
||||
void gedit_history_entry_append_text (GeditHistoryEntry *entry,
|
||||
const gchar *text);
|
||||
|
||||
void gedit_history_entry_clear (GeditHistoryEntry *entry);
|
||||
|
||||
void gedit_history_entry_set_history_length (GeditHistoryEntry *entry,
|
||||
guint max_saved);
|
||||
|
||||
guint gedit_history_entry_get_history_length (GeditHistoryEntry *gentry);
|
||||
|
||||
gchar *gedit_history_entry_get_history_id (GeditHistoryEntry *entry);
|
||||
|
||||
void gedit_history_entry_set_enable_completion
|
||||
(GeditHistoryEntry *entry,
|
||||
gboolean enable);
|
||||
|
||||
gboolean gedit_history_entry_get_enable_completion
|
||||
(GeditHistoryEntry *entry);
|
||||
|
||||
GtkWidget *gedit_history_entry_get_entry (GeditHistoryEntry *entry);
|
||||
|
||||
typedef gchar * (* GeditHistoryEntryEscapeFunc) (const gchar *str);
|
||||
void gedit_history_entry_set_escape_func (GeditHistoryEntry *entry,
|
||||
GeditHistoryEntryEscapeFunc escape_func);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_HISTORY_ENTRY_H__ */
|
||||
1288
gedit/gedit-io-error-message-area.c
Executable file
1288
gedit/gedit-io-error-message-area.c
Executable file
File diff suppressed because it is too large
Load Diff
68
gedit/gedit-io-error-message-area.h
Executable file
68
gedit/gedit-io-error-message-area.h
Executable file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* gedit-io-error-message-area.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_IO_ERROR_MESSAGE_AREA_H__
|
||||
#define __GEDIT_IO_ERROR_MESSAGE_AREA_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkWidget *gedit_io_loading_error_message_area_new (const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
const GError *error);
|
||||
|
||||
GtkWidget *gedit_unrecoverable_reverting_error_message_area_new (const gchar *uri,
|
||||
const GError *error);
|
||||
|
||||
GtkWidget *gedit_conversion_error_while_saving_message_area_new (const gchar *uri,
|
||||
const GeditEncoding *encoding,
|
||||
const GError *error);
|
||||
|
||||
const GeditEncoding
|
||||
*gedit_conversion_error_message_area_get_encoding (GtkWidget *message_area);
|
||||
|
||||
GtkWidget *gedit_file_already_open_warning_message_area_new (const gchar *uri);
|
||||
|
||||
GtkWidget *gedit_externally_modified_saving_error_message_area_new (const gchar *uri,
|
||||
const GError *error);
|
||||
|
||||
GtkWidget *gedit_no_backup_saving_error_message_area_new (const gchar *uri,
|
||||
const GError *error);
|
||||
|
||||
GtkWidget *gedit_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
||||
const GError *error);
|
||||
|
||||
GtkWidget *gedit_externally_modified_message_area_new (const gchar *uri,
|
||||
gboolean document_modified);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_IO_ERROR_MESSAGE_AREA_H__ */
|
||||
90
gedit/gedit-language-manager.c
Executable file
90
gedit/gedit-language-manager.c
Executable file
@@ -0,0 +1,90 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-languages-manager.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2006 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gedit-language-manager.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
static GtkSourceLanguageManager *language_manager = NULL;
|
||||
|
||||
GtkSourceLanguageManager *
|
||||
gedit_get_language_manager (void)
|
||||
{
|
||||
if (language_manager == NULL)
|
||||
{
|
||||
language_manager = gtk_source_language_manager_new ();
|
||||
}
|
||||
|
||||
return language_manager;
|
||||
}
|
||||
|
||||
static gint
|
||||
language_compare (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
GtkSourceLanguage *lang_a = (GtkSourceLanguage *)a;
|
||||
GtkSourceLanguage *lang_b = (GtkSourceLanguage *)b;
|
||||
const gchar *name_a = gtk_source_language_get_name (lang_a);
|
||||
const gchar *name_b = gtk_source_language_get_name (lang_b);
|
||||
|
||||
return g_utf8_collate (name_a, name_b);
|
||||
}
|
||||
|
||||
GSList *
|
||||
gedit_language_manager_list_languages_sorted (GtkSourceLanguageManager *lm,
|
||||
gboolean include_hidden)
|
||||
{
|
||||
GSList *languages = NULL;
|
||||
const gchar * const *ids;
|
||||
|
||||
ids = gtk_source_language_manager_get_language_ids (lm);
|
||||
if (ids == NULL)
|
||||
return NULL;
|
||||
|
||||
while (*ids != NULL)
|
||||
{
|
||||
GtkSourceLanguage *lang;
|
||||
|
||||
lang = gtk_source_language_manager_get_language (lm, *ids);
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), NULL);
|
||||
++ids;
|
||||
|
||||
if (include_hidden || !gtk_source_language_get_hidden (lang))
|
||||
{
|
||||
languages = g_slist_prepend (languages, lang);
|
||||
}
|
||||
}
|
||||
|
||||
return g_slist_sort (languages, (GCompareFunc)language_compare);
|
||||
}
|
||||
|
||||
47
gedit/gedit-language-manager.h
Executable file
47
gedit/gedit-language-manager.h
Executable file
@@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-languages-manager.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_LANGUAGES_MANAGER_H__
|
||||
#define __GEDIT_LANGUAGES_MANAGER_H__
|
||||
|
||||
#include <gtksourceview/gtksourcelanguagemanager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkSourceLanguageManager *gedit_get_language_manager (void);
|
||||
|
||||
GSList *gedit_language_manager_list_languages_sorted
|
||||
(GtkSourceLanguageManager *lm,
|
||||
gboolean include_hidden);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_LANGUAGES_MANAGER_H__ */
|
||||
13
gedit/gedit-marshal.list
Executable file
13
gedit/gedit-marshal.list
Executable file
@@ -0,0 +1,13 @@
|
||||
BOOLEAN:NONE
|
||||
BOOLEAN:OBJECT
|
||||
VOID:BOOLEAN
|
||||
VOID:BOOLEAN,POINTER
|
||||
VOID:BOXED,BOXED
|
||||
VOID:OBJECT
|
||||
VOID:POINTER
|
||||
VOID:STRING,BOXED,FLAGS
|
||||
VOID:STRING,BOXED,INT,BOOLEAN
|
||||
VOID:UINT,POINTER
|
||||
VOID:UINT64,UINT64
|
||||
VOID:VOID
|
||||
VOID:INT,INT
|
||||
626
gedit/gedit-message-area.c
Executable file
626
gedit/gedit-message-area.c
Executable file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* gedit-message-area.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* TODO: Style properties */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "gedit-message-area.h"
|
||||
|
||||
#define GEDIT_MESSAGE_AREA_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_MESSAGE_AREA, \
|
||||
GeditMessageAreaPrivate))
|
||||
|
||||
struct _GeditMessageAreaPrivate
|
||||
{
|
||||
GtkWidget *main_hbox;
|
||||
|
||||
GtkWidget *contents;
|
||||
GtkWidget *action_area;
|
||||
|
||||
gboolean changing_style;
|
||||
};
|
||||
|
||||
typedef struct _ResponseData ResponseData;
|
||||
|
||||
struct _ResponseData
|
||||
{
|
||||
gint response_id;
|
||||
};
|
||||
|
||||
enum {
|
||||
RESPONSE,
|
||||
CLOSE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(GeditMessageArea, gedit_message_area, GTK_TYPE_HBOX)
|
||||
|
||||
|
||||
static void
|
||||
gedit_message_area_finalize (GObject *object)
|
||||
{
|
||||
/*
|
||||
GeditMessageArea *message_area = GEDIT_MESSAGE_AREA (object);
|
||||
*/
|
||||
|
||||
G_OBJECT_CLASS (gedit_message_area_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static ResponseData *
|
||||
get_response_data (GtkWidget *widget,
|
||||
gboolean create)
|
||||
{
|
||||
ResponseData *ad = g_object_get_data (G_OBJECT (widget),
|
||||
"gedit-message-area-response-data");
|
||||
|
||||
if (ad == NULL && create)
|
||||
{
|
||||
ad = g_new (ResponseData, 1);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (widget),
|
||||
"gedit-message-area-response-data",
|
||||
ad,
|
||||
g_free);
|
||||
}
|
||||
|
||||
return ad;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
find_button (GeditMessageArea *message_area,
|
||||
gint response_id)
|
||||
{
|
||||
GList *children, *tmp_list;
|
||||
GtkWidget *child = NULL;
|
||||
|
||||
children = gtk_container_get_children (
|
||||
GTK_CONTAINER (message_area->priv->action_area));
|
||||
|
||||
for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
ResponseData *rd = get_response_data (tmp_list->data, FALSE);
|
||||
|
||||
if (rd && rd->response_id == response_id)
|
||||
{
|
||||
child = tmp_list->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_area_close (GeditMessageArea *message_area)
|
||||
{
|
||||
if (!find_button (message_area, GTK_RESPONSE_CANCEL))
|
||||
return;
|
||||
|
||||
/* emit response signal */
|
||||
gedit_message_area_response (GEDIT_MESSAGE_AREA (message_area),
|
||||
GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
paint_message_area (GtkWidget *widget,
|
||||
GdkEventExpose *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_paint_flat_box (widget->style,
|
||||
widget->window,
|
||||
GTK_STATE_NORMAL,
|
||||
GTK_SHADOW_OUT,
|
||||
NULL,
|
||||
widget,
|
||||
"tooltip",
|
||||
widget->allocation.x + 1,
|
||||
widget->allocation.y + 1,
|
||||
widget->allocation.width - 2,
|
||||
widget->allocation.height - 2);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_area_class_init (GeditMessageAreaClass *klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
GtkBindingSet *binding_set;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
object_class->finalize = gedit_message_area_finalize;
|
||||
|
||||
klass->close = gedit_message_area_close;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditMessageAreaPrivate));
|
||||
|
||||
signals[RESPONSE] = g_signal_new ("response",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditMessageAreaClass, response),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__INT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_INT);
|
||||
|
||||
signals[CLOSE] = g_signal_new ("close",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GeditMessageAreaClass, close),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
style_set (GtkWidget *widget,
|
||||
GtkStyle *prev_style,
|
||||
GeditMessageArea *message_area)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkStyle *style;
|
||||
|
||||
if (message_area->priv->changing_style)
|
||||
return;
|
||||
|
||||
/* This is a hack needed to use the tooltip background color */
|
||||
window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_widget_set_name (window, "gtk-tooltip");
|
||||
gtk_widget_ensure_style (window);
|
||||
style = gtk_widget_get_style (window);
|
||||
|
||||
message_area->priv->changing_style = TRUE;
|
||||
gtk_widget_set_style (GTK_WIDGET (message_area), style);
|
||||
message_area->priv->changing_style = FALSE;
|
||||
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (message_area));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_area_init (GeditMessageArea *message_area)
|
||||
{
|
||||
message_area->priv = GEDIT_MESSAGE_AREA_GET_PRIVATE (message_area);
|
||||
|
||||
message_area->priv->main_hbox = gtk_hbox_new (FALSE, 16); /* FIXME: use style properties */
|
||||
gtk_widget_show (message_area->priv->main_hbox);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (message_area->priv->main_hbox),
|
||||
8); /* FIXME: use style properties */
|
||||
|
||||
message_area->priv->action_area = gtk_vbox_new (TRUE, 10); /* FIXME: use style properties */
|
||||
gtk_widget_show (message_area->priv->action_area);
|
||||
gtk_box_pack_end (GTK_BOX (message_area->priv->main_hbox),
|
||||
message_area->priv->action_area,
|
||||
FALSE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (message_area),
|
||||
message_area->priv->main_hbox,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
gtk_widget_set_app_paintable (GTK_WIDGET (message_area), TRUE);
|
||||
|
||||
g_signal_connect (message_area,
|
||||
"expose-event",
|
||||
G_CALLBACK (paint_message_area),
|
||||
NULL);
|
||||
|
||||
/* Note that we connect to style-set on one of the internal
|
||||
* widgets, not on the message area itself, since gtk does
|
||||
* not deliver any further style-set signals for a widget on
|
||||
* which the style has been forced with gtk_widget_set_style() */
|
||||
g_signal_connect (message_area->priv->main_hbox,
|
||||
"style-set",
|
||||
G_CALLBACK (style_set),
|
||||
message_area);
|
||||
}
|
||||
|
||||
static gint
|
||||
get_response_for_widget (GeditMessageArea *message_area,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
ResponseData *rd;
|
||||
|
||||
rd = get_response_data (widget, FALSE);
|
||||
if (!rd)
|
||||
return GTK_RESPONSE_NONE;
|
||||
else
|
||||
return rd->response_id;
|
||||
}
|
||||
|
||||
static void
|
||||
action_widget_activated (GtkWidget *widget, GeditMessageArea *message_area)
|
||||
{
|
||||
gint response_id;
|
||||
|
||||
response_id = get_response_for_widget (message_area, widget);
|
||||
|
||||
gedit_message_area_response (message_area, response_id);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_message_area_add_action_widget (GeditMessageArea *message_area,
|
||||
GtkWidget *child,
|
||||
gint response_id)
|
||||
{
|
||||
ResponseData *ad;
|
||||
guint signal_id;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
|
||||
ad = get_response_data (child, TRUE);
|
||||
|
||||
ad->response_id = response_id;
|
||||
|
||||
if (GTK_IS_BUTTON (child))
|
||||
signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
|
||||
else
|
||||
signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal;
|
||||
|
||||
if (signal_id)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
|
||||
G_OBJECT (message_area));
|
||||
|
||||
g_signal_connect_closure_by_id (child,
|
||||
signal_id,
|
||||
0,
|
||||
closure,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
g_warning ("Only 'activatable' widgets can be packed into the action area of a GeditMessageArea");
|
||||
|
||||
if (response_id != GTK_RESPONSE_HELP)
|
||||
gtk_box_pack_start (GTK_BOX (message_area->priv->action_area),
|
||||
child,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
else
|
||||
gtk_box_pack_end (GTK_BOX (message_area->priv->action_area),
|
||||
child,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_set_contents:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @contents: widget you want to add to the contents area
|
||||
*
|
||||
* Adds the @contents widget to the contents area of #GeditMessageArea.
|
||||
*/
|
||||
void
|
||||
gedit_message_area_set_contents (GeditMessageArea *message_area,
|
||||
GtkWidget *contents)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
g_return_if_fail (GTK_IS_WIDGET (contents));
|
||||
|
||||
message_area->priv->contents = contents;
|
||||
gtk_box_pack_start (GTK_BOX (message_area->priv->main_hbox),
|
||||
message_area->priv->contents,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_add_button:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @button_text: text of button, or stock ID
|
||||
* @response_id: response ID for the button
|
||||
*
|
||||
* Adds a button with the given text (or a stock button, if button_text is a stock ID)
|
||||
* and sets things up so that clicking the button will emit the "response" signal
|
||||
* with the given response_id. The button is appended to the end of the message area's
|
||||
* action area. The button widget is returned, but usually you don't need it.
|
||||
*
|
||||
* Returns: the button widget that was added
|
||||
*/
|
||||
GtkWidget*
|
||||
gedit_message_area_add_button (GeditMessageArea *message_area,
|
||||
const gchar *button_text,
|
||||
gint response_id)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL);
|
||||
g_return_val_if_fail (button_text != NULL, NULL);
|
||||
|
||||
button = gtk_button_new_from_stock (button_text);
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
||||
|
||||
gtk_widget_show (button);
|
||||
|
||||
gedit_message_area_add_action_widget (message_area,
|
||||
button,
|
||||
response_id);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static void
|
||||
add_buttons_valist (GeditMessageArea *message_area,
|
||||
const gchar *first_button_text,
|
||||
va_list args)
|
||||
{
|
||||
const gchar* text;
|
||||
gint response_id;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
|
||||
if (first_button_text == NULL)
|
||||
return;
|
||||
|
||||
text = first_button_text;
|
||||
response_id = va_arg (args, gint);
|
||||
|
||||
while (text != NULL)
|
||||
{
|
||||
gedit_message_area_add_button (message_area,
|
||||
text,
|
||||
response_id);
|
||||
|
||||
text = va_arg (args, gchar*);
|
||||
if (text == NULL)
|
||||
break;
|
||||
|
||||
response_id = va_arg (args, int);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_add_buttons:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @first_button_text: button text or stock ID
|
||||
* @...: response ID for first button, then more text-response_id pairs
|
||||
*
|
||||
* Adds more buttons, same as calling gedit_message_area_add_button() repeatedly.
|
||||
* The variable argument list should be NULL-terminated as with
|
||||
* gedit_message_area_new_with_buttons(). Each button must have both text and response ID.
|
||||
*/
|
||||
void
|
||||
gedit_message_area_add_buttons (GeditMessageArea *message_area,
|
||||
const gchar *first_button_text,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, first_button_text);
|
||||
|
||||
add_buttons_valist (message_area,
|
||||
first_button_text,
|
||||
args);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_new:
|
||||
*
|
||||
* Creates a new #GeditMessageArea object.
|
||||
*
|
||||
* Returns: a new #GeditMessageArea object
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_message_area_new (void)
|
||||
{
|
||||
return g_object_new (GEDIT_TYPE_MESSAGE_AREA, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_new_with_buttons:
|
||||
* @first_button_text: stock ID or text to go in first button, or NULL
|
||||
* @...: response ID for first button, then additional buttons, ending with NULL
|
||||
*
|
||||
* Creates a new #GeditMessageArea with buttons. Button text/response ID pairs
|
||||
* should be listed, with a NULL pointer ending the list. Button text can be either
|
||||
* a stock ID such as GTK_STOCK_OK, or some arbitrary text. A response ID can be any
|
||||
* positive number, or one of the values in the GtkResponseType enumeration. If
|
||||
* the user clicks one of these dialog buttons, GeditMessageArea will emit the "response"
|
||||
* signal with the corresponding response ID.
|
||||
*
|
||||
* Returns: a new #GeditMessageArea
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_message_area_new_with_buttons (const gchar *first_button_text,
|
||||
...)
|
||||
{
|
||||
GeditMessageArea *message_area;
|
||||
va_list args;
|
||||
|
||||
message_area = GEDIT_MESSAGE_AREA (gedit_message_area_new ());
|
||||
|
||||
va_start (args, first_button_text);
|
||||
|
||||
add_buttons_valist (message_area,
|
||||
first_button_text,
|
||||
args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
return GTK_WIDGET (message_area);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_set_response_sensitive:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @response_id: a response ID
|
||||
* @setting: TRUE for sensitive
|
||||
*
|
||||
* Calls gtk_widget_set_sensitive (widget, setting) for each widget in the dialog's
|
||||
* action area with the given response_id. A convenient way to sensitize/desensitize
|
||||
* dialog buttons.
|
||||
*/
|
||||
void
|
||||
gedit_message_area_set_response_sensitive (GeditMessageArea *message_area,
|
||||
gint response_id,
|
||||
gboolean setting)
|
||||
{
|
||||
GList *children;
|
||||
GList *tmp_list;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area));
|
||||
|
||||
tmp_list = children;
|
||||
while (tmp_list != NULL)
|
||||
{
|
||||
GtkWidget *widget = tmp_list->data;
|
||||
ResponseData *rd = get_response_data (widget, FALSE);
|
||||
|
||||
if (rd && rd->response_id == response_id)
|
||||
gtk_widget_set_sensitive (widget, setting);
|
||||
|
||||
tmp_list = g_list_next (tmp_list);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_set_default_response:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @response_id: a response ID
|
||||
*
|
||||
* Sets the last widget in the message area's action area with the given response_id
|
||||
* as the default widget for the dialog. Pressing "Enter" normally activates the
|
||||
* default widget.
|
||||
*/
|
||||
void
|
||||
gedit_message_area_set_default_response (GeditMessageArea *message_area,
|
||||
gint response_id)
|
||||
{
|
||||
GList *children;
|
||||
GList *tmp_list;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area));
|
||||
|
||||
tmp_list = children;
|
||||
while (tmp_list != NULL)
|
||||
{
|
||||
GtkWidget *widget = tmp_list->data;
|
||||
ResponseData *rd = get_response_data (widget, FALSE);
|
||||
|
||||
if (rd && rd->response_id == response_id)
|
||||
gtk_widget_grab_default (widget);
|
||||
|
||||
tmp_list = g_list_next (tmp_list);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_set_default_response:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @response_id: a response ID
|
||||
*
|
||||
* Emits the 'response' signal with the given @response_id.
|
||||
*/
|
||||
void
|
||||
gedit_message_area_response (GeditMessageArea *message_area,
|
||||
gint response_id)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
|
||||
|
||||
g_signal_emit (message_area,
|
||||
signals[RESPONSE],
|
||||
0,
|
||||
response_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_area_add_stock_button_with_text:
|
||||
* @message_area: a #GeditMessageArea
|
||||
* @text: the text to visualize in the button
|
||||
* @stock_id: the stock ID of the button
|
||||
* @response_id: a response ID
|
||||
*
|
||||
* Same as gedit_message_area_add_button() but with a specific text.
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_message_area_add_stock_button_with_text (GeditMessageArea *message_area,
|
||||
const gchar *text,
|
||||
const gchar *stock_id,
|
||||
gint response_id)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL);
|
||||
g_return_val_if_fail (text != NULL, NULL);
|
||||
g_return_val_if_fail (stock_id != NULL, NULL);
|
||||
|
||||
button = gtk_button_new_with_mnemonic (text);
|
||||
gtk_button_set_image (GTK_BUTTON (button),
|
||||
gtk_image_new_from_stock (stock_id,
|
||||
GTK_ICON_SIZE_BUTTON));
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
||||
|
||||
gtk_widget_show (button);
|
||||
|
||||
gedit_message_area_add_action_widget (message_area,
|
||||
button,
|
||||
response_id);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
129
gedit/gedit-message-area.h
Executable file
129
gedit/gedit-message-area.h
Executable file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* gedit-message-area.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_MESSAGE_AREA_H__
|
||||
#define __GEDIT_MESSAGE_AREA_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_MESSAGE_AREA (gedit_message_area_get_type())
|
||||
#define GEDIT_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_MESSAGE_AREA, GeditMessageArea))
|
||||
#define GEDIT_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_MESSAGE_AREA, GeditMessageAreaClass))
|
||||
#define GEDIT_IS_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_MESSAGE_AREA))
|
||||
#define GEDIT_IS_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE_AREA))
|
||||
#define GEDIT_MESSAGE_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_MESSAGE_AREA, GeditMessageAreaClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditMessageAreaPrivate GeditMessageAreaPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditMessageArea GeditMessageArea;
|
||||
|
||||
struct _GeditMessageArea
|
||||
{
|
||||
GtkHBox parent;
|
||||
|
||||
/*< private > */
|
||||
GeditMessageAreaPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditMessageAreaClass GeditMessageAreaClass;
|
||||
|
||||
struct _GeditMessageAreaClass
|
||||
{
|
||||
GtkHBoxClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* response) (GeditMessageArea *message_area, gint response_id);
|
||||
|
||||
/* Keybinding signals */
|
||||
void (* close) (GeditMessageArea *message_area);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gedit_reserved1) (void);
|
||||
void (*_gedit_reserved2) (void);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_message_area_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_message_area_new (void);
|
||||
|
||||
GtkWidget *gedit_message_area_new_with_buttons (const gchar *first_button_text,
|
||||
...);
|
||||
|
||||
void gedit_message_area_set_contents (GeditMessageArea *message_area,
|
||||
GtkWidget *contents);
|
||||
|
||||
void gedit_message_area_add_action_widget (GeditMessageArea *message_area,
|
||||
GtkWidget *child,
|
||||
gint response_id);
|
||||
|
||||
GtkWidget *gedit_message_area_add_button (GeditMessageArea *message_area,
|
||||
const gchar *button_text,
|
||||
gint response_id);
|
||||
|
||||
GtkWidget *gedit_message_area_add_stock_button_with_text
|
||||
(GeditMessageArea *message_area,
|
||||
const gchar *text,
|
||||
const gchar *stock_id,
|
||||
gint response_id);
|
||||
|
||||
void gedit_message_area_add_buttons (GeditMessageArea *message_area,
|
||||
const gchar *first_button_text,
|
||||
...);
|
||||
|
||||
void gedit_message_area_set_response_sensitive
|
||||
(GeditMessageArea *message_area,
|
||||
gint response_id,
|
||||
gboolean setting);
|
||||
void gedit_message_area_set_default_response
|
||||
(GeditMessageArea *message_area,
|
||||
gint response_id);
|
||||
|
||||
/* Emit response signal */
|
||||
void gedit_message_area_response (GeditMessageArea *message_area,
|
||||
gint response_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_MESSAGE_AREA_H__ */
|
||||
1158
gedit/gedit-message-bus.c
Executable file
1158
gedit/gedit-message-bus.c
Executable file
File diff suppressed because it is too large
Load Diff
129
gedit/gedit-message-bus.h
Executable file
129
gedit/gedit-message-bus.h
Executable file
@@ -0,0 +1,129 @@
|
||||
#ifndef __GEDIT_MESSAGE_BUS_H__
|
||||
#define __GEDIT_MESSAGE_BUS_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gedit/gedit-message.h>
|
||||
#include <gedit/gedit-message-type.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_MESSAGE_BUS (gedit_message_bus_get_type ())
|
||||
#define GEDIT_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus))
|
||||
#define GEDIT_MESSAGE_BUS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus const))
|
||||
#define GEDIT_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
|
||||
#define GEDIT_IS_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE_BUS))
|
||||
#define GEDIT_IS_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE_BUS))
|
||||
#define GEDIT_MESSAGE_BUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
|
||||
|
||||
typedef struct _GeditMessageBus GeditMessageBus;
|
||||
typedef struct _GeditMessageBusClass GeditMessageBusClass;
|
||||
typedef struct _GeditMessageBusPrivate GeditMessageBusPrivate;
|
||||
|
||||
struct _GeditMessageBus {
|
||||
GObject parent;
|
||||
|
||||
GeditMessageBusPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditMessageBusClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*dispatch) (GeditMessageBus *bus,
|
||||
GeditMessage *message);
|
||||
void (*registered) (GeditMessageBus *bus,
|
||||
GeditMessageType *message_type);
|
||||
void (*unregistered) (GeditMessageBus *bus,
|
||||
GeditMessageType *message_type);
|
||||
};
|
||||
|
||||
typedef void (* GeditMessageCallback) (GeditMessageBus *bus,
|
||||
GeditMessage *message,
|
||||
gpointer userdata);
|
||||
|
||||
typedef void (* GeditMessageBusForeach) (GeditMessageType *message_type,
|
||||
gpointer userdata);
|
||||
|
||||
GType gedit_message_bus_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditMessageBus *gedit_message_bus_get_default (void);
|
||||
GeditMessageBus *gedit_message_bus_new (void);
|
||||
|
||||
/* registering messages */
|
||||
GeditMessageType *gedit_message_bus_lookup (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method);
|
||||
GeditMessageType *gedit_message_bus_register (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
guint num_optional,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
void gedit_message_bus_unregister (GeditMessageBus *bus,
|
||||
GeditMessageType *message_type);
|
||||
|
||||
void gedit_message_bus_unregister_all (GeditMessageBus *bus,
|
||||
const gchar *object_path);
|
||||
|
||||
gboolean gedit_message_bus_is_registered (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method);
|
||||
|
||||
void gedit_message_bus_foreach (GeditMessageBus *bus,
|
||||
GeditMessageBusForeach func,
|
||||
gpointer userdata);
|
||||
|
||||
|
||||
/* connecting to message events */
|
||||
guint gedit_message_bus_connect (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
GeditMessageCallback callback,
|
||||
gpointer userdata,
|
||||
GDestroyNotify destroy_data);
|
||||
|
||||
void gedit_message_bus_disconnect (GeditMessageBus *bus,
|
||||
guint id);
|
||||
|
||||
void gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
GeditMessageCallback callback,
|
||||
gpointer userdata);
|
||||
|
||||
/* blocking message event callbacks */
|
||||
void gedit_message_bus_block (GeditMessageBus *bus,
|
||||
guint id);
|
||||
void gedit_message_bus_block_by_func (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
GeditMessageCallback callback,
|
||||
gpointer userdata);
|
||||
|
||||
void gedit_message_bus_unblock (GeditMessageBus *bus,
|
||||
guint id);
|
||||
void gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
GeditMessageCallback callback,
|
||||
gpointer userdata);
|
||||
|
||||
/* sending messages */
|
||||
void gedit_message_bus_send_message (GeditMessageBus *bus,
|
||||
GeditMessage *message);
|
||||
void gedit_message_bus_send_message_sync (GeditMessageBus *bus,
|
||||
GeditMessage *message);
|
||||
|
||||
void gedit_message_bus_send (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
GeditMessage *gedit_message_bus_send_sync (GeditMessageBus *bus,
|
||||
const gchar *object_path,
|
||||
const gchar *method,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_MESSAGE_BUS_H__ */
|
||||
|
||||
// ex:ts=8:noet:
|
||||
526
gedit/gedit-message-type.c
Executable file
526
gedit/gedit-message-type.c
Executable file
@@ -0,0 +1,526 @@
|
||||
#include "gedit-message-type.h"
|
||||
|
||||
/**
|
||||
* SECTION:gedit-message-type
|
||||
* @short_description: message type description
|
||||
* @include: gedit/gedit-message-type.h
|
||||
*
|
||||
* A message type is a prototype description for a #GeditMessage used to
|
||||
* transmit messages on a #GeditMessageBus. The message type describes
|
||||
* the Object Path, Method and Arguments of the message.
|
||||
*
|
||||
* A message type can contain any number of required and optional arguments.
|
||||
* To instantiate a #GeditMessage from a #GeditMessageType, use
|
||||
* gedit_message_type_instantiate().
|
||||
*
|
||||
* Registering a new message type on a #GeditMessageBus with
|
||||
* gedit_message_bus_register() internally creates a new #GeditMessageType. When
|
||||
* then using gedit_message_bus_send(), an actual instantiation of the
|
||||
* registered type is internally created and send over the bus.
|
||||
*
|
||||
* <example>
|
||||
* <programlisting>
|
||||
* // Defining a new message type
|
||||
* GeditMessageType *message_type = gedit_message_type_new ("/plugins/example",
|
||||
* "method",
|
||||
* 0,
|
||||
* "arg1", G_TYPE_STRING,
|
||||
* NULL);
|
||||
*
|
||||
* // Instantiating an actual message from the type
|
||||
* GeditMessage *message = gedit_message_type_instantiate (message_type,
|
||||
* "arg1", "Hello World",
|
||||
* NULL);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* Since: 2.25.3
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
GType type;
|
||||
gboolean required;
|
||||
} ArgumentInfo;
|
||||
|
||||
struct _GeditMessageType
|
||||
{
|
||||
gint ref_count;
|
||||
|
||||
gchar *object_path;
|
||||
gchar *method;
|
||||
|
||||
guint num_arguments;
|
||||
guint num_required;
|
||||
|
||||
GHashTable *arguments; // mapping of key -> ArgumentInfo
|
||||
};
|
||||
|
||||
/**
|
||||
* gedit_message_type_ref:
|
||||
* @message_type: the #GeditMessageType
|
||||
*
|
||||
* Increases the reference count on @message_type.
|
||||
*
|
||||
* Return value: @message_type
|
||||
*
|
||||
*/
|
||||
GeditMessageType *
|
||||
gedit_message_type_ref (GeditMessageType *message_type)
|
||||
{
|
||||
g_return_val_if_fail (message_type != NULL, NULL);
|
||||
g_atomic_int_inc (&message_type->ref_count);
|
||||
|
||||
return message_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_unref:
|
||||
* @message_type: the #GeditMessageType
|
||||
*
|
||||
* Decreases the reference count on @message_type. When the reference count
|
||||
* drops to 0, @message_type is destroyed.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_type_unref (GeditMessageType *message_type)
|
||||
{
|
||||
g_return_if_fail (message_type != NULL);
|
||||
|
||||
if (!g_atomic_int_dec_and_test (&message_type->ref_count))
|
||||
return;
|
||||
|
||||
g_free (message_type->object_path);
|
||||
g_free (message_type->method);
|
||||
|
||||
g_hash_table_destroy (message_type->arguments);
|
||||
g_free (message_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_get_type:
|
||||
*
|
||||
* Retrieves the GType object which is associated with the
|
||||
* #GeditMessageType class.
|
||||
*
|
||||
* Return value: the GType associated with #GeditMessageType.
|
||||
**/
|
||||
GType
|
||||
gedit_message_type_get_type (void)
|
||||
{
|
||||
static GType our_type = 0;
|
||||
|
||||
if (!our_type)
|
||||
our_type = g_boxed_type_register_static (
|
||||
"GeditMessageType",
|
||||
(GBoxedCopyFunc) gedit_message_type_ref,
|
||||
(GBoxedFreeFunc) gedit_message_type_unref);
|
||||
|
||||
return our_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_identifier:
|
||||
* @object_path: the object path
|
||||
* @method: the method
|
||||
*
|
||||
* Get the string identifier for @method at @object_path.
|
||||
*
|
||||
* Return value: the identifier for @method at @object_path
|
||||
*
|
||||
*/
|
||||
gchar *
|
||||
gedit_message_type_identifier (const gchar *object_path,
|
||||
const gchar *method)
|
||||
{
|
||||
return g_strconcat (object_path, ".", method, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_is_valid_object_path:
|
||||
* @object_path: the object path
|
||||
*
|
||||
* Returns whether @object_path is a valid object path
|
||||
*
|
||||
* Return value: %TRUE if @object_path is a valid object path
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
gedit_message_type_is_valid_object_path (const gchar *object_path)
|
||||
{
|
||||
if (!object_path)
|
||||
return FALSE;
|
||||
|
||||
/* needs to start with / */
|
||||
if (*object_path != '/')
|
||||
return FALSE;
|
||||
|
||||
while (*object_path)
|
||||
{
|
||||
if (*object_path == '/')
|
||||
{
|
||||
++object_path;
|
||||
|
||||
if (!*object_path || !(g_ascii_isalpha (*object_path) || *object_path == '_'))
|
||||
return FALSE;
|
||||
}
|
||||
else if (!(g_ascii_isalnum (*object_path) || *object_path == '_'))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
++object_path;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_is_supported:
|
||||
* @type: the #GType
|
||||
*
|
||||
* Returns if @type is #GType supported by the message system.
|
||||
*
|
||||
* Return value: %TRUE if @type is a supported #GType
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
gedit_message_type_is_supported (GType type)
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
static const GType type_list[] =
|
||||
{
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_CHAR,
|
||||
G_TYPE_UCHAR,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_LONG,
|
||||
G_TYPE_ULONG,
|
||||
G_TYPE_INT64,
|
||||
G_TYPE_UINT64,
|
||||
G_TYPE_ENUM,
|
||||
G_TYPE_FLAGS,
|
||||
G_TYPE_FLOAT,
|
||||
G_TYPE_DOUBLE,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_POINTER,
|
||||
G_TYPE_BOXED,
|
||||
G_TYPE_OBJECT,
|
||||
G_TYPE_INVALID
|
||||
};
|
||||
|
||||
if (!G_TYPE_IS_VALUE_TYPE (type))
|
||||
return FALSE;
|
||||
|
||||
while (type_list[i] != G_TYPE_INVALID)
|
||||
{
|
||||
if (g_type_is_a (type, type_list[i]))
|
||||
return TRUE;
|
||||
i++;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_new_valist:
|
||||
* @object_path: the object path
|
||||
* @method: the method
|
||||
* @num_optional: number of optional arguments
|
||||
* @var_args: key/gtype pair variable argument list
|
||||
*
|
||||
* Create a new #GeditMessageType for @method at @object_path. Argument names
|
||||
* and values are supplied by the NULL terminated variable argument list.
|
||||
* The last @num_optional provided arguments are considered optional.
|
||||
*
|
||||
* Return value: the newly constructed #GeditMessageType
|
||||
*
|
||||
*/
|
||||
GeditMessageType *
|
||||
gedit_message_type_new_valist (const gchar *object_path,
|
||||
const gchar *method,
|
||||
guint num_optional,
|
||||
va_list var_args)
|
||||
{
|
||||
GeditMessageType *message_type;
|
||||
|
||||
g_return_val_if_fail (object_path != NULL, NULL);
|
||||
g_return_val_if_fail (method != NULL, NULL);
|
||||
g_return_val_if_fail (gedit_message_type_is_valid_object_path (object_path), NULL);
|
||||
|
||||
message_type = g_new0(GeditMessageType, 1);
|
||||
|
||||
message_type->ref_count = 1;
|
||||
message_type->object_path = g_strdup(object_path);
|
||||
message_type->method = g_strdup(method);
|
||||
message_type->num_arguments = 0;
|
||||
message_type->arguments = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_free);
|
||||
|
||||
gedit_message_type_set_valist (message_type, num_optional, var_args);
|
||||
return message_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_new:
|
||||
* @object_path: the object path
|
||||
* @method: the method
|
||||
* @num_optional: number of optional arguments
|
||||
* @...: key/gtype pair variable argument list
|
||||
*
|
||||
* Create a new #GeditMessageType for @method at @object_path. Argument names
|
||||
* and values are supplied by the NULL terminated variable argument list.
|
||||
* The last @num_optional provided arguments are considered optional.
|
||||
*
|
||||
* Return value: the newly constructed #GeditMessageType
|
||||
*
|
||||
*/
|
||||
GeditMessageType *
|
||||
gedit_message_type_new (const gchar *object_path,
|
||||
const gchar *method,
|
||||
guint num_optional,
|
||||
...)
|
||||
{
|
||||
GeditMessageType *message_type;
|
||||
va_list var_args;
|
||||
|
||||
va_start(var_args, num_optional);
|
||||
message_type = gedit_message_type_new_valist (object_path, method, num_optional, var_args);
|
||||
va_end(var_args);
|
||||
|
||||
return message_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_set:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @num_optional: number of optional arguments
|
||||
* @...: key/gtype pair variable argument list
|
||||
*
|
||||
* Sets argument names/types supplied by the NULL terminated variable
|
||||
* argument list. The last @num_optional provided arguments are considered
|
||||
* optional.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_type_set (GeditMessageType *message_type,
|
||||
guint num_optional,
|
||||
...)
|
||||
{
|
||||
va_list va_args;
|
||||
|
||||
va_start (va_args, num_optional);
|
||||
gedit_message_type_set_valist (message_type, num_optional, va_args);
|
||||
va_end (va_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_set_valist:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @num_optional: number of optional arguments
|
||||
* @var_args: key/gtype pair variable argument list
|
||||
*
|
||||
* Sets argument names/types supplied by the NULL terminated variable
|
||||
* argument list @var_args. The last @num_optional provided arguments are
|
||||
* considered optional.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_type_set_valist (GeditMessageType *message_type,
|
||||
guint num_optional,
|
||||
va_list var_args)
|
||||
{
|
||||
const gchar *key;
|
||||
ArgumentInfo **optional = g_new0(ArgumentInfo *, num_optional);
|
||||
guint i;
|
||||
guint added = 0;
|
||||
|
||||
// parse key -> gtype pair arguments
|
||||
while ((key = va_arg (var_args, const gchar *)) != NULL)
|
||||
{
|
||||
// get corresponding GType
|
||||
GType gtype = va_arg (var_args, GType);
|
||||
ArgumentInfo *info;
|
||||
|
||||
if (!gedit_message_type_is_supported (gtype))
|
||||
{
|
||||
g_error ("Message type '%s' is not supported", g_type_name (gtype));
|
||||
|
||||
gedit_message_type_unref (message_type);
|
||||
g_free (optional);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_new(ArgumentInfo, 1);
|
||||
info->type = gtype;
|
||||
info->required = TRUE;
|
||||
|
||||
g_hash_table_insert (message_type->arguments, g_strdup (key), info);
|
||||
|
||||
++message_type->num_arguments;
|
||||
++added;
|
||||
|
||||
if (num_optional > 0)
|
||||
{
|
||||
for (i = num_optional - 1; i > 0; --i)
|
||||
optional[i] = optional[i - 1];
|
||||
|
||||
*optional = info;
|
||||
}
|
||||
}
|
||||
|
||||
message_type->num_required += added;
|
||||
|
||||
// set required for last num_optional arguments
|
||||
for (i = 0; i < num_optional; ++i)
|
||||
{
|
||||
if (optional[i])
|
||||
{
|
||||
optional[i]->required = FALSE;
|
||||
--message_type->num_required;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (optional);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_instantiate_valist:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @va_args: NULL terminated variable list of key/value pairs
|
||||
*
|
||||
* Instantiate a new message from the message type with specific values
|
||||
* for the message arguments.
|
||||
*
|
||||
* Return value: the newly created message
|
||||
*
|
||||
*/
|
||||
GeditMessage *
|
||||
gedit_message_type_instantiate_valist (GeditMessageType *message_type,
|
||||
va_list va_args)
|
||||
{
|
||||
GeditMessage *message;
|
||||
|
||||
g_return_val_if_fail (message_type != NULL, NULL);
|
||||
|
||||
message = GEDIT_MESSAGE (g_object_new (GEDIT_TYPE_MESSAGE, "type", message_type, NULL));
|
||||
gedit_message_set_valist (message, va_args);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_instantiate:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @...: NULL terminated variable list of key/value pairs
|
||||
*
|
||||
* Instantiate a new message from the message type with specific values
|
||||
* for the message arguments.
|
||||
*
|
||||
* Return value: the newly created message
|
||||
*
|
||||
*/
|
||||
GeditMessage *
|
||||
gedit_message_type_instantiate (GeditMessageType *message_type,
|
||||
...)
|
||||
{
|
||||
GeditMessage *message;
|
||||
va_list va_args;
|
||||
|
||||
va_start (va_args, message_type);
|
||||
message = gedit_message_type_instantiate_valist (message_type, va_args);
|
||||
va_end (va_args);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_get_object_path:
|
||||
* @message_type: the #GeditMessageType
|
||||
*
|
||||
* Get the message type object path.
|
||||
*
|
||||
* Return value: the message type object path
|
||||
*
|
||||
*/
|
||||
const gchar *
|
||||
gedit_message_type_get_object_path (GeditMessageType *message_type)
|
||||
{
|
||||
return message_type->object_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_get_method:
|
||||
* @message_type: the #GeditMessageType
|
||||
*
|
||||
* Get the message type method.
|
||||
*
|
||||
* Return value: the message type method
|
||||
*
|
||||
*/
|
||||
const gchar *
|
||||
gedit_message_type_get_method (GeditMessageType *message_type)
|
||||
{
|
||||
return message_type->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_lookup:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @key: the argument key
|
||||
*
|
||||
* Get the argument key #GType.
|
||||
*
|
||||
* Return value: the #GType of @key
|
||||
*
|
||||
*/
|
||||
GType
|
||||
gedit_message_type_lookup (GeditMessageType *message_type,
|
||||
const gchar *key)
|
||||
{
|
||||
ArgumentInfo *info = g_hash_table_lookup (message_type->arguments, key);
|
||||
|
||||
if (!info)
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
return info->type;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeditMessageTypeForeach func;
|
||||
gpointer user_data;
|
||||
} ForeachInfo;
|
||||
|
||||
static void
|
||||
foreach_gtype (const gchar *key,
|
||||
ArgumentInfo *info,
|
||||
ForeachInfo *finfo)
|
||||
{
|
||||
finfo->func (key, info->type, info->required, finfo->user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_type_foreach:
|
||||
* @message_type: the #GeditMessageType
|
||||
* @func: the callback function
|
||||
* @user_data: user data supplied to the callback function
|
||||
*
|
||||
* Calls @func for each argument in the message type.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_type_foreach (GeditMessageType *message_type,
|
||||
GeditMessageTypeForeach func,
|
||||
gpointer user_data)
|
||||
{
|
||||
ForeachInfo info = {func, user_data};
|
||||
g_hash_table_foreach (message_type->arguments, (GHFunc)foreach_gtype, &info);
|
||||
}
|
||||
|
||||
// ex:ts=8:noet:
|
||||
67
gedit/gedit-message-type.h
Executable file
67
gedit/gedit-message-type.h
Executable file
@@ -0,0 +1,67 @@
|
||||
#ifndef __GEDIT_MESSAGE_TYPE_H__
|
||||
#define __GEDIT_MESSAGE_TYPE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "gedit-message.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_MESSAGE_TYPE (gedit_message_type_get_type ())
|
||||
#define GEDIT_MESSAGE_TYPE(x) ((GeditMessageType *)(x))
|
||||
|
||||
typedef void (*GeditMessageTypeForeach) (const gchar *key,
|
||||
GType type,
|
||||
gboolean required,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _GeditMessageType GeditMessageType;
|
||||
|
||||
GType gedit_message_type_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean gedit_message_type_is_supported (GType type);
|
||||
gchar *gedit_message_type_identifier (const gchar *object_path,
|
||||
const gchar *method);
|
||||
gboolean gedit_message_type_is_valid_object_path (const gchar *object_path);
|
||||
|
||||
GeditMessageType *gedit_message_type_new (const gchar *object_path,
|
||||
const gchar *method,
|
||||
guint num_optional,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
GeditMessageType *gedit_message_type_new_valist (const gchar *object_path,
|
||||
const gchar *method,
|
||||
guint num_optional,
|
||||
va_list va_args);
|
||||
|
||||
void gedit_message_type_set (GeditMessageType *message_type,
|
||||
guint num_optional,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void gedit_message_type_set_valist (GeditMessageType *message_type,
|
||||
guint num_optional,
|
||||
va_list va_args);
|
||||
|
||||
GeditMessageType *gedit_message_type_ref (GeditMessageType *message_type);
|
||||
void gedit_message_type_unref (GeditMessageType *message_type);
|
||||
|
||||
|
||||
GeditMessage *gedit_message_type_instantiate_valist (GeditMessageType *message_type,
|
||||
va_list va_args);
|
||||
GeditMessage *gedit_message_type_instantiate (GeditMessageType *message_type,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
const gchar *gedit_message_type_get_object_path (GeditMessageType *message_type);
|
||||
const gchar *gedit_message_type_get_method (GeditMessageType *message_type);
|
||||
|
||||
GType gedit_message_type_lookup (GeditMessageType *message_type,
|
||||
const gchar *key);
|
||||
|
||||
void gedit_message_type_foreach (GeditMessageType *message_type,
|
||||
GeditMessageTypeForeach func,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_MESSAGE_TYPE_H__ */
|
||||
|
||||
// ex:ts=8:noet:
|
||||
593
gedit/gedit-message.c
Executable file
593
gedit/gedit-message.c
Executable file
@@ -0,0 +1,593 @@
|
||||
#include "gedit-message.h"
|
||||
#include "gedit-message-type.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
/**
|
||||
* SECTION:gedit-message
|
||||
* @short_description: message bus message object
|
||||
* @include: gedit/gedit-message.h
|
||||
*
|
||||
* Communication on a #GeditMessageBus is done through messages. Messages are
|
||||
* sent over the bus and received by connecting callbacks on the message bus.
|
||||
* A #GeditMessage is an instantiation of a #GeditMessageType, containing
|
||||
* values for the arguments as specified in the message type.
|
||||
*
|
||||
* A message can be seen as a method call, or signal emission depending on
|
||||
* who is the sender and who is the receiver. There is no explicit distinction
|
||||
* between methods and signals.
|
||||
*
|
||||
* Since: 2.25.3
|
||||
*
|
||||
*/
|
||||
#define GEDIT_MESSAGE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_MESSAGE, GeditMessagePrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_METHOD,
|
||||
PROP_TYPE
|
||||
};
|
||||
|
||||
struct _GeditMessagePrivate
|
||||
{
|
||||
GeditMessageType *type;
|
||||
gboolean valid;
|
||||
|
||||
GHashTable *values;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GeditMessage, gedit_message, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gedit_message_finalize (GObject *object)
|
||||
{
|
||||
GeditMessage *message = GEDIT_MESSAGE (object);
|
||||
|
||||
gedit_message_type_unref (message->priv->type);
|
||||
g_hash_table_destroy (message->priv->values);
|
||||
|
||||
G_OBJECT_CLASS (gedit_message_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditMessage *msg = GEDIT_MESSAGE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, gedit_message_type_get_object_path (msg->priv->type));
|
||||
break;
|
||||
case PROP_METHOD:
|
||||
g_value_set_string (value, gedit_message_type_get_method (msg->priv->type));
|
||||
break;
|
||||
case PROP_TYPE:
|
||||
g_value_set_boxed (value, msg->priv->type);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditMessage *msg = GEDIT_MESSAGE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TYPE:
|
||||
msg->priv->type = GEDIT_MESSAGE_TYPE (g_value_dup_boxed (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GValue *
|
||||
add_value (GeditMessage *message,
|
||||
const gchar *key)
|
||||
{
|
||||
GValue *value;
|
||||
GType type = gedit_message_type_lookup (message->priv->type, key);
|
||||
|
||||
if (type == G_TYPE_INVALID)
|
||||
return NULL;
|
||||
|
||||
value = g_new0 (GValue, 1);
|
||||
g_value_init (value, type);
|
||||
g_value_reset (value);
|
||||
|
||||
g_hash_table_insert (message->priv->values, g_strdup (key), value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_class_init (GeditMessageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gedit_message_finalize;
|
||||
object_class->get_property = gedit_message_get_property;
|
||||
object_class->set_property = gedit_message_set_property;
|
||||
|
||||
/**
|
||||
* GeditMessage:object_path:
|
||||
*
|
||||
* The messages object path (e.g. /gedit/object/path).
|
||||
*
|
||||
*/
|
||||
g_object_class_install_property (object_class, PROP_OBJECT_PATH,
|
||||
g_param_spec_string ("object-path",
|
||||
"OBJECT_PATH",
|
||||
"The message object path",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GeditMessage:method:
|
||||
*
|
||||
* The messages method.
|
||||
*
|
||||
*/
|
||||
g_object_class_install_property (object_class, PROP_METHOD,
|
||||
g_param_spec_string ("method",
|
||||
"METHOD",
|
||||
"The message method",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GeditMEssage:type:
|
||||
*
|
||||
* The message type.
|
||||
*
|
||||
*/
|
||||
g_object_class_install_property (object_class, PROP_TYPE,
|
||||
g_param_spec_boxed ("type",
|
||||
"TYPE",
|
||||
"The message type",
|
||||
GEDIT_TYPE_MESSAGE_TYPE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GeditMessagePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_value (GValue *value)
|
||||
{
|
||||
g_value_unset (value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_message_init (GeditMessage *self)
|
||||
{
|
||||
self->priv = GEDIT_MESSAGE_GET_PRIVATE (self);
|
||||
|
||||
self->priv->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)destroy_value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_value_real (GValue *to,
|
||||
const GValue *from)
|
||||
{
|
||||
GType from_type;
|
||||
GType to_type;
|
||||
|
||||
from_type = G_VALUE_TYPE (from);
|
||||
to_type = G_VALUE_TYPE (to);
|
||||
|
||||
if (!g_type_is_a (from_type, to_type))
|
||||
{
|
||||
if (!g_value_transform (from, to))
|
||||
{
|
||||
g_warning ("%s: Unable to make conversion from %s to %s",
|
||||
G_STRLOC,
|
||||
g_type_name (from_type),
|
||||
g_type_name (to_type));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_value_copy (from, to);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline static GValue *
|
||||
value_lookup (GeditMessage *message,
|
||||
const gchar *key,
|
||||
gboolean create)
|
||||
{
|
||||
GValue *ret = (GValue *)g_hash_table_lookup (message->priv->values, key);
|
||||
|
||||
if (!ret && create)
|
||||
ret = add_value (message, key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get_method:
|
||||
* @message: the #GeditMessage
|
||||
*
|
||||
* Get the message method.
|
||||
*
|
||||
* Return value: the message method
|
||||
*
|
||||
*/
|
||||
const gchar *
|
||||
gedit_message_get_method (GeditMessage *message)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
|
||||
|
||||
return gedit_message_type_get_method (message->priv->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get_object_path:
|
||||
* @message: the #GeditMessage
|
||||
*
|
||||
* Get the message object path.
|
||||
*
|
||||
* Return value: the message object path
|
||||
*
|
||||
*/
|
||||
const gchar *
|
||||
gedit_message_get_object_path (GeditMessage *message)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
|
||||
|
||||
return gedit_message_type_get_object_path (message->priv->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_set:
|
||||
* @message: the #GeditMessage
|
||||
* @...: a NULL terminated variable list of key/value pairs
|
||||
*
|
||||
* Set values of message arguments. The supplied @var_args should contain
|
||||
* pairs of keys and argument values.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_set (GeditMessage *message,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
va_start (ap, message);
|
||||
gedit_message_set_valist (message, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_set_valist:
|
||||
* @message: the #GeditMessage
|
||||
* @var_args: a NULL terminated variable list of key/value pairs
|
||||
*
|
||||
* Set values of message arguments. The supplied @var_args should contain
|
||||
* pairs of keys and argument values.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_set_valist (GeditMessage *message,
|
||||
va_list var_args)
|
||||
{
|
||||
const gchar *key;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
while ((key = va_arg (var_args, const gchar *)) != NULL)
|
||||
{
|
||||
/* lookup the key */
|
||||
GValue *container = value_lookup (message, key, TRUE);
|
||||
GValue value = {0,};
|
||||
gchar *error = NULL;
|
||||
|
||||
if (!container)
|
||||
{
|
||||
g_warning ("%s: Cannot set value for %s, does not exist",
|
||||
G_STRLOC,
|
||||
key);
|
||||
|
||||
/* skip value */
|
||||
va_arg (var_args, gpointer);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_value_init (&value, G_VALUE_TYPE (container));
|
||||
G_VALUE_COLLECT (&value, var_args, 0, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
continue;
|
||||
}
|
||||
|
||||
set_value_real (container, &value);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_set_value:
|
||||
* @message: the #GeditMessage
|
||||
* @key: the argument key
|
||||
* @value: the argument value
|
||||
*
|
||||
* Set value of message argument @key to @value.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_set_value (GeditMessage *message,
|
||||
const gchar *key,
|
||||
GValue *value)
|
||||
{
|
||||
GValue *container;
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
container = value_lookup (message, key, TRUE);
|
||||
|
||||
if (!container)
|
||||
{
|
||||
g_warning ("%s: Cannot set value for %s, does not exist",
|
||||
G_STRLOC,
|
||||
key);
|
||||
return;
|
||||
}
|
||||
|
||||
set_value_real (container, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_set_valuesv:
|
||||
* @message: the #GeditMessage
|
||||
* @keys: keys to set values for
|
||||
* @values: values to set
|
||||
* @n_values: number of arguments to set values for
|
||||
*
|
||||
* Set message argument values.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_set_valuesv (GeditMessage *message,
|
||||
const gchar **keys,
|
||||
GValue *values,
|
||||
gint n_values)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
for (i = 0; i < n_values; i++)
|
||||
{
|
||||
gedit_message_set_value (message, keys[i], &values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get:
|
||||
* @message: the #GeditMessage
|
||||
* @...: a NULL variable argument list of key/value container pairs
|
||||
*
|
||||
* Get values of message arguments. The supplied @var_args should contain
|
||||
* pairs of keys and pointers to variables which are set to the argument
|
||||
* value for the specified key.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_get (GeditMessage *message,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
va_start (ap, message);
|
||||
gedit_message_get_valist (message, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get_valist:
|
||||
* @message: the #GeditMessage
|
||||
* @var_args: a NULL variable argument list of key/value container pairs
|
||||
*
|
||||
* Get values of message arguments. The supplied @var_args should contain
|
||||
* pairs of keys and pointers to variables which are set to the argument
|
||||
* value for the specified key.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_get_valist (GeditMessage *message,
|
||||
va_list var_args)
|
||||
{
|
||||
const gchar *key;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
while ((key = va_arg (var_args, const gchar *)) != NULL)
|
||||
{
|
||||
GValue *container;
|
||||
GValue copy = {0,};
|
||||
gchar *error = NULL;
|
||||
|
||||
container = value_lookup (message, key, FALSE);
|
||||
|
||||
if (!container)
|
||||
{
|
||||
/* skip value */
|
||||
va_arg (var_args, gpointer);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the value here, to be sure it isn't tainted */
|
||||
g_value_init (©, G_VALUE_TYPE (container));
|
||||
g_value_copy (container, ©);
|
||||
|
||||
G_VALUE_LCOPY (©, var_args, 0, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
|
||||
/* purposely leak the value here, because it might
|
||||
be in a bad state */
|
||||
continue;
|
||||
}
|
||||
|
||||
g_value_unset (©);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get_value:
|
||||
* @message: the #GeditMessage
|
||||
* @key: the argument key
|
||||
* @value: value return container
|
||||
*
|
||||
* Get the value of a specific message argument. @value will be initialized
|
||||
* with the correct type.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gedit_message_get_value (GeditMessage *message,
|
||||
const gchar *key,
|
||||
GValue *value)
|
||||
{
|
||||
GValue *container;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_MESSAGE (message));
|
||||
|
||||
container = value_lookup (message, key, FALSE);
|
||||
|
||||
if (!container)
|
||||
{
|
||||
g_warning ("%s: Invalid key `%s'",
|
||||
G_STRLOC,
|
||||
key);
|
||||
return;
|
||||
}
|
||||
|
||||
g_value_init (value, G_VALUE_TYPE (container));
|
||||
set_value_real (value, container);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_get_key_type:
|
||||
* @message: the #GeditMessage
|
||||
* @key: the argument key
|
||||
*
|
||||
* Get the type of a message argument.
|
||||
*
|
||||
* Return value: the type of @key
|
||||
*
|
||||
*/
|
||||
GType
|
||||
gedit_message_get_key_type (GeditMessage *message,
|
||||
const gchar *key)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE (message), G_TYPE_INVALID);
|
||||
g_return_val_if_fail (message->priv->type != NULL, G_TYPE_INVALID);
|
||||
|
||||
return gedit_message_type_lookup (message->priv->type, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_has_key:
|
||||
* @message: the #GeditMessage
|
||||
* @key: the argument key
|
||||
*
|
||||
* Check whether the message has a specific key.
|
||||
*
|
||||
* Return value: %TRUE if @message has argument @key
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
gedit_message_has_key (GeditMessage *message,
|
||||
const gchar *key)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE (message), FALSE);
|
||||
|
||||
return value_lookup (message, key, FALSE) != NULL;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeditMessage *message;
|
||||
gboolean valid;
|
||||
} ValidateInfo;
|
||||
|
||||
static void
|
||||
validate_key (const gchar *key,
|
||||
GType type,
|
||||
gboolean required,
|
||||
ValidateInfo *info)
|
||||
{
|
||||
GValue *value;
|
||||
|
||||
if (!info->valid || !required)
|
||||
return;
|
||||
|
||||
value = value_lookup (info->message, key, FALSE);
|
||||
|
||||
if (!value)
|
||||
info->valid = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_message_validate:
|
||||
* @message: the #GeditMessage
|
||||
*
|
||||
* Validates the message arguments according to the message type.
|
||||
*
|
||||
* Return value: %TRUE if the message is valid
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
gedit_message_validate (GeditMessage *message)
|
||||
{
|
||||
ValidateInfo info = {message, TRUE};
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_MESSAGE (message), FALSE);
|
||||
g_return_val_if_fail (message->priv->type != NULL, FALSE);
|
||||
|
||||
if (!message->priv->valid)
|
||||
{
|
||||
gedit_message_type_foreach (message->priv->type,
|
||||
(GeditMessageTypeForeach)validate_key,
|
||||
&info);
|
||||
|
||||
message->priv->valid = info.valid;
|
||||
}
|
||||
|
||||
return message->priv->valid;
|
||||
}
|
||||
|
||||
// ex:ts=8:noet:
|
||||
71
gedit/gedit-message.h
Executable file
71
gedit/gedit-message.h
Executable file
@@ -0,0 +1,71 @@
|
||||
#ifndef __GEDIT_MESSAGE_H__
|
||||
#define __GEDIT_MESSAGE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_MESSAGE (gedit_message_get_type ())
|
||||
#define GEDIT_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage))
|
||||
#define GEDIT_MESSAGE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage const))
|
||||
#define GEDIT_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE, GeditMessageClass))
|
||||
#define GEDIT_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE))
|
||||
#define GEDIT_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE))
|
||||
#define GEDIT_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE, GeditMessageClass))
|
||||
|
||||
typedef struct _GeditMessage GeditMessage;
|
||||
typedef struct _GeditMessageClass GeditMessageClass;
|
||||
typedef struct _GeditMessagePrivate GeditMessagePrivate;
|
||||
|
||||
struct _GeditMessage {
|
||||
GObject parent;
|
||||
|
||||
GeditMessagePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GeditMessageClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gedit_message_get_type (void) G_GNUC_CONST;
|
||||
|
||||
struct _GeditMessageType gedit_message_get_message_type (GeditMessage *message);
|
||||
|
||||
void gedit_message_get (GeditMessage *message,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void gedit_message_get_valist (GeditMessage *message,
|
||||
va_list var_args);
|
||||
void gedit_message_get_value (GeditMessage *message,
|
||||
const gchar *key,
|
||||
GValue *value);
|
||||
|
||||
void gedit_message_set (GeditMessage *message,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void gedit_message_set_valist (GeditMessage *message,
|
||||
va_list var_args);
|
||||
void gedit_message_set_value (GeditMessage *message,
|
||||
const gchar *key,
|
||||
GValue *value);
|
||||
void gedit_message_set_valuesv (GeditMessage *message,
|
||||
const gchar **keys,
|
||||
GValue *values,
|
||||
gint n_values);
|
||||
|
||||
const gchar *gedit_message_get_object_path (GeditMessage *message);
|
||||
const gchar *gedit_message_get_method (GeditMessage *message);
|
||||
|
||||
gboolean gedit_message_has_key (GeditMessage *message,
|
||||
const gchar *key);
|
||||
|
||||
GType gedit_message_get_key_type (GeditMessage *message,
|
||||
const gchar *key);
|
||||
|
||||
gboolean gedit_message_validate (GeditMessage *message);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_MESSAGE_H__ */
|
||||
|
||||
// ex:ts=8:noet:
|
||||
563
gedit/gedit-metadata-manager.c
Executable file
563
gedit/gedit-metadata-manager.c
Executable file
@@ -0,0 +1,563 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-metadata-manager.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003-2007 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* 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 "gedit-metadata-manager.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
/*
|
||||
#define GEDIT_METADATA_VERBOSE_DEBUG 1
|
||||
*/
|
||||
|
||||
#define METADATA_FILE "gedit-metadata.xml"
|
||||
|
||||
#define MAX_ITEMS 50
|
||||
|
||||
typedef struct _GeditMetadataManager GeditMetadataManager;
|
||||
|
||||
typedef struct _Item Item;
|
||||
|
||||
struct _Item
|
||||
{
|
||||
time_t atime; /* time of last access */
|
||||
|
||||
GHashTable *values;
|
||||
};
|
||||
|
||||
struct _GeditMetadataManager
|
||||
{
|
||||
gboolean values_loaded; /* It is true if the file
|
||||
has been read */
|
||||
|
||||
guint timeout_id;
|
||||
|
||||
GHashTable *items;
|
||||
};
|
||||
|
||||
static gboolean gedit_metadata_manager_save (gpointer data);
|
||||
|
||||
|
||||
static GeditMetadataManager *gedit_metadata_manager = NULL;
|
||||
|
||||
static void
|
||||
item_free (gpointer data)
|
||||
{
|
||||
Item *item;
|
||||
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
item = (Item *)data;
|
||||
|
||||
if (item->values != NULL)
|
||||
g_hash_table_destroy (item->values);
|
||||
|
||||
g_free (item);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_metadata_manager_arm_timeout (void)
|
||||
{
|
||||
if (gedit_metadata_manager->timeout_id == 0)
|
||||
{
|
||||
gedit_metadata_manager->timeout_id =
|
||||
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
2,
|
||||
(GSourceFunc)gedit_metadata_manager_save,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gedit_metadata_manager_init (void)
|
||||
{
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
|
||||
if (gedit_metadata_manager != NULL)
|
||||
return TRUE;
|
||||
|
||||
gedit_metadata_manager = g_new0 (GeditMetadataManager, 1);
|
||||
|
||||
gedit_metadata_manager->values_loaded = FALSE;
|
||||
|
||||
gedit_metadata_manager->items =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
item_free);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This function must be called before exiting gedit */
|
||||
void
|
||||
gedit_metadata_manager_shutdown (void)
|
||||
{
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
|
||||
if (gedit_metadata_manager == NULL)
|
||||
return;
|
||||
|
||||
if (gedit_metadata_manager->timeout_id)
|
||||
{
|
||||
g_source_remove (gedit_metadata_manager->timeout_id);
|
||||
gedit_metadata_manager->timeout_id = 0;
|
||||
gedit_metadata_manager_save (NULL);
|
||||
}
|
||||
|
||||
if (gedit_metadata_manager->items != NULL)
|
||||
g_hash_table_destroy (gedit_metadata_manager->items);
|
||||
|
||||
g_free (gedit_metadata_manager);
|
||||
gedit_metadata_manager = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
parseItem (xmlDocPtr doc, xmlNodePtr cur)
|
||||
{
|
||||
Item *item;
|
||||
|
||||
xmlChar *uri;
|
||||
xmlChar *atime;
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
|
||||
return;
|
||||
|
||||
uri = xmlGetProp (cur, (const xmlChar *)"uri");
|
||||
if (uri == NULL)
|
||||
return;
|
||||
|
||||
atime = xmlGetProp (cur, (const xmlChar *)"atime");
|
||||
if (atime == NULL)
|
||||
{
|
||||
xmlFree (uri);
|
||||
return;
|
||||
}
|
||||
|
||||
item = g_new0 (Item, 1);
|
||||
|
||||
item->atime = g_ascii_strtoull ((char *)atime, NULL, 0);
|
||||
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
|
||||
cur = cur->xmlChildrenNode;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
|
||||
{
|
||||
xmlChar *key;
|
||||
xmlChar *value;
|
||||
|
||||
key = xmlGetProp (cur, (const xmlChar *)"key");
|
||||
value = xmlGetProp (cur, (const xmlChar *)"value");
|
||||
|
||||
if ((key != NULL) && (value != NULL))
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup ((gchar *)key),
|
||||
g_strdup ((gchar *)value));
|
||||
|
||||
if (key != NULL)
|
||||
xmlFree (key);
|
||||
if (value != NULL)
|
||||
xmlFree (value);
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
g_hash_table_insert (gedit_metadata_manager->items,
|
||||
g_strdup ((gchar *)uri),
|
||||
item);
|
||||
|
||||
xmlFree (uri);
|
||||
xmlFree (atime);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_metadata_filename (void)
|
||||
{
|
||||
gchar *cache_dir;
|
||||
gchar *metadata;
|
||||
|
||||
cache_dir = gedit_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;
|
||||
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
|
||||
g_return_val_if_fail (gedit_metadata_manager != NULL, FALSE);
|
||||
g_return_val_if_fail (gedit_metadata_manager->values_loaded == FALSE, FALSE);
|
||||
|
||||
gedit_metadata_manager->values_loaded = TRUE;
|
||||
|
||||
xmlKeepBlanksDefault (0);
|
||||
|
||||
/* FIXME: file locking - Paolo */
|
||||
file_name = get_metadata_filename ();
|
||||
if ((file_name == NULL) ||
|
||||
(!g_file_test (file_name, G_FILE_TEST_EXISTS)))
|
||||
{
|
||||
g_free (file_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
doc = xmlParseFile (file_name);
|
||||
g_free (file_name);
|
||||
|
||||
if (doc == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
if (cur == NULL)
|
||||
{
|
||||
g_message ("The metadata file '%s' is empty", METADATA_FILE);
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
|
||||
{
|
||||
g_message ("File '%s' is of the wrong type", METADATA_FILE);
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
cur = cur->xmlChildrenNode;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
parseItem (doc, cur);
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gedit_metadata_manager_get (const gchar *uri,
|
||||
const gchar *key)
|
||||
{
|
||||
Item *item;
|
||||
gchar *value;
|
||||
|
||||
g_return_val_if_fail (uri != NULL, NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
|
||||
|
||||
gedit_metadata_manager_init ();
|
||||
|
||||
if (!gedit_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
res = load_values ();
|
||||
|
||||
if (!res)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = (Item *)g_hash_table_lookup (gedit_metadata_manager->items,
|
||||
uri);
|
||||
|
||||
if (item == NULL)
|
||||
return NULL;
|
||||
|
||||
item->atime = time (NULL);
|
||||
|
||||
if (item->values == NULL)
|
||||
return NULL;
|
||||
|
||||
value = g_hash_table_lookup (item->values, key);
|
||||
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (value);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_metadata_manager_set (const gchar *uri,
|
||||
const gchar *key,
|
||||
const gchar *value)
|
||||
{
|
||||
Item *item;
|
||||
|
||||
g_return_if_fail (uri != NULL);
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
|
||||
|
||||
gedit_metadata_manager_init ();
|
||||
|
||||
if (!gedit_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
res = load_values ();
|
||||
|
||||
if (!res)
|
||||
return;
|
||||
}
|
||||
|
||||
item = (Item *)g_hash_table_lookup (gedit_metadata_manager->items,
|
||||
uri);
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
item = g_new0 (Item, 1);
|
||||
|
||||
g_hash_table_insert (gedit_metadata_manager->items,
|
||||
g_strdup (uri),
|
||||
item);
|
||||
}
|
||||
|
||||
if (item->values == NULL)
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
if (value != NULL)
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup (key),
|
||||
g_strdup (value));
|
||||
else
|
||||
g_hash_table_remove (item->values,
|
||||
key);
|
||||
|
||||
item->atime = time (NULL);
|
||||
|
||||
gedit_metadata_manager_arm_timeout ();
|
||||
}
|
||||
|
||||
static void
|
||||
save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr xml_node;
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
xml_node = xmlNewChild (parent,
|
||||
NULL,
|
||||
(const xmlChar *)"entry",
|
||||
NULL);
|
||||
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"key",
|
||||
(const xmlChar *)key);
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"value",
|
||||
(const xmlChar *)value);
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr xml_node;
|
||||
const Item *item = (const Item *)data;
|
||||
gchar *atime;
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
|
||||
|
||||
xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug_message (DEBUG_METADATA, "uri: %s", key);
|
||||
#endif
|
||||
|
||||
atime = g_strdup_printf ("%ld", item->atime);
|
||||
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
|
||||
|
||||
#ifdef GEDIT_METADATA_VERBOSE_DEBUG
|
||||
gedit_debug_message (DEBUG_METADATA, "atime: %s", atime);
|
||||
#endif
|
||||
|
||||
g_free (atime);
|
||||
|
||||
g_hash_table_foreach (item->values,
|
||||
(GHFunc)save_values,
|
||||
xml_node);
|
||||
}
|
||||
|
||||
static void
|
||||
get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove)
|
||||
{
|
||||
const Item *item = (const Item *)value;
|
||||
|
||||
if (*key_to_remove == NULL)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Item *item_to_remove =
|
||||
g_hash_table_lookup (gedit_metadata_manager->items,
|
||||
*key_to_remove);
|
||||
|
||||
g_return_if_fail (item_to_remove != NULL);
|
||||
|
||||
if (item->atime < item_to_remove->atime)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resize_items (void)
|
||||
{
|
||||
while (g_hash_table_size (gedit_metadata_manager->items) > MAX_ITEMS)
|
||||
{
|
||||
gpointer key_to_remove = NULL;
|
||||
|
||||
g_hash_table_foreach (gedit_metadata_manager->items,
|
||||
(GHFunc)get_oldest,
|
||||
&key_to_remove);
|
||||
|
||||
g_return_if_fail (key_to_remove != NULL);
|
||||
|
||||
g_hash_table_remove (gedit_metadata_manager->items,
|
||||
key_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gedit_metadata_manager_save (gpointer data)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root;
|
||||
gchar *file_name;
|
||||
|
||||
gedit_debug (DEBUG_METADATA);
|
||||
|
||||
gedit_metadata_manager->timeout_id = 0;
|
||||
|
||||
resize_items ();
|
||||
|
||||
xmlIndentTreeOutput = TRUE;
|
||||
|
||||
doc = xmlNewDoc ((const xmlChar *)"1.0");
|
||||
if (doc == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* Create metadata root */
|
||||
root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
|
||||
xmlDocSetRootElement (doc, root);
|
||||
|
||||
g_hash_table_foreach (gedit_metadata_manager->items,
|
||||
(GHFunc)save_item,
|
||||
root);
|
||||
|
||||
/* FIXME: lock file - Paolo */
|
||||
file_name = get_metadata_filename ();
|
||||
if (file_name != NULL)
|
||||
{
|
||||
gchar *cache_dir;
|
||||
int res;
|
||||
|
||||
/* make sure the cache dir exists */
|
||||
cache_dir = gedit_dirs_get_user_cache_dir ();
|
||||
res = g_mkdir_with_parents (cache_dir, 0755);
|
||||
if (res != -1)
|
||||
{
|
||||
xmlSaveFormatFile (file_name, doc, 1);
|
||||
}
|
||||
|
||||
g_free (cache_dir);
|
||||
g_free (file_name);
|
||||
}
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
gedit_debug_message (DEBUG_METADATA, "DONE");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
50
gedit/gedit-metadata-manager.h
Executable file
50
gedit/gedit-metadata-manager.h
Executable file
@@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-metadata-manager.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2003 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2003. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_METADATA_MANAGER_H__
|
||||
#define __GEDIT_METADATA_MANAGER_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/* This function must be called before exiting gedit */
|
||||
void gedit_metadata_manager_shutdown (void);
|
||||
|
||||
|
||||
gchar *gedit_metadata_manager_get (const gchar *uri,
|
||||
const gchar *key);
|
||||
void gedit_metadata_manager_set (const gchar *uri,
|
||||
const gchar *key,
|
||||
const gchar *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_METADATA_MANAGER_H__ */
|
||||
1099
gedit/gedit-notebook.c
Executable file
1099
gedit/gedit-notebook.c
Executable file
File diff suppressed because it is too large
Load Diff
143
gedit/gedit-notebook.h
Executable file
143
gedit/gedit-notebook.h
Executable file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* gedit-notebook.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
/* This file is a modified version of the epiphany file ephy-notebook.h
|
||||
* Here the relevant copyright:
|
||||
*
|
||||
* Copyright (C) 2002 Christophe Fergeau
|
||||
* Copyright (C) 2003 Marco Pesenti Gritti
|
||||
* Copyright (C) 2003, 2004 Christian Persch
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GEDIT_NOTEBOOK_H
|
||||
#define GEDIT_NOTEBOOK_H
|
||||
|
||||
#include <gedit/gedit-tab.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_NOTEBOOK (gedit_notebook_get_type ())
|
||||
#define GEDIT_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_NOTEBOOK, GeditNotebook))
|
||||
#define GEDIT_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_NOTEBOOK, GeditNotebookClass))
|
||||
#define GEDIT_IS_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_NOTEBOOK))
|
||||
#define GEDIT_IS_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_NOTEBOOK))
|
||||
#define GEDIT_NOTEBOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_NOTEBOOK, GeditNotebookClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditNotebookPrivate GeditNotebookPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditNotebook GeditNotebook;
|
||||
|
||||
struct _GeditNotebook
|
||||
{
|
||||
GtkNotebook notebook;
|
||||
|
||||
/*< private >*/
|
||||
GeditNotebookPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditNotebookClass GeditNotebookClass;
|
||||
|
||||
struct _GeditNotebookClass
|
||||
{
|
||||
GtkNotebookClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* tab_added) (GeditNotebook *notebook,
|
||||
GeditTab *tab);
|
||||
void (* tab_removed) (GeditNotebook *notebook,
|
||||
GeditTab *tab);
|
||||
void (* tab_detached) (GeditNotebook *notebook,
|
||||
GeditTab *tab);
|
||||
void (* tabs_reordered) (GeditNotebook *notebook);
|
||||
void (* tab_close_request)
|
||||
(GeditNotebook *notebook,
|
||||
GeditTab *tab);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_notebook_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_notebook_new (void);
|
||||
|
||||
void gedit_notebook_add_tab (GeditNotebook *nb,
|
||||
GeditTab *tab,
|
||||
gint position,
|
||||
gboolean jump_to);
|
||||
|
||||
void gedit_notebook_remove_tab (GeditNotebook *nb,
|
||||
GeditTab *tab);
|
||||
|
||||
void gedit_notebook_remove_all_tabs (GeditNotebook *nb);
|
||||
|
||||
void gedit_notebook_reorder_tab (GeditNotebook *src,
|
||||
GeditTab *tab,
|
||||
gint dest_position);
|
||||
|
||||
void gedit_notebook_move_tab (GeditNotebook *src,
|
||||
GeditNotebook *dest,
|
||||
GeditTab *tab,
|
||||
gint dest_position);
|
||||
|
||||
/* FIXME: do we really need this function ? */
|
||||
void gedit_notebook_set_always_show_tabs
|
||||
(GeditNotebook *nb,
|
||||
gboolean show_tabs);
|
||||
|
||||
void gedit_notebook_set_close_buttons_sensitive
|
||||
(GeditNotebook *nb,
|
||||
gboolean sensitive);
|
||||
|
||||
gboolean gedit_notebook_get_close_buttons_sensitive
|
||||
(GeditNotebook *nb);
|
||||
|
||||
void gedit_notebook_set_tab_drag_and_drop_enabled
|
||||
(GeditNotebook *nb,
|
||||
gboolean enable);
|
||||
|
||||
gboolean gedit_notebook_get_tab_drag_and_drop_enabled
|
||||
(GeditNotebook *nb);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GEDIT_NOTEBOOK_H */
|
||||
343
gedit/gedit-object-module.c
Executable file
343
gedit/gedit-object-module.c
Executable file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* gedit-object-module.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* This is a modified version of ephy-module.c from Epiphany source code.
|
||||
* Here the original copyright assignment:
|
||||
*
|
||||
* Copyright (C) 2003 Marco Pesenti Gritti
|
||||
* Copyright (C) 2003, 2004 Christian Persch
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id: gedit-module.c 6314 2008-06-05 12:57:53Z pborelli $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gedit-object-module.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
typedef GType (*GeditObjectModuleRegisterFunc) (GTypeModule *);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_MODULE_NAME,
|
||||
PROP_PATH,
|
||||
PROP_TYPE_REGISTRATION,
|
||||
PROP_RESIDENT
|
||||
};
|
||||
|
||||
struct _GeditObjectModulePrivate
|
||||
{
|
||||
GModule *library;
|
||||
|
||||
GType type;
|
||||
gchar *path;
|
||||
gchar *module_name;
|
||||
gchar *type_registration;
|
||||
|
||||
gboolean resident;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GeditObjectModule, gedit_object_module, G_TYPE_TYPE_MODULE);
|
||||
|
||||
static gboolean
|
||||
gedit_object_module_load (GTypeModule *gmodule)
|
||||
{
|
||||
GeditObjectModule *module = GEDIT_OBJECT_MODULE (gmodule);
|
||||
GeditObjectModuleRegisterFunc register_func;
|
||||
gchar *path;
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Loading %s module from %s",
|
||||
module->priv->module_name, module->priv->path);
|
||||
|
||||
path = g_module_build_path (module->priv->path, module->priv->module_name);
|
||||
g_return_val_if_fail (path != NULL, FALSE);
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Module filename: %s", path);
|
||||
|
||||
module->priv->library = g_module_open (path,
|
||||
G_MODULE_BIND_LAZY);
|
||||
g_free (path);
|
||||
|
||||
if (module->priv->library == NULL)
|
||||
{
|
||||
g_warning ("%s: %s", module->priv->module_name, g_module_error());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* extract symbols from the lib */
|
||||
if (!g_module_symbol (module->priv->library, module->priv->type_registration,
|
||||
(void *) ®ister_func))
|
||||
{
|
||||
g_warning ("%s: %s", module->priv->module_name, g_module_error());
|
||||
g_module_close (module->priv->library);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* symbol can still be NULL even though g_module_symbol
|
||||
* returned TRUE */
|
||||
if (register_func == NULL)
|
||||
{
|
||||
g_warning ("Symbol '%s' should not be NULL", module->priv->type_registration);
|
||||
g_module_close (module->priv->library);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
module->priv->type = register_func (gmodule);
|
||||
|
||||
if (module->priv->type == 0)
|
||||
{
|
||||
g_warning ("Invalid object contained by module %s", module->priv->module_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (module->priv->resident)
|
||||
{
|
||||
g_module_make_resident (module->priv->library);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_unload (GTypeModule *gmodule)
|
||||
{
|
||||
GeditObjectModule *module = GEDIT_OBJECT_MODULE (gmodule);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Unloading %s", module->priv->path);
|
||||
|
||||
g_module_close (module->priv->library);
|
||||
|
||||
module->priv->library = NULL;
|
||||
module->priv->type = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_init (GeditObjectModule *module)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS, "GeditObjectModule %p initialising", module);
|
||||
|
||||
module->priv = G_TYPE_INSTANCE_GET_PRIVATE (module,
|
||||
GEDIT_TYPE_OBJECT_MODULE,
|
||||
GeditObjectModulePrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_finalize (GObject *object)
|
||||
{
|
||||
GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "GeditObjectModule %p finalising", module);
|
||||
|
||||
g_free (module->priv->path);
|
||||
g_free (module->priv->module_name);
|
||||
g_free (module->priv->type_registration);
|
||||
|
||||
G_OBJECT_CLASS (gedit_object_module_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MODULE_NAME:
|
||||
g_value_set_string (value, module->priv->module_name);
|
||||
break;
|
||||
case PROP_PATH:
|
||||
g_value_set_string (value, module->priv->path);
|
||||
break;
|
||||
case PROP_TYPE_REGISTRATION:
|
||||
g_value_set_string (value, module->priv->type_registration);
|
||||
break;
|
||||
case PROP_RESIDENT:
|
||||
g_value_set_boolean (value, module->priv->resident);
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MODULE_NAME:
|
||||
module->priv->module_name = g_value_dup_string (value);
|
||||
g_type_module_set_name (G_TYPE_MODULE (object),
|
||||
module->priv->module_name);
|
||||
break;
|
||||
case PROP_PATH:
|
||||
module->priv->path = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_TYPE_REGISTRATION:
|
||||
module->priv->type_registration = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_RESIDENT:
|
||||
module->priv->resident = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_object_module_class_init (GeditObjectModuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
|
||||
|
||||
object_class->set_property = gedit_object_module_set_property;
|
||||
object_class->get_property = gedit_object_module_get_property;
|
||||
object_class->finalize = gedit_object_module_finalize;
|
||||
|
||||
module_class->load = gedit_object_module_load;
|
||||
module_class->unload = gedit_object_module_unload;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_MODULE_NAME,
|
||||
g_param_spec_string ("module-name",
|
||||
"Module Name",
|
||||
"The module to load for this object",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PATH,
|
||||
g_param_spec_string ("path",
|
||||
"Path",
|
||||
"The path to use when loading this module",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_TYPE_REGISTRATION,
|
||||
g_param_spec_string ("type-registration",
|
||||
"Type Registration",
|
||||
"The name of the type registration function",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_RESIDENT,
|
||||
g_param_spec_boolean ("resident",
|
||||
"Resident",
|
||||
"Whether the module is resident",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditObjectModulePrivate));
|
||||
}
|
||||
|
||||
GeditObjectModule *
|
||||
gedit_object_module_new (const gchar *module_name,
|
||||
const gchar *path,
|
||||
const gchar *type_registration,
|
||||
gboolean resident)
|
||||
{
|
||||
return (GeditObjectModule *)g_object_new (GEDIT_TYPE_OBJECT_MODULE,
|
||||
"module-name",
|
||||
module_name,
|
||||
"path",
|
||||
path,
|
||||
"type-registration",
|
||||
type_registration,
|
||||
"resident",
|
||||
resident,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GObject *
|
||||
gedit_object_module_new_object (GeditObjectModule *module,
|
||||
const gchar *first_property_name,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
GObject *result;
|
||||
|
||||
g_return_val_if_fail (module->priv->type != 0, NULL);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Creating object of type %s",
|
||||
g_type_name (module->priv->type));
|
||||
|
||||
va_start (var_args, first_property_name);
|
||||
result = g_object_new_valist (module->priv->type, first_property_name, var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_object_module_get_path (GeditObjectModule *module)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
|
||||
|
||||
return module->priv->path;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_object_module_get_module_name (GeditObjectModule *module)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
|
||||
|
||||
return module->priv->module_name;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_object_module_get_type_registration (GeditObjectModule *module)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
|
||||
|
||||
return module->priv->type_registration;
|
||||
}
|
||||
|
||||
GType
|
||||
gedit_object_module_get_object_type (GeditObjectModule *module)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), 0);
|
||||
|
||||
return module->priv->type;
|
||||
}
|
||||
94
gedit/gedit-object-module.h
Executable file
94
gedit/gedit-object-module.h
Executable file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* gedit-object-module.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* This is a modified version of gedit-module.h from Epiphany source code.
|
||||
* Here the original copyright assignment:
|
||||
*
|
||||
* Copyright (C) 2003 Marco Pesenti Gritti
|
||||
* Copyright (C) 2003, 2004 Christian Persch
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id: gedit-module.h 6263 2008-05-05 10:52:10Z sfre $
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_OBJECT_MODULE_H__
|
||||
#define __GEDIT_OBJECT_MODULE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_OBJECT_MODULE (gedit_object_module_get_type ())
|
||||
#define GEDIT_OBJECT_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModule))
|
||||
#define GEDIT_OBJECT_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModuleClass))
|
||||
#define GEDIT_IS_OBJECT_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_OBJECT_MODULE))
|
||||
#define GEDIT_IS_OBJECT_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_OBJECT_MODULE))
|
||||
#define GEDIT_OBJECT_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModuleClass))
|
||||
|
||||
typedef struct _GeditObjectModule GeditObjectModule;
|
||||
typedef struct _GeditObjectModulePrivate GeditObjectModulePrivate;
|
||||
|
||||
struct _GeditObjectModule
|
||||
{
|
||||
GTypeModule parent;
|
||||
|
||||
GeditObjectModulePrivate *priv;
|
||||
};
|
||||
|
||||
typedef struct _GeditObjectModuleClass GeditObjectModuleClass;
|
||||
|
||||
struct _GeditObjectModuleClass
|
||||
{
|
||||
GTypeModuleClass parent_class;
|
||||
|
||||
/* Virtual class methods */
|
||||
void (* garbage_collect) ();
|
||||
};
|
||||
|
||||
GType gedit_object_module_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditObjectModule *gedit_object_module_new (const gchar *module_name,
|
||||
const gchar *path,
|
||||
const gchar *type_registration,
|
||||
gboolean resident);
|
||||
|
||||
GObject *gedit_object_module_new_object (GeditObjectModule *module,
|
||||
const gchar *first_property_name,
|
||||
...);
|
||||
|
||||
GType gedit_object_module_get_object_type (GeditObjectModule *module);
|
||||
const gchar *gedit_object_module_get_path (GeditObjectModule *module);
|
||||
const gchar *gedit_object_module_get_module_name (GeditObjectModule *module);
|
||||
const gchar *gedit_object_module_get_type_registration (GeditObjectModule *module);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
950
gedit/gedit-panel.c
Executable file
950
gedit/gedit-panel.c
Executable file
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* gedit-panel.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "gedit-panel.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "gedit-close-button.h"
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
#define PANEL_ITEM_KEY "GeditPanelItemKey"
|
||||
|
||||
#define GEDIT_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PANEL, GeditPanelPrivate))
|
||||
|
||||
struct _GeditPanelPrivate
|
||||
{
|
||||
GtkOrientation orientation;
|
||||
|
||||
/* Title bar (vertical panel only) */
|
||||
GtkWidget *title_image;
|
||||
GtkWidget *title_label;
|
||||
|
||||
/* Notebook */
|
||||
GtkWidget *notebook;
|
||||
};
|
||||
|
||||
typedef struct _GeditPanelItem GeditPanelItem;
|
||||
|
||||
struct _GeditPanelItem
|
||||
{
|
||||
gchar *name;
|
||||
GtkWidget *icon;
|
||||
};
|
||||
|
||||
/* Properties */
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ORIENTATION
|
||||
};
|
||||
|
||||
/* Signals */
|
||||
enum {
|
||||
ITEM_ADDED,
|
||||
ITEM_REMOVED,
|
||||
CLOSE,
|
||||
FOCUS_DOCUMENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static GObject *gedit_panel_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties);
|
||||
|
||||
|
||||
G_DEFINE_TYPE(GeditPanel, gedit_panel, GTK_TYPE_VBOX)
|
||||
|
||||
static void
|
||||
gedit_panel_finalize (GObject *obj)
|
||||
{
|
||||
if (G_OBJECT_CLASS (gedit_panel_parent_class)->finalize)
|
||||
(*G_OBJECT_CLASS (gedit_panel_parent_class)->finalize) (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditPanel *panel = GEDIT_PANEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum(value, panel->priv->orientation);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditPanel *panel = GEDIT_PANEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ORIENTATION:
|
||||
panel->priv->orientation = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_close (GeditPanel *panel)
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET (panel));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_focus_document (GeditPanel *panel)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel));
|
||||
#if !GTK_CHECK_VERSION (2, 18, 0)
|
||||
if (GTK_WIDGET_TOPLEVEL (toplevel) && GEDIT_IS_WINDOW (toplevel))
|
||||
#else
|
||||
if (gtk_widget_is_toplevel (toplevel) && GEDIT_IS_WINDOW (toplevel))
|
||||
#endif
|
||||
{
|
||||
GeditView *view;
|
||||
|
||||
view = gedit_window_get_active_view (GEDIT_WINDOW (toplevel));
|
||||
if (view != NULL)
|
||||
gtk_widget_grab_focus (GTK_WIDGET (view));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_grab_focus (GtkWidget *w)
|
||||
{
|
||||
gint n;
|
||||
GtkWidget *tab;
|
||||
GeditPanel *panel = GEDIT_PANEL (w);
|
||||
|
||||
n = gtk_notebook_get_current_page (GTK_NOTEBOOK (panel->priv->notebook));
|
||||
if (n == -1)
|
||||
return;
|
||||
|
||||
tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
n);
|
||||
g_return_if_fail (tab != NULL);
|
||||
|
||||
gtk_widget_grab_focus (tab);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_class_init (GeditPanelClass *klass)
|
||||
{
|
||||
GtkBindingSet *binding_set;
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditPanelPrivate));
|
||||
|
||||
object_class->constructor = gedit_panel_constructor;
|
||||
object_class->finalize = gedit_panel_finalize;
|
||||
object_class->get_property = gedit_panel_get_property;
|
||||
object_class->set_property = gedit_panel_set_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ORIENTATION,
|
||||
g_param_spec_enum ("orientation",
|
||||
"Orientation",
|
||||
"The panel's orientation",
|
||||
GTK_TYPE_ORIENTATION,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
widget_class->grab_focus = gedit_panel_grab_focus;
|
||||
|
||||
klass->close = gedit_panel_close;
|
||||
klass->focus_document = gedit_panel_focus_document;
|
||||
|
||||
signals[ITEM_ADDED] =
|
||||
g_signal_new ("item_added",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GeditPanelClass, item_added),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GTK_TYPE_WIDGET);
|
||||
signals[ITEM_REMOVED] =
|
||||
g_signal_new ("item_removed",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GeditPanelClass, item_removed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GTK_TYPE_WIDGET);
|
||||
|
||||
/* Keybinding signals */
|
||||
signals[CLOSE] =
|
||||
g_signal_new ("close",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GeditPanelClass, close),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
signals[FOCUS_DOCUMENT] =
|
||||
g_signal_new ("focus_document",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GeditPanelClass, focus_document),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_Escape,
|
||||
0,
|
||||
"close",
|
||||
0);
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_Return,
|
||||
GDK_CONTROL_MASK,
|
||||
"focus_document",
|
||||
0);
|
||||
}
|
||||
|
||||
/* This is ugly, since it supports only known
|
||||
* storage types of GtkImage, otherwise fall back
|
||||
* to the empty icon.
|
||||
* See http://bugzilla.mate.org/show_bug.cgi?id=317520.
|
||||
*/
|
||||
static void
|
||||
set_gtk_image_from_gtk_image (GtkImage *image,
|
||||
GtkImage *source)
|
||||
{
|
||||
switch (gtk_image_get_storage_type (source))
|
||||
{
|
||||
case GTK_IMAGE_EMPTY:
|
||||
gtk_image_clear (image);
|
||||
break;
|
||||
case GTK_IMAGE_PIXMAP:
|
||||
{
|
||||
GdkPixmap *pm;
|
||||
GdkBitmap *bm;
|
||||
|
||||
gtk_image_get_pixmap (source, &pm, &bm);
|
||||
gtk_image_set_from_pixmap (image, pm, bm);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_IMAGE:
|
||||
{
|
||||
GdkImage *i;
|
||||
GdkBitmap *bm;
|
||||
|
||||
gtk_image_get_image (source, &i, &bm);
|
||||
gtk_image_set_from_image (image, i, bm);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_PIXBUF:
|
||||
{
|
||||
GdkPixbuf *pb;
|
||||
|
||||
pb = gtk_image_get_pixbuf (source);
|
||||
gtk_image_set_from_pixbuf (image, pb);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_STOCK:
|
||||
{
|
||||
gchar *s_id;
|
||||
GtkIconSize s;
|
||||
|
||||
gtk_image_get_stock (source, &s_id, &s);
|
||||
gtk_image_set_from_stock (image, s_id, s);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_ICON_SET:
|
||||
{
|
||||
GtkIconSet *is;
|
||||
GtkIconSize s;
|
||||
|
||||
gtk_image_get_icon_set (source, &is, &s);
|
||||
gtk_image_set_from_icon_set (image, is, s);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_ANIMATION:
|
||||
{
|
||||
GdkPixbufAnimation *a;
|
||||
|
||||
a = gtk_image_get_animation (source);
|
||||
gtk_image_set_from_animation (image, a);
|
||||
}
|
||||
break;
|
||||
case GTK_IMAGE_ICON_NAME:
|
||||
{
|
||||
const gchar *n;
|
||||
GtkIconSize s;
|
||||
|
||||
gtk_image_get_icon_name (source, &n, &s);
|
||||
gtk_image_set_from_icon_name (image, n, s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gtk_image_set_from_stock (image,
|
||||
GTK_STOCK_FILE,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sync_title (GeditPanel *panel,
|
||||
GeditPanelItem *item)
|
||||
{
|
||||
if (panel->priv->orientation != GTK_ORIENTATION_VERTICAL)
|
||||
return;
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
|
||||
item->name);
|
||||
|
||||
set_gtk_image_from_gtk_image (GTK_IMAGE (panel->priv->title_image),
|
||||
GTK_IMAGE (item->icon));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
|
||||
_("Empty"));
|
||||
|
||||
gtk_image_set_from_stock (GTK_IMAGE (panel->priv->title_image),
|
||||
GTK_STOCK_FILE,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notebook_page_changed (GtkNotebook *notebook,
|
||||
GtkNotebookPage *page,
|
||||
guint page_num,
|
||||
GeditPanel *panel)
|
||||
{
|
||||
GtkWidget *item;
|
||||
GeditPanelItem *data;
|
||||
|
||||
item = gtk_notebook_get_nth_page (notebook, page_num);
|
||||
g_return_if_fail (item != NULL);
|
||||
|
||||
data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
sync_title (panel, data);
|
||||
}
|
||||
|
||||
static void
|
||||
panel_show (GeditPanel *panel,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint page;
|
||||
GtkNotebook *nb;
|
||||
|
||||
nb = GTK_NOTEBOOK (panel->priv->notebook);
|
||||
|
||||
page = gtk_notebook_get_current_page (nb);
|
||||
|
||||
if (page != -1)
|
||||
notebook_page_changed (nb, NULL, page, panel);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_panel_init (GeditPanel *panel)
|
||||
{
|
||||
panel->priv = GEDIT_PANEL_GET_PRIVATE (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
close_button_clicked_cb (GtkWidget *widget,
|
||||
GtkWidget *panel)
|
||||
{
|
||||
gtk_widget_hide (panel);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_close_button (GeditPanel *panel)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
button = gedit_close_button_new ();
|
||||
|
||||
gtk_widget_set_tooltip_text (button, _("Hide panel"));
|
||||
|
||||
g_signal_connect (button,
|
||||
"clicked",
|
||||
G_CALLBACK (close_button_clicked_cb),
|
||||
panel);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static void
|
||||
build_notebook_for_panel (GeditPanel *panel)
|
||||
{
|
||||
/* Create the panel notebook */
|
||||
panel->priv->notebook = gtk_notebook_new ();
|
||||
|
||||
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
GTK_POS_BOTTOM);
|
||||
gtk_notebook_set_scrollable (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
TRUE);
|
||||
gtk_notebook_popup_enable (GTK_NOTEBOOK (panel->priv->notebook));
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (panel->priv->notebook));
|
||||
|
||||
g_signal_connect (panel->priv->notebook,
|
||||
"switch-page",
|
||||
G_CALLBACK (notebook_page_changed),
|
||||
panel);
|
||||
}
|
||||
|
||||
static void
|
||||
build_horizontal_panel (GeditPanel *panel)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *sidebar;
|
||||
GtkWidget *close_button;
|
||||
|
||||
box = gtk_hbox_new(FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (box),
|
||||
panel->priv->notebook,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
/* Toolbar, close button and first separator */
|
||||
sidebar = gtk_vbox_new(FALSE, 6);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (sidebar), 4);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (box),
|
||||
sidebar,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
|
||||
close_button = create_close_button (panel);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (sidebar),
|
||||
close_button,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
|
||||
gtk_widget_show_all (box);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (panel),
|
||||
box,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
build_vertical_panel (GeditPanel *panel)
|
||||
{
|
||||
GtkWidget *close_button;
|
||||
GtkWidget *title_hbox;
|
||||
GtkWidget *icon_name_hbox;
|
||||
GtkWidget *dummy_label;
|
||||
|
||||
/* Create title hbox */
|
||||
title_hbox = gtk_hbox_new (FALSE, 6);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (title_hbox), 5);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (panel), title_hbox, FALSE, FALSE, 0);
|
||||
|
||||
icon_name_hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (title_hbox),
|
||||
icon_name_hbox,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
panel->priv->title_image =
|
||||
gtk_image_new_from_stock (GTK_STOCK_FILE,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
|
||||
panel->priv->title_image,
|
||||
FALSE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
dummy_label = gtk_label_new (" ");
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
|
||||
dummy_label,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
|
||||
panel->priv->title_label = gtk_label_new (_("Empty"));
|
||||
gtk_misc_set_alignment (GTK_MISC (panel->priv->title_label), 0, 0.5);
|
||||
gtk_label_set_ellipsize(GTK_LABEL (panel->priv->title_label), PANGO_ELLIPSIZE_END);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
|
||||
panel->priv->title_label,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
|
||||
close_button = create_close_button (panel);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (title_hbox),
|
||||
close_button,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0);
|
||||
|
||||
gtk_widget_show_all (title_hbox);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (panel),
|
||||
panel->priv->notebook,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gedit_panel_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
|
||||
/* Invoke parent constructor. */
|
||||
GeditPanelClass *klass = GEDIT_PANEL_CLASS (g_type_class_peek (GEDIT_TYPE_PANEL));
|
||||
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
|
||||
GObject *obj = parent_class->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_properties);
|
||||
|
||||
/* Build the panel, now that we know the orientation
|
||||
(_init has been called previously) */
|
||||
GeditPanel *panel = GEDIT_PANEL (obj);
|
||||
|
||||
build_notebook_for_panel (panel);
|
||||
if (panel->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
build_horizontal_panel (panel);
|
||||
else
|
||||
build_vertical_panel (panel);
|
||||
|
||||
g_signal_connect (panel,
|
||||
"show",
|
||||
G_CALLBACK (panel_show),
|
||||
NULL);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_new:
|
||||
* @orientation: a #GtkOrientation
|
||||
*
|
||||
* Creates a new #GeditPanel with the given @orientation. You shouldn't create
|
||||
* a new panel use gedit_window_get_side_panel() or gedit_window_get_bottom_panel()
|
||||
* instead.
|
||||
*
|
||||
* Returns: a new #GeditPanel object.
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_panel_new (GtkOrientation orientation)
|
||||
{
|
||||
return GTK_WIDGET (g_object_new (GEDIT_TYPE_PANEL, "orientation", orientation, NULL));
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
build_tab_label (GeditPanel *panel,
|
||||
GtkWidget *item,
|
||||
const gchar *name,
|
||||
GtkWidget *icon)
|
||||
{
|
||||
GtkWidget *hbox, *label_hbox, *label_ebox;
|
||||
GtkWidget *label;
|
||||
|
||||
/* set hbox spacing and label padding (see below) so that there's an
|
||||
* equal amount of space around the label */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
|
||||
label_ebox = gtk_event_box_new ();
|
||||
gtk_event_box_set_visible_window (GTK_EVENT_BOX (label_ebox), FALSE);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0);
|
||||
|
||||
label_hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_container_add (GTK_CONTAINER (label_ebox), label_hbox);
|
||||
|
||||
/* setup icon */
|
||||
gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0);
|
||||
|
||||
/* setup label */
|
||||
label = gtk_label_new (name);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
||||
gtk_misc_set_padding (GTK_MISC (label), 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (label_hbox), label, TRUE, TRUE, 0);
|
||||
|
||||
gtk_widget_set_tooltip_text (label_ebox, name);
|
||||
|
||||
gtk_widget_show_all (hbox);
|
||||
|
||||
if (panel->priv->orientation == GTK_ORIENTATION_VERTICAL)
|
||||
gtk_widget_hide(label);
|
||||
|
||||
g_object_set_data (G_OBJECT (item), "label", label);
|
||||
g_object_set_data (G_OBJECT (item), "hbox", hbox);
|
||||
|
||||
return hbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_add_item:
|
||||
* @panel: a #GeditPanel
|
||||
* @item: the #GtkWidget to add to the @panel
|
||||
* @name: the name to be shown in the @panel
|
||||
* @image: the image to be shown in the @panel
|
||||
*
|
||||
* Adds a new item to the @panel.
|
||||
*/
|
||||
void
|
||||
gedit_panel_add_item (GeditPanel *panel,
|
||||
GtkWidget *item,
|
||||
const gchar *name,
|
||||
GtkWidget *image)
|
||||
{
|
||||
GeditPanelItem *data;
|
||||
GtkWidget *tab_label;
|
||||
GtkWidget *menu_label;
|
||||
gint w, h;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PANEL (panel));
|
||||
g_return_if_fail (GTK_IS_WIDGET (item));
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (image == NULL || GTK_IS_IMAGE (image));
|
||||
|
||||
data = g_new (GeditPanelItem, 1);
|
||||
|
||||
data->name = g_strdup (name);
|
||||
|
||||
if (image == NULL)
|
||||
{
|
||||
/* default to empty */
|
||||
data->icon = gtk_image_new_from_stock (GTK_STOCK_FILE,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->icon = image;
|
||||
}
|
||||
|
||||
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
||||
gtk_widget_set_size_request (data->icon, w, h);
|
||||
|
||||
g_object_set_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY,
|
||||
data);
|
||||
|
||||
tab_label = build_tab_label (panel, item, data->name, data->icon);
|
||||
|
||||
menu_label = gtk_label_new (name);
|
||||
gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (item))
|
||||
gtk_widget_show (item);
|
||||
|
||||
gtk_notebook_append_page_menu (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
item,
|
||||
tab_label,
|
||||
menu_label);
|
||||
|
||||
g_signal_emit (G_OBJECT (panel), signals[ITEM_ADDED], 0, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_add_item_with_stock_icon:
|
||||
* @panel: a #GeditPanel
|
||||
* @item: the #GtkWidget to add to the @panel
|
||||
* @name: the name to be shown in the @panel
|
||||
* @stock_id: a stock id
|
||||
*
|
||||
* Same as gedit_panel_add_item() but using an image from stock.
|
||||
*/
|
||||
void
|
||||
gedit_panel_add_item_with_stock_icon (GeditPanel *panel,
|
||||
GtkWidget *item,
|
||||
const gchar *name,
|
||||
const gchar *stock_id)
|
||||
{
|
||||
GtkWidget *icon = NULL;
|
||||
|
||||
if (stock_id != NULL)
|
||||
{
|
||||
icon = gtk_image_new_from_stock (stock_id,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
}
|
||||
|
||||
gedit_panel_add_item (panel, item, name, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_remove_item:
|
||||
* @panel: a #GeditPanel
|
||||
* @item: the item to be removed from the panel
|
||||
*
|
||||
* Removes the widget @item from the panel if it is in the @panel and returns
|
||||
* TRUE if there was not any problem.
|
||||
*
|
||||
* Returns: TRUE if it was well removed.
|
||||
*/
|
||||
gboolean
|
||||
gedit_panel_remove_item (GeditPanel *panel,
|
||||
GtkWidget *item)
|
||||
{
|
||||
GeditPanelItem *data;
|
||||
gint page_num;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
|
||||
|
||||
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
item);
|
||||
|
||||
if (page_num == -1)
|
||||
return FALSE;
|
||||
|
||||
data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY);
|
||||
g_return_val_if_fail (data != NULL, FALSE);
|
||||
|
||||
g_free (data->name);
|
||||
g_free (data);
|
||||
|
||||
g_object_set_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY,
|
||||
NULL);
|
||||
|
||||
/* ref the item to keep it alive during signal emission */
|
||||
g_object_ref (G_OBJECT (item));
|
||||
|
||||
gtk_notebook_remove_page (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
page_num);
|
||||
|
||||
/* if we removed all the pages, reset the title */
|
||||
if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook)) == 0)
|
||||
sync_title (panel, NULL);
|
||||
|
||||
g_signal_emit (G_OBJECT (panel), signals[ITEM_REMOVED], 0, item);
|
||||
|
||||
g_object_unref (G_OBJECT (item));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_activate_item:
|
||||
* @panel: a #GeditPanel
|
||||
* @item: the item to be activated
|
||||
*
|
||||
* Switches to the page that contains @item.
|
||||
*
|
||||
* Returns: TRUE if it was activated
|
||||
*/
|
||||
gboolean
|
||||
gedit_panel_activate_item (GeditPanel *panel,
|
||||
GtkWidget *item)
|
||||
{
|
||||
gint page_num;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
|
||||
|
||||
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
item);
|
||||
|
||||
if (page_num == -1)
|
||||
return FALSE;
|
||||
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
page_num);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_item_is_active:
|
||||
* @panel: a #GeditPanel
|
||||
* @item: a widget contained in #GeditPanel
|
||||
*
|
||||
* Wheter @item is the one current active in @panel
|
||||
*
|
||||
* Returns: TRUE if the widget is active
|
||||
*/
|
||||
gboolean
|
||||
gedit_panel_item_is_active (GeditPanel *panel,
|
||||
GtkWidget *item)
|
||||
{
|
||||
gint cur_page;
|
||||
gint page_num;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
|
||||
|
||||
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
|
||||
item);
|
||||
|
||||
if (page_num == -1)
|
||||
return FALSE;
|
||||
|
||||
cur_page = gtk_notebook_get_current_page (
|
||||
GTK_NOTEBOOK (panel->priv->notebook));
|
||||
|
||||
return (page_num == cur_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_get_orientation:
|
||||
* @panel: a #GeditPanel
|
||||
*
|
||||
* Gets the orientation of the @panel.
|
||||
*
|
||||
* Returns: the #GtkOrientation of #GeditPanel
|
||||
*/
|
||||
GtkOrientation
|
||||
gedit_panel_get_orientation (GeditPanel *panel)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), GTK_ORIENTATION_VERTICAL);
|
||||
|
||||
return panel->priv->orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_panel_get_n_items:
|
||||
* @panel: a #GeditPanel
|
||||
*
|
||||
* Gets the number of items in a @panel.
|
||||
*
|
||||
* Returns: the number of items contained in #GeditPanel
|
||||
*/
|
||||
gint
|
||||
gedit_panel_get_n_items (GeditPanel *panel)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), -1);
|
||||
|
||||
return gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook));
|
||||
}
|
||||
|
||||
gint
|
||||
_gedit_panel_get_active_item_id (GeditPanel *panel)
|
||||
{
|
||||
gint cur_page;
|
||||
GtkWidget *item;
|
||||
GeditPanelItem *data;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PANEL (panel), 0);
|
||||
|
||||
cur_page = gtk_notebook_get_current_page (
|
||||
GTK_NOTEBOOK (panel->priv->notebook));
|
||||
if (cur_page == -1)
|
||||
return 0;
|
||||
|
||||
item = gtk_notebook_get_nth_page (
|
||||
GTK_NOTEBOOK (panel->priv->notebook),
|
||||
cur_page);
|
||||
|
||||
/* FIXME: for now we use as the hash of the name as id.
|
||||
* However the name is not guaranteed to be unique and
|
||||
* it is a translated string, so it's subotimal, but should
|
||||
* be good enough for now since we don't want to add an
|
||||
* ad hoc id argument.
|
||||
*/
|
||||
|
||||
data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY);
|
||||
g_return_val_if_fail (data != NULL, 0);
|
||||
|
||||
return g_str_hash (data->name);
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_panel_set_active_item_by_id (GeditPanel *panel,
|
||||
gint id)
|
||||
{
|
||||
gint n, i;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PANEL (panel));
|
||||
|
||||
if (id == 0)
|
||||
return;
|
||||
|
||||
n = gtk_notebook_get_n_pages (
|
||||
GTK_NOTEBOOK (panel->priv->notebook));
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GtkWidget *item;
|
||||
GeditPanelItem *data;
|
||||
|
||||
item = gtk_notebook_get_nth_page (
|
||||
GTK_NOTEBOOK (panel->priv->notebook), i);
|
||||
|
||||
data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item),
|
||||
PANEL_ITEM_KEY);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
if (g_str_hash (data->name) == id)
|
||||
{
|
||||
gtk_notebook_set_current_page (
|
||||
GTK_NOTEBOOK (panel->priv->notebook), i);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
130
gedit/gedit-panel.h
Executable file
130
gedit/gedit-panel.h
Executable file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* gedit-panel.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PANEL_H__
|
||||
#define __GEDIT_PANEL_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_PANEL (gedit_panel_get_type())
|
||||
#define GEDIT_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PANEL, GeditPanel))
|
||||
#define GEDIT_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PANEL, GeditPanelClass))
|
||||
#define GEDIT_IS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PANEL))
|
||||
#define GEDIT_IS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PANEL))
|
||||
#define GEDIT_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PANEL, GeditPanelClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditPanelPrivate GeditPanelPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditPanel GeditPanel;
|
||||
|
||||
struct _GeditPanel
|
||||
{
|
||||
GtkVBox vbox;
|
||||
|
||||
/*< private > */
|
||||
GeditPanelPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditPanelClass GeditPanelClass;
|
||||
|
||||
struct _GeditPanelClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
|
||||
void (* item_added) (GeditPanel *panel,
|
||||
GtkWidget *item);
|
||||
void (* item_removed) (GeditPanel *panel,
|
||||
GtkWidget *item);
|
||||
|
||||
/* Keybinding signals */
|
||||
void (* close) (GeditPanel *panel);
|
||||
void (* focus_document) (GeditPanel *panel);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gedit_reserved1) (void);
|
||||
void (*_gedit_reserved2) (void);
|
||||
void (*_gedit_reserved3) (void);
|
||||
void (*_gedit_reserved4) (void);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_panel_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_panel_new (GtkOrientation orientation);
|
||||
|
||||
void gedit_panel_add_item (GeditPanel *panel,
|
||||
GtkWidget *item,
|
||||
const gchar *name,
|
||||
GtkWidget *image);
|
||||
|
||||
void gedit_panel_add_item_with_stock_icon (GeditPanel *panel,
|
||||
GtkWidget *item,
|
||||
const gchar *name,
|
||||
const gchar *stock_id);
|
||||
|
||||
gboolean gedit_panel_remove_item (GeditPanel *panel,
|
||||
GtkWidget *item);
|
||||
|
||||
gboolean gedit_panel_activate_item (GeditPanel *panel,
|
||||
GtkWidget *item);
|
||||
|
||||
gboolean gedit_panel_item_is_active (GeditPanel *panel,
|
||||
GtkWidget *item);
|
||||
|
||||
GtkOrientation gedit_panel_get_orientation (GeditPanel *panel);
|
||||
|
||||
gint gedit_panel_get_n_items (GeditPanel *panel);
|
||||
|
||||
|
||||
/*
|
||||
* Non exported functions
|
||||
*/
|
||||
gint _gedit_panel_get_active_item_id (GeditPanel *panel);
|
||||
|
||||
void _gedit_panel_set_active_item_by_id (GeditPanel *panel,
|
||||
gint id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PANEL_H__ */
|
||||
68
gedit/gedit-plugin-info-priv.h
Executable file
68
gedit/gedit-plugin-info-priv.h
Executable file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* gedit-plugin-info-priv.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGIN_INFO_PRIV_H__
|
||||
#define __GEDIT_PLUGIN_INFO_PRIV_H__
|
||||
|
||||
#include "gedit-plugin-info.h"
|
||||
#include "gedit-plugin.h"
|
||||
|
||||
struct _GeditPluginInfo
|
||||
{
|
||||
gint refcount;
|
||||
|
||||
GeditPlugin *plugin;
|
||||
gchar *file;
|
||||
|
||||
gchar *module_name;
|
||||
gchar *loader;
|
||||
gchar **dependencies;
|
||||
|
||||
gchar *name;
|
||||
gchar *desc;
|
||||
gchar *icon_name;
|
||||
gchar **authors;
|
||||
gchar *copyright;
|
||||
gchar *website;
|
||||
gchar *version;
|
||||
|
||||
/* A plugin is unavailable if it is not possible to activate it
|
||||
due to an error loading the plugin module (e.g. for Python plugins
|
||||
when the interpreter has not been correctly initializated) */
|
||||
gint available : 1;
|
||||
};
|
||||
|
||||
GeditPluginInfo *_gedit_plugin_info_new (const gchar *file);
|
||||
void _gedit_plugin_info_ref (GeditPluginInfo *info);
|
||||
void _gedit_plugin_info_unref (GeditPluginInfo *info);
|
||||
|
||||
|
||||
#endif /* __GEDIT_PLUGIN_INFO_PRIV_H__ */
|
||||
394
gedit/gedit-plugin-info.c
Executable file
394
gedit/gedit-plugin-info.c
Executable file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* gedit-plugin-info.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "gedit-plugin-info.h"
|
||||
#include "gedit-plugin-info-priv.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-plugin.h"
|
||||
|
||||
void
|
||||
_gedit_plugin_info_ref (GeditPluginInfo *info)
|
||||
{
|
||||
g_atomic_int_inc (&info->refcount);
|
||||
}
|
||||
|
||||
static GeditPluginInfo *
|
||||
gedit_plugin_info_copy (GeditPluginInfo *info)
|
||||
{
|
||||
_gedit_plugin_info_ref (info);
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
_gedit_plugin_info_unref (GeditPluginInfo *info)
|
||||
{
|
||||
if (!g_atomic_int_dec_and_test (&info->refcount))
|
||||
return;
|
||||
|
||||
if (info->plugin != NULL)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name);
|
||||
|
||||
g_object_unref (info->plugin);
|
||||
}
|
||||
|
||||
g_free (info->file);
|
||||
g_free (info->module_name);
|
||||
g_strfreev (info->dependencies);
|
||||
g_free (info->name);
|
||||
g_free (info->desc);
|
||||
g_free (info->icon_name);
|
||||
g_free (info->website);
|
||||
g_free (info->copyright);
|
||||
g_free (info->loader);
|
||||
g_free (info->version);
|
||||
g_strfreev (info->authors);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_info_get_type:
|
||||
*
|
||||
* Retrieves the #GType object which is associated with the #GeditPluginInfo
|
||||
* class.
|
||||
*
|
||||
* Return value: the GType associated with #GeditPluginInfo.
|
||||
**/
|
||||
GType
|
||||
gedit_plugin_info_get_type (void)
|
||||
{
|
||||
static GType the_type = 0;
|
||||
|
||||
if (G_UNLIKELY (!the_type))
|
||||
the_type = g_boxed_type_register_static (
|
||||
"GeditPluginInfo",
|
||||
(GBoxedCopyFunc) gedit_plugin_info_copy,
|
||||
(GBoxedFreeFunc) _gedit_plugin_info_unref);
|
||||
|
||||
return the_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_info_new:
|
||||
* @filename: the filename where to read the plugin information
|
||||
*
|
||||
* Creates a new #GeditPluginInfo from a file on the disk.
|
||||
*
|
||||
* Return value: a newly created #GeditPluginInfo.
|
||||
*/
|
||||
GeditPluginInfo *
|
||||
_gedit_plugin_info_new (const gchar *file)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
GKeyFile *plugin_file = NULL;
|
||||
gchar *str;
|
||||
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Loading plugin: %s", file);
|
||||
|
||||
info = g_new0 (GeditPluginInfo, 1);
|
||||
info->refcount = 1;
|
||||
info->file = g_strdup (file);
|
||||
|
||||
plugin_file = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL))
|
||||
{
|
||||
g_warning ("Bad plugin file: %s", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!g_key_file_has_key (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"IAge",
|
||||
NULL))
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS,
|
||||
"IAge key does not exist in file: %s", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check IAge=2 */
|
||||
if (g_key_file_get_integer (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"IAge",
|
||||
NULL) != 2)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS,
|
||||
"Wrong IAge in file: %s", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get module name */
|
||||
str = g_key_file_get_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Module",
|
||||
NULL);
|
||||
|
||||
if ((str != NULL) && (*str != '\0'))
|
||||
{
|
||||
info->module_name = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Could not find 'Module' in %s", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get the dependency list */
|
||||
info->dependencies = g_key_file_get_string_list (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Depends",
|
||||
NULL,
|
||||
NULL);
|
||||
if (info->dependencies == NULL)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Depends' in %s", file);
|
||||
info->dependencies = g_new0 (gchar *, 1);
|
||||
}
|
||||
|
||||
/* Get the loader for this plugin */
|
||||
str = g_key_file_get_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Loader",
|
||||
NULL);
|
||||
|
||||
if ((str != NULL) && (*str != '\0'))
|
||||
{
|
||||
info->loader = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default to the C loader */
|
||||
info->loader = g_strdup("c");
|
||||
}
|
||||
|
||||
/* Get Name */
|
||||
str = g_key_file_get_locale_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Name",
|
||||
NULL, NULL);
|
||||
if (str)
|
||||
info->name = str;
|
||||
else
|
||||
{
|
||||
g_warning ("Could not find 'Name' in %s", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get Description */
|
||||
str = g_key_file_get_locale_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Description",
|
||||
NULL, NULL);
|
||||
if (str)
|
||||
info->desc = str;
|
||||
else
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Description' in %s", file);
|
||||
|
||||
/* Get Icon */
|
||||
str = g_key_file_get_locale_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Icon",
|
||||
NULL, NULL);
|
||||
if (str)
|
||||
info->icon_name = str;
|
||||
else
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Icon' in %s, using 'gedit-plugin'", file);
|
||||
|
||||
|
||||
/* Get Authors */
|
||||
info->authors = g_key_file_get_string_list (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Authors",
|
||||
NULL,
|
||||
NULL);
|
||||
if (info->authors == NULL)
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Authors' in %s", file);
|
||||
|
||||
|
||||
/* Get Copyright */
|
||||
str = g_key_file_get_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Copyright",
|
||||
NULL);
|
||||
if (str)
|
||||
info->copyright = str;
|
||||
else
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Copyright' in %s", file);
|
||||
|
||||
/* Get Website */
|
||||
str = g_key_file_get_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Website",
|
||||
NULL);
|
||||
if (str)
|
||||
info->website = str;
|
||||
else
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Website' in %s", file);
|
||||
|
||||
/* Get Version */
|
||||
str = g_key_file_get_string (plugin_file,
|
||||
"Gedit Plugin",
|
||||
"Version",
|
||||
NULL);
|
||||
if (str)
|
||||
info->version = str;
|
||||
else
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Version' in %s", file);
|
||||
|
||||
g_key_file_free (plugin_file);
|
||||
|
||||
/* If we know nothing about the availability of the plugin,
|
||||
set it as available */
|
||||
info->available = TRUE;
|
||||
|
||||
return info;
|
||||
|
||||
error:
|
||||
g_free (info->file);
|
||||
g_free (info->module_name);
|
||||
g_free (info->name);
|
||||
g_free (info->loader);
|
||||
g_free (info);
|
||||
g_key_file_free (plugin_file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_plugin_info_is_active (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
return info->available && info->plugin != NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_plugin_info_is_available (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
return info->available != FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_plugin_info_is_configurable (GeditPluginInfo *info)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Is '%s' configurable?", info->name);
|
||||
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
if (info->plugin == NULL || !info->available)
|
||||
return FALSE;
|
||||
|
||||
return gedit_plugin_is_configurable (info->plugin);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_module_name (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->module_name;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_name (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->name;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_description (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->desc;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_icon_name (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
/* use the gedit-plugin icon as a default if the plugin does not
|
||||
have its own */
|
||||
if (info->icon_name != NULL &&
|
||||
gtk_icon_theme_has_icon (gtk_icon_theme_get_default (),
|
||||
info->icon_name))
|
||||
return info->icon_name;
|
||||
else
|
||||
return "gedit-plugin";
|
||||
}
|
||||
|
||||
const gchar **
|
||||
gedit_plugin_info_get_authors (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, (const gchar **)NULL);
|
||||
|
||||
return (const gchar **) info->authors;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_website (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->website;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_copyright (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->copyright;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_info_get_version (GeditPluginInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->version;
|
||||
}
|
||||
63
gedit/gedit-plugin-info.h
Executable file
63
gedit/gedit-plugin-info.h
Executable file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* gedit-plugin-info.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 - Paolo Maggi
|
||||
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGIN_INFO_H__
|
||||
#define __GEDIT_PLUGIN_INFO_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_PLUGIN_INFO (gedit_plugin_info_get_type ())
|
||||
#define GEDIT_PLUGIN_INFO(obj) ((GeditPluginInfo *) (obj))
|
||||
|
||||
typedef struct _GeditPluginInfo GeditPluginInfo;
|
||||
|
||||
GType gedit_plugin_info_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean gedit_plugin_info_is_active (GeditPluginInfo *info);
|
||||
gboolean gedit_plugin_info_is_available (GeditPluginInfo *info);
|
||||
gboolean gedit_plugin_info_is_configurable (GeditPluginInfo *info);
|
||||
|
||||
const gchar *gedit_plugin_info_get_module_name (GeditPluginInfo *info);
|
||||
|
||||
const gchar *gedit_plugin_info_get_name (GeditPluginInfo *info);
|
||||
const gchar *gedit_plugin_info_get_description (GeditPluginInfo *info);
|
||||
const gchar *gedit_plugin_info_get_icon_name (GeditPluginInfo *info);
|
||||
const gchar **gedit_plugin_info_get_authors (GeditPluginInfo *info);
|
||||
const gchar *gedit_plugin_info_get_website (GeditPluginInfo *info);
|
||||
const gchar *gedit_plugin_info_get_copyright (GeditPluginInfo *info);
|
||||
const gchar *gedit_plugin_info_get_version (GeditPluginInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PLUGIN_INFO_H__ */
|
||||
|
||||
131
gedit/gedit-plugin-loader.c
Executable file
131
gedit/gedit-plugin-loader.c
Executable file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* gedit-plugin-loader.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gedit-plugin-loader.h"
|
||||
|
||||
static void
|
||||
gedit_plugin_loader_base_init (gpointer g_class)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (G_UNLIKELY (!initialized))
|
||||
{
|
||||
/* create interface signals here. */
|
||||
initialized = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
GType
|
||||
gedit_plugin_loader_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (type == 0))
|
||||
{
|
||||
static const GTypeInfo info =
|
||||
{
|
||||
sizeof (GeditPluginLoaderInterface),
|
||||
gedit_plugin_loader_base_init, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL, /* class_init */
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL /* instance_init */
|
||||
};
|
||||
|
||||
type = g_type_register_static (G_TYPE_INTERFACE, "GeditPluginLoader", &info, 0);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_plugin_loader_type_get_id (GType type)
|
||||
{
|
||||
GTypeClass *klass;
|
||||
GeditPluginLoaderInterface *iface;
|
||||
|
||||
klass = g_type_class_ref (type);
|
||||
|
||||
if (klass == NULL)
|
||||
{
|
||||
g_warning ("Could not get class info for plugin loader");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iface = g_type_interface_peek (klass, GEDIT_TYPE_PLUGIN_LOADER);
|
||||
|
||||
if (iface == NULL)
|
||||
{
|
||||
g_warning ("Could not get plugin loader interface");
|
||||
g_type_class_unref (klass);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (iface->get_id != NULL, NULL);
|
||||
return iface->get_id ();
|
||||
}
|
||||
|
||||
GeditPlugin *
|
||||
gedit_plugin_loader_load (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info,
|
||||
const gchar *path)
|
||||
{
|
||||
GeditPluginLoaderInterface *iface;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PLUGIN_LOADER (loader), NULL);
|
||||
|
||||
iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
|
||||
g_return_val_if_fail (iface->load != NULL, NULL);
|
||||
|
||||
return iface->load (loader, info, path);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugin_loader_unload (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
GeditPluginLoaderInterface *iface;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
|
||||
|
||||
iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
|
||||
g_return_if_fail (iface->unload != NULL);
|
||||
|
||||
iface->unload (loader, info);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugin_loader_garbage_collect (GeditPluginLoader *loader)
|
||||
{
|
||||
GeditPluginLoaderInterface *iface;
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
|
||||
|
||||
iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
|
||||
|
||||
if (iface->garbage_collect != NULL)
|
||||
iface->garbage_collect (loader);
|
||||
}
|
||||
106
gedit/gedit-plugin-loader.h
Executable file
106
gedit/gedit-plugin-loader.h
Executable file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* gedit-plugin-loader.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2008 - Jesse van den Kieboom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGIN_LOADER_H__
|
||||
#define __GEDIT_PLUGIN_LOADER_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gedit/gedit-plugin.h>
|
||||
#include <gedit/gedit-plugin-info.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_PLUGIN_LOADER (gedit_plugin_loader_get_type ())
|
||||
#define GEDIT_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoader))
|
||||
#define GEDIT_IS_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PLUGIN_LOADER))
|
||||
#define GEDIT_PLUGIN_LOADER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoaderInterface))
|
||||
|
||||
typedef struct _GeditPluginLoader GeditPluginLoader; /* dummy object */
|
||||
typedef struct _GeditPluginLoaderInterface GeditPluginLoaderInterface;
|
||||
|
||||
struct _GeditPluginLoaderInterface {
|
||||
GTypeInterface parent;
|
||||
|
||||
const gchar *(*get_id) (void);
|
||||
|
||||
GeditPlugin *(*load) (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info,
|
||||
const gchar *path);
|
||||
|
||||
void (*unload) (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info);
|
||||
|
||||
void (*garbage_collect) (GeditPluginLoader *loader);
|
||||
};
|
||||
|
||||
GType gedit_plugin_loader_get_type (void);
|
||||
|
||||
const gchar *gedit_plugin_loader_type_get_id (GType type);
|
||||
GeditPlugin *gedit_plugin_loader_load (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info,
|
||||
const gchar *path);
|
||||
void gedit_plugin_loader_unload (GeditPluginLoader *loader,
|
||||
GeditPluginInfo *info);
|
||||
void gedit_plugin_loader_garbage_collect (GeditPluginLoader *loader);
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
|
||||
*
|
||||
* Utility macro used to register interfaces for gobject types in plugin loaders.
|
||||
*/
|
||||
#define GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
|
||||
const GInterfaceInfo g_implement_interface_info = \
|
||||
{ \
|
||||
(GInterfaceInitFunc) iface_init, \
|
||||
NULL, \
|
||||
NULL \
|
||||
}; \
|
||||
\
|
||||
g_type_module_add_interface (type_module, \
|
||||
g_define_type_id, \
|
||||
TYPE_IFACE, \
|
||||
&g_implement_interface_info);
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_interface_init):
|
||||
*
|
||||
* Utility macro used to register plugin loaders.
|
||||
*/
|
||||
#define GEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_iface_init) \
|
||||
G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginLoaderName, \
|
||||
plugin_loader_name, \
|
||||
PARENT_TYPE, \
|
||||
0, \
|
||||
GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(GEDIT_TYPE_PLUGIN_LOADER, loader_iface_init)); \
|
||||
\
|
||||
\
|
||||
G_MODULE_EXPORT GType \
|
||||
register_gedit_plugin_loader (GTypeModule *type_module) \
|
||||
{ \
|
||||
plugin_loader_name##_register_type (type_module); \
|
||||
\
|
||||
return plugin_loader_name##_get_type(); \
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PLUGIN_LOADER_H__ */
|
||||
889
gedit/gedit-plugin-manager.c
Executable file
889
gedit/gedit-plugin-manager.c
Executable file
@@ -0,0 +1,889 @@
|
||||
/*
|
||||
* gedit-plugin-manager.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi and James Willcox
|
||||
* Copyright (C) 2003-2006 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2006. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-plugin-manager.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-plugins-engine.h"
|
||||
#include "gedit-plugin.h"
|
||||
#include "gedit-debug.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ACTIVE_COLUMN,
|
||||
AVAILABLE_COLUMN,
|
||||
INFO_COLUMN,
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
#define PLUGIN_MANAGER_NAME_TITLE _("Plugin")
|
||||
#define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled")
|
||||
|
||||
#define GEDIT_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerPrivate))
|
||||
|
||||
struct _GeditPluginManagerPrivate
|
||||
{
|
||||
GtkWidget *tree;
|
||||
|
||||
GtkWidget *about_button;
|
||||
GtkWidget *configure_button;
|
||||
|
||||
GeditPluginsEngine *engine;
|
||||
|
||||
GtkWidget *about;
|
||||
|
||||
GtkWidget *popup_menu;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GeditPluginManager, gedit_plugin_manager, GTK_TYPE_VBOX)
|
||||
|
||||
static GeditPluginInfo *plugin_manager_get_selected_plugin (GeditPluginManager *pm);
|
||||
static void plugin_manager_toggle_active (GeditPluginManager *pm, GtkTreeIter *iter, GtkTreeModel *model);
|
||||
static void gedit_plugin_manager_finalize (GObject *object);
|
||||
|
||||
static void
|
||||
gedit_plugin_manager_class_init (GeditPluginManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_plugin_manager_finalize;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditPluginManagerPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
about_button_cb (GtkWidget *button,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
info = plugin_manager_get_selected_plugin (pm);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
/* if there is another about dialog already open destroy it */
|
||||
if (pm->priv->about)
|
||||
gtk_widget_destroy (pm->priv->about);
|
||||
|
||||
pm->priv->about = g_object_new (GTK_TYPE_ABOUT_DIALOG,
|
||||
"program-name", gedit_plugin_info_get_name (info),
|
||||
"copyright", gedit_plugin_info_get_copyright (info),
|
||||
"authors", gedit_plugin_info_get_authors (info),
|
||||
"comments", gedit_plugin_info_get_description (info),
|
||||
"website", gedit_plugin_info_get_website (info),
|
||||
"logo-icon-name", gedit_plugin_info_get_icon_name (info),
|
||||
"version", gedit_plugin_info_get_version (info),
|
||||
NULL);
|
||||
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (pm->priv->about),
|
||||
TRUE);
|
||||
|
||||
g_signal_connect (pm->priv->about,
|
||||
"response",
|
||||
G_CALLBACK (gtk_widget_destroy),
|
||||
NULL);
|
||||
g_signal_connect (pm->priv->about,
|
||||
"destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed),
|
||||
&pm->priv->about);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (pm->priv->about),
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm))));
|
||||
gtk_widget_show (pm->priv->about);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_button_cb (GtkWidget *button,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
GtkWindow *toplevel;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
info = plugin_manager_get_selected_plugin (pm);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Configuring: %s\n",
|
||||
gedit_plugin_info_get_name (info));
|
||||
|
||||
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm)));
|
||||
|
||||
gedit_plugins_engine_configure_plugin (pm->priv->engine,
|
||||
info, toplevel);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Done");
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_view_info_cell_cb (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
gchar *text;
|
||||
|
||||
g_return_if_fail (tree_model != NULL);
|
||||
g_return_if_fail (tree_column != NULL);
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
text = g_markup_printf_escaped ("<b>%s</b>\n%s",
|
||||
gedit_plugin_info_get_name (info),
|
||||
gedit_plugin_info_get_description (info));
|
||||
g_object_set (G_OBJECT (cell),
|
||||
"markup", text,
|
||||
"sensitive", gedit_plugin_info_is_available (info),
|
||||
NULL);
|
||||
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_view_icon_cell_cb (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
|
||||
g_return_if_fail (tree_model != NULL);
|
||||
g_return_if_fail (tree_column != NULL);
|
||||
|
||||
gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
g_object_set (G_OBJECT (cell),
|
||||
"icon-name", gedit_plugin_info_get_icon_name (info),
|
||||
"sensitive", gedit_plugin_info_is_available (info),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
active_toggled_cb (GtkCellRendererToggle *cell,
|
||||
gchar *path_str,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
GtkTreeModel *model;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
path = gtk_tree_path_new_from_string (path_str);
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_if_fail (model != NULL);
|
||||
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
|
||||
if (&iter != NULL)
|
||||
plugin_manager_toggle_active (pm, &iter, model);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_changed_cb (GtkTreeView *view,
|
||||
gpointer data)
|
||||
{
|
||||
GeditPluginManager *pm = data;
|
||||
GeditPluginInfo *info;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
info = plugin_manager_get_selected_plugin (pm);
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->about_button),
|
||||
info != NULL);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
|
||||
(info != NULL) &&
|
||||
gedit_plugin_info_is_configurable (info));
|
||||
}
|
||||
|
||||
static void
|
||||
row_activated_cb (GtkTreeView *tree_view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
gpointer data)
|
||||
{
|
||||
GeditPluginManager *pm = data;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
|
||||
|
||||
g_return_if_fail (model != NULL);
|
||||
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
|
||||
g_return_if_fail (&iter != NULL);
|
||||
|
||||
plugin_manager_toggle_active (pm, &iter, model);
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_populate_lists (GeditPluginManager *pm)
|
||||
{
|
||||
const GList *plugins;
|
||||
GtkListStore *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
plugins = gedit_plugins_engine_get_plugin_list (pm->priv->engine);
|
||||
|
||||
model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)));
|
||||
|
||||
while (plugins)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
info = (GeditPluginInfo *)plugins->data;
|
||||
|
||||
gtk_list_store_append (model, &iter);
|
||||
gtk_list_store_set (model, &iter,
|
||||
ACTIVE_COLUMN, gedit_plugin_info_is_active (info),
|
||||
AVAILABLE_COLUMN, gedit_plugin_info_is_available (info),
|
||||
INFO_COLUMN, info,
|
||||
-1);
|
||||
|
||||
plugins = plugins->next;
|
||||
}
|
||||
|
||||
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GeditPluginInfo* info;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_if_fail (selection != NULL);
|
||||
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
|
||||
INFO_COLUMN, &info, -1);
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
|
||||
gedit_plugin_info_is_configurable (info));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_manager_set_active (GeditPluginManager *pm,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeModel *model,
|
||||
gboolean active)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
gboolean res = TRUE;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
|
||||
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
if (active)
|
||||
{
|
||||
/* activate the plugin */
|
||||
if (!gedit_plugins_engine_activate_plugin (pm->priv->engine, info)) {
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not activate %s.\n",
|
||||
gedit_plugin_info_get_name (info));
|
||||
|
||||
res = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* deactivate the plugin */
|
||||
if (!gedit_plugins_engine_deactivate_plugin (pm->priv->engine, info)) {
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Could not deactivate %s.\n",
|
||||
gedit_plugin_info_get_name (info));
|
||||
|
||||
res = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_toggle_active (GeditPluginManager *pm,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeModel *model)
|
||||
{
|
||||
gboolean active;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
gtk_tree_model_get (model, iter, ACTIVE_COLUMN, &active, -1);
|
||||
|
||||
active ^= 1;
|
||||
|
||||
plugin_manager_set_active (pm, iter, model, active);
|
||||
}
|
||||
|
||||
static GeditPluginInfo *
|
||||
plugin_manager_get_selected_plugin (GeditPluginManager *pm)
|
||||
{
|
||||
GeditPluginInfo *info = NULL;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_val_if_fail (model != NULL, NULL);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_val_if_fail (selection != NULL, NULL);
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, INFO_COLUMN, &info, -1);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_set_active_all (GeditPluginManager *pm,
|
||||
gboolean active)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
|
||||
|
||||
g_return_if_fail (model != NULL);
|
||||
|
||||
gtk_tree_model_get_iter_first (model, &iter);
|
||||
|
||||
do {
|
||||
plugin_manager_set_active (pm, &iter, model, active);
|
||||
}
|
||||
while (gtk_tree_model_iter_next (model, &iter));
|
||||
}
|
||||
|
||||
/* Callback used as the interactive search comparison function */
|
||||
static gboolean
|
||||
name_search_cb (GtkTreeModel *model,
|
||||
gint column,
|
||||
const gchar *key,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
gchar *normalized_string;
|
||||
gchar *normalized_key;
|
||||
gchar *case_normalized_string;
|
||||
gchar *case_normalized_key;
|
||||
gint key_len;
|
||||
gboolean retval;
|
||||
|
||||
gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
normalized_string = g_utf8_normalize (gedit_plugin_info_get_name (info), -1, G_NORMALIZE_ALL);
|
||||
normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
|
||||
case_normalized_string = g_utf8_casefold (normalized_string, -1);
|
||||
case_normalized_key = g_utf8_casefold (normalized_key, -1);
|
||||
|
||||
key_len = strlen (case_normalized_key);
|
||||
|
||||
/* Oddly enough, this callback must return whether to stop the search
|
||||
* because we found a match, not whether we actually matched.
|
||||
*/
|
||||
retval = (strncmp (case_normalized_key, case_normalized_string, key_len) != 0);
|
||||
|
||||
g_free (normalized_key);
|
||||
g_free (normalized_string);
|
||||
g_free (case_normalized_key);
|
||||
g_free (case_normalized_string);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
enable_plugin_menu_cb (GtkMenu *menu,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_if_fail (model != NULL);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
|
||||
g_return_if_fail (selection != NULL);
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
plugin_manager_toggle_active (pm, &iter, model);
|
||||
}
|
||||
|
||||
static void
|
||||
enable_all_menu_cb (GtkMenu *menu,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
plugin_manager_set_active_all (pm, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
disable_all_menu_cb (GtkMenu *menu,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
plugin_manager_set_active_all (pm, FALSE);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_tree_popup_menu (GeditPluginManager *pm)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
GtkWidget *image;
|
||||
GeditPluginInfo *info;
|
||||
|
||||
info = plugin_manager_get_selected_plugin (pm);
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
|
||||
item = gtk_image_menu_item_new_with_mnemonic (_("_About"));
|
||||
image = gtk_image_new_from_stock (GTK_STOCK_ABOUT,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
|
||||
g_signal_connect (item, "activate",
|
||||
G_CALLBACK (about_button_cb), pm);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_image_menu_item_new_with_mnemonic (_("C_onfigure"));
|
||||
image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES,
|
||||
GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
|
||||
g_signal_connect (item, "activate",
|
||||
G_CALLBACK (configure_button_cb), pm);
|
||||
gtk_widget_set_sensitive (item, gedit_plugin_info_is_configurable (info));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_check_menu_item_new_with_mnemonic (_("A_ctivate"));
|
||||
gtk_widget_set_sensitive (item, gedit_plugin_info_is_available (info));
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
|
||||
gedit_plugin_info_is_active (info));
|
||||
g_signal_connect (item, "toggled",
|
||||
G_CALLBACK (enable_plugin_menu_cb), pm);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_mnemonic (_("Ac_tivate All"));
|
||||
g_signal_connect (item, "activate",
|
||||
G_CALLBACK (enable_all_menu_cb), pm);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_mnemonic (_("_Deactivate All"));
|
||||
g_signal_connect (item, "activate",
|
||||
G_CALLBACK (disable_all_menu_cb), pm);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
gtk_widget_show_all (menu);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
static void
|
||||
tree_popup_menu_detach (GeditPluginManager *pm,
|
||||
GtkMenu *menu)
|
||||
{
|
||||
pm->priv->popup_menu = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
show_tree_popup_menu (GtkTreeView *tree,
|
||||
GeditPluginManager *pm,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
if (pm->priv->popup_menu)
|
||||
gtk_widget_destroy (pm->priv->popup_menu);
|
||||
|
||||
pm->priv->popup_menu = create_tree_popup_menu (pm);
|
||||
|
||||
gtk_menu_attach_to_widget (GTK_MENU (pm->priv->popup_menu),
|
||||
GTK_WIDGET (pm),
|
||||
(GtkMenuDetachFunc) tree_popup_menu_detach);
|
||||
|
||||
if (event != NULL)
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
|
||||
NULL, NULL,
|
||||
event->button, event->time);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
|
||||
gedit_utils_menu_position_under_tree_view, tree,
|
||||
0, gtk_get_current_event_time ());
|
||||
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (pm->priv->popup_menu),
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_press_event_cb (GtkWidget *tree,
|
||||
GdkEventButton *event,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
/* We want the treeview selection to be updated before showing the menu.
|
||||
* This code is evil, thanks to Federico Mena Quintero's black magic.
|
||||
* See: http://mail.mate.org/archives/gtk-devel-list/2006-February/msg00168.html
|
||||
* FIXME: Let's remove it asap.
|
||||
*/
|
||||
|
||||
static gboolean in_press = FALSE;
|
||||
gboolean handled;
|
||||
|
||||
if (in_press)
|
||||
return FALSE; /* we re-entered */
|
||||
|
||||
if (GDK_BUTTON_PRESS != event->type || 3 != event->button)
|
||||
return FALSE; /* let the normal handler run */
|
||||
|
||||
in_press = TRUE;
|
||||
handled = gtk_widget_event (tree, (GdkEvent *) event);
|
||||
in_press = FALSE;
|
||||
|
||||
if (!handled)
|
||||
return FALSE;
|
||||
|
||||
/* The selection is fully updated by now */
|
||||
show_tree_popup_menu (GTK_TREE_VIEW (tree), pm, event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
popup_menu_cb (GtkTreeView *tree,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
show_tree_popup_menu (tree, pm, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
model_name_sort_func (GtkTreeModel *model,
|
||||
GtkTreeIter *iter1,
|
||||
GtkTreeIter *iter2,
|
||||
gpointer user_data)
|
||||
{
|
||||
GeditPluginInfo *info1, *info2;
|
||||
|
||||
gtk_tree_model_get (model, iter1, INFO_COLUMN, &info1, -1);
|
||||
gtk_tree_model_get (model, iter2, INFO_COLUMN, &info2, -1);
|
||||
|
||||
return g_utf8_collate (gedit_plugin_info_get_name (info1),
|
||||
gedit_plugin_info_get_name (info2));
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_manager_construct_tree (GeditPluginManager *pm)
|
||||
{
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *cell;
|
||||
GtkListStore *model;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
model = gtk_list_store_new (N_COLUMNS,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (pm->priv->tree),
|
||||
GTK_TREE_MODEL (model));
|
||||
g_object_unref (model);
|
||||
|
||||
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm->priv->tree), TRUE);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pm->priv->tree), FALSE);
|
||||
|
||||
/* first column */
|
||||
cell = gtk_cell_renderer_toggle_new ();
|
||||
g_object_set (cell, "xpad", 6, NULL);
|
||||
g_signal_connect (cell,
|
||||
"toggled",
|
||||
G_CALLBACK (active_toggled_cb),
|
||||
pm);
|
||||
column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE,
|
||||
cell,
|
||||
"active",
|
||||
ACTIVE_COLUMN,
|
||||
"activatable",
|
||||
AVAILABLE_COLUMN,
|
||||
"sensitive",
|
||||
AVAILABLE_COLUMN,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
|
||||
|
||||
/* second column */
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (column, PLUGIN_MANAGER_NAME_TITLE);
|
||||
gtk_tree_view_column_set_resizable (column, TRUE);
|
||||
|
||||
cell = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, cell, FALSE);
|
||||
g_object_set (cell, "stock-size", GTK_ICON_SIZE_SMALL_TOOLBAR, NULL);
|
||||
gtk_tree_view_column_set_cell_data_func (column, cell,
|
||||
plugin_manager_view_icon_cell_cb,
|
||||
pm, NULL);
|
||||
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, cell, TRUE);
|
||||
g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_tree_view_column_set_cell_data_func (column, cell,
|
||||
plugin_manager_view_info_cell_cb,
|
||||
pm, NULL);
|
||||
|
||||
|
||||
gtk_tree_view_column_set_spacing (column, 6);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
|
||||
|
||||
/* Sort on the plugin names */
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
|
||||
model_name_sort_func,
|
||||
NULL,
|
||||
NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
/* Enable search for our non-string column */
|
||||
gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm->priv->tree),
|
||||
INFO_COLUMN);
|
||||
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm->priv->tree),
|
||||
name_search_cb,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (pm->priv->tree,
|
||||
"cursor_changed",
|
||||
G_CALLBACK (cursor_changed_cb),
|
||||
pm);
|
||||
g_signal_connect (pm->priv->tree,
|
||||
"row_activated",
|
||||
G_CALLBACK (row_activated_cb),
|
||||
pm);
|
||||
|
||||
g_signal_connect (pm->priv->tree,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_press_event_cb),
|
||||
pm);
|
||||
g_signal_connect (pm->priv->tree,
|
||||
"popup-menu",
|
||||
G_CALLBACK (popup_menu_cb),
|
||||
pm);
|
||||
gtk_widget_show (pm->priv->tree);
|
||||
}
|
||||
|
||||
static void
|
||||
plugin_toggled_cb (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info,
|
||||
GeditPluginManager *pm)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean info_found = FALSE;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
{
|
||||
/* There is an item selected: it's probably the one we want! */
|
||||
GeditPluginInfo *tinfo;
|
||||
gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
|
||||
info_found = info == tinfo;
|
||||
}
|
||||
|
||||
if (!info_found)
|
||||
{
|
||||
gtk_tree_model_get_iter_first (model, &iter);
|
||||
|
||||
do
|
||||
{
|
||||
GeditPluginInfo *tinfo;
|
||||
gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
|
||||
info_found = info == tinfo;
|
||||
}
|
||||
while (!info_found && gtk_tree_model_iter_next (model, &iter));
|
||||
}
|
||||
|
||||
if (!info_found)
|
||||
{
|
||||
g_warning ("GeditPluginManager: plugin '%s' not found in the tree model",
|
||||
gedit_plugin_info_get_name (info));
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter, ACTIVE_COLUMN, gedit_plugin_info_is_active (info), -1);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_manager_init (GeditPluginManager *pm)
|
||||
{
|
||||
GtkWidget *label;
|
||||
GtkWidget *viewport;
|
||||
GtkWidget *hbuttonbox;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
pm->priv = GEDIT_PLUGIN_MANAGER_GET_PRIVATE (pm);
|
||||
|
||||
/*
|
||||
* Always we create the manager, firstly we rescan the plugins directory
|
||||
*/
|
||||
gedit_plugins_engine_rescan_plugins (gedit_plugins_engine_get_default ());
|
||||
|
||||
gtk_box_set_spacing (GTK_BOX (pm), 6);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("Active _Plugins:"));
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (pm), label, FALSE, TRUE, 0);
|
||||
|
||||
viewport = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (viewport),
|
||||
GTK_SHADOW_IN);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (pm), viewport, TRUE, TRUE, 0);
|
||||
|
||||
pm->priv->tree = gtk_tree_view_new ();
|
||||
gtk_container_add (GTK_CONTAINER (viewport), pm->priv->tree);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), pm->priv->tree);
|
||||
|
||||
hbuttonbox = gtk_hbutton_box_new ();
|
||||
gtk_box_pack_start (GTK_BOX (pm), hbuttonbox, FALSE, FALSE, 0);
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
|
||||
gtk_box_set_spacing (GTK_BOX (hbuttonbox), 8);
|
||||
|
||||
pm->priv->about_button = gedit_gtk_button_new_with_stock_icon (_("_About Plugin"),
|
||||
GTK_STOCK_ABOUT);
|
||||
gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->about_button);
|
||||
|
||||
pm->priv->configure_button = gedit_gtk_button_new_with_stock_icon (_("C_onfigure Plugin"),
|
||||
GTK_STOCK_PREFERENCES);
|
||||
gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->configure_button);
|
||||
|
||||
/* setup a window of a sane size. */
|
||||
gtk_widget_set_size_request (GTK_WIDGET (viewport), 270, 100);
|
||||
|
||||
g_signal_connect (pm->priv->about_button,
|
||||
"clicked",
|
||||
G_CALLBACK (about_button_cb),
|
||||
pm);
|
||||
g_signal_connect (pm->priv->configure_button,
|
||||
"clicked",
|
||||
G_CALLBACK (configure_button_cb),
|
||||
pm);
|
||||
|
||||
plugin_manager_construct_tree (pm);
|
||||
|
||||
/* get the plugin engine and populate the treeview */
|
||||
pm->priv->engine = gedit_plugins_engine_get_default ();
|
||||
|
||||
g_signal_connect_after (pm->priv->engine,
|
||||
"activate-plugin",
|
||||
G_CALLBACK (plugin_toggled_cb),
|
||||
pm);
|
||||
g_signal_connect_after (pm->priv->engine,
|
||||
"deactivate-plugin",
|
||||
G_CALLBACK (plugin_toggled_cb),
|
||||
pm);
|
||||
|
||||
if (gedit_plugins_engine_get_plugin_list (pm->priv->engine) != NULL)
|
||||
{
|
||||
plugin_manager_populate_lists (pm);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (pm->priv->about_button, FALSE);
|
||||
gtk_widget_set_sensitive (pm->priv->configure_button, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_manager_finalize (GObject *object)
|
||||
{
|
||||
GeditPluginManager *pm = GEDIT_PLUGIN_MANAGER (object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (pm->priv->engine,
|
||||
plugin_toggled_cb,
|
||||
pm);
|
||||
|
||||
if (pm->priv->popup_menu)
|
||||
gtk_widget_destroy (pm->priv->popup_menu);
|
||||
|
||||
G_OBJECT_CLASS (gedit_plugin_manager_parent_class)->finalize (object);
|
||||
|
||||
}
|
||||
|
||||
GtkWidget *gedit_plugin_manager_new (void)
|
||||
{
|
||||
return g_object_new (GEDIT_TYPE_PLUGIN_MANAGER,0);
|
||||
}
|
||||
83
gedit/gedit-plugin-manager.h
Executable file
83
gedit/gedit-plugin-manager.h
Executable file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* gedit-plugin-manager.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGIN_MANAGER_H__
|
||||
#define __GEDIT_PLUGIN_MANAGER_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_PLUGIN_MANAGER (gedit_plugin_manager_get_type())
|
||||
#define GEDIT_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManager))
|
||||
#define GEDIT_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass))
|
||||
#define GEDIT_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN_MANAGER))
|
||||
#define GEDIT_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN_MANAGER))
|
||||
#define GEDIT_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditPluginManagerPrivate GeditPluginManagerPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditPluginManager GeditPluginManager;
|
||||
|
||||
struct _GeditPluginManager
|
||||
{
|
||||
GtkVBox vbox;
|
||||
|
||||
/*< private > */
|
||||
GeditPluginManagerPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditPluginManagerClass GeditPluginManagerClass;
|
||||
|
||||
struct _GeditPluginManagerClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_plugin_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gedit_plugin_manager_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PLUGIN_MANAGER_H__ */
|
||||
334
gedit/gedit-plugin.c
Executable file
334
gedit/gedit-plugin.c
Executable file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* gedit-plugin.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "gedit-plugin.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
/* properties */
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_INSTALL_DIR,
|
||||
PROP_DATA_DIR_NAME,
|
||||
PROP_DATA_DIR
|
||||
};
|
||||
|
||||
typedef struct _GeditPluginPrivate GeditPluginPrivate;
|
||||
|
||||
struct _GeditPluginPrivate
|
||||
{
|
||||
gchar *install_dir;
|
||||
gchar *data_dir_name;
|
||||
};
|
||||
|
||||
#define GEDIT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PLUGIN, GeditPluginPrivate))
|
||||
|
||||
G_DEFINE_TYPE(GeditPlugin, gedit_plugin, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
dummy (GeditPlugin *plugin, GeditWindow *window)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_configure_dialog (GeditPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_configurable (GeditPlugin *plugin)
|
||||
{
|
||||
return (GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog !=
|
||||
create_configure_dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INSTALL_DIR:
|
||||
g_value_take_string (value, gedit_plugin_get_install_dir (GEDIT_PLUGIN (object)));
|
||||
break;
|
||||
case PROP_DATA_DIR:
|
||||
g_value_take_string (value, gedit_plugin_get_data_dir (GEDIT_PLUGIN (object)));
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditPluginPrivate *priv = GEDIT_PLUGIN_GET_PRIVATE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INSTALL_DIR:
|
||||
priv->install_dir = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_DATA_DIR_NAME:
|
||||
priv->data_dir_name = g_value_dup_string (value);
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_finalize (GObject *object)
|
||||
{
|
||||
GeditPluginPrivate *priv = GEDIT_PLUGIN_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->install_dir);
|
||||
g_free (priv->data_dir_name);
|
||||
|
||||
G_OBJECT_CLASS (gedit_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_class_init (GeditPluginClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->activate = dummy;
|
||||
klass->deactivate = dummy;
|
||||
klass->update_ui = dummy;
|
||||
|
||||
klass->create_configure_dialog = create_configure_dialog;
|
||||
klass->is_configurable = is_configurable;
|
||||
|
||||
object_class->get_property = gedit_plugin_get_property;
|
||||
object_class->set_property = gedit_plugin_set_property;
|
||||
object_class->finalize = gedit_plugin_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_INSTALL_DIR,
|
||||
g_param_spec_string ("install-dir",
|
||||
"Install Directory",
|
||||
"The directory where the plugin is installed",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/* the basename of the data dir is set at construction time by the plugin loader
|
||||
* while the full path is constructed on the fly to take into account relocability
|
||||
* that's why we have a writeonly prop and a readonly prop */
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DATA_DIR_NAME,
|
||||
g_param_spec_string ("data-dir-name",
|
||||
"Basename of the data directory",
|
||||
"The basename of the directory where the plugin should look for its data files",
|
||||
NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DATA_DIR,
|
||||
g_param_spec_string ("data-dir",
|
||||
"Data Directory",
|
||||
"The full path of the directory where the plugin should look for its data files",
|
||||
NULL,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugin_init (GeditPlugin *plugin)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_get_install_dir:
|
||||
* @plugin: a #GeditPlugin
|
||||
*
|
||||
* Get the path of the directory where the plugin is installed.
|
||||
*
|
||||
* Return value: a newly allocated string with the path of the
|
||||
* directory where the plugin is installed
|
||||
*/
|
||||
gchar *
|
||||
gedit_plugin_get_install_dir (GeditPlugin *plugin)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
|
||||
|
||||
return g_strdup (GEDIT_PLUGIN_GET_PRIVATE (plugin)->install_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_get_data_dir:
|
||||
* @plugin: a #GeditPlugin
|
||||
*
|
||||
* Get the path of the directory where the plugin should look for
|
||||
* its data files.
|
||||
*
|
||||
* Return value: a newly allocated string with the path of the
|
||||
* directory where the plugin should look for its data files
|
||||
*/
|
||||
gchar *
|
||||
gedit_plugin_get_data_dir (GeditPlugin *plugin)
|
||||
{
|
||||
GeditPluginPrivate *priv;
|
||||
gchar *gedit_lib_dir;
|
||||
gchar *data_dir;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
|
||||
|
||||
priv = GEDIT_PLUGIN_GET_PRIVATE (plugin);
|
||||
|
||||
/* If it's a "user" plugin the data dir is
|
||||
* install_dir/data_dir_name if instead it's a
|
||||
* "system" plugin the data dir is under gedit_data_dir,
|
||||
* so it's under $prefix/share/gedit-2/plugins/data_dir_name
|
||||
* where data_dir_name usually it's the name of the plugin
|
||||
*/
|
||||
gedit_lib_dir = gedit_dirs_get_gedit_lib_dir ();
|
||||
|
||||
/* CHECK: is checking the prefix enough or should we be more
|
||||
* careful about normalizing paths etc? */
|
||||
if (g_str_has_prefix (priv->install_dir, gedit_lib_dir))
|
||||
{
|
||||
gchar *gedit_data_dir;
|
||||
|
||||
gedit_data_dir = gedit_dirs_get_gedit_data_dir ();
|
||||
|
||||
data_dir = g_build_filename (gedit_data_dir,
|
||||
"plugins",
|
||||
priv->data_dir_name,
|
||||
NULL);
|
||||
|
||||
g_free (gedit_data_dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_dir = g_build_filename (priv->install_dir,
|
||||
priv->data_dir_name,
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_free (gedit_lib_dir);
|
||||
|
||||
return data_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_activate:
|
||||
* @plugin: a #GeditPlugin
|
||||
* @window: a #GeditWindow
|
||||
*
|
||||
* Activates the plugin.
|
||||
*/
|
||||
void
|
||||
gedit_plugin_activate (GeditPlugin *plugin,
|
||||
GeditWindow *window)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
GEDIT_PLUGIN_GET_CLASS (plugin)->activate (plugin, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_deactivate:
|
||||
* @plugin: a #GeditPlugin
|
||||
* @window: a #GeditWindow
|
||||
*
|
||||
* Deactivates the plugin.
|
||||
*/
|
||||
void
|
||||
gedit_plugin_deactivate (GeditPlugin *plugin,
|
||||
GeditWindow *window)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
GEDIT_PLUGIN_GET_CLASS (plugin)->deactivate (plugin, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_update_ui:
|
||||
* @plugin: a #GeditPlugin
|
||||
* @window: a #GeditWindow
|
||||
*
|
||||
* Triggers an update of the user interface to take into account state changes
|
||||
* caused by the plugin.
|
||||
*/
|
||||
void
|
||||
gedit_plugin_update_ui (GeditPlugin *plugin,
|
||||
GeditWindow *window)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
GEDIT_PLUGIN_GET_CLASS (plugin)->update_ui (plugin, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_is_configurable:
|
||||
* @plugin: a #GeditPlugin
|
||||
*
|
||||
* Whether the plugin is configurable.
|
||||
*
|
||||
* Returns: TRUE if the plugin is configurable:
|
||||
*/
|
||||
gboolean
|
||||
gedit_plugin_is_configurable (GeditPlugin *plugin)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), FALSE);
|
||||
|
||||
return GEDIT_PLUGIN_GET_CLASS (plugin)->is_configurable (plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* gedit_plugin_create_configure_dialog:
|
||||
* @plugin: a #GeditPlugin
|
||||
*
|
||||
* Creates the configure dialog widget for the plugin.
|
||||
*
|
||||
* Returns: the configure dialog widget for the plugin.
|
||||
*/
|
||||
GtkWidget *
|
||||
gedit_plugin_create_configure_dialog (GeditPlugin *plugin)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
|
||||
|
||||
return GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog (plugin);
|
||||
}
|
||||
240
gedit/gedit-plugin.h
Executable file
240
gedit/gedit-plugin.h
Executable file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* gedit-plugin.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGIN_H__
|
||||
#define __GEDIT_PLUGIN_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <gedit/gedit-window.h>
|
||||
#include <gedit/gedit-debug.h>
|
||||
|
||||
/* TODO: add a .h file that includes all the .h files normally needed to
|
||||
* develop a plugin */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_PLUGIN (gedit_plugin_get_type())
|
||||
#define GEDIT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN, GeditPlugin))
|
||||
#define GEDIT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN, GeditPluginClass))
|
||||
#define GEDIT_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN))
|
||||
#define GEDIT_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN))
|
||||
#define GEDIT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN, GeditPluginClass))
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditPlugin GeditPlugin;
|
||||
|
||||
struct _GeditPlugin
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditPluginClass GeditPluginClass;
|
||||
|
||||
struct _GeditPluginClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Virtual public methods */
|
||||
|
||||
void (*activate) (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
void (*deactivate) (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
|
||||
void (*update_ui) (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
|
||||
GtkWidget *(*create_configure_dialog)
|
||||
(GeditPlugin *plugin);
|
||||
|
||||
/* Plugins should not override this, it's handled automatically by
|
||||
the GeditPluginClass */
|
||||
gboolean (*is_configurable)
|
||||
(GeditPlugin *plugin);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gedit_reserved1) (void);
|
||||
void (*_gedit_reserved2) (void);
|
||||
void (*_gedit_reserved3) (void);
|
||||
void (*_gedit_reserved4) (void);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_plugin_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gchar *gedit_plugin_get_install_dir (GeditPlugin *plugin);
|
||||
gchar *gedit_plugin_get_data_dir (GeditPlugin *plugin);
|
||||
|
||||
void gedit_plugin_activate (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
void gedit_plugin_deactivate (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
|
||||
void gedit_plugin_update_ui (GeditPlugin *plugin,
|
||||
GeditWindow *window);
|
||||
|
||||
gboolean gedit_plugin_is_configurable (GeditPlugin *plugin);
|
||||
GtkWidget *gedit_plugin_create_configure_dialog
|
||||
(GeditPlugin *plugin);
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE):
|
||||
*
|
||||
* Utility macro used to register plugins with additional code.
|
||||
*/
|
||||
#define GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE) \
|
||||
G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginName, \
|
||||
plugin_name, \
|
||||
GEDIT_TYPE_PLUGIN, \
|
||||
0, \
|
||||
GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
|
||||
CODE) \
|
||||
\
|
||||
/* This is not very nice, but G_DEFINE_DYNAMIC wants it and our old macro \
|
||||
* did not support it */ \
|
||||
static void \
|
||||
plugin_name##_class_finalize (PluginName##Class *klass) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
\
|
||||
G_MODULE_EXPORT GType \
|
||||
register_gedit_plugin (GTypeModule *type_module) \
|
||||
{ \
|
||||
plugin_name##_register_type (type_module); \
|
||||
\
|
||||
return plugin_name##_get_type(); \
|
||||
}
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name):
|
||||
*
|
||||
* Utility macro used to register plugins.
|
||||
*/
|
||||
#define GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name) \
|
||||
GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, ;)
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE):
|
||||
*
|
||||
* Utility macro used to register gobject types in plugins with additional code.
|
||||
*
|
||||
* Deprecated: use G_DEFINE_DYNAMIC_TYPE_EXTENDED instead
|
||||
*/
|
||||
#define GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE) \
|
||||
\
|
||||
static GType g_define_type_id = 0; \
|
||||
\
|
||||
GType \
|
||||
object_name##_get_type (void) \
|
||||
{ \
|
||||
return g_define_type_id; \
|
||||
} \
|
||||
\
|
||||
static void object_name##_init (ObjectName *self); \
|
||||
static void object_name##_class_init (ObjectName##Class *klass); \
|
||||
static gpointer object_name##_parent_class = NULL; \
|
||||
static void object_name##_class_intern_init (gpointer klass) \
|
||||
{ \
|
||||
object_name##_parent_class = g_type_class_peek_parent (klass); \
|
||||
object_name##_class_init ((ObjectName##Class *) klass); \
|
||||
} \
|
||||
\
|
||||
GType \
|
||||
object_name##_register_type (GTypeModule *type_module) \
|
||||
{ \
|
||||
GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
|
||||
static const GTypeInfo our_info = \
|
||||
{ \
|
||||
sizeof (ObjectName##Class), \
|
||||
NULL, /* base_init */ \
|
||||
NULL, /* base_finalize */ \
|
||||
(GClassInitFunc) object_name##_class_intern_init, \
|
||||
NULL, \
|
||||
NULL, /* class_data */ \
|
||||
sizeof (ObjectName), \
|
||||
0, /* n_preallocs */ \
|
||||
(GInstanceInitFunc) object_name##_init \
|
||||
}; \
|
||||
\
|
||||
g_define_type_id = g_type_module_register_type (type_module, \
|
||||
PARENT_TYPE, \
|
||||
#ObjectName, \
|
||||
&our_info, \
|
||||
0); \
|
||||
\
|
||||
CODE \
|
||||
\
|
||||
return g_define_type_id; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE):
|
||||
*
|
||||
* Utility macro used to register gobject types in plugins.
|
||||
*
|
||||
* Deprecated: use G_DEFINE_DYNAMIC instead
|
||||
*/
|
||||
#define GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE) \
|
||||
GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, ;)
|
||||
|
||||
/**
|
||||
* GEDIT_PLUGIN_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
|
||||
*
|
||||
* Utility macro used to register interfaces for gobject types in plugins.
|
||||
*/
|
||||
#define GEDIT_PLUGIN_IMPLEMENT_INTERFACE(object_name, TYPE_IFACE, iface_init) \
|
||||
const GInterfaceInfo object_name##_interface_info = \
|
||||
{ \
|
||||
(GInterfaceInitFunc) iface_init, \
|
||||
NULL, \
|
||||
NULL \
|
||||
}; \
|
||||
\
|
||||
g_type_module_add_interface (type_module, \
|
||||
g_define_type_id, \
|
||||
TYPE_IFACE, \
|
||||
&object_name##_interface_info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PLUGIN_H__ */
|
||||
861
gedit/gedit-plugins-engine.c
Executable file
861
gedit/gedit-plugins-engine.c
Executable file
@@ -0,0 +1,861 @@
|
||||
/*
|
||||
* gedit-plugins-engine.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gedit-plugins-engine.h"
|
||||
#include "gedit-plugin-info-priv.h"
|
||||
#include "gedit-plugin.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-app.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-plugin-loader.h"
|
||||
#include "gedit-object-module.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
#define GEDIT_PLUGINS_ENGINE_BASE_KEY "/apps/gedit-2/plugins"
|
||||
#define GEDIT_PLUGINS_ENGINE_KEY GEDIT_PLUGINS_ENGINE_BASE_KEY "/active-plugins"
|
||||
|
||||
#define PLUGIN_EXT ".gedit-plugin"
|
||||
#define LOADER_EXT G_MODULE_SUFFIX
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeditPluginLoader *loader;
|
||||
GeditObjectModule *module;
|
||||
} LoaderInfo;
|
||||
|
||||
/* Signals */
|
||||
enum
|
||||
{
|
||||
ACTIVATE_PLUGIN,
|
||||
DEACTIVATE_PLUGIN,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(GeditPluginsEngine, gedit_plugins_engine, G_TYPE_OBJECT)
|
||||
|
||||
struct _GeditPluginsEnginePrivate
|
||||
{
|
||||
GList *plugin_list;
|
||||
GHashTable *loaders;
|
||||
|
||||
gboolean activate_from_prefs;
|
||||
};
|
||||
|
||||
GeditPluginsEngine *default_engine = NULL;
|
||||
|
||||
static void gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
static void gedit_plugins_engine_deactivate_plugin_real (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
|
||||
typedef gboolean (*LoadDirCallback)(GeditPluginsEngine *engine, const gchar *filename, gpointer userdata);
|
||||
|
||||
static gboolean
|
||||
load_dir_real (GeditPluginsEngine *engine,
|
||||
const gchar *dir,
|
||||
const gchar *suffix,
|
||||
LoadDirCallback callback,
|
||||
gpointer userdata)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GDir *d;
|
||||
const gchar *dirent;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
g_return_val_if_fail (dir != NULL, TRUE);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir);
|
||||
|
||||
d = g_dir_open (dir, 0, &error);
|
||||
if (!d)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while ((dirent = g_dir_read_name (d)))
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
if (!g_str_has_suffix (dirent, suffix))
|
||||
continue;
|
||||
|
||||
filename = g_build_filename (dir, dirent, NULL);
|
||||
|
||||
ret = callback (engine, filename, userdata);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
||||
g_dir_close (d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_plugin_info (GeditPluginsEngine *engine,
|
||||
const gchar *filename,
|
||||
gpointer userdata)
|
||||
{
|
||||
GeditPluginInfo *info;
|
||||
|
||||
info = _gedit_plugin_info_new (filename);
|
||||
|
||||
if (info == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* If a plugin with this name has already been loaded
|
||||
* drop this one (user plugins override system plugins) */
|
||||
if (gedit_plugins_engine_get_plugin_info (engine, gedit_plugin_info_get_module_name (info)) != NULL)
|
||||
{
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Two or more plugins named '%s'. "
|
||||
"Only the first will be considered.\n",
|
||||
gedit_plugin_info_get_module_name (info));
|
||||
|
||||
_gedit_plugin_info_unref (info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
engine->priv->plugin_list = g_list_prepend (engine->priv->plugin_list, info);
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_all_plugins (GeditPluginsEngine *engine)
|
||||
{
|
||||
gchar *plugin_dir;
|
||||
const gchar *pdirs_env = NULL;
|
||||
|
||||
/* load user plugins */
|
||||
plugin_dir = gedit_dirs_get_user_plugins_dir ();
|
||||
if (g_file_test (plugin_dir, G_FILE_TEST_IS_DIR))
|
||||
{
|
||||
load_dir_real (engine,
|
||||
plugin_dir,
|
||||
PLUGIN_EXT,
|
||||
load_plugin_info,
|
||||
NULL);
|
||||
|
||||
}
|
||||
g_free (plugin_dir);
|
||||
|
||||
/* load system plugins */
|
||||
pdirs_env = g_getenv ("GEDIT_PLUGINS_PATH");
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "GEDIT_PLUGINS_PATH=%s", pdirs_env);
|
||||
|
||||
if (pdirs_env != NULL)
|
||||
{
|
||||
gchar **pdirs;
|
||||
gint i;
|
||||
|
||||
pdirs = g_strsplit (pdirs_env, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
|
||||
for (i = 0; pdirs[i] != NULL; i++)
|
||||
{
|
||||
if (!load_dir_real (engine,
|
||||
pdirs[i],
|
||||
PLUGIN_EXT,
|
||||
load_plugin_info,
|
||||
NULL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (pdirs);
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_dir = gedit_dirs_get_gedit_plugins_dir ();
|
||||
|
||||
load_dir_real (engine,
|
||||
plugin_dir,
|
||||
PLUGIN_EXT,
|
||||
load_plugin_info,
|
||||
NULL);
|
||||
|
||||
g_free (plugin_dir);
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
hash_lowercase (gconstpointer data)
|
||||
{
|
||||
gchar *lowercase;
|
||||
guint ret;
|
||||
|
||||
lowercase = g_ascii_strdown ((const gchar *)data, -1);
|
||||
ret = g_str_hash (lowercase);
|
||||
g_free (lowercase);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
equal_lowercase (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
return g_ascii_strcasecmp ((const gchar *)a, (const gchar *)b) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
loader_destroy (LoaderInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (info->loader)
|
||||
g_object_unref (info->loader);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
add_loader (GeditPluginsEngine *engine,
|
||||
const gchar *loader_id,
|
||||
GeditObjectModule *module)
|
||||
{
|
||||
LoaderInfo *info;
|
||||
|
||||
info = g_new (LoaderInfo, 1);
|
||||
info->loader = NULL;
|
||||
info->module = module;
|
||||
|
||||
g_hash_table_insert (engine->priv->loaders, g_strdup (loader_id), info);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugins_engine_init (GeditPluginsEngine *engine)
|
||||
{
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
if (!g_module_supported ())
|
||||
{
|
||||
g_warning ("gedit is not able to initialize the plugins engine.");
|
||||
return;
|
||||
}
|
||||
|
||||
engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine,
|
||||
GEDIT_TYPE_PLUGINS_ENGINE,
|
||||
GeditPluginsEnginePrivate);
|
||||
|
||||
load_all_plugins (engine);
|
||||
|
||||
/* make sure that the first reactivation will read active plugins
|
||||
from the prefs */
|
||||
engine->priv->activate_from_prefs = TRUE;
|
||||
|
||||
/* mapping from loadername -> loader object */
|
||||
engine->priv->loaders = g_hash_table_new_full (hash_lowercase,
|
||||
equal_lowercase,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)loader_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
loader_garbage_collect (const char *id, LoaderInfo *info)
|
||||
{
|
||||
if (info->loader)
|
||||
gedit_plugin_loader_garbage_collect (info->loader);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_garbage_collect (GeditPluginsEngine *engine)
|
||||
{
|
||||
g_hash_table_foreach (engine->priv->loaders,
|
||||
(GHFunc) loader_garbage_collect,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugins_engine_finalize (GObject *object)
|
||||
{
|
||||
GeditPluginsEngine *engine = GEDIT_PLUGINS_ENGINE (object);
|
||||
GList *item;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
/* Firs deactivate all plugins */
|
||||
for (item = engine->priv->plugin_list; item; item = item->next)
|
||||
{
|
||||
GeditPluginInfo *info = GEDIT_PLUGIN_INFO (item->data);
|
||||
|
||||
if (gedit_plugin_info_is_active (info))
|
||||
gedit_plugins_engine_deactivate_plugin_real (engine, info);
|
||||
}
|
||||
|
||||
/* unref the loaders */
|
||||
g_hash_table_destroy (engine->priv->loaders);
|
||||
|
||||
/* and finally free the infos */
|
||||
for (item = engine->priv->plugin_list; item; item = item->next)
|
||||
{
|
||||
GeditPluginInfo *info = GEDIT_PLUGIN_INFO (item->data);
|
||||
|
||||
_gedit_plugin_info_unref (info);
|
||||
}
|
||||
|
||||
g_list_free (engine->priv->plugin_list);
|
||||
|
||||
G_OBJECT_CLASS (gedit_plugins_engine_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugins_engine_class_init (GeditPluginsEngineClass *klass)
|
||||
{
|
||||
GType the_type = G_TYPE_FROM_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gedit_plugins_engine_finalize;
|
||||
klass->activate_plugin = gedit_plugins_engine_activate_plugin_real;
|
||||
klass->deactivate_plugin = gedit_plugins_engine_deactivate_plugin_real;
|
||||
|
||||
signals[ACTIVATE_PLUGIN] =
|
||||
g_signal_new ("activate-plugin",
|
||||
the_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditPluginsEngineClass, activate_plugin),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__BOXED,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
signals[DEACTIVATE_PLUGIN] =
|
||||
g_signal_new ("deactivate-plugin",
|
||||
the_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditPluginsEngineClass, deactivate_plugin),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__BOXED,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GeditPluginsEnginePrivate));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_loader (GeditPluginsEngine *engine,
|
||||
const gchar *filename,
|
||||
gpointer data)
|
||||
{
|
||||
GeditObjectModule *module;
|
||||
gchar *base;
|
||||
gchar *path;
|
||||
const gchar *id;
|
||||
GType type;
|
||||
|
||||
/* try to load in the module */
|
||||
path = g_path_get_dirname (filename);
|
||||
base = g_path_get_basename (filename);
|
||||
|
||||
/* for now they are all resident */
|
||||
module = gedit_object_module_new (base,
|
||||
path,
|
||||
"register_gedit_plugin_loader",
|
||||
TRUE);
|
||||
|
||||
g_free (base);
|
||||
g_free (path);
|
||||
|
||||
/* make sure to load the type definition */
|
||||
if (!g_type_module_use (G_TYPE_MODULE (module)))
|
||||
{
|
||||
g_object_unref (module);
|
||||
g_warning ("Plugin loader module `%s' could not be loaded", filename);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* get the exported type and check the name as exported by the
|
||||
* loader interface */
|
||||
type = gedit_object_module_get_object_type (module);
|
||||
id = gedit_plugin_loader_type_get_id (type);
|
||||
|
||||
add_loader (engine, id, module);
|
||||
g_type_module_unuse (G_TYPE_MODULE (module));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_loader (LoaderInfo *info)
|
||||
{
|
||||
if (info->loader == NULL && info->module != NULL)
|
||||
{
|
||||
/* create a new loader object */
|
||||
GeditPluginLoader *loader;
|
||||
loader = (GeditPluginLoader *)gedit_object_module_new_object (info->module, NULL);
|
||||
|
||||
if (loader == NULL || !GEDIT_IS_PLUGIN_LOADER (loader))
|
||||
{
|
||||
g_warning ("Loader object is not a valid GeditPluginLoader instance");
|
||||
|
||||
if (loader != NULL && G_IS_OBJECT (loader))
|
||||
g_object_unref (loader);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->loader = loader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GeditPluginLoader *
|
||||
get_plugin_loader (GeditPluginsEngine *engine, GeditPluginInfo *info)
|
||||
{
|
||||
const gchar *loader_id;
|
||||
LoaderInfo *loader_info;
|
||||
|
||||
loader_id = info->loader;
|
||||
|
||||
loader_info = (LoaderInfo *)g_hash_table_lookup (
|
||||
engine->priv->loaders,
|
||||
loader_id);
|
||||
|
||||
if (loader_info == NULL)
|
||||
{
|
||||
gchar *loader_dir;
|
||||
|
||||
loader_dir = gedit_dirs_get_gedit_plugin_loaders_dir ();
|
||||
|
||||
/* loader could not be found in the hash, try to find it by
|
||||
scanning */
|
||||
load_dir_real (engine,
|
||||
loader_dir,
|
||||
LOADER_EXT,
|
||||
(LoadDirCallback)load_loader,
|
||||
NULL);
|
||||
g_free (loader_dir);
|
||||
|
||||
loader_info = (LoaderInfo *)g_hash_table_lookup (
|
||||
engine->priv->loaders,
|
||||
loader_id);
|
||||
}
|
||||
|
||||
if (loader_info == NULL)
|
||||
{
|
||||
/* cache non-existent so we don't scan again */
|
||||
add_loader (engine, loader_id, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ensure_loader (loader_info);
|
||||
return loader_info->loader;
|
||||
}
|
||||
|
||||
GeditPluginsEngine *
|
||||
gedit_plugins_engine_get_default (void)
|
||||
{
|
||||
if (default_engine != NULL)
|
||||
return default_engine;
|
||||
|
||||
default_engine = GEDIT_PLUGINS_ENGINE (g_object_new (GEDIT_TYPE_PLUGINS_ENGINE, NULL));
|
||||
g_object_add_weak_pointer (G_OBJECT (default_engine),
|
||||
(gpointer) &default_engine);
|
||||
return default_engine;
|
||||
}
|
||||
|
||||
const GList *
|
||||
gedit_plugins_engine_get_plugin_list (GeditPluginsEngine *engine)
|
||||
{
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
return engine->priv->plugin_list;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_plugin_info_and_name (GeditPluginInfo *info,
|
||||
const gchar *module_name)
|
||||
{
|
||||
return strcmp (gedit_plugin_info_get_module_name (info), module_name);
|
||||
}
|
||||
|
||||
GeditPluginInfo *
|
||||
gedit_plugins_engine_get_plugin_info (GeditPluginsEngine *engine,
|
||||
const gchar *name)
|
||||
{
|
||||
GList *l = g_list_find_custom (engine->priv->plugin_list,
|
||||
name,
|
||||
(GCompareFunc) compare_plugin_info_and_name);
|
||||
|
||||
return l == NULL ? NULL : (GeditPluginInfo *) l->data;
|
||||
}
|
||||
|
||||
static void
|
||||
save_active_plugin_list (GeditPluginsEngine *engine)
|
||||
{
|
||||
GSList *active_plugins = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = engine->priv->plugin_list; l != NULL; l = l->next)
|
||||
{
|
||||
GeditPluginInfo *info = (GeditPluginInfo *) l->data;
|
||||
|
||||
if (gedit_plugin_info_is_active (info))
|
||||
{
|
||||
active_plugins = g_slist_prepend (active_plugins,
|
||||
(gpointer)gedit_plugin_info_get_module_name (info));
|
||||
}
|
||||
}
|
||||
|
||||
gedit_prefs_manager_set_active_plugins (active_plugins);
|
||||
|
||||
g_slist_free (active_plugins);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
GeditPluginLoader *loader;
|
||||
gchar *path;
|
||||
|
||||
if (gedit_plugin_info_is_active (info))
|
||||
return TRUE;
|
||||
|
||||
if (!gedit_plugin_info_is_available (info))
|
||||
return FALSE;
|
||||
|
||||
loader = get_plugin_loader (engine, info);
|
||||
|
||||
if (loader == NULL)
|
||||
{
|
||||
g_warning ("Could not find loader `%s' for plugin `%s'", info->loader, info->name);
|
||||
info->available = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
path = g_path_get_dirname (info->file);
|
||||
g_return_val_if_fail (path != NULL, FALSE);
|
||||
|
||||
info->plugin = gedit_plugin_loader_load (loader, info, path);
|
||||
|
||||
g_free (path);
|
||||
|
||||
if (info->plugin == NULL)
|
||||
{
|
||||
g_warning ("Error loading plugin '%s'", info->name);
|
||||
info->available = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
const GList *wins;
|
||||
|
||||
if (!load_plugin (engine, info))
|
||||
return;
|
||||
|
||||
for (wins = gedit_app_get_windows (gedit_app_get_default ());
|
||||
wins != NULL;
|
||||
wins = wins->next)
|
||||
{
|
||||
gedit_plugin_activate (info->plugin, GEDIT_WINDOW (wins->data));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_plugins_engine_activate_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
if (!gedit_plugin_info_is_available (info))
|
||||
return FALSE;
|
||||
|
||||
if (gedit_plugin_info_is_active (info))
|
||||
return TRUE;
|
||||
|
||||
g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
|
||||
|
||||
if (gedit_plugin_info_is_active (info))
|
||||
save_active_plugin_list (engine);
|
||||
|
||||
return gedit_plugin_info_is_active (info);
|
||||
}
|
||||
|
||||
static void
|
||||
call_plugin_deactivate (GeditPlugin *plugin,
|
||||
GeditWindow *window)
|
||||
{
|
||||
gedit_plugin_deactivate (plugin, window);
|
||||
|
||||
/* ensure update of ui manager, because we suspect it does something
|
||||
with expected static strings in the type module (when unloaded the
|
||||
strings don't exist anymore, and ui manager updates in an idle
|
||||
func) */
|
||||
gtk_ui_manager_ensure_update (gedit_window_get_ui_manager (window));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_plugins_engine_deactivate_plugin_real (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
const GList *wins;
|
||||
GeditPluginLoader *loader;
|
||||
|
||||
if (!gedit_plugin_info_is_active (info) ||
|
||||
!gedit_plugin_info_is_available (info))
|
||||
return;
|
||||
|
||||
for (wins = gedit_app_get_windows (gedit_app_get_default ());
|
||||
wins != NULL;
|
||||
wins = wins->next)
|
||||
{
|
||||
call_plugin_deactivate (info->plugin, GEDIT_WINDOW (wins->data));
|
||||
}
|
||||
|
||||
/* first unref the plugin (the loader still has one) */
|
||||
g_object_unref (info->plugin);
|
||||
|
||||
/* find the loader and tell it to gc and unload the plugin */
|
||||
loader = get_plugin_loader (engine, info);
|
||||
|
||||
gedit_plugin_loader_garbage_collect (loader);
|
||||
gedit_plugin_loader_unload (loader, info);
|
||||
|
||||
info->plugin = NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gedit_plugins_engine_deactivate_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info)
|
||||
{
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
if (!gedit_plugin_info_is_active (info))
|
||||
return TRUE;
|
||||
|
||||
g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
|
||||
if (!gedit_plugin_info_is_active (info))
|
||||
save_active_plugin_list (engine);
|
||||
|
||||
return !gedit_plugin_info_is_active (info);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_activate_plugins (GeditPluginsEngine *engine,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GSList *active_plugins = NULL;
|
||||
GList *pl;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
/* the first time, we get the 'active' plugins from mateconf */
|
||||
if (engine->priv->activate_from_prefs)
|
||||
{
|
||||
active_plugins = gedit_prefs_manager_get_active_plugins ();
|
||||
}
|
||||
|
||||
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
|
||||
{
|
||||
GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
|
||||
|
||||
if (engine->priv->activate_from_prefs &&
|
||||
g_slist_find_custom (active_plugins,
|
||||
gedit_plugin_info_get_module_name (info),
|
||||
(GCompareFunc)strcmp) == NULL)
|
||||
continue;
|
||||
|
||||
/* If plugin is not active, don't try to activate/load it */
|
||||
if (!engine->priv->activate_from_prefs &&
|
||||
!gedit_plugin_info_is_active (info))
|
||||
continue;
|
||||
|
||||
if (load_plugin (engine, info))
|
||||
gedit_plugin_activate (info->plugin,
|
||||
window);
|
||||
}
|
||||
|
||||
if (engine->priv->activate_from_prefs)
|
||||
{
|
||||
g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
|
||||
g_slist_free (active_plugins);
|
||||
engine->priv->activate_from_prefs = FALSE;
|
||||
}
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "End");
|
||||
|
||||
/* also call update_ui after activation */
|
||||
gedit_plugins_engine_update_plugins_ui (engine, window);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_deactivate_plugins (GeditPluginsEngine *engine,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GList *pl;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
|
||||
{
|
||||
GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
|
||||
|
||||
/* check if the plugin is actually active */
|
||||
if (!gedit_plugin_info_is_active (info))
|
||||
continue;
|
||||
|
||||
/* call deactivate for the plugin for this window */
|
||||
gedit_plugin_deactivate (info->plugin, window);
|
||||
}
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "End");
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_update_plugins_ui (GeditPluginsEngine *engine,
|
||||
GeditWindow *window)
|
||||
{
|
||||
GList *pl;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
|
||||
g_return_if_fail (GEDIT_IS_WINDOW (window));
|
||||
|
||||
/* call update_ui for all active plugins */
|
||||
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
|
||||
{
|
||||
GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
|
||||
|
||||
if (!gedit_plugin_info_is_active (info))
|
||||
continue;
|
||||
|
||||
gedit_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name);
|
||||
gedit_plugin_update_ui (info->plugin, window);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_configure_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info,
|
||||
GtkWindow *parent)
|
||||
{
|
||||
GtkWidget *conf_dlg;
|
||||
|
||||
GtkWindowGroup *wg;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
conf_dlg = gedit_plugin_create_configure_dialog (info->plugin);
|
||||
g_return_if_fail (conf_dlg != NULL);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (conf_dlg),
|
||||
parent);
|
||||
|
||||
wg = gtk_window_get_group (parent);
|
||||
if (wg == NULL)
|
||||
{
|
||||
wg = gtk_window_group_new ();
|
||||
gtk_window_group_add_window (wg, parent);
|
||||
}
|
||||
|
||||
gtk_window_group_add_window (wg,
|
||||
GTK_WINDOW (conf_dlg));
|
||||
|
||||
gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE);
|
||||
gtk_widget_show (conf_dlg);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_active_plugins_changed (GeditPluginsEngine *engine)
|
||||
{
|
||||
gboolean to_activate;
|
||||
GSList *active_plugins;
|
||||
GList *pl;
|
||||
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
active_plugins = gedit_prefs_manager_get_active_plugins ();
|
||||
|
||||
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
|
||||
{
|
||||
GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
|
||||
|
||||
if (!gedit_plugin_info_is_available (info))
|
||||
continue;
|
||||
|
||||
to_activate = (g_slist_find_custom (active_plugins,
|
||||
gedit_plugin_info_get_module_name (info),
|
||||
(GCompareFunc)strcmp) != NULL);
|
||||
|
||||
if (!gedit_plugin_info_is_active (info) && to_activate)
|
||||
g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
|
||||
else if (gedit_plugin_info_is_active (info) && !to_activate)
|
||||
g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
|
||||
}
|
||||
|
||||
g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
|
||||
g_slist_free (active_plugins);
|
||||
}
|
||||
|
||||
void
|
||||
gedit_plugins_engine_rescan_plugins (GeditPluginsEngine *engine)
|
||||
{
|
||||
gedit_debug (DEBUG_PLUGINS);
|
||||
|
||||
load_all_plugins (engine);
|
||||
}
|
||||
107
gedit/gedit-plugins-engine.h
Executable file
107
gedit/gedit-plugins-engine.h
Executable file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* gedit-plugins-engine.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 - Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PLUGINS_ENGINE_H__
|
||||
#define __GEDIT_PLUGINS_ENGINE_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include "gedit-window.h"
|
||||
#include "gedit-plugin-info.h"
|
||||
#include "gedit-plugin.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEDIT_TYPE_PLUGINS_ENGINE (gedit_plugins_engine_get_type ())
|
||||
#define GEDIT_PLUGINS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGINS_ENGINE, GeditPluginsEngine))
|
||||
#define GEDIT_PLUGINS_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGINS_ENGINE, GeditPluginsEngineClass))
|
||||
#define GEDIT_IS_PLUGINS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGINS_ENGINE))
|
||||
#define GEDIT_IS_PLUGINS_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGINS_ENGINE))
|
||||
#define GEDIT_PLUGINS_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGINS_ENGINE, GeditPluginsEngineClass))
|
||||
|
||||
typedef struct _GeditPluginsEngine GeditPluginsEngine;
|
||||
typedef struct _GeditPluginsEnginePrivate GeditPluginsEnginePrivate;
|
||||
|
||||
struct _GeditPluginsEngine
|
||||
{
|
||||
GObject parent;
|
||||
GeditPluginsEnginePrivate *priv;
|
||||
};
|
||||
|
||||
typedef struct _GeditPluginsEngineClass GeditPluginsEngineClass;
|
||||
|
||||
struct _GeditPluginsEngineClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* activate_plugin) (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
|
||||
void (* deactivate_plugin) (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
};
|
||||
|
||||
GType gedit_plugins_engine_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditPluginsEngine *gedit_plugins_engine_get_default (void);
|
||||
|
||||
void gedit_plugins_engine_garbage_collect (GeditPluginsEngine *engine);
|
||||
|
||||
const GList *gedit_plugins_engine_get_plugin_list (GeditPluginsEngine *engine);
|
||||
|
||||
GeditPluginInfo *gedit_plugins_engine_get_plugin_info (GeditPluginsEngine *engine,
|
||||
const gchar *name);
|
||||
|
||||
/* plugin load and unloading (overall, for all windows) */
|
||||
gboolean gedit_plugins_engine_activate_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
gboolean gedit_plugins_engine_deactivate_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info);
|
||||
|
||||
void gedit_plugins_engine_configure_plugin (GeditPluginsEngine *engine,
|
||||
GeditPluginInfo *info,
|
||||
GtkWindow *parent);
|
||||
|
||||
/* plugin activation/deactivation per window, private to GeditWindow */
|
||||
void gedit_plugins_engine_activate_plugins (GeditPluginsEngine *engine,
|
||||
GeditWindow *window);
|
||||
void gedit_plugins_engine_deactivate_plugins (GeditPluginsEngine *engine,
|
||||
GeditWindow *window);
|
||||
void gedit_plugins_engine_update_plugins_ui (GeditPluginsEngine *engine,
|
||||
GeditWindow *window);
|
||||
|
||||
/* private for mateconf notification */
|
||||
void gedit_plugins_engine_active_plugins_changed
|
||||
(GeditPluginsEngine *engine);
|
||||
|
||||
void gedit_plugins_engine_rescan_plugins (GeditPluginsEngine *engine);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PLUGINS_ENGINE_H__ */
|
||||
1620
gedit/gedit-prefs-manager-app.c
Executable file
1620
gedit/gedit-prefs-manager-app.c
Executable file
File diff suppressed because it is too large
Load Diff
84
gedit/gedit-prefs-manager-app.h
Executable file
84
gedit/gedit-prefs-manager-app.h
Executable file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* gedit-prefs-manager-app.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002-2005 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PREFS_MANAGER_APP_H__
|
||||
#define __GEDIT_PREFS_MANAGER_APP_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gedit/gedit-prefs-manager.h>
|
||||
|
||||
/** LIFE CYCLE MANAGEMENT FUNCTIONS **/
|
||||
|
||||
gboolean gedit_prefs_manager_app_init (void);
|
||||
|
||||
/* This function must be called before exiting gedit */
|
||||
void gedit_prefs_manager_app_shutdown (void);
|
||||
|
||||
|
||||
/* Window state */
|
||||
gint gedit_prefs_manager_get_window_state (void);
|
||||
void gedit_prefs_manager_set_window_state (gint ws);
|
||||
gboolean gedit_prefs_manager_window_state_can_set (void);
|
||||
|
||||
/* Window size */
|
||||
void gedit_prefs_manager_get_window_size (gint *width,
|
||||
gint *height);
|
||||
void gedit_prefs_manager_get_default_window_size (gint *width,
|
||||
gint *height);
|
||||
void gedit_prefs_manager_set_window_size (gint width,
|
||||
gint height);
|
||||
gboolean gedit_prefs_manager_window_size_can_set (void);
|
||||
|
||||
/* Side panel */
|
||||
gint gedit_prefs_manager_get_side_panel_size (void);
|
||||
gint gedit_prefs_manager_get_default_side_panel_size(void);
|
||||
void gedit_prefs_manager_set_side_panel_size (gint ps);
|
||||
gboolean gedit_prefs_manager_side_panel_size_can_set (void);
|
||||
gint gedit_prefs_manager_get_side_panel_active_page (void);
|
||||
void gedit_prefs_manager_set_side_panel_active_page (gint id);
|
||||
gboolean gedit_prefs_manager_side_panel_active_page_can_set (void);
|
||||
|
||||
/* Bottom panel */
|
||||
gint gedit_prefs_manager_get_bottom_panel_size (void);
|
||||
gint gedit_prefs_manager_get_default_bottom_panel_size(void);
|
||||
void gedit_prefs_manager_set_bottom_panel_size (gint ps);
|
||||
gboolean gedit_prefs_manager_bottom_panel_size_can_set (void);
|
||||
gint gedit_prefs_manager_get_bottom_panel_active_page (void);
|
||||
void gedit_prefs_manager_set_bottom_panel_active_page (gint id);
|
||||
gboolean gedit_prefs_manager_bottom_panel_active_page_can_set (void);
|
||||
|
||||
/* File filter */
|
||||
gint gedit_prefs_manager_get_active_file_filter (void);
|
||||
void gedit_prefs_manager_set_active_file_filter (gint id);
|
||||
gboolean gedit_prefs_manager_active_file_filter_can_set (void);
|
||||
|
||||
|
||||
#endif /* __GEDIT_PREFS_MANAGER_APP_H__ */
|
||||
45
gedit/gedit-prefs-manager-private.h
Executable file
45
gedit/gedit-prefs-manager-private.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-prefs-manager-private.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PREFS_MANAGER_PRIVATE_H__
|
||||
#define __GEDIT_PREFS_MANAGER_PRIVATE_H__
|
||||
|
||||
#include <mateconf/mateconf-client.h>
|
||||
|
||||
typedef struct _GeditPrefsManager GeditPrefsManager;
|
||||
|
||||
struct _GeditPrefsManager {
|
||||
MateConfClient *mateconf_client;
|
||||
};
|
||||
|
||||
extern GeditPrefsManager *gedit_prefs_manager;
|
||||
|
||||
#endif /* __GEDIT_PREFS_MANAGER_PRIVATE_H__ */
|
||||
|
||||
|
||||
1241
gedit/gedit-prefs-manager.c
Executable file
1241
gedit/gedit-prefs-manager.c
Executable file
File diff suppressed because it is too large
Load Diff
423
gedit/gedit-prefs-manager.h
Executable file
423
gedit/gedit-prefs-manager.h
Executable file
@@ -0,0 +1,423 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gedit-prefs-manager.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PREFS_MANAGER_H__
|
||||
#define __GEDIT_PREFS_MANAGER_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include <gtksourceview/gtksourceview.h>
|
||||
#include "gedit-app.h"
|
||||
|
||||
#define GEDIT_BASE_KEY "/apps/gedit-2"
|
||||
|
||||
#define GPM_PREFS_DIR GEDIT_BASE_KEY "/preferences"
|
||||
|
||||
/* Editor */
|
||||
#define GPM_FONT_DIR GPM_PREFS_DIR "/editor/font"
|
||||
#define GPM_USE_DEFAULT_FONT GPM_FONT_DIR "/use_default_font"
|
||||
#define GPM_EDITOR_FONT GPM_FONT_DIR "/editor_font"
|
||||
#define GPM_SYSTEM_FONT "/desktop/mate/interface/monospace_font_name"
|
||||
|
||||
#define GPM_SAVE_DIR GPM_PREFS_DIR "/editor/save"
|
||||
#define GPM_CREATE_BACKUP_COPY GPM_SAVE_DIR "/create_backup_copy"
|
||||
|
||||
#define GPM_AUTO_SAVE GPM_SAVE_DIR "/auto_save"
|
||||
#define GPM_AUTO_SAVE_INTERVAL GPM_SAVE_DIR "/auto_save_interval"
|
||||
|
||||
#define GPM_UNDO_DIR GPM_PREFS_DIR "/editor/undo"
|
||||
#define GPM_UNDO_ACTIONS_LIMIT GPM_UNDO_DIR "/max_undo_actions"
|
||||
|
||||
#define GPM_WRAP_MODE_DIR GPM_PREFS_DIR "/editor/wrap_mode"
|
||||
#define GPM_WRAP_MODE GPM_WRAP_MODE_DIR "/wrap_mode"
|
||||
|
||||
#define GPM_TABS_DIR GPM_PREFS_DIR "/editor/tabs"
|
||||
#define GPM_TABS_SIZE GPM_TABS_DIR "/tabs_size"
|
||||
#define GPM_INSERT_SPACES GPM_TABS_DIR "/insert_spaces"
|
||||
|
||||
#define GPM_AUTO_INDENT_DIR GPM_PREFS_DIR "/editor/auto_indent"
|
||||
#define GPM_AUTO_INDENT GPM_AUTO_INDENT_DIR "/auto_indent"
|
||||
|
||||
#define GPM_LINE_NUMBERS_DIR GPM_PREFS_DIR "/editor/line_numbers"
|
||||
#define GPM_DISPLAY_LINE_NUMBERS GPM_LINE_NUMBERS_DIR "/display_line_numbers"
|
||||
|
||||
#define GPM_CURRENT_LINE_DIR GPM_PREFS_DIR "/editor/current_line"
|
||||
#define GPM_HIGHLIGHT_CURRENT_LINE GPM_CURRENT_LINE_DIR "/highlight_current_line"
|
||||
|
||||
#define GPM_BRACKET_MATCHING_DIR GPM_PREFS_DIR "/editor/bracket_matching"
|
||||
#define GPM_BRACKET_MATCHING GPM_BRACKET_MATCHING_DIR "/bracket_matching"
|
||||
|
||||
#define GPM_RIGHT_MARGIN_DIR GPM_PREFS_DIR "/editor/right_margin"
|
||||
#define GPM_DISPLAY_RIGHT_MARGIN GPM_RIGHT_MARGIN_DIR "/display_right_margin"
|
||||
#define GPM_RIGHT_MARGIN_POSITION GPM_RIGHT_MARGIN_DIR "/right_margin_position"
|
||||
|
||||
#define GPM_SMART_HOME_END_DIR GPM_PREFS_DIR "/editor/smart_home_end"
|
||||
#define GPM_SMART_HOME_END GPM_SMART_HOME_END_DIR "/smart_home_end"
|
||||
|
||||
#define GPM_CURSOR_POSITION_DIR GPM_PREFS_DIR "/editor/cursor_position"
|
||||
#define GPM_RESTORE_CURSOR_POSITION GPM_CURSOR_POSITION_DIR "/restore_cursor_position"
|
||||
|
||||
#define GPM_SEARCH_HIGHLIGHTING_DIR GPM_PREFS_DIR "/editor/search_highlighting"
|
||||
#define GPM_SEARCH_HIGHLIGHTING_ENABLE GPM_SEARCH_HIGHLIGHTING_DIR "/enable"
|
||||
|
||||
#define GPM_SOURCE_STYLE_DIR GPM_PREFS_DIR "/editor/colors"
|
||||
#define GPM_SOURCE_STYLE_SCHEME GPM_SOURCE_STYLE_DIR "/scheme"
|
||||
|
||||
/* UI */
|
||||
#define GPM_TOOLBAR_DIR GPM_PREFS_DIR "/ui/toolbar"
|
||||
#define GPM_TOOLBAR_VISIBLE GPM_TOOLBAR_DIR "/toolbar_visible"
|
||||
#define GPM_TOOLBAR_BUTTONS_STYLE GPM_TOOLBAR_DIR "/toolbar_buttons_style"
|
||||
|
||||
#define GPM_STATUSBAR_DIR GPM_PREFS_DIR "/ui/statusbar"
|
||||
#define GPM_STATUSBAR_VISIBLE GPM_STATUSBAR_DIR "/statusbar_visible"
|
||||
|
||||
#define GPM_SIDE_PANE_DIR GPM_PREFS_DIR "/ui/side_pane"
|
||||
#define GPM_SIDE_PANE_VISIBLE GPM_SIDE_PANE_DIR "/side_pane_visible"
|
||||
|
||||
#define GPM_BOTTOM_PANEL_DIR GPM_PREFS_DIR "/ui/bottom_panel"
|
||||
#define GPM_BOTTOM_PANEL_VISIBLE GPM_BOTTOM_PANEL_DIR "/bottom_panel_visible"
|
||||
|
||||
#define GPM_RECENTS_DIR GPM_PREFS_DIR "/ui/recents"
|
||||
#define GPM_MAX_RECENTS GPM_RECENTS_DIR "/max_recents"
|
||||
|
||||
/* Print */
|
||||
#define GPM_PRINT_PAGE_DIR GPM_PREFS_DIR "/print/page"
|
||||
#define GPM_PRINT_SYNTAX GPM_PRINT_PAGE_DIR "/print_syntax_highlighting"
|
||||
#define GPM_PRINT_HEADER GPM_PRINT_PAGE_DIR "/print_header"
|
||||
#define GPM_PRINT_WRAP_MODE GPM_PRINT_PAGE_DIR "/print_wrap_mode"
|
||||
#define GPM_PRINT_LINE_NUMBERS GPM_PRINT_PAGE_DIR "/print_line_numbers"
|
||||
|
||||
#define GPM_PRINT_FONT_DIR GPM_PREFS_DIR "/print/fonts"
|
||||
#define GPM_PRINT_FONT_BODY GPM_PRINT_FONT_DIR "/print_font_body_pango"
|
||||
#define GPM_PRINT_FONT_HEADER GPM_PRINT_FONT_DIR "/print_font_header_pango"
|
||||
#define GPM_PRINT_FONT_NUMBERS GPM_PRINT_FONT_DIR "/print_font_numbers_pango"
|
||||
|
||||
/* Encodings */
|
||||
#define GPM_ENCODINGS_DIR GPM_PREFS_DIR "/encodings"
|
||||
#define GPM_AUTO_DETECTED_ENCODINGS GPM_ENCODINGS_DIR "/auto_detected"
|
||||
#define GPM_SHOWN_IN_MENU_ENCODINGS GPM_ENCODINGS_DIR "/shown_in_menu"
|
||||
|
||||
/* Syntax highlighting */
|
||||
#define GPM_SYNTAX_HL_DIR GPM_PREFS_DIR "/syntax_highlighting"
|
||||
#define GPM_SYNTAX_HL_ENABLE GPM_SYNTAX_HL_DIR "/enable"
|
||||
|
||||
/* White list of writable mate-vfs methods */
|
||||
#define GPM_WRITABLE_VFS_SCHEMES GPM_SAVE_DIR "/writable_vfs_schemes"
|
||||
|
||||
/* Plugins */
|
||||
#define GPM_PLUGINS_DIR GEDIT_BASE_KEY "/plugins"
|
||||
#define GPM_ACTIVE_PLUGINS GPM_PLUGINS_DIR "/active-plugins"
|
||||
|
||||
/* Global Lockdown keys */
|
||||
#define GPM_LOCKDOWN_DIR "/desktop/mate/lockdown"
|
||||
#define GPM_LOCKDOWN_COMMAND_LINE GPM_LOCKDOWN_DIR "/disable_command_line"
|
||||
#define GPM_LOCKDOWN_PRINTING GPM_LOCKDOWN_DIR "/disable_printing"
|
||||
#define GPM_LOCKDOWN_PRINT_SETUP GPM_LOCKDOWN_DIR "/disable_print_setup"
|
||||
#define GPM_LOCKDOWN_SAVE_TO_DISK GPM_LOCKDOWN_DIR "/disable_save_to_disk"
|
||||
|
||||
/* Fallback default values. Keep in sync with gedit.schemas */
|
||||
|
||||
#define GPM_DEFAULT_USE_DEFAULT_FONT 1 /* TRUE */
|
||||
|
||||
#ifndef PLATFORM_OSX
|
||||
#define GPM_DEFAULT_EDITOR_FONT (const gchar*) "Monospace 12"
|
||||
#define GPM_DEFAULT_SYSTEM_FONT (const gchar*) "Monospace 10"
|
||||
#else
|
||||
#define GPM_DEFAULT_EDITOR_FONT (const gchar*) "Monaco 12"
|
||||
#define GPM_DEFAULT_SYSTEM_FONT (const gchar*) "Monaco 12"
|
||||
#endif
|
||||
|
||||
#define GPM_DEFAULT_CREATE_BACKUP_COPY 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_AUTO_SAVE 0 /* FALSE */
|
||||
#define GPM_DEFAULT_AUTO_SAVE_INTERVAL 10 /* minutes */
|
||||
|
||||
#define GPM_DEFAULT_UNDO_ACTIONS_LIMIT 2000 /* actions */
|
||||
|
||||
#define GPM_DEFAULT_WRAP_MODE "GTK_WRAP_WORD"
|
||||
|
||||
#define GPM_DEFAULT_TABS_SIZE 8
|
||||
#define GPM_DEFAULT_INSERT_SPACES 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_AUTO_INDENT 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_DISPLAY_LINE_NUMBERS 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_AUTO_DETECTED_ENCODINGS {"UTF-8", "CURRENT", "ISO-8859-15", NULL}
|
||||
|
||||
#define GPM_DEFAULT_TOOLBAR_VISIBLE 1 /* TRUE */
|
||||
#define GPM_DEFAULT_TOOLBAR_BUTTONS_STYLE "GEDIT_TOOLBAR_SYSTEM"
|
||||
#define GPM_DEFAULT_TOOLBAR_SHOW_TOOLTIPS 1 /* TRUE */
|
||||
|
||||
#define GPM_DEFAULT_STATUSBAR_VISIBLE 1 /* TRUE */
|
||||
#define GPM_DEFAULT_SIDE_PANE_VISIBLE 0 /* FALSE */
|
||||
#define GPM_DEFAULT_BOTTOM_PANEL_VISIBLE 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_PRINT_SYNTAX 1 /* TRUE */
|
||||
#define GPM_DEFAULT_PRINT_HEADER 1 /* TRUE */
|
||||
#define GPM_DEFAULT_PRINT_WRAP_MODE "GTK_WRAP_WORD"
|
||||
#define GPM_DEFAULT_PRINT_LINE_NUMBERS 0 /* No numbers */
|
||||
|
||||
#ifndef PLATFORM_OSX
|
||||
#define GPM_DEFAULT_PRINT_FONT_BODY (const gchar*) "Monospace 9"
|
||||
#else
|
||||
#define GPM_DEFAULT_PRINT_FONT_BODY (const gchar*) "Monaco 10"
|
||||
#endif
|
||||
|
||||
#define GPM_DEFAULT_PRINT_FONT_HEADER (const gchar*) "Sans 11"
|
||||
#define GPM_DEFAULT_PRINT_FONT_NUMBERS (const gchar*) "Sans 8"
|
||||
|
||||
#define GPM_DEFAULT_MAX_RECENTS 5
|
||||
|
||||
#define GPM_DEFAULT_HIGHLIGHT_CURRENT_LINE 1 /* TRUE */
|
||||
|
||||
#define GPM_DEFAULT_BRACKET_MATCHING 0 /* FALSE */
|
||||
|
||||
#define GPM_DEFAULT_DISPLAY_RIGHT_MARGIN 0 /* FALSE */
|
||||
#define GPM_DEFAULT_RIGHT_MARGIN_POSITION 80
|
||||
|
||||
#define GPM_DEFAULT_SMART_HOME_END "AFTER"
|
||||
|
||||
#define GPM_DEFAULT_SYNTAX_HL_ENABLE 1 /* TRUE */
|
||||
|
||||
#define GPM_DEFAULT_WRITABLE_VFS_SCHEMES {"ssh", "sftp", "smb", "dav", "davs", NULL}
|
||||
|
||||
#define GPM_DEFAULT_RESTORE_CURSOR_POSITION 1 /* TRUE */
|
||||
|
||||
#define GPM_DEFAULT_SEARCH_HIGHLIGHTING_ENABLE 1 /* TRUE */
|
||||
|
||||
#define GPM_DEFAULT_SOURCE_STYLE_SCHEME "classic"
|
||||
|
||||
typedef enum {
|
||||
GEDIT_TOOLBAR_SYSTEM = 0,
|
||||
GEDIT_TOOLBAR_ICONS,
|
||||
GEDIT_TOOLBAR_ICONS_AND_TEXT,
|
||||
GEDIT_TOOLBAR_ICONS_BOTH_HORIZ
|
||||
} GeditToolbarSetting;
|
||||
|
||||
/** LIFE CYCLE MANAGEMENT FUNCTIONS **/
|
||||
|
||||
gboolean gedit_prefs_manager_init (void);
|
||||
|
||||
/* This function must be called before exiting gedit */
|
||||
void gedit_prefs_manager_shutdown (void);
|
||||
|
||||
|
||||
/** PREFS MANAGEMENT FUNCTIONS **/
|
||||
|
||||
/* Use default font */
|
||||
gboolean gedit_prefs_manager_get_use_default_font (void);
|
||||
void gedit_prefs_manager_set_use_default_font (gboolean udf);
|
||||
gboolean gedit_prefs_manager_use_default_font_can_set (void);
|
||||
|
||||
/* Editor font */
|
||||
gchar *gedit_prefs_manager_get_editor_font (void);
|
||||
void gedit_prefs_manager_set_editor_font (const gchar *font);
|
||||
gboolean gedit_prefs_manager_editor_font_can_set (void);
|
||||
|
||||
/* System font */
|
||||
gchar *gedit_prefs_manager_get_system_font (void);
|
||||
|
||||
/* Create backup copy */
|
||||
gboolean gedit_prefs_manager_get_create_backup_copy (void);
|
||||
void gedit_prefs_manager_set_create_backup_copy (gboolean cbc);
|
||||
gboolean gedit_prefs_manager_create_backup_copy_can_set (void);
|
||||
|
||||
/* Auto save */
|
||||
gboolean gedit_prefs_manager_get_auto_save (void);
|
||||
void gedit_prefs_manager_set_auto_save (gboolean as);
|
||||
gboolean gedit_prefs_manager_auto_save_can_set (void);
|
||||
|
||||
/* Auto save interval */
|
||||
gint gedit_prefs_manager_get_auto_save_interval (void);
|
||||
void gedit_prefs_manager_set_auto_save_interval (gint asi);
|
||||
gboolean gedit_prefs_manager_auto_save_interval_can_set (void);
|
||||
|
||||
/* Undo actions limit: if < 1 then no limits */
|
||||
gint gedit_prefs_manager_get_undo_actions_limit (void);
|
||||
void gedit_prefs_manager_set_undo_actions_limit (gint ual);
|
||||
gboolean gedit_prefs_manager_undo_actions_limit_can_set (void);
|
||||
|
||||
/* Wrap mode */
|
||||
GtkWrapMode gedit_prefs_manager_get_wrap_mode (void);
|
||||
void gedit_prefs_manager_set_wrap_mode (GtkWrapMode wp);
|
||||
gboolean gedit_prefs_manager_wrap_mode_can_set (void);
|
||||
|
||||
/* Tabs size */
|
||||
gint gedit_prefs_manager_get_tabs_size (void);
|
||||
void gedit_prefs_manager_set_tabs_size (gint ts);
|
||||
gboolean gedit_prefs_manager_tabs_size_can_set (void);
|
||||
|
||||
/* Insert spaces */
|
||||
gboolean gedit_prefs_manager_get_insert_spaces (void);
|
||||
void gedit_prefs_manager_set_insert_spaces (gboolean ai);
|
||||
gboolean gedit_prefs_manager_insert_spaces_can_set (void);
|
||||
|
||||
/* Auto indent */
|
||||
gboolean gedit_prefs_manager_get_auto_indent (void);
|
||||
void gedit_prefs_manager_set_auto_indent (gboolean ai);
|
||||
gboolean gedit_prefs_manager_auto_indent_can_set (void);
|
||||
|
||||
/* Display line numbers */
|
||||
gboolean gedit_prefs_manager_get_display_line_numbers (void);
|
||||
void gedit_prefs_manager_set_display_line_numbers (gboolean dln);
|
||||
gboolean gedit_prefs_manager_display_line_numbers_can_set (void);
|
||||
|
||||
/* Toolbar visible */
|
||||
gboolean gedit_prefs_manager_get_toolbar_visible (void);
|
||||
void gedit_prefs_manager_set_toolbar_visible (gboolean tv);
|
||||
gboolean gedit_prefs_manager_toolbar_visible_can_set (void);
|
||||
|
||||
/* Toolbar buttons style */
|
||||
GeditToolbarSetting gedit_prefs_manager_get_toolbar_buttons_style (void);
|
||||
void gedit_prefs_manager_set_toolbar_buttons_style (GeditToolbarSetting tbs);
|
||||
gboolean gedit_prefs_manager_toolbar_buttons_style_can_set (void);
|
||||
|
||||
/* Statusbar visible */
|
||||
gboolean gedit_prefs_manager_get_statusbar_visible (void);
|
||||
void gedit_prefs_manager_set_statusbar_visible (gboolean sv);
|
||||
gboolean gedit_prefs_manager_statusbar_visible_can_set (void);
|
||||
|
||||
/* Side pane visible */
|
||||
gboolean gedit_prefs_manager_get_side_pane_visible (void);
|
||||
void gedit_prefs_manager_set_side_pane_visible (gboolean tv);
|
||||
gboolean gedit_prefs_manager_side_pane_visible_can_set (void);
|
||||
|
||||
/* Bottom panel visible */
|
||||
gboolean gedit_prefs_manager_get_bottom_panel_visible (void);
|
||||
void gedit_prefs_manager_set_bottom_panel_visible (gboolean tv);
|
||||
gboolean gedit_prefs_manager_bottom_panel_visible_can_set(void);
|
||||
/* Print syntax highlighting */
|
||||
gboolean gedit_prefs_manager_get_print_syntax_hl (void);
|
||||
void gedit_prefs_manager_set_print_syntax_hl (gboolean ps);
|
||||
gboolean gedit_prefs_manager_print_syntax_hl_can_set (void);
|
||||
|
||||
/* Print header */
|
||||
gboolean gedit_prefs_manager_get_print_header (void);
|
||||
void gedit_prefs_manager_set_print_header (gboolean ph);
|
||||
gboolean gedit_prefs_manager_print_header_can_set (void);
|
||||
|
||||
/* Wrap mode while printing */
|
||||
GtkWrapMode gedit_prefs_manager_get_print_wrap_mode (void);
|
||||
void gedit_prefs_manager_set_print_wrap_mode (GtkWrapMode pwm);
|
||||
gboolean gedit_prefs_manager_print_wrap_mode_can_set (void);
|
||||
|
||||
/* Print line numbers */
|
||||
gint gedit_prefs_manager_get_print_line_numbers (void);
|
||||
void gedit_prefs_manager_set_print_line_numbers (gint pln);
|
||||
gboolean gedit_prefs_manager_print_line_numbers_can_set (void);
|
||||
|
||||
/* Font used to print the body of documents */
|
||||
gchar *gedit_prefs_manager_get_print_font_body (void);
|
||||
void gedit_prefs_manager_set_print_font_body (const gchar *font);
|
||||
gboolean gedit_prefs_manager_print_font_body_can_set (void);
|
||||
const gchar *gedit_prefs_manager_get_default_print_font_body (void);
|
||||
|
||||
/* Font used to print headers */
|
||||
gchar *gedit_prefs_manager_get_print_font_header (void);
|
||||
void gedit_prefs_manager_set_print_font_header (const gchar *font);
|
||||
gboolean gedit_prefs_manager_print_font_header_can_set (void);
|
||||
const gchar *gedit_prefs_manager_get_default_print_font_header (void);
|
||||
|
||||
/* Font used to print line numbers */
|
||||
gchar *gedit_prefs_manager_get_print_font_numbers (void);
|
||||
void gedit_prefs_manager_set_print_font_numbers (const gchar *font);
|
||||
gboolean gedit_prefs_manager_print_font_numbers_can_set (void);
|
||||
const gchar *gedit_prefs_manager_get_default_print_font_numbers (void);
|
||||
|
||||
/* Max number of files in "Recent Files" menu.
|
||||
* This is configurable only using mateconftool or mateconf-editor
|
||||
*/
|
||||
gint gedit_prefs_manager_get_max_recents (void);
|
||||
|
||||
/* Encodings */
|
||||
GSList *gedit_prefs_manager_get_auto_detected_encodings (void);
|
||||
|
||||
GSList *gedit_prefs_manager_get_shown_in_menu_encodings (void);
|
||||
void gedit_prefs_manager_set_shown_in_menu_encodings (const GSList *encs);
|
||||
gboolean gedit_prefs_manager_shown_in_menu_encodings_can_set (void);
|
||||
|
||||
/* Highlight current line */
|
||||
gboolean gedit_prefs_manager_get_highlight_current_line (void);
|
||||
void gedit_prefs_manager_set_highlight_current_line (gboolean hl);
|
||||
gboolean gedit_prefs_manager_highlight_current_line_can_set (void);
|
||||
|
||||
/* Highlight matching bracket */
|
||||
gboolean gedit_prefs_manager_get_bracket_matching (void);
|
||||
void gedit_prefs_manager_set_bracket_matching (gboolean bm);
|
||||
gboolean gedit_prefs_manager_bracket_matching_can_set (void);
|
||||
|
||||
/* Display right margin */
|
||||
gboolean gedit_prefs_manager_get_display_right_margin (void);
|
||||
void gedit_prefs_manager_set_display_right_margin (gboolean drm);
|
||||
gboolean gedit_prefs_manager_display_right_margin_can_set (void);
|
||||
|
||||
/* Right margin position */
|
||||
gint gedit_prefs_manager_get_right_margin_position (void);
|
||||
void gedit_prefs_manager_set_right_margin_position (gint rmp);
|
||||
gboolean gedit_prefs_manager_right_margin_position_can_set (void);
|
||||
|
||||
/* Smart home end */
|
||||
GtkSourceSmartHomeEndType
|
||||
gedit_prefs_manager_get_smart_home_end (void);
|
||||
void gedit_prefs_manager_set_smart_home_end (GtkSourceSmartHomeEndType smart_he);
|
||||
gboolean gedit_prefs_manager_smart_home_end_can_set (void);
|
||||
|
||||
/* Enable syntax highlighting */
|
||||
gboolean gedit_prefs_manager_get_enable_syntax_highlighting (void);
|
||||
void gedit_prefs_manager_set_enable_syntax_highlighting (gboolean esh);
|
||||
gboolean gedit_prefs_manager_enable_syntax_highlighting_can_set (void);
|
||||
|
||||
/* Writable VFS schemes */
|
||||
GSList *gedit_prefs_manager_get_writable_vfs_schemes (void);
|
||||
|
||||
/* Restore cursor position */
|
||||
gboolean gedit_prefs_manager_get_restore_cursor_position (void);
|
||||
|
||||
/* Enable search highlighting */
|
||||
gboolean gedit_prefs_manager_get_enable_search_highlighting (void);
|
||||
void gedit_prefs_manager_set_enable_search_highlighting (gboolean esh);
|
||||
gboolean gedit_prefs_manager_enable_search_highlighting_can_set (void);
|
||||
|
||||
/* Style scheme */
|
||||
gchar *gedit_prefs_manager_get_source_style_scheme (void);
|
||||
void gedit_prefs_manager_set_source_style_scheme (const gchar *scheme);
|
||||
gboolean gedit_prefs_manager_source_style_scheme_can_set(void);
|
||||
|
||||
/* Plugins */
|
||||
GSList *gedit_prefs_manager_get_active_plugins (void);
|
||||
void gedit_prefs_manager_set_active_plugins (const GSList *plugins);
|
||||
gboolean gedit_prefs_manager_active_plugins_can_set (void);
|
||||
|
||||
/* Global lockdown */
|
||||
GeditLockdownMask gedit_prefs_manager_get_lockdown (void);
|
||||
|
||||
#endif /* __GEDIT_PREFS_MANAGER_H__ */
|
||||
|
||||
|
||||
865
gedit/gedit-print-job.c
Executable file
865
gedit/gedit-print-job.c
Executable file
@@ -0,0 +1,865 @@
|
||||
/*
|
||||
* gedit-print.c
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2000-2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2008 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id: gedit-print.c 6022 2007-12-09 14:38:57Z pborelli $
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtksourceview/gtksourceprintcompositor.h>
|
||||
|
||||
#include "gedit-print-job.h"
|
||||
#include "gedit-debug.h"
|
||||
#include "gedit-prefs-manager.h"
|
||||
#include "gedit-print-preview.h"
|
||||
#include "gedit-marshal.h"
|
||||
#include "gedit-utils.h"
|
||||
#include "gedit-dirs.h"
|
||||
|
||||
|
||||
#define GEDIT_PRINT_JOB_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
|
||||
GEDIT_TYPE_PRINT_JOB, \
|
||||
GeditPrintJobPrivate))
|
||||
|
||||
struct _GeditPrintJobPrivate
|
||||
{
|
||||
GeditView *view;
|
||||
GeditDocument *doc;
|
||||
|
||||
GtkPrintOperation *operation;
|
||||
GtkSourcePrintCompositor *compositor;
|
||||
|
||||
GtkPrintSettings *settings;
|
||||
|
||||
GtkWidget *preview;
|
||||
|
||||
GeditPrintJobStatus status;
|
||||
|
||||
gchar *status_string;
|
||||
|
||||
gdouble progress;
|
||||
|
||||
gboolean is_preview;
|
||||
|
||||
/* widgets part of the custom print preferences widget.
|
||||
* These pointers are valid just when the dialog is displayed */
|
||||
GtkWidget *syntax_checkbutton;
|
||||
GtkWidget *page_header_checkbutton;
|
||||
GtkWidget *line_numbers_checkbutton;
|
||||
GtkWidget *line_numbers_hbox;
|
||||
GtkWidget *line_numbers_spinbutton;
|
||||
GtkWidget *text_wrapping_checkbutton;
|
||||
GtkWidget *do_not_split_checkbutton;
|
||||
GtkWidget *fonts_table;
|
||||
GtkWidget *body_font_label;
|
||||
GtkWidget *headers_font_label;
|
||||
GtkWidget *numbers_font_label;
|
||||
GtkWidget *body_fontbutton;
|
||||
GtkWidget *headers_fontbutton;
|
||||
GtkWidget *numbers_fontbutton;
|
||||
GtkWidget *restore_button;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_VIEW
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PRINTING,
|
||||
SHOW_PREVIEW,
|
||||
DONE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint print_job_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (GeditPrintJob, gedit_print_job, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
set_view (GeditPrintJob *job, GeditView *view)
|
||||
{
|
||||
job->priv->view = view;
|
||||
job->priv->doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_print_job_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditPrintJob *job = GEDIT_PRINT_JOB (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_VIEW:
|
||||
g_value_set_object (value, job->priv->view);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_print_job_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GeditPrintJob *job = GEDIT_PRINT_JOB (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_VIEW:
|
||||
set_view (job, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_print_job_finalize (GObject *object)
|
||||
{
|
||||
GeditPrintJob *job = GEDIT_PRINT_JOB (object);
|
||||
|
||||
g_free (job->priv->status_string);
|
||||
|
||||
if (job->priv->compositor != NULL)
|
||||
g_object_unref (job->priv->compositor);
|
||||
|
||||
if (job->priv->operation != NULL)
|
||||
g_object_unref (job->priv->operation);
|
||||
|
||||
G_OBJECT_CLASS (gedit_print_job_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_print_job_class_init (GeditPrintJobClass *klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gedit_print_job_get_property;
|
||||
object_class->set_property = gedit_print_job_set_property;
|
||||
object_class->finalize = gedit_print_job_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_VIEW,
|
||||
g_param_spec_object ("view",
|
||||
"Gedit View",
|
||||
"Gedit View to print",
|
||||
GEDIT_TYPE_VIEW,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
print_job_signals[PRINTING] =
|
||||
g_signal_new ("printing",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditPrintJobClass, printing),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_UINT);
|
||||
|
||||
print_job_signals[SHOW_PREVIEW] =
|
||||
g_signal_new ("show-preview",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditPrintJobClass, show_preview),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
GTK_TYPE_WIDGET);
|
||||
|
||||
print_job_signals[DONE] =
|
||||
g_signal_new ("done",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GeditPrintJobClass, done),
|
||||
NULL, NULL,
|
||||
gedit_marshal_VOID__UINT_POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GeditPrintJobPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
line_numbers_checkbutton_toggled (GtkToggleButton *button,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (button))
|
||||
{
|
||||
gtk_widget_set_sensitive (job->priv->line_numbers_hbox,
|
||||
gedit_prefs_manager_print_line_numbers_can_set ());
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (job->priv->line_numbers_hbox, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wrap_mode_checkbutton_toggled (GtkToggleButton *button,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->text_wrapping_checkbutton)))
|
||||
{
|
||||
gtk_widget_set_sensitive (job->priv->do_not_split_checkbutton,
|
||||
FALSE);
|
||||
gtk_toggle_button_set_inconsistent (
|
||||
GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton),
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (job->priv->do_not_split_checkbutton,
|
||||
TRUE);
|
||||
gtk_toggle_button_set_inconsistent (
|
||||
GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton),
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
restore_button_clicked (GtkButton *button,
|
||||
GeditPrintJob *job)
|
||||
|
||||
{
|
||||
if (gedit_prefs_manager_print_font_body_can_set ())
|
||||
{
|
||||
const gchar *font;
|
||||
|
||||
font = gedit_prefs_manager_get_default_print_font_body ();
|
||||
|
||||
gtk_font_button_set_font_name (
|
||||
GTK_FONT_BUTTON (job->priv->body_fontbutton),
|
||||
font);
|
||||
}
|
||||
|
||||
if (gedit_prefs_manager_print_font_header_can_set ())
|
||||
{
|
||||
const gchar *font;
|
||||
|
||||
font = gedit_prefs_manager_get_default_print_font_header ();
|
||||
|
||||
gtk_font_button_set_font_name (
|
||||
GTK_FONT_BUTTON (job->priv->headers_fontbutton),
|
||||
font);
|
||||
}
|
||||
|
||||
if (gedit_prefs_manager_print_font_numbers_can_set ())
|
||||
{
|
||||
const gchar *font;
|
||||
|
||||
font = gedit_prefs_manager_get_default_print_font_numbers ();
|
||||
|
||||
gtk_font_button_set_font_name (
|
||||
GTK_FONT_BUTTON (job->priv->numbers_fontbutton),
|
||||
font);
|
||||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
create_custom_widget_cb (GtkPrintOperation *operation,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
gboolean ret;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *error_widget;
|
||||
gchar *font;
|
||||
gint line_numbers;
|
||||
gboolean can_set;
|
||||
GtkWrapMode wrap_mode;
|
||||
gchar *file;
|
||||
gchar *root_objects[] = {
|
||||
"adjustment1",
|
||||
"contents",
|
||||
NULL
|
||||
};
|
||||
|
||||
file = gedit_dirs_get_ui_file ("gedit-print-preferences.ui");
|
||||
ret = gedit_utils_get_ui_objects (file,
|
||||
root_objects,
|
||||
&error_widget,
|
||||
"contents", &widget,
|
||||
"syntax_checkbutton", &job->priv->syntax_checkbutton,
|
||||
"line_numbers_checkbutton", &job->priv->line_numbers_checkbutton,
|
||||
"line_numbers_hbox", &job->priv->line_numbers_hbox,
|
||||
"line_numbers_spinbutton", &job->priv->line_numbers_spinbutton,
|
||||
"page_header_checkbutton", &job->priv->page_header_checkbutton,
|
||||
"text_wrapping_checkbutton", &job->priv->text_wrapping_checkbutton,
|
||||
"do_not_split_checkbutton", &job->priv->do_not_split_checkbutton,
|
||||
"fonts_table", &job->priv->fonts_table,
|
||||
"body_font_label", &job->priv->body_font_label,
|
||||
"body_fontbutton", &job->priv->body_fontbutton,
|
||||
"headers_font_label", &job->priv->headers_font_label,
|
||||
"headers_fontbutton", &job->priv->headers_fontbutton,
|
||||
"numbers_font_label", &job->priv->numbers_font_label,
|
||||
"numbers_fontbutton", &job->priv->numbers_fontbutton,
|
||||
"restore_button", &job->priv->restore_button,
|
||||
NULL);
|
||||
g_free (file);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
return G_OBJECT (error_widget);
|
||||
}
|
||||
|
||||
/* Print syntax */
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (job->priv->syntax_checkbutton),
|
||||
gedit_prefs_manager_get_print_syntax_hl ());
|
||||
gtk_widget_set_sensitive (job->priv->syntax_checkbutton,
|
||||
gedit_prefs_manager_print_syntax_hl_can_set ());
|
||||
|
||||
/* Print page headers */
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (job->priv->page_header_checkbutton),
|
||||
gedit_prefs_manager_get_print_header ());
|
||||
gtk_widget_set_sensitive (job->priv->page_header_checkbutton,
|
||||
gedit_prefs_manager_print_header_can_set ());
|
||||
|
||||
/* Line numbers */
|
||||
line_numbers = gedit_prefs_manager_get_print_line_numbers ();
|
||||
can_set = gedit_prefs_manager_print_line_numbers_can_set ();
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (job->priv->line_numbers_checkbutton),
|
||||
line_numbers > 0);
|
||||
gtk_widget_set_sensitive (job->priv->line_numbers_checkbutton, can_set);
|
||||
|
||||
if (line_numbers > 0)
|
||||
{
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (job->priv->line_numbers_spinbutton),
|
||||
(guint) line_numbers);
|
||||
gtk_widget_set_sensitive (job->priv->line_numbers_hbox, can_set);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (job->priv->line_numbers_spinbutton),
|
||||
1);
|
||||
gtk_widget_set_sensitive (job->priv->line_numbers_hbox, FALSE);
|
||||
}
|
||||
|
||||
/* Text wrapping */
|
||||
wrap_mode = gedit_prefs_manager_get_print_wrap_mode ();
|
||||
|
||||
switch (wrap_mode)
|
||||
{
|
||||
case GTK_WRAP_WORD:
|
||||
gtk_toggle_button_set_active (
|
||||
GTK_TOGGLE_BUTTON (job->priv->text_wrapping_checkbutton), TRUE);
|
||||
gtk_toggle_button_set_active (
|
||||
GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton), TRUE);
|
||||
break;
|
||||
case GTK_WRAP_CHAR:
|
||||
gtk_toggle_button_set_active (
|
||||
GTK_TOGGLE_BUTTON (job->priv->text_wrapping_checkbutton), TRUE);
|
||||
gtk_toggle_button_set_active (
|
||||
GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton), FALSE);
|
||||
break;
|
||||
default:
|
||||
gtk_toggle_button_set_active (
|
||||
GTK_TOGGLE_BUTTON (job->priv->text_wrapping_checkbutton), FALSE);
|
||||
gtk_toggle_button_set_inconsistent (
|
||||
GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton), TRUE);
|
||||
}
|
||||
|
||||
can_set = gedit_prefs_manager_print_wrap_mode_can_set ();
|
||||
|
||||
gtk_widget_set_sensitive (job->priv->text_wrapping_checkbutton, can_set);
|
||||
gtk_widget_set_sensitive (job->priv->do_not_split_checkbutton,
|
||||
can_set && (wrap_mode != GTK_WRAP_NONE));
|
||||
|
||||
/* Set initial values */
|
||||
font = gedit_prefs_manager_get_print_font_body ();
|
||||
gtk_font_button_set_font_name (GTK_FONT_BUTTON (job->priv->body_fontbutton),
|
||||
font);
|
||||
g_free (font);
|
||||
|
||||
font = gedit_prefs_manager_get_print_font_header ();
|
||||
gtk_font_button_set_font_name (GTK_FONT_BUTTON (job->priv->headers_fontbutton),
|
||||
font);
|
||||
g_free (font);
|
||||
|
||||
font = gedit_prefs_manager_get_print_font_numbers ();
|
||||
gtk_font_button_set_font_name (GTK_FONT_BUTTON (job->priv->numbers_fontbutton),
|
||||
font);
|
||||
g_free (font);
|
||||
|
||||
can_set = gedit_prefs_manager_print_font_body_can_set ();
|
||||
gtk_widget_set_sensitive (job->priv->body_fontbutton, can_set);
|
||||
gtk_widget_set_sensitive (job->priv->body_font_label, can_set);
|
||||
|
||||
can_set = gedit_prefs_manager_print_font_header_can_set ();
|
||||
gtk_widget_set_sensitive (job->priv->headers_fontbutton, can_set);
|
||||
gtk_widget_set_sensitive (job->priv->headers_font_label, can_set);
|
||||
|
||||
can_set = gedit_prefs_manager_print_font_numbers_can_set ();
|
||||
gtk_widget_set_sensitive (job->priv->numbers_fontbutton, can_set);
|
||||
gtk_widget_set_sensitive (job->priv->numbers_font_label, can_set);
|
||||
|
||||
g_signal_connect (job->priv->line_numbers_checkbutton,
|
||||
"toggled",
|
||||
G_CALLBACK (line_numbers_checkbutton_toggled),
|
||||
job);
|
||||
g_signal_connect (job->priv->text_wrapping_checkbutton,
|
||||
"toggled",
|
||||
G_CALLBACK (wrap_mode_checkbutton_toggled),
|
||||
job);
|
||||
g_signal_connect (job->priv->do_not_split_checkbutton,
|
||||
"toggled",
|
||||
G_CALLBACK (wrap_mode_checkbutton_toggled),
|
||||
job);
|
||||
g_signal_connect (job->priv->restore_button,
|
||||
"clicked",
|
||||
G_CALLBACK (restore_button_clicked),
|
||||
job);
|
||||
|
||||
return G_OBJECT (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
custom_widget_apply_cb (GtkPrintOperation *operation,
|
||||
GtkWidget *widget,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
gedit_prefs_manager_set_print_syntax_hl (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->syntax_checkbutton)));
|
||||
|
||||
gedit_prefs_manager_set_print_header (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->page_header_checkbutton)));
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->line_numbers_checkbutton)))
|
||||
{
|
||||
gedit_prefs_manager_set_print_line_numbers (
|
||||
MAX (1, gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (job->priv->line_numbers_spinbutton))));
|
||||
}
|
||||
else
|
||||
{
|
||||
gedit_prefs_manager_set_print_line_numbers (0);
|
||||
}
|
||||
|
||||
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->text_wrapping_checkbutton)))
|
||||
{
|
||||
gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (job->priv->do_not_split_checkbutton)))
|
||||
{
|
||||
gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_WORD);
|
||||
}
|
||||
else
|
||||
{
|
||||
gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_CHAR);
|
||||
}
|
||||
}
|
||||
|
||||
gedit_prefs_manager_set_print_font_body (gtk_font_button_get_font_name (GTK_FONT_BUTTON (job->priv->body_fontbutton)));
|
||||
gedit_prefs_manager_set_print_font_header (gtk_font_button_get_font_name (GTK_FONT_BUTTON (job->priv->headers_fontbutton)));
|
||||
gedit_prefs_manager_set_print_font_numbers (gtk_font_button_get_font_name (GTK_FONT_BUTTON (job->priv->numbers_fontbutton)));
|
||||
}
|
||||
|
||||
static void
|
||||
create_compositor (GeditPrintJob *job)
|
||||
{
|
||||
gchar *print_font_body;
|
||||
gchar *print_font_header;
|
||||
gchar *print_font_numbers;
|
||||
|
||||
/* Create and initialize print compositor */
|
||||
print_font_body = gedit_prefs_manager_get_print_font_body ();
|
||||
print_font_header = gedit_prefs_manager_get_print_font_header ();
|
||||
print_font_numbers = gedit_prefs_manager_get_print_font_numbers ();
|
||||
|
||||
job->priv->compositor = GTK_SOURCE_PRINT_COMPOSITOR (
|
||||
g_object_new (GTK_TYPE_SOURCE_PRINT_COMPOSITOR,
|
||||
"buffer", GTK_SOURCE_BUFFER (job->priv->doc),
|
||||
"tab-width", gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (job->priv->view)),
|
||||
"highlight-syntax", gtk_source_buffer_get_highlight_syntax (GTK_SOURCE_BUFFER (job->priv->doc)) &&
|
||||
gedit_prefs_manager_get_print_syntax_hl (),
|
||||
"wrap-mode", gedit_prefs_manager_get_print_wrap_mode (),
|
||||
"print-line-numbers", gedit_prefs_manager_get_print_line_numbers (),
|
||||
"print-header", gedit_prefs_manager_get_print_header (),
|
||||
"print-footer", FALSE,
|
||||
"body-font-name", print_font_body,
|
||||
"line-numbers-font-name", print_font_numbers,
|
||||
"header-font-name", print_font_header,
|
||||
NULL));
|
||||
|
||||
g_free (print_font_body);
|
||||
g_free (print_font_header);
|
||||
g_free (print_font_numbers);
|
||||
|
||||
if (gedit_prefs_manager_get_print_header ())
|
||||
{
|
||||
gchar *doc_name;
|
||||
gchar *name_to_display;
|
||||
gchar *left;
|
||||
|
||||
doc_name = gedit_document_get_uri_for_display (job->priv->doc);
|
||||
name_to_display = gedit_utils_str_middle_truncate (doc_name, 60);
|
||||
|
||||
left = g_strdup_printf (_("File: %s"), name_to_display);
|
||||
|
||||
/* Translators: %N is the current page number, %Q is the total
|
||||
* number of pages (ex. Page 2 of 10)
|
||||
*/
|
||||
gtk_source_print_compositor_set_header_format (job->priv->compositor,
|
||||
TRUE,
|
||||
left,
|
||||
NULL,
|
||||
_("Page %N of %Q"));
|
||||
|
||||
g_free (doc_name);
|
||||
g_free (name_to_display);
|
||||
g_free (left);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
begin_print_cb (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
create_compositor (job);
|
||||
|
||||
job->priv->status = GEDIT_PRINT_JOB_STATUS_PAGINATING;
|
||||
|
||||
job->priv->progress = 0.0;
|
||||
|
||||
g_signal_emit (job, print_job_signals[PRINTING], 0, job->priv->status);
|
||||
}
|
||||
|
||||
static void
|
||||
preview_ready (GtkPrintOperationPreview *gtk_preview,
|
||||
GtkPrintContext *context,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
job->priv->is_preview = TRUE;
|
||||
|
||||
g_signal_emit (job, print_job_signals[SHOW_PREVIEW], 0, job->priv->preview);
|
||||
}
|
||||
|
||||
static void
|
||||
preview_destroyed (GtkWidget *preview,
|
||||
GtkPrintOperationPreview *gtk_preview)
|
||||
{
|
||||
gtk_print_operation_preview_end_preview (gtk_preview);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
preview_cb (GtkPrintOperation *op,
|
||||
GtkPrintOperationPreview *gtk_preview,
|
||||
GtkPrintContext *context,
|
||||
GtkWindow *parent,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
job->priv->preview = gedit_print_preview_new (op, gtk_preview, context);
|
||||
|
||||
g_signal_connect_after (gtk_preview,
|
||||
"ready",
|
||||
G_CALLBACK (preview_ready),
|
||||
job);
|
||||
|
||||
/* FIXME: should this go in the preview widget itself? */
|
||||
g_signal_connect (job->priv->preview,
|
||||
"destroy",
|
||||
G_CALLBACK (preview_destroyed),
|
||||
gtk_preview);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
paginate_cb (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
job->priv->status = GEDIT_PRINT_JOB_STATUS_PAGINATING;
|
||||
|
||||
res = gtk_source_print_compositor_paginate (job->priv->compositor, context);
|
||||
|
||||
if (res)
|
||||
{
|
||||
gint n_pages;
|
||||
|
||||
n_pages = gtk_source_print_compositor_get_n_pages (job->priv->compositor);
|
||||
gtk_print_operation_set_n_pages (job->priv->operation, n_pages);
|
||||
}
|
||||
|
||||
job->priv->progress = gtk_source_print_compositor_get_pagination_progress (job->priv->compositor);
|
||||
|
||||
/* When previewing, the progress is just for pagination, when printing
|
||||
* it's split between pagination and rendering */
|
||||
if (!job->priv->is_preview)
|
||||
job->priv->progress /= 2.0;
|
||||
|
||||
g_signal_emit (job, print_job_signals[PRINTING], 0, job->priv->status);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_page_cb (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
gint page_nr,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
gint n_pages;
|
||||
|
||||
/* In preview, pages are drawn on the fly, so rendering is
|
||||
* not part of the progress */
|
||||
if (!job->priv->is_preview)
|
||||
{
|
||||
g_free (job->priv->status_string);
|
||||
|
||||
n_pages = gtk_source_print_compositor_get_n_pages (job->priv->compositor);
|
||||
|
||||
job->priv->status = GEDIT_PRINT_JOB_STATUS_DRAWING;
|
||||
|
||||
job->priv->status_string = g_strdup_printf ("Rendering page %d of %d...",
|
||||
page_nr + 1,
|
||||
n_pages);
|
||||
|
||||
job->priv->progress = page_nr / (2.0 * n_pages) + 0.5;
|
||||
|
||||
g_signal_emit (job, print_job_signals[PRINTING], 0, job->priv->status);
|
||||
}
|
||||
|
||||
gtk_source_print_compositor_draw_page (job->priv->compositor, context, page_nr);
|
||||
}
|
||||
|
||||
static void
|
||||
end_print_cb (GtkPrintOperation *operation,
|
||||
GtkPrintContext *context,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
g_object_unref (job->priv->compositor);
|
||||
job->priv->compositor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
done_cb (GtkPrintOperation *operation,
|
||||
GtkPrintOperationResult result,
|
||||
GeditPrintJob *job)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GeditPrintJobResult print_result;
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case GTK_PRINT_OPERATION_RESULT_CANCEL:
|
||||
print_result = GEDIT_PRINT_JOB_RESULT_CANCEL;
|
||||
break;
|
||||
|
||||
case GTK_PRINT_OPERATION_RESULT_APPLY:
|
||||
print_result = GEDIT_PRINT_JOB_RESULT_OK;
|
||||
break;
|
||||
|
||||
case GTK_PRINT_OPERATION_RESULT_ERROR:
|
||||
print_result = GEDIT_PRINT_JOB_RESULT_ERROR;
|
||||
gtk_print_operation_get_error (operation, &error);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
/* Avoid job is destroyed in the handler of the "done" message */
|
||||
g_object_ref (job);
|
||||
|
||||
g_signal_emit (job, print_job_signals[DONE], 0, print_result, error);
|
||||
|
||||
g_object_unref (operation);
|
||||
job->priv->operation = NULL;
|
||||
|
||||
g_object_unref (job);
|
||||
}
|
||||
|
||||
/* Note that gedit_print_job_print can can only be called once on a given GeditPrintJob */
|
||||
GtkPrintOperationResult
|
||||
gedit_print_job_print (GeditPrintJob *job,
|
||||
GtkPrintOperationAction action,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintSettings *settings,
|
||||
GtkWindow *parent,
|
||||
GError **error)
|
||||
{
|
||||
GeditPrintJobPrivate *priv;
|
||||
gchar *job_name;
|
||||
|
||||
g_return_val_if_fail (job->priv->compositor == NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
|
||||
|
||||
priv = job->priv;
|
||||
|
||||
/* Check if we are previewing */
|
||||
priv->is_preview = (action == GTK_PRINT_OPERATION_ACTION_PREVIEW);
|
||||
|
||||
/* Create print operation */
|
||||
job->priv->operation = gtk_print_operation_new ();
|
||||
|
||||
if (settings)
|
||||
gtk_print_operation_set_print_settings (priv->operation,
|
||||
settings);
|
||||
|
||||
if (page_setup != NULL)
|
||||
gtk_print_operation_set_default_page_setup (priv->operation,
|
||||
page_setup);
|
||||
|
||||
job_name = gedit_document_get_short_name_for_display (priv->doc);
|
||||
gtk_print_operation_set_job_name (priv->operation, job_name);
|
||||
g_free (job_name);
|
||||
|
||||
#if GTK_CHECK_VERSION (2, 17, 4)
|
||||
gtk_print_operation_set_embed_page_setup (priv->operation, TRUE);
|
||||
#endif
|
||||
|
||||
gtk_print_operation_set_custom_tab_label (priv->operation,
|
||||
_("Text Editor"));
|
||||
|
||||
gtk_print_operation_set_allow_async (priv->operation, TRUE);
|
||||
|
||||
g_signal_connect (priv->operation,
|
||||
"create-custom-widget",
|
||||
G_CALLBACK (create_custom_widget_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"custom-widget-apply",
|
||||
G_CALLBACK (custom_widget_apply_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"begin-print",
|
||||
G_CALLBACK (begin_print_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"preview",
|
||||
G_CALLBACK (preview_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"paginate",
|
||||
G_CALLBACK (paginate_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"draw-page",
|
||||
G_CALLBACK (draw_page_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"end-print",
|
||||
G_CALLBACK (end_print_cb),
|
||||
job);
|
||||
g_signal_connect (priv->operation,
|
||||
"done",
|
||||
G_CALLBACK (done_cb),
|
||||
job);
|
||||
|
||||
return gtk_print_operation_run (priv->operation,
|
||||
action,
|
||||
parent,
|
||||
error);
|
||||
}
|
||||
|
||||
static void
|
||||
gedit_print_job_init (GeditPrintJob *job)
|
||||
{
|
||||
job->priv = GEDIT_PRINT_JOB_GET_PRIVATE (job);
|
||||
|
||||
job->priv->status = GEDIT_PRINT_JOB_STATUS_INIT;
|
||||
|
||||
job->priv->status_string = g_strdup (_("Preparing..."));
|
||||
}
|
||||
|
||||
GeditPrintJob *
|
||||
gedit_print_job_new (GeditView *view)
|
||||
{
|
||||
GeditPrintJob *job;
|
||||
|
||||
g_return_val_if_fail (GEDIT_IS_VIEW (view), NULL);
|
||||
|
||||
job = GEDIT_PRINT_JOB (g_object_new (GEDIT_TYPE_PRINT_JOB,
|
||||
"view", view,
|
||||
NULL));
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
void
|
||||
gedit_print_job_cancel (GeditPrintJob *job)
|
||||
{
|
||||
g_return_if_fail (GEDIT_IS_PRINT_JOB (job));
|
||||
|
||||
gtk_print_operation_cancel (job->priv->operation);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gedit_print_job_get_status_string (GeditPrintJob *job)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
|
||||
g_return_val_if_fail (job->priv->status_string != NULL, NULL);
|
||||
|
||||
return job->priv->status_string;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gedit_print_job_get_progress (GeditPrintJob *job)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), 0.0);
|
||||
|
||||
return job->priv->progress;
|
||||
}
|
||||
|
||||
GtkPrintSettings *
|
||||
gedit_print_job_get_print_settings (GeditPrintJob *job)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
|
||||
|
||||
return gtk_print_operation_get_print_settings (job->priv->operation);
|
||||
}
|
||||
|
||||
GtkPageSetup *
|
||||
gedit_print_job_get_page_setup (GeditPrintJob *job)
|
||||
{
|
||||
g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
|
||||
|
||||
return gtk_print_operation_get_default_page_setup (job->priv->operation);
|
||||
}
|
||||
133
gedit/gedit-print-job.h
Executable file
133
gedit/gedit-print-job.h
Executable file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* gedit-print-job.h
|
||||
* This file is part of gedit
|
||||
*
|
||||
* Copyright (C) 2000-2001 Chema Celorio, Paolo Maggi
|
||||
* Copyright (C) 2002-2008 Paolo Maggi
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
|
||||
* list of people on the gedit Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __GEDIT_PRINT_JOB_H__
|
||||
#define __GEDIT_PRINT_JOB_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gedit/gedit-view.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GEDIT_TYPE_PRINT_JOB (gedit_print_job_get_type())
|
||||
#define GEDIT_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PRINT_JOB, GeditPrintJob))
|
||||
#define GEDIT_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PRINT_JOB, GeditPrintJobClass))
|
||||
#define GEDIT_IS_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PRINT_JOB))
|
||||
#define GEDIT_IS_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PRINT_JOB))
|
||||
#define GEDIT_PRINT_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PRINT_JOB, GeditPrintJobClass))
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_PRINT_JOB_STATUS_INIT,
|
||||
GEDIT_PRINT_JOB_STATUS_PAGINATING,
|
||||
GEDIT_PRINT_JOB_STATUS_DRAWING,
|
||||
GEDIT_PRINT_JOB_STATUS_DONE
|
||||
} GeditPrintJobStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GEDIT_PRINT_JOB_RESULT_OK,
|
||||
GEDIT_PRINT_JOB_RESULT_CANCEL,
|
||||
GEDIT_PRINT_JOB_RESULT_ERROR
|
||||
} GeditPrintJobResult;
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GeditPrintJobPrivate GeditPrintJobPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GeditPrintJob GeditPrintJob;
|
||||
|
||||
|
||||
struct _GeditPrintJob
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/* <private> */
|
||||
GeditPrintJobPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GeditPrintJobClass GeditPrintJobClass;
|
||||
|
||||
struct _GeditPrintJobClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* printing) (GeditPrintJob *job,
|
||||
GeditPrintJobStatus status);
|
||||
|
||||
void (* show_preview) (GeditPrintJob *job,
|
||||
GtkWidget *preview);
|
||||
|
||||
void (*done) (GeditPrintJob *job,
|
||||
GeditPrintJobResult result,
|
||||
const GError *error);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType gedit_print_job_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GeditPrintJob *gedit_print_job_new (GeditView *view);
|
||||
|
||||
void gedit_print_job_set_export_filename (GeditPrintJob *job,
|
||||
const gchar *filename);
|
||||
|
||||
GtkPrintOperationResult gedit_print_job_print (GeditPrintJob *job,
|
||||
GtkPrintOperationAction action,
|
||||
GtkPageSetup *page_setup,
|
||||
GtkPrintSettings *settings,
|
||||
GtkWindow *parent,
|
||||
GError **error);
|
||||
|
||||
void gedit_print_job_cancel (GeditPrintJob *job);
|
||||
|
||||
const gchar *gedit_print_job_get_status_string (GeditPrintJob *job);
|
||||
|
||||
gdouble gedit_print_job_get_progress (GeditPrintJob *job);
|
||||
|
||||
GtkPrintSettings *gedit_print_job_get_print_settings (GeditPrintJob *job);
|
||||
|
||||
GtkPageSetup *gedit_print_job_get_page_setup (GeditPrintJob *job);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEDIT_PRINT_JOB_H__ */
|
||||
497
gedit/gedit-print-preferences.ui
Executable file
497
gedit/gedit-print-preferences.ui
Executable file
@@ -0,0 +1,497 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="value">1</property>
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">window1</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="contents">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">12</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox20">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox26">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label33">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Syntax Highlighting</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="syntax_checkbutton">
|
||||
<property name="label" translatable="yes">Print synta_x highlighting</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox22">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label27">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Line Numbers</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="line_numbers_checkbutton">
|
||||
<property name="label" translatable="yes">Print line nu_mbers</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="line_numbers_hbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.47999998927116394</property>
|
||||
<property name="label" translatable="yes" comments="'Number every' from 'Number every 3 lines' in the 'Text Editor' tab of the print preferences.">_Number every</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">line_numbers_spinbutton</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="line_numbers_spinbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
<property name="climb_rate">1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes" comments="'lines' from 'Number every 3 lines' in the 'Text Editor' tab of the print preferences.">lines</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox24">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label31">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Text Wrapping</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox25">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="text_wrapping_checkbutton">
|
||||
<property name="label" translatable="yes">Enable text _wrapping</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox20">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="do_not_split_checkbutton">
|
||||
<property name="label" translatable="yes">Do not _split words over two lines</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox39">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label45">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Page header</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="page_header_checkbutton">
|
||||
<property name="label" translatable="yes">Print page _headers</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox36">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox37">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label43">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Fonts</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment5">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="fonts_table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<property name="row_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="body_font_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Body:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">body_fontbutton</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="numbers_font_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Line numbers:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">numbers_fontbutton</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="headers_font_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">He_aders and footers:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">headers_fontbutton</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="body_fontbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_font">True</property>
|
||||
<property name="show_style">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="numbers_fontbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_font">True</property>
|
||||
<property name="show_style">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="headers_fontbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_font">True</property>
|
||||
<property name="show_style">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHButtonBox" id="hbuttonbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="restore_button">
|
||||
<property name="label" translatable="yes">_Restore Default Fonts</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
1327
gedit/gedit-print-preview.c
Executable file
1327
gedit/gedit-print-preview.c
Executable file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user