[Xfce4-commits] <mousepad:master> * configure.in.in: Mousepad does not depend on exo anymore. Only when you run in maintainer-mode, exo-csource is required. * mousepad/mousepad-document.*: Renamed mousepad-screen to mousepad-document. * mousepad/mousepad-{search-bar, document, window).*: Added function for searching, including the type-ahead search bar. * mousepad/mousepad-statusbar.*: A custom statusbar suitable for displaying the tooltips, overwrite/insert and the line- and column-number. * mousepad/mousepad-exo.*: The exo-bindings so we don't depend on exo anymore, although I want to get rid of all of them. * mousepad/mousepad-marshal.list: Custom marshal for sending search signals. * mousepad/mousepad-types.h: Search types (a mousepad-enum-types.{c, h} is generated during build). * Various performance inprovements and code cleanups.
Nick Schermer
noreply at xfce.org
Sat May 5 21:30:11 CEST 2012
Updating branch refs/heads/master
to a0b89f341abe283462ad6f5c476b9d37ee644774 (commit)
from cab0d1a984369283d99376e364e216e7fff04bc3 (commit)
commit a0b89f341abe283462ad6f5c476b9d37ee644774
Author: Nick Schermer <nick at xfce.org>
Date: Wed Apr 4 15:50:00 2007 +0000
* configure.in.in: Mousepad does not depend on exo anymore. Only
when you run in maintainer-mode, exo-csource is required.
* mousepad/mousepad-document.*: Renamed mousepad-screen to mousepad-document.
* mousepad/mousepad-{search-bar,document,window).*: Added function for
searching, including the type-ahead search bar.
* mousepad/mousepad-statusbar.*: A custom statusbar suitable for displaying
the tooltips, overwrite/insert and the line- and column-number.
* mousepad/mousepad-exo.*: The exo-bindings so we don't depend on exo anymore,
although I want to get rid of all of them.
* mousepad/mousepad-marshal.list: Custom marshal for sending search signals.
* mousepad/mousepad-types.h: Search types (a mousepad-enum-types.{c,h} is
generated during build).
* Various performance inprovements and code cleanups.
(Old svn revision: 25379)
ChangeLog | 17 +
Makefile.am | 28 +-
NEWS | 1 +
TODO | 1 -
configure.in.in | 10 +-
mousepad/Makefile.am | 167 ++++--
mousepad/main.c | 2 +-
mousepad/mousepad-application.c | 16 +-
mousepad/mousepad-application.h | 2 -
mousepad/mousepad-dbus.c | 3 +-
mousepad/mousepad-dbus.h | 2 -
mousepad/mousepad-dialogs.c | 53 ++-
mousepad/mousepad-document.c | 1132 +++++++++++++++++++++++++++++++++++++
mousepad/mousepad-document.h | 118 ++++
mousepad/mousepad-exo.c | 447 +++++++++++++++
mousepad/mousepad-exo.h | 101 ++++
mousepad/mousepad-file.c | 16 +-
mousepad/mousepad-marshal.list | 2 +
mousepad/mousepad-preferences.c | 86 +---
mousepad/mousepad-preferences.h | 2 -
mousepad/mousepad-private.h | 45 +-
mousepad/mousepad-screen.c | 628 ---------------------
mousepad/mousepad-screen.h | 70 ---
mousepad/mousepad-search-bar.c | 491 ++++++++++++++++
mousepad/mousepad-search-bar.h | 47 ++
mousepad/mousepad-statusbar.c | 184 ++++++
mousepad/mousepad-statusbar.h | 51 ++
mousepad/mousepad-tab-label.c | 265 ---------
mousepad/mousepad-tab-label.h | 41 --
mousepad/mousepad-types.h | 34 ++
mousepad/mousepad-view.c | 4 +-
mousepad/mousepad-window-ui.xml | 14 +-
mousepad/mousepad-window.c | 1168 +++++++++++++++++++++++++--------------
mousepad/mousepad-window.h | 5 +-
34 files changed, 3645 insertions(+), 1608 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index ab7c9cd..bd78621 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2007-04-04 Nick Schermer <nick at xfce.org>
+
+ * configure.in.in: Mousepad does not depend on exo anymore. Only
+ when you run in maintainer-mode, exo-csource is required.
+ * mousepad/mousepad-document.*: Renamed mousepad-screen to mousepad-document.
+ * mousepad/mousepad-{search-bar,document,window).*: Added function for
+ searching, including the type-ahead search bar.
+ * mousepad/mousepad-statusbar.*: A custom statusbar suitable for displaying
+ the tooltips, overwrite/insert and the line- and column-number.
+ * mousepad/mousepad-exo.*: The exo-bindings so we don't depend on exo anymore,
+ although I want to get rid of all of them.
+ * mousepad/mousepad-marshal.list: Custom marshal for sending search signals.
+ * mousepad/mousepad-types.h: Search types (a mousepad-enum-types.{c,h} is
+ generated during build).
+ * Various performance inprovements and code cleanups.
+
+
2007-03-03 Nick Schermer <nick at xfce.org>
* mousepad/mousepad-dialogs.{c,h}: Add response actions for Mousepad so it's
diff --git a/Makefile.am b/Makefile.am
index 039c6a0..d7f22d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,8 +1,8 @@
# $Id$
-SUBDIRS = \
- icons \
- mousepad \
+SUBDIRS = \
+ icons \
+ mousepad \
po
distclean-local:
@@ -13,7 +13,7 @@ rpm: dist
@rm -f $(PACKAGE)-$(VERSION).tar.gz
desktopdir = $(datadir)/applications
-desktop_in_in_files = \
+desktop_in_in_files = \
Mousepad.desktop.in.in
desktop_in_files = $(desktop_in_in_files:.desktop.in.in=.desktop.in)
%.desktop.in: %.desktop.in.in
@@ -21,20 +21,20 @@ desktop_in_files = $(desktop_in_in_files:.desktop.in.in=.desktop.in)
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
@INTLTOOL_DESKTOP_RULE@
-EXTRA_DIST = \
- intltool-extract.in \
- intltool-merge.in \
- intltool-update.in \
+EXTRA_DIST = \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in \
$(desktop_in_in_files)
-DISTCLEANFILES = \
- intltool-extract \
- intltool-merge \
- intltool-update \
- $(desktop_in_files) \
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update \
+ $(desktop_in_files) \
$(desktop_DATA)
-DISTCHECK_CONFIGURE_FLAGS = \
+DISTCHECK_CONFIGURE_FLAGS = \
--enable-gtk-doc
# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/NEWS b/NEWS
index 76ba3a4..0acaa08 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Mousepad 0.3.x
New core features:
- Everything is written in GObjects.
- Run multiple windows in one instance.
+ - Type-ahead find feature like Firefox.
- Tab support.
- Loading multiple files at once (in new tabs). Both multiple
select in the open dialog and by using the command line is supported.
diff --git a/TODO b/TODO
index e64fc10..bc2f4bd 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
- Interface
- Dialog when closing multiple (modified) tabs.
- - Right-click menu for the tab label.
- Tab font color when the file is modified or readonly.
- Test the application with a screen reader and add Atk objects
where needed.
diff --git a/configure.in.in b/configure.in.in
index dbf3aba..c63151f 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -7,6 +7,7 @@ dnl
dnl ***************************
dnl *** Version information ***
dnl ***************************
+m4_define([mousepad_version_api], [1])
m4_define([mousepad_version_major], [0])
m4_define([mousepad_version_minor], [3])
m4_define([mousepad_version_micro], [0])
@@ -59,9 +60,11 @@ AC_PROG_LIBTOOL()
dnl **************************************
dnl *** Substitute version information ***
dnl **************************************
+MOUSEPAD_VERSION_API=mousepad_version_api()
MOUSEPAD_VERSION_MAJOR=mousepad_version_major()
MOUSEPAD_VERSION_MINOR=mousepad_version_minor()
MOUSEPAD_VERSION_MICRO=mousepad_version_micro()
+AC_SUBST([MOUSEPAD_VERSION_API])
AC_SUBST([MOUSEPAD_VERSION_MAJOR])
AC_SUBST([MOUSEPAD_VERSION_MINOR])
AC_SUBST([MOUSEPAD_VERSION_MICRO])
@@ -86,17 +89,12 @@ XDT_I18N([@LINGUAS@])
dnl ***********************************
dnl *** Check for required packages ***
dnl ***********************************
-XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.2])
XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([GMODULE], [gmodule-2.0], [2.12.0])
XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.12.0])
XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
-dnl ********************************************
-dnl *** Check for session management support ***
-dnl ********************************************
-XDT_CHECK_LIBSM()
-
dnl **********************************
dnl *** Optional support for D-BUS ***
dnl **********************************
diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
index 4c76498..9cdf554 100644
--- a/mousepad/Makefile.am
+++ b/mousepad/Makefile.am
@@ -1,77 +1,105 @@
# $Id$
-INCLUDES = \
- -I$(top_builddir) \
- -I$(top_srcdir) \
- -DBINDIR=\"$(bindir)\" \
- -DDATADIR=\"$(datadir)\" \
- -DLIBDIR=\"$(libdir)\" \
- -DLIBEXECDIR=\"$(libexecdir)\" \
- -DG_LOG_DOMAIN=\"Mousepad\" \
- -DLIBEXECDIR=\"$(libexecdir)\" \
- -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -DBINDIR=\"$(bindir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DG_LOG_DOMAIN=\"Mousepad\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
$(PLATFORM_CPPFLAGS)
-bin_PROGRAMS = \
+bin_PROGRAMS = \
mousepad
-mousepad_SOURCES = \
- main.c \
- mousepad-application.c \
- mousepad-application.h \
- mousepad-dialogs.c \
- mousepad-dialogs.h \
- mousepad-file.c \
- mousepad-file.h \
- mousepad-preferences.c \
- mousepad-preferences.h \
- mousepad-private.h \
- mousepad-screen.c \
- mousepad-screen.h \
- mousepad-tab-label.c \
- mousepad-tab-label.h \
- mousepad-view.c \
- mousepad-view.h \
- mousepad-window.c \
- mousepad-window.h \
+mousepad_headers = \
+ mousepad-types.h
+
+mousepad_built_sources = \
+ mousepad-enum-types.c \
+ mousepad-enum-types.h \
+ mousepad-marshal.c \
+ mousepad-marshal.h
+
+mousepad_SOURCES = \
+ $(mousepad_headers) \
+ $(mousepad_built_sources) \
+ $(mousepad_dbus_sources) \
+ main.c \
+ mousepad-application.c \
+ mousepad-application.h \
+ mousepad-dialogs.c \
+ mousepad-dialogs.h \
+ mousepad-document.c \
+ mousepad-document.h \
+ mousepad-exo.c \
+ mousepad-exo.h \
+ mousepad-file.c \
+ mousepad-file.h \
+ mousepad-preferences.c \
+ mousepad-preferences.h \
+ mousepad-private.h \
+ mousepad-search-bar.c \
+ mousepad-search-bar.h \
+ mousepad-statusbar.c \
+ mousepad-statusbar.h \
+ mousepad-view.c \
+ mousepad-view.h \
+ mousepad-window.c \
+ mousepad-window.h \
mousepad-window-ui.h
-mousepad_CFLAGS = \
- $(EXO_CFLAGS) \
- $(GTHREAD_CFLAGS) \
+mousepad_CFLAGS = \
+ $(GTK_CFLAGS) \
+ $(LIBXFCE4UTIL_CFLAGS) \
+ $(GMODULE_CFLAGS) \
+ $(GTHREAD_CFLAGS) \
$(PLATFORM_CFLAGS)
-mousepad_LDFLAGS = \
- -no-undefined \
- $(LIBSM_LDFLAGS) \
+mousepad_LDFLAGS = \
+ -no-undefined \
$(PLATFORM_LDFLAGS)
-mousepad_LDADD = \
- $(EXO_LIBS) \
+mousepad_LDADD = \
+ $(GTK_LIBS) \
+ $(LIBXFCE4UTIL_LIBS) \
+ $(GMODULE_LIBS) \
$(GTHREAD_LIBS)
if HAVE_DBUS
-mousepad_build_sources = \
+mousepad_built_sources += \
mousepad-dbus-infos.h
-mousepad_SOURCES += \
- mousepad-dbus.c \
+mousepad_dbus_sources = \
+ mousepad-dbus.c \
mousepad-dbus.h
-mousepad_CFLAGS += \
- -DDBUS_API_SUBJECT_TO_CHANGE \
+mousepad_CFLAGS += \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
$(DBUS_CFLAGS)
-mousepad_LDADD += \
+mousepad_LDADD += \
$(DBUS_LIBS)
endif
if MAINTAINER_MODE
-DISTCLEANFILES = \
+CLEANFILES = \
+ xgen-mmc \
+ xgen-mmh \
+ xgen-metc \
+ xgen-meth
+
+DISTCLEANFILES = \
+ $(mousepad_built_sources) \
+ stamp-mousepad-marshal.h \
+ stamp-mousepad-enum-types.h \
mousepad-window-ui.h
-BUILT_SOURCES = \
- $(mousepad_build_sources) \
+BUILT_SOURCES = \
+ $(mousepad_built_sources) \
mousepad-window-ui.h
if HAVE_DBUS
@@ -81,10 +109,51 @@ endif
mousepad-window-ui.h: Makefile $(srcdir)/mousepad-window-ui.xml
exo-csource --static --name=mousepad_window_ui $(srcdir)/mousepad-window-ui.xml > mousepad-window-ui.h
+
+mousepad-enum-types.h: stamp-mousepad-enum-types.h
+ @true
+stamp-mousepad-enum-types.h: $(mousepad_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#ifndef __MOUSEPAD_ENUM_TYPES_H__\n#define __MOUSEPAD_ENUM_TYPES_H__\n#include <glib-object.h>\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name at _get_type (void) G_GNUC_CONST;\n#define MOUSEPAD_TYPE_ at ENUMSHORT@ (@enum_name at _get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* !__MOUSEPAD_ENUM_TYPES_H__ */" \
+ $(mousepad_headers) ) >> xgen-meth \
+ && ( cmp -s xgen-meth mousepad-enum-types.h || cp xgen-meth mousepad-enum-types.h ) \
+ && rm -f xgen-meth \
+ && echo timestamp > $(@F)
+mousepad-enum-types.c: $(mousepad_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#include <mousepad/mousepad-enum-types.h>\n#include <mousepad/mousepad-types.h>" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n at enum_name@_get_type (void)\n{\n\tstatic GType type = 0;\n\tif (type == 0) {\n\tstatic const G at Type@Value values[] = {"\
+ --vprod "\t{ @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail "\t{ 0, NULL, NULL }\n\t};\n\ttype = g_ at type@_register_static (\"@EnumName@\", values);\n }\n\treturn type;\n}\n" \
+ $(mousepad_headers) ) >> xgen-metc \
+ && cp xgen-metc mousepad-enum-types.c \
+ && rm -f xgen-metc
+
+mousepad-marshal.h: stamp-mousepad-marshal.h
+ @true
+stamp-mousepad-marshal.h: mousepad-marshal.list Makefile
+ ( cd $(srcdir) && glib-genmarshal \
+ --prefix=_mousepad_marshal \
+ --header mousepad-marshal.list ) >> xgen-mmh \
+ && ( cmp -s xgen-mmh mousepad-marshal.h || cp xgen-mmh mousepad-marshal.h ) \
+ && rm -f xgen-mmh \
+ && echo timestamp > $(@F)
+
+mousepad-marshal.c: mousepad-marshal.list Makefile
+ ( cd $(srcdir) && glib-genmarshal \
+ --prefix=_mousepad_marshal \
+ --body mousepad-marshal.list ) >> xgen-mmc \
+ && cp xgen-mmc mousepad-marshal.c \
+ && rm -f xgen-mmc
endif
-EXTRA_DIST = \
- mousepad-dbus-infos.xml \
+EXTRA_DIST = \
+ mousepad-dbus-infos.xml \
+ mousepad-marshal.list \
mousepad-window-ui.xml
# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/mousepad/main.c b/mousepad/main.c
index b88bd15..22c188b 100644
--- a/mousepad/main.c
+++ b/mousepad/main.c
@@ -83,7 +83,7 @@ main (gint argc, gchar **argv)
#endif
/* initialize the GThread system */
- if (!g_thread_supported ())
+ if (G_LIKELY (!g_thread_supported ()))
g_thread_init (NULL);
/* initialize Gtk+ */
diff --git a/mousepad/mousepad-application.c b/mousepad/mousepad-application.c
index da88720..9b3caa6 100644
--- a/mousepad/mousepad-application.c
+++ b/mousepad/mousepad-application.c
@@ -229,6 +229,7 @@ mousepad_application_open_window (MousepadApplication *application,
gchar **filenames)
{
GtkWidget *window;
+ gboolean succeed;
_mousepad_return_if_fail (MOUSEPAD_IS_APPLICATION (application));
_mousepad_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen));
@@ -245,11 +246,18 @@ mousepad_application_open_window (MousepadApplication *application,
/* open the filenames or an empty tab */
if (filenames != NULL && *filenames != NULL)
- mousepad_window_open_files (MOUSEPAD_WINDOW (window), working_directory, filenames);
- else
- mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
+ {
+ /* try to open the files */
+ succeed = mousepad_window_open_files (MOUSEPAD_WINDOW (window), working_directory, filenames);
- /* TODO: check if there are actually some tabs in the window, if not, open an empty tab */
+ /* if we failed, open an empty tab */
+ if (G_UNLIKELY (succeed == FALSE))
+ mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
+ }
+ else
+ {
+ mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
+ }
/* connect to the "destroy" signal */
g_signal_connect (G_OBJECT (window), "destroy",
diff --git a/mousepad/mousepad-application.h b/mousepad/mousepad-application.h
index de4dde9..4920b12 100644
--- a/mousepad/mousepad-application.h
+++ b/mousepad/mousepad-application.h
@@ -20,8 +20,6 @@
#ifndef __MOUSEPAD_APPLICATION_H__
#define __MOUSEPAD_APPLICATION_H__
-#include <exo/exo.h>
-
G_BEGIN_DECLS
typedef struct _MousepadApplicationClass MousepadApplicationClass;
diff --git a/mousepad/mousepad-dbus.c b/mousepad/mousepad-dbus.c
index 1b7288a..ad2467e 100644
--- a/mousepad/mousepad-dbus.c
+++ b/mousepad/mousepad-dbus.c
@@ -33,8 +33,9 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
-#include <mousepad/mousepad-dbus.h>
#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-dbus.h>
+#include <mousepad/mousepad-application.h>
diff --git a/mousepad/mousepad-dbus.h b/mousepad/mousepad-dbus.h
index d02bef6..7e2d2d0 100644
--- a/mousepad/mousepad-dbus.h
+++ b/mousepad/mousepad-dbus.h
@@ -23,8 +23,6 @@
typedef struct _MousepadDBusServiceClass MousepadDBusServiceClass;
typedef struct _MousepadDBusService MousepadDBusService;
-#include <mousepad/mousepad-application.h>
-
#define MOUSEPAD_TYPE_DBUS_SERVICE (mousepad_dbus_service_get_type ())
#define MOUSEPAD_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusService))
#define MOUSEPAD_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
diff --git a/mousepad/mousepad-dialogs.c b/mousepad/mousepad-dialogs.c
index a26a478..4fa1686 100644
--- a/mousepad/mousepad-dialogs.c
+++ b/mousepad/mousepad-dialogs.c
@@ -50,15 +50,13 @@ mousepad_dialogs_show_about (GtkWindow *parent)
{
static const gchar *authors[] =
{
+ "Benedikt Meurer <benny at xfce.org>",
"Erik Harrison <erikharrison at xfce.org>",
"Nick Schermer <nick at xfce.org>",
- "Benedikt Meurer <benny at xfce.org>",
NULL,
};
/* show the dialog */
- gtk_about_dialog_set_email_hook (exo_url_about_dialog_hook, NULL, NULL);
- gtk_about_dialog_set_url_hook (exo_url_about_dialog_hook, NULL, NULL);
gtk_show_about_dialog (parent,
"authors", authors,
"comments", _("Mousepad is a fast text editor for the Xfce Desktop Environment."),
@@ -69,7 +67,7 @@ mousepad_dialogs_show_about (GtkWindow *parent)
"name", PACKAGE_NAME,
"version", PACKAGE_VERSION,
"translator-credits", _("translator-credits"),
- "website", "http://www.xfce.org/projects/mousepad",
+ "website", "http://www.xfce.org/",
NULL);
}
@@ -162,23 +160,30 @@ gboolean
mousepad_dialogs_clear_recent (GtkWindow *parent)
{
GtkWidget *dialog;
+ GtkWidget *image;
gboolean succeed = FALSE;
- dialog = gtk_message_dialog_new (parent,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("Are you sure you want to clear\nthe Recent History?"));
+ /* the dialog icon */
+ image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_DIALOG);
+ gtk_widget_show (image);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- _("This will only remove the items from the "
- "history owned by Mousepad."));
+ /* create the question dialog */
+ dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
+ _("Remove all entries from the document history?"));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
GTK_STOCK_CLEAR, MOUSEPAD_RESPONSE_CLEAR,
NULL);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Clear Document History"));
gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
+ gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Clearing the document history will permanently "
+ "remove all currently listed entries."));
/* popup the dialog */
if (gtk_dialog_run (GTK_DIALOG (dialog)) == MOUSEPAD_RESPONSE_CLEAR)
@@ -196,27 +201,34 @@ gint
mousepad_dialogs_save_changes (GtkWindow *parent)
{
GtkWidget *dialog;
+ GtkWidget *image;
gint response;
+ /* the dialog icon */
+ image = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_DIALOG);
+ gtk_widget_show (image);
+
/* create the question dialog */
- dialog = gtk_message_dialog_new (parent,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("Do you want to save changes to this\n"
- "document before closing?"));
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- _("If you don't save, your changes will be lost."));
+ dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
+ _("Do you want to save the changes before closing?"));
gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
mousepad_dialogs_image_button (GTK_STOCK_DELETE, _("_Don't Save")),
MOUSEPAD_RESPONSE_DONT_SAVE);
+
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
GTK_STOCK_SAVE, MOUSEPAD_RESPONSE_SAVE,
NULL);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Save Changes"));
+ gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_SAVE);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you don't save the document, all the changes will be lost."));
+
/* run the dialog and wait for a response */
response = gtk_dialog_run (GTK_DIALOG (dialog));
@@ -311,6 +323,7 @@ mousepad_dialogs_ask_overwrite (GtkWindow *parent,
GTK_BUTTONS_NONE,
_("The file has been externally modified. Are you sure "
"you want to save the file?"));
+
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("If you save the file, the external changes "
"to \"%s\" will be lost."), filename);
diff --git a/mousepad/mousepad-document.c b/mousepad/mousepad-document.c
new file mode 100644
index 0000000..a538dc5
--- /dev/null
+++ b/mousepad/mousepad-document.c
@@ -0,0 +1,1132 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-types.h>
+#include <mousepad/mousepad-exo.h>
+#include <mousepad/mousepad-document.h>
+#include <mousepad/mousepad-file.h>
+#include <mousepad/mousepad-marshal.h>
+#include <mousepad/mousepad-view.h>
+#include <mousepad/mousepad-window.h>
+
+
+
+#define DEFAULT_SEARCH_FLAGS (GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY)
+
+
+
+static void mousepad_document_class_init (MousepadDocumentClass *klass);
+static void mousepad_document_init (MousepadDocument *document);
+static void mousepad_document_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mousepad_document_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void mousepad_document_finalize (GObject *object);
+static void mousepad_document_modified_changed (GtkTextBuffer *buffer,
+ MousepadDocument *document);
+static void mousepad_document_notify_has_selection (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadDocument *document);
+static void mousepad_document_notify_cursor_position (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadDocument *document);
+static void mousepad_document_toggle_overwrite (GtkTextView *textview,
+ GParamSpec *pspec,
+ MousepadDocument *document);
+static void mousepad_document_scroll_to_visible_area (MousepadDocument *document);
+static void mousepad_document_set_font (MousepadDocument *document,
+ const gchar *font_name);
+static void mousepad_document_tab_set_tooltip (MousepadDocument *document,
+ GParamSpec *pspec,
+ GtkWidget *ebox);
+static void mousepad_document_tab_button_clicked (GtkWidget *widget,
+ MousepadDocument *document);
+
+
+
+enum
+{
+ PROP_0,
+ PROP_FILENAME,
+ PROP_FONT_NAME,
+ PROP_TITLE,
+};
+
+enum
+{
+ CLOSE_TAB,
+ SELECTION_CHANGED,
+ MODIFIED_CHANGED,
+ CURSOR_CHANGED,
+ OVERWRITE_CHANGED,
+ LAST_SIGNAL,
+};
+
+struct _MousepadDocumentClass
+{
+ GtkScrolledWindowClass __parent__;
+};
+
+struct _MousepadDocument
+{
+ GtkScrolledWindow __parent__;
+
+ /* text view */
+ GtkTextView *textview;
+ GtkTextBuffer *buffer;
+
+ /* the highlight tag */
+ GtkTextTag *tag;
+
+ /* absolute path of the file */
+ gchar *filename;
+
+ /* name of the file used for the titles */
+ gchar *display_name;
+
+ /* last document modified time */
+ time_t mtime;
+
+ /* settings */
+ guint word_wrap : 1;
+ guint line_numbers : 1;
+ guint auto_indent : 1;
+};
+
+
+
+static GObjectClass *mousepad_document_parent_class;
+static guint document_signals[LAST_SIGNAL];
+
+
+
+GtkWidget *
+mousepad_document_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_DOCUMENT, NULL);
+}
+
+
+
+GType
+mousepad_document_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_SCROLLED_WINDOW,
+ I_("MousepadDocument"),
+ sizeof (MousepadDocumentClass),
+ (GClassInitFunc) mousepad_document_class_init,
+ sizeof (MousepadDocument),
+ (GInstanceInitFunc) mousepad_document_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_document_class_init (MousepadDocumentClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ mousepad_document_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_document_finalize;
+ gobject_class->get_property = mousepad_document_get_property;
+ gobject_class->set_property = mousepad_document_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_FILENAME,
+ g_param_spec_string ("filename",
+ "filename",
+ "filename",
+ NULL,
+ MOUSEPAD_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FONT_NAME,
+ g_param_spec_string ("font-name",
+ "font-name",
+ "font-name",
+ NULL,
+ MOUSEPAD_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "title",
+ "title",
+ NULL,
+ MOUSEPAD_PARAM_READWRITE));
+
+ document_signals[CLOSE_TAB] =
+ g_signal_new (I_("close-tab"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ document_signals[SELECTION_CHANGED] =
+ g_signal_new (I_("selection-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ document_signals[MODIFIED_CHANGED] =
+ g_signal_new (I_("modified-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ document_signals[CURSOR_CHANGED] =
+ g_signal_new (I_("cursor-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ _mousepad_marshal_VOID__UINT_UINT,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+ document_signals[OVERWRITE_CHANGED] =
+ g_signal_new (I_("overwrite-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+
+
+static void
+mousepad_document_init (MousepadDocument *document)
+{
+ /* initialize the variables */
+ document->filename = NULL;
+ document->display_name = NULL;
+ document->mtime = 0;
+
+ /* setup the scolled window */
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (document), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (document), GTK_SHADOW_ETCHED_IN);
+ gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (document), NULL);
+ gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (document), NULL);
+
+ /* create a textbuffer */
+ document->buffer = gtk_text_buffer_new (NULL);
+
+ /* create the highlight tag */
+ document->tag = gtk_text_buffer_create_tag (document->buffer, NULL, "background", "#ffff78", NULL);
+
+ /* setup the textview */
+ document->textview = g_object_new (MOUSEPAD_TYPE_VIEW, "buffer", document->buffer, NULL);
+ gtk_container_add (GTK_CONTAINER (document), GTK_WIDGET (document->textview));
+ gtk_widget_show (GTK_WIDGET (document->textview));
+
+ /* attach signals to the text view and buffer */
+ g_signal_connect (G_OBJECT (document->buffer), "modified-changed",
+ G_CALLBACK (mousepad_document_modified_changed), document);
+ g_signal_connect (G_OBJECT (document->buffer), "notify::has-selection",
+ G_CALLBACK (mousepad_document_notify_has_selection), document);
+ g_signal_connect (G_OBJECT (document->buffer), "notify::cursor-position",
+ G_CALLBACK (mousepad_document_notify_cursor_position), document);
+ g_signal_connect (G_OBJECT (document->textview), "notify::overwrite",
+ G_CALLBACK (mousepad_document_toggle_overwrite), document);
+}
+
+
+
+static void
+mousepad_document_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadDocument *document = MOUSEPAD_DOCUMENT (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILENAME:
+ g_value_set_static_string (value, mousepad_document_get_filename (document));
+ break;
+
+ case PROP_TITLE:
+ g_value_set_static_string (value, mousepad_document_get_title (document, FALSE));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_document_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadDocument *document = MOUSEPAD_DOCUMENT (object);
+
+ switch (prop_id)
+ {
+ case PROP_FONT_NAME:
+ mousepad_document_set_font (document, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_document_finalize (GObject *object)
+{
+ MousepadDocument *document = MOUSEPAD_DOCUMENT (object);
+
+ /* cleanup */
+ g_free (document->filename);
+ g_free (document->display_name);
+
+ /* release our reference from the buffer */
+ g_object_unref (G_OBJECT (document->buffer));
+
+ (*G_OBJECT_CLASS (mousepad_document_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_document_modified_changed (GtkTextBuffer *buffer,
+ MousepadDocument *document)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* emit the signal */
+ g_signal_emit (G_OBJECT (document), document_signals[MODIFIED_CHANGED], 0);
+}
+
+
+
+static void
+mousepad_document_notify_has_selection (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadDocument *document)
+{
+ gboolean has_selection;
+
+ _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* check if we have selected text or not */
+ has_selection = mousepad_document_get_has_selection (document);
+
+ /* emit the signal */
+ g_signal_emit (G_OBJECT (document), document_signals[SELECTION_CHANGED], 0, has_selection);
+}
+
+
+
+static void
+mousepad_document_notify_cursor_position (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadDocument *document)
+{
+ GtkTextIter iter, start;
+ guint line, column = 0;
+
+ _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* get the current iter position */
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+
+ /* get the current line numbr */
+ line = gtk_text_iter_get_line (&iter) + 1;
+
+ /* get the column */
+ start = iter;
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ while (!gtk_text_iter_equal (&start, &iter))
+ {
+ if (gtk_text_iter_get_char (&start) == '\t')
+ column += (8 - (column % 8));
+ else
+ ++column;
+
+ gtk_text_iter_forward_char (&start);
+ }
+
+ /* emit the signal */
+ g_signal_emit (G_OBJECT (document), document_signals[CURSOR_CHANGED], 0, line, column + 1);
+}
+
+
+
+static void
+mousepad_document_toggle_overwrite (GtkTextView *textview,
+ GParamSpec *pspec,
+ MousepadDocument *document)
+{
+ gboolean overwrite;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+ _mousepad_return_if_fail (GTK_IS_TEXT_VIEW (textview));
+
+ /* whether overwrite is enabled */
+ overwrite = gtk_text_view_get_overwrite (textview);
+
+ /* emit the signal */
+ g_signal_emit (G_OBJECT (document), document_signals[OVERWRITE_CHANGED], 0, overwrite);
+}
+
+
+
+static void
+mousepad_document_scroll_to_visible_area (MousepadDocument *document)
+{
+ /* scroll to visible area */
+ gtk_text_view_scroll_to_mark (document->textview,
+ gtk_text_buffer_get_insert (document->buffer),
+ 0.25, FALSE, 0.0, 0.0);
+}
+
+
+
+gboolean
+mousepad_document_reload (MousepadDocument *document,
+ GError **error)
+{
+ GtkTextIter start, end;
+ gchar *filename;
+ gboolean succeed = FALSE;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* remove the content of the textview */
+ gtk_text_buffer_get_bounds (document->buffer, &start, &end);
+ gtk_text_buffer_delete (document->buffer, &start, &end);
+
+ /* we have to copy the filename, because mousepad_screen_open_file (resets) the name */
+ filename = g_strdup (document->filename);
+
+ /* reload the document */
+ succeed = mousepad_document_open_file (document, filename, error);
+
+ /* cleanup */
+ g_free (filename);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_document_save_file (MousepadDocument *document,
+ const gchar *filename,
+ GError **error)
+{
+ gchar *content;
+ gchar *converted = NULL;
+ GtkTextIter start, end;
+ gsize bytes;
+ gint new_mtime;
+ gboolean succeed = FALSE;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+
+ /* get the textview content */
+ gtk_text_buffer_get_bounds (document->buffer, &start, &end);
+ content = gtk_text_buffer_get_slice (document->buffer, &start, &end, TRUE);
+
+ if (G_LIKELY (content != NULL))
+ {
+ /* TODO: fix the file encoding here, basic utf8 for testing */
+ converted = g_convert (content,
+ strlen (content),
+ "UTF-8",
+ "UTF-8",
+ NULL,
+ &bytes,
+ error);
+
+ /* cleanup */
+ g_free (content);
+
+ if (G_LIKELY (converted != NULL))
+ {
+ succeed = mousepad_file_save_data (filename, converted, bytes,
+ &new_mtime, error);
+
+ /* cleanup */
+ g_free (converted);
+
+ /* saving work w/o problems */
+ if (G_LIKELY (succeed))
+ {
+ /* set the new mtime */
+ document->mtime = new_mtime;
+
+ /* nothing happend */
+ gtk_text_buffer_set_modified (document->buffer, FALSE);
+
+ /* we were allowed to write */
+ gtk_text_view_set_editable (document->textview, TRUE);
+
+ /* emit the modified-changed signal */
+ mousepad_document_modified_changed (NULL, document);
+ }
+ }
+ }
+
+ return succeed;
+}
+
+
+
+void
+mousepad_document_set_filename (MousepadDocument *document,
+ const gchar *filename)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+ _mousepad_return_if_fail (filename != NULL);
+
+ /* cleanup the old names */
+ g_free (document->filename);
+ g_free (document->display_name);
+
+ /* create the new names */
+ document->filename = g_strdup (filename);
+ document->display_name = g_filename_display_basename (filename);
+
+ /* tell the listeners */
+ g_object_notify (G_OBJECT (document), "title");
+}
+
+
+
+void
+mousepad_document_set_auto_indent (MousepadDocument *document,
+ gboolean auto_indent)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* store the setting */
+ document->auto_indent = auto_indent;
+
+ mousepad_view_set_auto_indent (MOUSEPAD_VIEW (document->textview), auto_indent);
+}
+
+
+
+void
+mousepad_document_set_line_numbers (MousepadDocument *document,
+ gboolean line_numbers)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* store the setting */
+ document->line_numbers = line_numbers;
+
+ mousepad_view_set_show_line_numbers (MOUSEPAD_VIEW (document->textview), line_numbers);
+}
+
+
+
+void
+mousepad_document_set_word_wrap (MousepadDocument *document,
+ gboolean word_wrap)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* store the setting */
+ document->word_wrap = word_wrap;
+
+ /* set the wrapping mode */
+ gtk_text_view_set_wrap_mode (document->textview,
+ word_wrap ? GTK_WRAP_WORD : GTK_WRAP_NONE);
+}
+
+
+
+static void
+mousepad_document_set_font (MousepadDocument *document,
+ const gchar *font_name)
+{
+ PangoFontDescription *font_desc;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ if (G_LIKELY (font_name))
+ {
+ font_desc = pango_font_description_from_string (font_name);
+ gtk_widget_modify_font (GTK_WIDGET (document->textview), font_desc);
+ pango_font_description_free (font_desc);
+ }
+}
+
+
+
+gboolean
+mousepad_document_open_file (MousepadDocument *document,
+ const gchar *filename,
+ GError **error)
+{
+ GtkTextIter iter;
+ gboolean succeed = FALSE;
+ gboolean readonly;
+ gint new_mtime;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+
+ /* we're going to add the file content */
+ gtk_text_buffer_begin_user_action (document->buffer);
+
+ /* insert the file content */
+ if (mousepad_file_read_to_buffer (filename,
+ document->buffer,
+ &new_mtime,
+ &readonly,
+ error))
+ {
+ /* set the new filename */
+ mousepad_document_set_filename (document, filename);
+
+ /* set the new mtime */
+ document->mtime = new_mtime;
+
+ /* whether the textview is editable */
+ gtk_text_view_set_editable (document->textview, !readonly);
+
+ /* move the cursors to the first place and pretend nothing happend */
+ gtk_text_buffer_get_start_iter (document->buffer, &iter);
+ gtk_text_buffer_place_cursor (document->buffer, &iter);
+ gtk_text_buffer_set_modified (document->buffer, FALSE);
+ gtk_text_view_scroll_to_iter (document->textview, &iter, 0, FALSE, 0, 0);
+
+ /* it worked out very well */
+ succeed = TRUE;
+ }
+
+ /* and we're done */
+ gtk_text_buffer_end_user_action (document->buffer);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_document_find (MousepadDocument *document,
+ const gchar *string,
+ MousepadSearchFlags flags)
+{
+ gboolean found;
+ gboolean already_wrapped = FALSE;
+ GtkTextIter doc_start, doc_end;
+ GtkTextIter sel_start, sel_end;
+ GtkTextIter match_start, match_end;
+ GtkTextIter start, end;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+ _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (document->buffer), FALSE);
+
+ /* get the bounds */
+ gtk_text_buffer_get_bounds (document->buffer, &doc_start, &doc_end);
+ gtk_text_buffer_get_selection_bounds (document->buffer, &sel_start, &sel_end);
+
+ if (flags & MOUSEPAD_SEARCH_FORWARDS)
+ {
+ start = sel_end;
+ end = doc_end;
+ }
+ else if (flags & MOUSEPAD_SEARCH_BACKWARDS)
+ {
+ start = sel_start;
+ end = doc_start;
+ }
+ else /* type-ahead */
+ {
+ start = sel_start;
+ end = doc_end;
+ }
+
+search:
+ /* try to find the next occurence of the string */
+ if (flags & MOUSEPAD_SEARCH_BACKWARDS)
+ found = gtk_text_iter_backward_search (&start, string, DEFAULT_SEARCH_FLAGS, &match_start, &match_end, &end);
+ else
+ found = gtk_text_iter_forward_search (&start, string, DEFAULT_SEARCH_FLAGS, &match_start, &match_end, &end);
+
+ /* select the occurence */
+ if (found)
+ {
+ /* set the cursor in from of the matched iter */
+ gtk_text_buffer_place_cursor (document->buffer, &match_start);
+
+ /* select the match */
+ gtk_text_buffer_move_mark_by_name (document->buffer, "insert", &match_end);
+
+ /* scroll document so the cursor is visible */
+ mousepad_document_scroll_to_visible_area (document);
+ }
+ /* wrap around */
+ else if (already_wrapped == FALSE)
+ {
+ /* set the new start and end iter */
+ if (flags & MOUSEPAD_SEARCH_BACKWARDS)
+ {
+ end = start;
+ start = doc_end;
+ }
+ else
+ {
+ end = start;
+ start = doc_start;
+ }
+
+ /* set we did the wrap, so we don't end up in a loop */
+ already_wrapped = TRUE;
+
+ /* search again */
+ goto search;
+ }
+
+ return found;
+}
+
+
+
+void
+mousepad_document_replace (MousepadDocument *document)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+
+}
+
+
+
+void
+mousepad_document_highlight_all (MousepadDocument *document,
+ const gchar *string,
+ MousepadSearchFlags flags)
+{
+ GtkTextIter iter;
+ GtkTextIter doc_start, doc_end;
+ GtkTextIter match_start, match_end;
+ gboolean found;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+ _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
+
+ /* get the document bounds */
+ gtk_text_buffer_get_bounds (document->buffer, &doc_start, &doc_end);
+
+ /* remove all the highlight tags */
+ gtk_text_buffer_remove_tag (document->buffer, document->tag, &doc_start, &doc_end);
+
+ /* highlight the new string */
+ if (G_LIKELY (string != NULL))
+ {
+ /* set the iter to the beginning of the document */
+ iter = doc_start;
+
+ /* highlight all the occurences of the strings */
+ do
+ {
+ /* search for the next occurence of the string */
+ found = gtk_text_iter_forward_search (&iter, string, DEFAULT_SEARCH_FLAGS, &match_start, &match_end, NULL);
+
+ if (G_LIKELY (found))
+ {
+ /* highlight the found occurence */
+ gtk_text_buffer_apply_tag (document->buffer, document->tag, &match_start, &match_end);
+
+ /* jump to the end of the highlighted string and continue searching */
+ iter = match_end;
+ }
+ } while (found);
+ }
+}
+
+
+
+void
+mousepad_document_cut_selection (MousepadDocument *document)
+{
+ GtkClipboard *clipboard;
+
+ /* get the clipboard */
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
+
+ /* cut the text */
+ gtk_text_buffer_cut_clipboard (document->buffer, clipboard, gtk_text_view_get_editable (document->textview));
+
+ /* make sure the cursor is in the visible area */
+ mousepad_document_scroll_to_visible_area (document);
+}
+
+
+
+
+
+void
+mousepad_document_copy_selection (MousepadDocument *document)
+{
+ GtkClipboard *clipboard;
+
+ /* get the clipboard */
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
+
+ /* copy the selected text */
+ gtk_text_buffer_copy_clipboard (document->buffer, clipboard);
+}
+
+
+
+void
+mousepad_document_paste_clipboard (MousepadDocument *document)
+{
+ GtkClipboard *clipboard;
+
+ /* get the clipboard */
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
+
+ /* paste the clipboard content */
+ gtk_text_buffer_paste_clipboard (document->buffer, clipboard, NULL, gtk_text_view_get_editable (document->textview));
+
+ /* make sure the cursor is in the visible area */
+ mousepad_document_scroll_to_visible_area (document);
+}
+
+
+
+void
+mousepad_document_delete_selection (MousepadDocument *document)
+{
+ /* delete the selected text */
+ gtk_text_buffer_delete_selection (document->buffer, TRUE, gtk_text_view_get_editable (document->textview));
+
+ /* make sure the cursor is in the visible area */
+ mousepad_document_scroll_to_visible_area (document);
+}
+
+
+
+void
+mousepad_document_select_all (MousepadDocument *document)
+{
+ GtkTextIter start, end;
+
+ /* get the start and end iter */
+ gtk_text_buffer_get_bounds (document->buffer, &start, &end);
+
+ /* select everything between those iters */
+ gtk_text_buffer_select_range (document->buffer, &start, &end);
+}
+
+
+
+void
+mousepad_document_focus_textview (MousepadDocument *document)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* focus the textview */
+ gtk_widget_grab_focus (GTK_WIDGET (document->textview));
+}
+
+
+
+void
+mousepad_document_jump_to_line (MousepadDocument *document,
+ gint line_number)
+{
+ GtkTextIter iter;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* move the cursor */
+ gtk_text_buffer_get_iter_at_line (document->buffer, &iter, line_number-1);
+ gtk_text_buffer_place_cursor (document->buffer, &iter);
+
+ /* make sure the cursor is in the visible area */
+ mousepad_document_scroll_to_visible_area (document);
+}
+
+
+
+void
+mousepad_document_send_statusbar_signals (MousepadDocument *document)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* re-send the cursor changed signal */
+ mousepad_document_notify_cursor_position (document->buffer, NULL, document);
+
+ /* re-send the overwrite signal */
+ mousepad_document_toggle_overwrite (document->textview, NULL, document);
+}
+
+
+
+void
+mousepad_document_line_numbers (MousepadDocument *document,
+ gint *current_line,
+ gint *last_line)
+{
+ GtkTextIter iter;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* get the current line number */
+ gtk_text_buffer_get_iter_at_mark (document->buffer, &iter, gtk_text_buffer_get_insert (document->buffer));
+ *current_line = gtk_text_iter_get_line (&iter) + 1;
+
+ /* get the last line number */
+ gtk_text_buffer_get_end_iter (document->buffer, &iter);
+ *last_line = gtk_text_iter_get_line (&iter) + 1;
+}
+
+
+
+gboolean
+mousepad_document_get_externally_modified (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+ _mousepad_return_val_if_fail (document->filename != NULL, FALSE);
+
+ /* return whether the file has been externally modified */
+ return mousepad_file_get_externally_modified (document->filename, document->mtime);
+}
+
+
+
+const gchar *
+mousepad_document_get_filename (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), NULL);
+
+ return document->filename;
+}
+
+
+
+gboolean
+mousepad_document_get_has_selection (MousepadDocument *document)
+{
+ gboolean has_selection;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ /* check if we have selected text or not */
+ g_object_get (G_OBJECT (document->buffer), "has-selection", &has_selection, NULL);
+
+ return has_selection;
+}
+
+
+
+gboolean
+mousepad_document_get_modified (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ /* return whether the buffer has been modified */
+ return gtk_text_buffer_get_modified (document->buffer);
+}
+
+
+
+gboolean
+mousepad_document_get_readonly (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ return !gtk_text_view_get_editable (document->textview);
+}
+
+
+
+GtkWidget *
+mousepad_document_get_tab_label (MousepadDocument *document)
+{
+ GtkWidget *hbox;
+ GtkWidget *label, *ebox;
+ GtkWidget *button, *image;
+
+ /* create the box */
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox);
+
+ /* the ebox */
+ ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), ebox, TRUE, TRUE, 0);
+ gtk_widget_show (ebox);
+ mousepad_document_tab_set_tooltip (document, NULL, ebox);
+ g_signal_connect (G_OBJECT (document), "notify::title",
+ G_CALLBACK (mousepad_document_tab_set_tooltip), ebox);
+
+ /* create the label */
+ label = g_object_new (GTK_TYPE_LABEL,
+ "selectable", FALSE,
+ "xalign", 0.0, NULL);
+ gtk_container_add (GTK_CONTAINER (ebox), label);
+ exo_binding_new (G_OBJECT (document), "title", G_OBJECT (label), "label");
+ gtk_widget_show (label);
+
+ /* create the button */
+ button = g_object_new (GTK_TYPE_BUTTON,
+ "relief", GTK_RELIEF_NONE,
+ "focus-on-click", FALSE,
+ "border-width", 0,
+ "can-default", FALSE,
+ "can-focus", FALSE, NULL);
+ mousepad_gtk_set_tooltip (button, _("Close this tab"));
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (mousepad_document_tab_button_clicked), document);
+ gtk_widget_show (button);
+
+ /* button image */
+ image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_widget_show (image);
+
+ return hbox;
+}
+
+
+
+static void
+mousepad_document_tab_set_tooltip (MousepadDocument *document,
+ GParamSpec *pspec,
+ GtkWidget *ebox)
+{
+ mousepad_gtk_set_tooltip (ebox, document->filename);
+}
+
+
+
+static void
+mousepad_document_tab_button_clicked (GtkWidget *widget,
+ MousepadDocument *document)
+{
+ g_signal_emit (G_OBJECT (document), document_signals[CLOSE_TAB], 0);
+}
+
+
+
+const gchar *
+mousepad_document_get_title (MousepadDocument *document,
+ gboolean show_full_path)
+{
+ const gchar *title;
+ static guint untitled_counter = 0;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), NULL);
+
+ if (G_UNLIKELY (show_full_path && document->filename))
+ {
+ /* return the filename */
+ title = document->filename;
+ }
+ else
+ {
+ /* check if the document is still untitled, if so, fix it */
+ if (G_UNLIKELY (document->display_name == NULL))
+ document->display_name = g_strdup_printf ("%s %d", _("Untitled"), ++untitled_counter);
+
+ /* return the display_name */
+ title = document->display_name;
+ }
+
+ return title;
+}
+
+
+
+gboolean
+mousepad_document_get_word_wrap (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ return document->word_wrap;
+}
+
+
+
+gboolean
+mousepad_document_get_line_numbers (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ return document->line_numbers;
+}
+
+
+
+gboolean
+mousepad_document_get_auto_indent (MousepadDocument *document)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
+ return document->auto_indent;
+}
diff --git a/mousepad/mousepad-document.h b/mousepad/mousepad-document.h
new file mode 100644
index 0000000..e483fcd
--- /dev/null
+++ b/mousepad/mousepad-document.h
@@ -0,0 +1,118 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 __MOUSEPAD_DOCUMENT_H__
+#define __MOUSEPAD_DOCUMENT_H__
+
+G_BEGIN_DECLS
+
+typedef struct _MousepadDocumentClass MousepadDocumentClass;
+typedef struct _MousepadDocument MousepadDocument;
+
+#define MOUSEPAD_SCROLL_MARGIN 0.02
+
+#define MOUSEPAD_TYPE_DOCUMENT (mousepad_document_get_type ())
+#define MOUSEPAD_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_DOCUMENT, MousepadDocument))
+#define MOUSEPAD_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_DOCUMENT, MousepadDocumentClass))
+#define MOUSEPAD_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DOCUMENT))
+#define MOUSEPAD_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DOCUMENT))
+#define MOUSEPAD_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DOCUMENT, MousepadDocumentClass))
+
+GType mousepad_document_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_document_new (void);
+
+gboolean mousepad_document_reload (MousepadDocument *document,
+ GError **error);
+
+gboolean mousepad_document_save_file (MousepadDocument *document,
+ const gchar *filename,
+ GError **error);
+
+void mousepad_document_set_filename (MousepadDocument *document,
+ const gchar *filename);
+
+void mousepad_document_set_auto_indent (MousepadDocument *document,
+ gboolean auto_indent);
+
+void mousepad_document_set_line_numbers (MousepadDocument *document,
+ gboolean line_numbers);
+
+void mousepad_document_set_word_wrap (MousepadDocument *document,
+ gboolean word_wrap);
+
+gboolean mousepad_document_open_file (MousepadDocument *document,
+ const gchar *filename,
+ GError **error);
+
+gboolean mousepad_document_find (MousepadDocument *document,
+ const gchar *string,
+ MousepadSearchFlags flags);
+
+void mousepad_document_replace (MousepadDocument *document);
+
+void mousepad_document_highlight_all (MousepadDocument *document,
+ const gchar *string,
+ MousepadSearchFlags flags);
+
+void mousepad_document_cut_selection (MousepadDocument *document);;
+
+void mousepad_document_copy_selection (MousepadDocument *document);
+
+void mousepad_document_paste_clipboard (MousepadDocument *document);
+
+void mousepad_document_delete_selection (MousepadDocument *document);
+
+void mousepad_document_select_all (MousepadDocument *document);
+
+void mousepad_document_focus_textview (MousepadDocument *document);
+
+void mousepad_document_jump_to_line (MousepadDocument *document,
+ gint line_number);
+
+void mousepad_document_send_statusbar_signals (MousepadDocument *document);
+
+void mousepad_document_line_numbers (MousepadDocument *document,
+ gint *current_line,
+ gint *last_line);
+
+gboolean mousepad_document_get_externally_modified (MousepadDocument *document);
+
+const gchar *mousepad_document_get_filename (MousepadDocument *document);
+
+gboolean mousepad_document_get_has_selection (MousepadDocument *document);
+
+gboolean mousepad_document_get_modified (MousepadDocument *document);
+
+gboolean mousepad_document_get_readonly (MousepadDocument *document);
+
+GtkWidget *mousepad_document_get_tab_label (MousepadDocument *document);
+
+const gchar *mousepad_document_get_title (MousepadDocument *document,
+ gboolean show_full_path);
+
+gboolean mousepad_document_get_word_wrap (MousepadDocument *document);
+
+gboolean mousepad_document_get_line_numbers (MousepadDocument *document);
+
+gboolean mousepad_document_get_auto_indent (MousepadDocument *document);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_DOCUMENT_H__ */
diff --git a/mousepad/mousepad-exo.c b/mousepad/mousepad-exo.c
new file mode 100644
index 0000000..b1d75e5
--- /dev/null
+++ b/mousepad/mousepad-exo.c
@@ -0,0 +1,447 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2004-2006 os-cillation e.K.
+ * Copyright (c) 2004 Victor Porton (http://ex-code.com/~porton/)
+ *
+ * Written by Benedikt Meurer <benny at xfce.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-exo.h>
+
+static void
+exo_bind_properties_transfer (GObject *src_object,
+ GParamSpec *src_pspec,
+ GObject *dst_object,
+ GParamSpec *dst_pspec,
+ ExoBindingTransform transform,
+ gpointer user_data)
+{
+ const gchar *src_name;
+ const gchar *dst_name;
+ gboolean result;
+ GValue src_value = { 0, };
+ GValue dst_value = { 0, };
+
+ src_name = g_param_spec_get_name (src_pspec);
+ dst_name = g_param_spec_get_name (dst_pspec);
+
+ g_value_init (&src_value, G_PARAM_SPEC_VALUE_TYPE (src_pspec));
+ g_object_get_property (src_object, src_name, &src_value);
+
+ g_value_init (&dst_value, G_PARAM_SPEC_VALUE_TYPE (dst_pspec));
+ result = (*transform) (&src_value, &dst_value, user_data);
+
+ g_value_unset (&src_value);
+
+ g_return_if_fail (result);
+
+ g_param_value_validate (dst_pspec, &dst_value);
+ g_object_set_property (dst_object, dst_name, &dst_value);
+ g_value_unset (&dst_value);
+}
+
+
+
+static void
+exo_bind_properties_notify (GObject *src_object,
+ GParamSpec *src_pspec,
+ gpointer data)
+{
+ ExoBindingLink *link = data;
+
+ /* block the destination handler for mutual bindings,
+ * so we don't recurse here.
+ */
+ if (link->dst_handler != 0)
+ g_signal_handler_block (link->dst_object, link->dst_handler);
+
+ exo_bind_properties_transfer (src_object,
+ src_pspec,
+ link->dst_object,
+ link->dst_pspec,
+ link->transform,
+ link->user_data);
+
+ /* unblock destination handler */
+ if (link->dst_handler != 0)
+ g_signal_handler_unblock (link->dst_object, link->dst_handler);
+}
+
+
+
+static void
+exo_binding_on_dst_object_destroy (gpointer data,
+ GObject *object)
+{
+ ExoBinding *binding = data;
+
+ binding->link.dst_object = NULL;
+
+ /* calls exo_binding_on_disconnect() */
+ g_signal_handler_disconnect (binding->src_object, binding->link.handler);
+}
+
+
+
+static void
+exo_binding_on_disconnect (gpointer data,
+ GClosure *closure)
+{
+ ExoBindingLink *link = data;
+ ExoBinding *binding;
+
+ binding = (ExoBinding *) (((gchar *) link) - G_STRUCT_OFFSET (ExoBinding, link));
+
+ if (binding->base.destroy != NULL)
+ binding->base.destroy (link->user_data);
+
+ if (link->dst_object != NULL)
+ g_object_weak_unref (link->dst_object, exo_binding_on_dst_object_destroy, binding);
+
+ g_slice_free (ExoBinding, binding);
+}
+
+
+
+/* recursively calls exo_mutual_binding_on_disconnect_object2() */
+static void
+exo_mutual_binding_on_disconnect_object1 (gpointer data,
+ GClosure *closure)
+{
+ ExoMutualBinding *binding;
+ ExoBindingLink *link = data;
+ GObject *object2;
+
+ binding = (ExoMutualBinding *) (((gchar *) link) - G_STRUCT_OFFSET (ExoMutualBinding, direct));
+ binding->reverse.dst_object = NULL;
+
+ object2 = binding->direct.dst_object;
+ if (object2 != NULL)
+ {
+ if (binding->base.destroy != NULL)
+ binding->base.destroy (binding->direct.user_data);
+ binding->direct.dst_object = NULL;
+ g_signal_handler_disconnect (object2, binding->reverse.handler);
+ g_slice_free (ExoMutualBinding, binding);
+ }
+}
+
+
+
+/* recursively calls exo_mutual_binding_on_disconnect_object1() */
+static void
+exo_mutual_binding_on_disconnect_object2 (gpointer data,
+ GClosure *closure)
+{
+ ExoMutualBinding *binding;
+ ExoBindingLink *link = data;
+ GObject *object1;
+
+ binding = (ExoMutualBinding *) (((gchar *) link) - G_STRUCT_OFFSET (ExoMutualBinding, reverse));
+ binding->direct.dst_object = NULL;
+
+ object1 = binding->reverse.dst_object;
+ if (object1 != NULL)
+ {
+ binding->reverse.dst_object = NULL;
+ g_signal_handler_disconnect (object1, binding->direct.handler);
+ }
+}
+
+
+
+static void
+exo_binding_link_init (ExoBindingLink *link,
+ GObject *src_object,
+ const gchar *src_property,
+ GObject *dst_object,
+ GParamSpec *dst_pspec,
+ ExoBindingTransform transform,
+ GClosureNotify destroy_notify,
+ gpointer user_data)
+{
+ gchar *signal_name;
+
+ link->dst_object = dst_object;
+ link->dst_pspec = dst_pspec;
+ link->dst_handler = 0;
+ link->transform = transform;
+ link->user_data = user_data;
+
+ signal_name = g_strconcat ("notify::", src_property, NULL);
+ link->handler = g_signal_connect_data (src_object,
+ signal_name,
+ G_CALLBACK (exo_bind_properties_notify),
+ link,
+ destroy_notify,
+ 0);
+ g_free (signal_name);
+}
+
+
+
+/**
+ * exo_binding_new:
+ * @src_object : The source #GObject.
+ * @src_property : The name of the property to bind from.
+ * @dst_object : The destination #GObject.
+ * @dst_property : The name of the property to bind to.
+ *
+ * One-way binds @src_property in @src_object to @dst_property
+ * in @dst_object.
+ *
+ * Before binding the value of @dst_property is set to the
+ * value of @src_property.
+ *
+ * Return value: The descriptor of the binding. It is automatically
+ * removed if one of the objects is finalized.
+ **/
+ExoBinding*
+exo_binding_new (GObject *src_object,
+ const gchar *src_property,
+ GObject *dst_object,
+ const gchar *dst_property)
+{
+ return exo_binding_new_full (src_object, src_property,
+ dst_object, dst_property,
+ NULL, NULL, NULL);
+}
+
+
+
+/**
+ * exo_binding_new_full:
+ * @src_object : The source #GObject.
+ * @src_property : The name of the property to bind from.
+ * @dst_object : The destination #GObject.
+ * @dst_property : The name of the property to bind to.
+ * @transform : Transformation function or %NULL.
+ * @destroy_notify : Callback function that is called on
+ * disconnection with @user_data or %NULL.
+ * @user_data : User data associated with the binding.
+ *
+ * One-way binds @src_property in @src_object to @dst_property
+ * in @dst_object.
+ *
+ * Before binding the value of @dst_property is set to the
+ * value of @src_property.
+ *
+ * Return value: The descriptor of the binding. It is automatically
+ * removed if one of the objects is finalized.
+ **/
+ExoBinding*
+exo_binding_new_full (GObject *src_object,
+ const gchar *src_property,
+ GObject *dst_object,
+ const gchar *dst_property,
+ ExoBindingTransform transform,
+ GDestroyNotify destroy_notify,
+ gpointer user_data)
+{
+ ExoBinding *binding;
+ GParamSpec *src_pspec;
+ GParamSpec *dst_pspec;
+
+ g_return_val_if_fail (G_IS_OBJECT (src_object), NULL);
+ g_return_val_if_fail (G_IS_OBJECT (dst_object), NULL);
+
+ src_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (src_object), src_property);
+ dst_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (dst_object), dst_property);
+
+ if (transform == NULL)
+ transform = (ExoBindingTransform) g_value_transform;
+
+ exo_bind_properties_transfer (src_object,
+ src_pspec,
+ dst_object,
+ dst_pspec,
+ transform,
+ user_data);
+
+ binding = g_slice_new (ExoBinding);
+ binding->src_object = src_object;
+ binding->base.destroy = destroy_notify;
+
+ exo_binding_link_init (&binding->link,
+ src_object,
+ src_property,
+ dst_object,
+ dst_pspec,
+ transform,
+ exo_binding_on_disconnect,
+ user_data);
+
+ g_object_weak_ref (dst_object, exo_binding_on_dst_object_destroy, binding);
+
+ return binding;
+}
+
+
+
+/**
+ * exo_binding_unbind:
+ * @binding: An #ExoBinding to unbind.
+ *
+ * Disconnects the binding between two properties. Should be
+ * rarely used by applications.
+ *
+ * This functions also calls the @destroy_notify function that
+ * was specified when @binding was created.
+ **/
+void
+exo_binding_unbind (ExoBinding *binding)
+{
+ g_signal_handler_disconnect (binding->src_object, binding->link.handler);
+}
+
+
+
+/**
+ * exo_mutual_binding_new:
+ * @object1 : The first #GObject.
+ * @property1 : The first property to bind.
+ * @object2 : The second #GObject.
+ * @property2 : The second property to bind.
+ *
+ * Mutually binds values of two properties.
+ *
+ * Before binding the value of @property2 is set to the value
+ * of @property1.
+ *
+ * Return value: The descriptor of the binding. It is automatically
+ * removed if one of the objects is finalized.
+ **/
+ExoMutualBinding*
+exo_mutual_binding_new (GObject *object1,
+ const gchar *property1,
+ GObject *object2,
+ const gchar *property2)
+{
+ return exo_mutual_binding_new_full (object1, property1,
+ object2, property2,
+ NULL, NULL, NULL, NULL);
+}
+
+
+
+/**
+ * exo_mutual_binding_new_full:
+ * @object1 : The first #GObject.
+ * @property1 : The first property to bind.
+ * @object2 : The second #GObject.
+ * @property2 : The second property to bind.
+ * @transform : Transformation function or %NULL.
+ * @reverse_transform : The inverse transformation function or %NULL.
+ * @destroy_notify : Callback function called on disconnection with
+ * @user_data as argument or %NULL.
+ * @user_data : User data associated with the binding.
+ *
+ * Mutually binds values of two properties.
+ *
+ * Before binding the value of @property2 is set to the value of
+ * @property1.
+ *
+ * Both @transform and @reverse_transform should simultaneously be
+ * %NULL or non-%NULL. If they are non-%NULL, they should be reverse
+ * in each other.
+ *
+ * Return value: The descriptor of the binding. It is automatically
+ * removed if one of the objects is finalized.
+ **/
+ExoMutualBinding*
+exo_mutual_binding_new_full (GObject *object1,
+ const gchar *property1,
+ GObject *object2,
+ const gchar *property2,
+ ExoBindingTransform transform,
+ ExoBindingTransform reverse_transform,
+ GDestroyNotify destroy_notify,
+ gpointer user_data)
+{
+ ExoMutualBinding *binding;
+ GParamSpec *pspec1;
+ GParamSpec *pspec2;
+
+ g_return_val_if_fail (G_IS_OBJECT (object1), NULL);
+ g_return_val_if_fail (G_IS_OBJECT (object2), NULL);
+
+ pspec1 = g_object_class_find_property (G_OBJECT_GET_CLASS (object1), property1);
+ pspec2 = g_object_class_find_property (G_OBJECT_GET_CLASS (object2), property2);
+
+ if (transform == NULL)
+ transform = (ExoBindingTransform) g_value_transform;
+
+ if (reverse_transform == NULL)
+ reverse_transform = (ExoBindingTransform) g_value_transform;
+
+ exo_bind_properties_transfer (object1,
+ pspec1,
+ object2,
+ pspec2,
+ transform,
+ user_data);
+
+ binding = g_slice_new (ExoMutualBinding);
+ binding->base.destroy = destroy_notify;
+
+ exo_binding_link_init (&binding->direct,
+ object1,
+ property1,
+ object2,
+ pspec2,
+ transform,
+ exo_mutual_binding_on_disconnect_object1,
+ user_data);
+
+ exo_binding_link_init (&binding->reverse,
+ object2,
+ property2,
+ object1,
+ pspec1,
+ reverse_transform,
+ exo_mutual_binding_on_disconnect_object2,
+ user_data);
+
+ /* tell each link about the reverse link for mutual
+ * bindings, to make sure that we do not ever recurse
+ * in notify (yeah, the GObject notify dispatching is
+ * really weird!).
+ */
+ binding->direct.dst_handler = binding->reverse.handler;
+ binding->reverse.dst_handler = binding->direct.handler;
+
+ return binding;
+}
+
+
+/**
+ * exo_mutual_binding_unbind:
+ * @binding: An #ExoMutualBinding to unbind.
+ *
+ * Disconnects the binding between two properties. Should be
+ * rarely used by applications.
+ *
+ * This functions also calls the @destroy_notify function that
+ * was specified when @binding was created.
+ **/
+void
+exo_mutual_binding_unbind (ExoMutualBinding *binding)
+{
+ g_signal_handler_disconnect (binding->direct.dst_object, binding->direct.handler);
+}
diff --git a/mousepad/mousepad-exo.h b/mousepad/mousepad-exo.h
new file mode 100644
index 0000000..17a9b22
--- /dev/null
+++ b/mousepad/mousepad-exo.h
@@ -0,0 +1,101 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2004-2006 os-cillation e.K.
+ * Copyright (c) 2004 Victor Porton (http://ex-code.com/~porton/)
+ *
+ * Written by Benedikt Meurer <benny at xfce.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MOUSEPAD_EXO_H__
+#define __MOUSEPAD_EXO_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExoBindingBase ExoBindingBase;
+typedef struct _ExoBindingLink ExoBindingLink;
+typedef struct _ExoBinding ExoBinding;
+typedef struct _ExoMutualBinding ExoMutualBinding;
+
+typedef gboolean (*ExoBindingTransform) (const GValue *src_value,
+ GValue *dst_value,
+ gpointer user_data);
+
+struct _ExoBindingBase
+{
+ GDestroyNotify destroy;
+};
+
+struct _ExoBindingLink
+{
+ GObject *dst_object;
+ GParamSpec *dst_pspec;
+ gulong dst_handler; /* only set for mutual bindings */
+ gulong handler;
+ ExoBindingTransform transform;
+ gpointer user_data;
+};
+
+struct _ExoBinding
+{
+ /*< private >*/
+ GObject *src_object;
+ ExoBindingBase base;
+ ExoBindingLink link;
+};
+
+struct _ExoMutualBinding
+{
+ /*< private >*/
+ ExoBindingBase base;
+ ExoBindingLink direct;
+ ExoBindingLink reverse;
+};
+
+
+ExoBinding *exo_binding_new (GObject *src_object,
+ const gchar *src_property,
+ GObject *dst_object,
+ const gchar *dst_property);
+ExoBinding *exo_binding_new_full (GObject *src_object,
+ const gchar *src_property,
+ GObject *dst_object,
+ const gchar *dst_property,
+ ExoBindingTransform transform,
+ GDestroyNotify destroy_notify,
+ gpointer user_data);
+void exo_binding_unbind (ExoBinding *binding);
+
+ExoMutualBinding *exo_mutual_binding_new (GObject *object1,
+ const gchar *property1,
+ GObject *object2,
+ const gchar *property2);
+ExoMutualBinding *exo_mutual_binding_new_full (GObject *object1,
+ const gchar *property1,
+ GObject *object2,
+ const gchar *property2,
+ ExoBindingTransform transform,
+ ExoBindingTransform reverse_transform,
+ GDestroyNotify destroy_notify,
+ gpointer user_data);
+void exo_mutual_binding_unbind (ExoMutualBinding *binding);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_EXO_H__ */
diff --git a/mousepad/mousepad-file.c b/mousepad/mousepad-file.c
index 389ee6e..e0d6a17 100644
--- a/mousepad/mousepad-file.c
+++ b/mousepad/mousepad-file.c
@@ -253,9 +253,19 @@ mousepad_file_read_to_buffer (const gchar *filename,
fd = open (filename, O_RDONLY);
if (G_UNLIKELY (fd < 0))
{
- g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
- _("Failed to open \"%s\" for reading"), filename);
- return FALSE;
+ /* the file does not exists, so probably the user ran 'mousepad newfile' from the command line */
+ if (G_LIKELY (errno == ENOENT))
+ {
+ /* we can write the new file */
+ *readonly = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to open \"%s\" for reading"), filename);
+ return FALSE;
+ }
}
/* read the file information */
diff --git a/mousepad/mousepad-marshal.list b/mousepad/mousepad-marshal.list
new file mode 100644
index 0000000..37e8a58
--- /dev/null
+++ b/mousepad/mousepad-marshal.list
@@ -0,0 +1,2 @@
+VOID:UINT,UINT
+BOOLEAN:STRING,FLAGS
diff --git a/mousepad/mousepad-preferences.c b/mousepad/mousepad-preferences.c
index c5ec45f..8a7c751 100644
--- a/mousepad/mousepad-preferences.c
+++ b/mousepad/mousepad-preferences.c
@@ -48,11 +48,9 @@
enum
{
PROP_0,
- PROP_AUTO_INDENT,
PROP_FONT_NAME,
PROP_LAST_WINDOW_HEIGHT,
PROP_LAST_WINDOW_WIDTH,
- PROP_LINE_NUMBERS,
PROP_STATUSBAR,
PROP_WORD_WRAP,
PROP_MISC_ALWAYS_SHOW_TABS,
@@ -60,7 +58,6 @@ enum
PROP_MISC_SHOW_FULL_PATH_IN_TITLE,
PROP_MISC_RECENT_MENU_LIMIT,
PROP_MISC_REMEMBER_GEOMETRY,
- PROP_MISC_TAB_CLOSE_BUTTONS,
N_PROPERTIES,
};
@@ -179,19 +176,6 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
g_value_register_transform_func (G_TYPE_STRING, G_TYPE_INT, transform_string_to_int);
/**
- * MousepadPreferences:auto-indent
- *
- * Whether line identation is enabled.
- **/
- g_object_class_install_property (gobject_class,
- PROP_AUTO_INDENT,
- g_param_spec_boolean ("auto-indent",
- "auto-indent",
- "auto-indent",
- FALSE,
- EXO_PARAM_READWRITE));
-
- /**
* MousepadPreferences:font-name
*
* The font name and size used in the text view. If this value is
@@ -203,7 +187,20 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"font-name",
"font-name",
NULL,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
+
+ /**
+ * MousepadPreferences:statusbar
+ *
+ * Whether to display the statusbar in the Mousepad window.
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_STATUSBAR,
+ g_param_spec_boolean ("last-statusbar-visible",
+ "last-statusbar-visible",
+ "last-statusbar-visible",
+ TRUE,
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:last-window-height
@@ -217,7 +214,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"last-window-height",
"last-window-height",
1, G_MAXINT, 480,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:last-window-width
@@ -231,33 +228,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"last-window-width",
"last-window-width",
1, G_MAXINT, 640,
- EXO_PARAM_READWRITE));
-
- /**
- * MousepadPreferences:line-numbers
- *
- * Whether line numbers are visible in the text view.
- **/
- g_object_class_install_property (gobject_class,
- PROP_LINE_NUMBERS,
- g_param_spec_boolean ("line-numbers",
- "line-numbers",
- "line-numbers",
- FALSE,
- EXO_PARAM_READWRITE));
-
- /**
- * MousepadPreferences:statusbar
- *
- * Whether to display the statusbar in the Mousepad window.
- **/
- g_object_class_install_property (gobject_class,
- PROP_STATUSBAR,
- g_param_spec_boolean ("statusbar",
- "statusbar",
- "statusbar",
- TRUE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:word-wrap
@@ -270,7 +241,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"word-wrap",
"word-wrap",
FALSE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:misc-always-show-tabs
@@ -284,7 +255,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"misc-always-show-tabs",
"misc-always-show-tabs",
FALSE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:misc-cycle-tabs
@@ -297,7 +268,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"misc-cycle-tabs",
"misc-cycle-tabs",
FALSE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:misc-show-full-path-in-title
@@ -310,7 +281,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"misc-show-full-path-in-title",
"misc-show-full-path-in-title",
FALSE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:misc-recent-menu-limit
@@ -323,7 +294,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"misc-recent-menu-limit",
"misc-recent-menu-limit",
1, G_MAXINT, 10,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
/**
* MousepadPreferences:misc-remember-geometry
@@ -340,20 +311,7 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
"misc-remember-geometry",
"misc-remember-geometry",
TRUE,
- EXO_PARAM_READWRITE));
-
- /**
- * MousepadPreferences:misc-tab-close-buttons
- *
- * Whether the close buttons are visible in the tabs.
- **/
- g_object_class_install_property (gobject_class,
- PROP_MISC_TAB_CLOSE_BUTTONS,
- g_param_spec_boolean ("misc-tab-close-buttons",
- "misc-tab-close-buttons",
- "misc-tab-close-buttons",
- TRUE,
- EXO_PARAM_READWRITE));
+ MOUSEPAD_PARAM_READWRITE));
}
diff --git a/mousepad/mousepad-preferences.h b/mousepad/mousepad-preferences.h
index c3d9d9b..f1b91ec 100644
--- a/mousepad/mousepad-preferences.h
+++ b/mousepad/mousepad-preferences.h
@@ -20,8 +20,6 @@
#ifndef __MOUSEPAD_PREFERENCIES_H__
#define __MOUSEPAD_PREFERENCIES_H__
-#include <exo/exo.h>
-
G_BEGIN_DECLS
#define MOUSEPAD_TYPE_PREFERENCES (mousepad_preferences_get_type ())
diff --git a/mousepad/mousepad-private.h b/mousepad/mousepad-private.h
index 9c4aa14..a87225b 100644
--- a/mousepad/mousepad-private.h
+++ b/mousepad/mousepad-private.h
@@ -21,11 +21,31 @@
#ifndef __MOUSEPAD_PRIVATE_H__
#define __MOUSEPAD_PRIVATE_H__
-#include <exo/exo.h>
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
G_BEGIN_DECLS
-#define DEBUG_LINE g_print ("%d\n", __LINE__);
+/* test timers */
+#define TIMER_START \
+ GTimer *__FUNCTION__timer = g_timer_new();
+
+#define TIMER_SPLIT \
+ g_print ("%s (%d): %f\n", __FUNCTION__, __LINE__, g_timer_elapsed (__FUNCTION__timer, NULL));
+
+#define TIMER_STOP \
+ g_print ("%s (%d): %f\n", __FUNCTION__, __LINE__, g_timer_elapsed (__FUNCTION__timer, NULL)); \
+ g_timer_destroy (__FUNCTION__timer);
+
+
+/* optimize the properties */
+#define MOUSEPAD_PARAM_READWRITE (G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
+
+
+
+/* support for canonical strings */
+#define I_(string) (g_intern_static_string ((string)))
+
/* support macros for debugging */
@@ -45,24 +65,9 @@ G_BEGIN_DECLS
/* avoid trivial g_value_get_*() function calls */
#ifdef NDEBUG
-#define g_value_get_boolean(v) (((const GValue *) (v))->data[0].v_int)
-#define g_value_get_char(v) (((const GValue *) (v))->data[0].v_int)
-#define g_value_get_uchar(v) (((const GValue *) (v))->data[0].v_uint)
-#define g_value_get_int(v) (((const GValue *) (v))->data[0].v_int)
-#define g_value_get_uint(v) (((const GValue *) (v))->data[0].v_uint)
-#define g_value_get_long(v) (((const GValue *) (v))->data[0].v_long)
-#define g_value_get_ulong(v) (((const GValue *) (v))->data[0].v_ulong)
-#define g_value_get_int64(v) (((const GValue *) (v))->data[0].v_int64)
-#define g_value_get_uint64(v) (((const GValue *) (v))->data[0].v_uint64)
-#define g_value_get_enum(v) (((const GValue *) (v))->data[0].v_long)
-#define g_value_get_flags(v) (((const GValue *) (v))->data[0].v_ulong)
-#define g_value_get_float(v) (((const GValue *) (v))->data[0].v_float)
-#define g_value_get_double(v) (((const GValue *) (v))->data[0].v_double)
-#define g_value_get_string(v) (((const GValue *) (v))->data[0].v_pointer)
-#define g_value_get_param(v) (((const GValue *) (v))->data[0].v_pointer)
-#define g_value_get_boxed(v) (((const GValue *) (v))->data[0].v_pointer)
-#define g_value_get_pointer(v) (((const GValue *) (v))->data[0].v_pointer)
-#define g_value_get_object(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_string(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_boxed(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_pointer(v) (((const GValue *) (v))->data[0].v_pointer)
#endif
diff --git a/mousepad/mousepad-screen.c b/mousepad/mousepad-screen.c
deleted file mode 100644
index 348a6a5..0000000
--- a/mousepad/mousepad-screen.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
- *
- * 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
-
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include <mousepad/mousepad-private.h>
-#include <mousepad/mousepad-file.h>
-#include <mousepad/mousepad-view.h>
-#include <mousepad/mousepad-screen.h>
-
-
-
-static void mousepad_screen_class_init (MousepadScreenClass *klass);
-static void mousepad_screen_init (MousepadScreen *screen);
-static void mousepad_screen_finalize (GObject *object);
-static void mousepad_screen_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void mousepad_screen_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void mousepad_screen_set_font (MousepadScreen *screen,
- const gchar *font_name);
-static void mousepad_screen_set_word_wrap (MousepadScreen *screen,
- gboolean word_wrap);
-static void mousepad_screen_modified_changed (GtkTextBuffer *buffer,
- MousepadScreen *screen);
-static void mousepad_screen_has_selection (GtkTextBuffer *buffer,
- GParamSpec *pspec,
- MousepadScreen *screen);
-
-
-
-enum
-{
- PROP_0,
- PROP_AUTO_INDENT,
- PROP_FILENAME,
- PROP_FONT_NAME,
- PROP_LINE_NUMBERS,
- PROP_TITLE,
- PROP_WORD_WRAP,
-};
-
-enum
-{
- SELECTION_CHANGED,
- MODIFIED_CHANGED,
- LAST_SIGNAL,
-};
-
-struct _MousepadScreenClass
-{
- GtkScrolledWindowClass __parent__;
-};
-
-struct _MousepadScreen
-{
- GtkScrolledWindow __parent__;
-
- GtkWidget *textview;
-
- /* absolute path of the file */
- gchar *filename;
-
- /* name of the file used for the titles */
- gchar *display_name;
-
- /* last document modified time */
- time_t mtime;
-};
-
-
-
-static guint screen_signals[LAST_SIGNAL];
-static GObjectClass *mousepad_screen_parent_class;
-static guint untitled_counter = 0;
-
-
-
-GtkWidget *
-mousepad_screen_new (void)
-{
- return g_object_new (MOUSEPAD_TYPE_SCREEN, NULL);
-}
-
-
-
-GType
-mousepad_screen_get_type (void)
-{
- static GType type = G_TYPE_INVALID;
-
- if (G_UNLIKELY (type == G_TYPE_INVALID))
- {
- type = g_type_register_static_simple (GTK_TYPE_SCROLLED_WINDOW,
- I_("MousepadScreen"),
- sizeof (MousepadScreenClass),
- (GClassInitFunc) mousepad_screen_class_init,
- sizeof (MousepadScreen),
- (GInstanceInitFunc) mousepad_screen_init,
- 0);
- }
-
- return type;
-}
-
-
-
-static void
-mousepad_screen_class_init (MousepadScreenClass *klass)
-{
- GObjectClass *gobject_class;
-
- mousepad_screen_parent_class = g_type_class_peek_parent (klass);
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->finalize = mousepad_screen_finalize;
- gobject_class->get_property = mousepad_screen_get_property;
- gobject_class->set_property = mousepad_screen_set_property;
-
- g_object_class_install_property (gobject_class,
- PROP_AUTO_INDENT,
- g_param_spec_boolean ("auto-indent",
- "auto-indent",
- "auto-indent",
- FALSE,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_FILENAME,
- g_param_spec_string ("filename",
- "filename",
- "filename",
- NULL,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_FONT_NAME,
- g_param_spec_string ("font-name",
- "font-name",
- "font-name",
- "Bitstream Vera Sans Mono 10",
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_LINE_NUMBERS,
- g_param_spec_boolean ("line-numbers",
- "line-numbers",
- "line-numbers",
- FALSE,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_TITLE,
- g_param_spec_string ("title",
- "title",
- "title",
- NULL,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_WORD_WRAP,
- g_param_spec_boolean ("word-wrap",
- "word-wrap",
- "word-wrap",
- FALSE,
- EXO_PARAM_READWRITE));
-
- screen_signals[SELECTION_CHANGED] =
- g_signal_new (I_("selection-changed"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
- screen_signals[MODIFIED_CHANGED] =
- g_signal_new (I_("modified-changed"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-}
-
-
-
-static void
-mousepad_screen_init (MousepadScreen *screen)
-{
- GtkTextBuffer *buffer;
-
- /* initialize the variables */
- screen->filename = NULL;
- screen->display_name = g_strdup_printf ("%s %d", _("Untitled"), ++untitled_counter);
- screen->mtime = 0;
-
- /* setup the scolled window */
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (screen),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (screen), NULL);
- gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (screen), NULL);
-
- /* setup the textview */
- screen->textview = g_object_new (MOUSEPAD_TYPE_VIEW, NULL);
- gtk_container_add (GTK_CONTAINER (screen), screen->textview);
- gtk_widget_show (screen->textview);
-
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
- g_signal_connect (G_OBJECT (buffer), "modified-changed",
- G_CALLBACK (mousepad_screen_modified_changed), screen);
- g_signal_connect (G_OBJECT (buffer), "notify::has-selection",
- G_CALLBACK (mousepad_screen_has_selection), screen);
-
-}
-
-
-
-static void
-mousepad_screen_finalize (GObject *object)
-{
- MousepadScreen *screen = MOUSEPAD_SCREEN (object);
-
- g_free (screen->filename);
- g_free (screen->display_name);
-
- (*G_OBJECT_CLASS (mousepad_screen_parent_class)->finalize) (object);
-}
-
-
-
-static void
-mousepad_screen_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MousepadScreen *screen = MOUSEPAD_SCREEN (object);
-
- switch (prop_id)
- {
- case PROP_FILENAME:
- g_value_set_static_string (value, mousepad_screen_get_filename (screen));
- break;
-
- case PROP_TITLE:
- g_value_set_static_string (value, mousepad_screen_get_title (screen, FALSE));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
-mousepad_screen_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MousepadScreen *screen = MOUSEPAD_SCREEN (object);
-
- switch (prop_id)
- {
- case PROP_FONT_NAME:
- mousepad_screen_set_font (screen, g_value_get_string (value));
- break;
-
- case PROP_LINE_NUMBERS:
- mousepad_view_set_show_line_numbers (MOUSEPAD_VIEW (screen->textview),
- g_value_get_boolean (value));
- break;
-
- case PROP_AUTO_INDENT:
- mousepad_view_set_auto_indent (MOUSEPAD_VIEW (screen->textview),
- g_value_get_boolean (value));
- break;
-
- case PROP_WORD_WRAP:
- mousepad_screen_set_word_wrap (screen, g_value_get_boolean (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
-mousepad_screen_set_font (MousepadScreen *screen,
- const gchar *font_name)
-{
- PangoFontDescription *font_desc;
-
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- if (G_LIKELY (font_name))
- {
- font_desc = pango_font_description_from_string (font_name);
- gtk_widget_modify_font (GTK_WIDGET (screen->textview), font_desc);
- pango_font_description_free (font_desc);
- }
-}
-
-
-
-static void
-mousepad_screen_set_word_wrap (MousepadScreen *screen,
- gboolean word_wrap)
-{
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (screen->textview),
- word_wrap ? GTK_WRAP_WORD : GTK_WRAP_NONE);
-}
-
-
-
-static void
-mousepad_screen_modified_changed (GtkTextBuffer *buffer,
- MousepadScreen *screen)
-{
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- g_signal_emit (G_OBJECT (screen), screen_signals[MODIFIED_CHANGED], 0);
-}
-
-
-
-static void
-mousepad_screen_has_selection (GtkTextBuffer *buffer,
- GParamSpec *pspec,
- MousepadScreen *screen)
-{
- gboolean selected;
-
- _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
-
- g_signal_emit (G_OBJECT (screen), screen_signals[SELECTION_CHANGED], 0, selected);
-}
-
-
-
-void
-mousepad_screen_set_filename (MousepadScreen *screen,
- const gchar *filename)
-{
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
- _mousepad_return_if_fail (filename != NULL);
-
- /* cleanup the old names */
- g_free (screen->filename);
- g_free (screen->display_name);
-
- /* create the new names */
- screen->filename = g_strdup (filename);
- screen->display_name = g_filename_display_basename (filename);
-
- /* tell the listeners */
- g_object_notify (G_OBJECT (screen), "title");
-}
-
-
-
-gboolean
-mousepad_screen_open_file (MousepadScreen *screen,
- const gchar *filename,
- GError **error)
-{
- GtkTextBuffer *buffer;
- GtkTextIter iter;
- gboolean succeed = FALSE;
- gboolean readonly;
- gint new_mtime;
-
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
- _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- _mousepad_return_val_if_fail (filename != NULL, FALSE);
-
- /* get the buffer */
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
-
- /* we're going to add the file content */
- gtk_text_buffer_begin_user_action (buffer);
-
- /* insert the file content */
- if (mousepad_file_read_to_buffer (filename,
- buffer,
- &new_mtime,
- &readonly,
- error))
- {
- /* set the new filename */
- mousepad_screen_set_filename (screen, filename);
-
- /* set the new mtime */
- screen->mtime = new_mtime;
-
- /* whether the textview is editable */
- gtk_text_view_set_editable (GTK_TEXT_VIEW (screen->textview), !readonly);
-
- /* move the cursors to the first place and pretend nothing happend */
- gtk_text_buffer_get_start_iter (buffer, &iter);
- gtk_text_buffer_place_cursor (buffer, &iter);
- gtk_text_buffer_set_modified (buffer, FALSE);
- gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (screen->textview), &iter, 0, FALSE, 0, 0);
-
- /* it worked out very well */
- succeed = TRUE;
- }
-
- /* and we're done */
- gtk_text_buffer_end_user_action (buffer);
-
- return succeed;
-}
-
-
-
-gboolean
-mousepad_screen_save_file (MousepadScreen *screen,
- const gchar *filename,
- GError **error)
-{
- gchar *content;
- gchar *converted = NULL;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- gsize bytes;
- gint new_mtime;
- gboolean succeed = FALSE;
-
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
- _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- _mousepad_return_val_if_fail (filename != NULL, FALSE);
-
- /* get the buffer */
- buffer = mousepad_screen_get_text_buffer (screen);
-
- /* get the textview content */
- gtk_text_buffer_get_bounds (buffer, &start, &end);
- content = gtk_text_buffer_get_slice (buffer, &start, &end, TRUE);
-
- if (G_LIKELY (content != NULL))
- {
- /* TODO: fix the file encoding here, basic utf8 for testing */
- converted = g_convert (content,
- strlen (content),
- "UTF-8",
- "UTF-8",
- NULL,
- &bytes,
- error);
-
- /* cleanup */
- g_free (content);
-
- if (G_LIKELY (converted != NULL))
- {
- succeed = mousepad_file_save_data (filename, converted, bytes,
- &new_mtime, error);
-
- /* cleanup */
- g_free (converted);
-
- /* saving work w/o problems */
- if (G_LIKELY (succeed))
- {
- /* set the new mtime */
- screen->mtime = new_mtime;
-
- /* nothing happend */
- gtk_text_buffer_set_modified (buffer, FALSE);
-
- /* we were allowed to write */
- gtk_text_view_set_editable (GTK_TEXT_VIEW (screen->textview), TRUE);
-
- /* emit the modified-changed signal */
- mousepad_screen_modified_changed (NULL, screen);
- }
- }
- }
-
- return succeed;
-}
-
-
-
-gboolean
-mousepad_screen_reload (MousepadScreen *screen,
- GError **error)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- gchar *filename;
- gboolean succeed = FALSE;
-
- _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* get the buffer */
- buffer = mousepad_screen_get_text_buffer (screen);
-
- /* remove the content of the textview */
- gtk_text_buffer_get_bounds (buffer, &start, &end);
- gtk_text_buffer_delete (buffer, &start, &end);
-
- /* we have to copy the filename, because mousepad_screen_open_file (resets) the name */
- filename = g_strdup (screen->filename);
-
- /* reload the document */
- succeed = mousepad_screen_open_file (screen, filename, error);
-
- /* cleanup */
- g_free (filename);
-
- return succeed;
-}
-
-
-
-const gchar *
-mousepad_screen_get_title (MousepadScreen *screen,
- gboolean show_full_path)
-{
- const gchar *title;
-
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
-
- if (G_UNLIKELY (show_full_path && screen->filename))
- title = screen->filename;
- else
- title = screen->display_name;
-
- return title;
-}
-
-
-
-const gchar *
-mousepad_screen_get_filename (MousepadScreen *screen)
-{
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
-
- return screen->filename;
-}
-
-
-
-gboolean
-mousepad_screen_get_mtime (MousepadScreen *screen)
-{
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
-
- return screen->mtime;
-}
-
-
-
-gboolean
-mousepad_screen_get_modified (MousepadScreen *screen)
-{
- GtkTextBuffer *buffer;
-
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
-
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
-
- return gtk_text_buffer_get_modified (buffer);
-}
-
-
-
-GtkTextView *
-mousepad_screen_get_text_view (MousepadScreen *screen)
-{
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
-
- return GTK_TEXT_VIEW (screen->textview);
-}
-
-
-
-GtkTextBuffer *
-mousepad_screen_get_text_buffer (MousepadScreen *screen)
-{
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
-
- return gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
-}
diff --git a/mousepad/mousepad-screen.h b/mousepad/mousepad-screen.h
deleted file mode 100644
index f7a69d2..0000000
--- a/mousepad/mousepad-screen.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
- *
- * 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 __MOUSEPAD_SCREEN_H__
-#define __MOUSEPAD_SCREEN_H__
-
-G_BEGIN_DECLS
-
-#define MOUSEPAD_SCROLL_MARGIN 0.02
-
-#define MOUSEPAD_TYPE_SCREEN (mousepad_screen_get_type ())
-#define MOUSEPAD_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_SCREEN, MousepadScreen))
-#define MOUSEPAD_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_SCREEN, MousepadScreenClass))
-#define MOUSEPAD_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_SCREEN))
-#define MOUSEPAD_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_SCREEN))
-#define MOUSEPAD_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_SCREEN, MousepadScreenClass))
-
-typedef struct _MousepadScreenClass MousepadScreenClass;
-typedef struct _MousepadScreen MousepadScreen;
-
-GType mousepad_screen_get_type (void) G_GNUC_CONST;
-
-GtkWidget *mousepad_screen_new (void);
-
-void mousepad_screen_set_filename (MousepadScreen *screen,
- const gchar *filename);
-
-gboolean mousepad_screen_open_file (MousepadScreen *screen,
- const gchar *filename,
- GError **error);
-
-gboolean mousepad_screen_save_file (MousepadScreen *screen,
- const gchar *filename,
- GError **error);
-
-gboolean mousepad_screen_reload (MousepadScreen *screen,
- GError **error);
-
-const gchar *mousepad_screen_get_title (MousepadScreen *screen,
- gboolean show_full_path);
-
-const gchar *mousepad_screen_get_filename (MousepadScreen *screen);
-
-gboolean mousepad_screen_get_mtime (MousepadScreen *screen);
-
-GtkTextView *mousepad_screen_get_text_view (MousepadScreen *screen);
-
-GtkTextBuffer *mousepad_screen_get_text_buffer (MousepadScreen *screen);
-
-gboolean mousepad_screen_get_modified (MousepadScreen *screen);
-
-G_END_DECLS
-
-#endif /* !__MOUSEPAD_SCREEN_H__ */
diff --git a/mousepad/mousepad-search-bar.c b/mousepad/mousepad-search-bar.c
new file mode 100644
index 0000000..733b22b
--- /dev/null
+++ b/mousepad/mousepad-search-bar.c
@@ -0,0 +1,491 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-exo.h>
+#include <mousepad/mousepad-marshal.h>
+#include <mousepad/mousepad-types.h>
+#include <mousepad/mousepad-enum-types.h>
+#include <mousepad/mousepad-search-bar.h>
+#include <mousepad/mousepad-window.h>
+
+
+
+#define TOOL_BAR_ICON_SIZE GTK_ICON_SIZE_MENU
+#define HIGHTLIGHT_TIMEOUT 500
+
+
+
+static void mousepad_search_bar_class_init (MousepadSearchBarClass *klass);
+static void mousepad_search_bar_init (MousepadSearchBar *search_bar);
+static void mousepad_search_bar_finalize (GObject *object);
+static void mousepad_search_bar_find_string (MousepadSearchBar *search_bar,
+ MousepadSearchFlags flags);
+static void mousepad_search_hide_clicked (MousepadSearchBar *search_bar);
+static void mousepad_search_bar_entry_changed (GtkWidget *entry,
+ MousepadSearchBar *search_bar);
+static void mousepad_search_bar_highlight_toggled (GtkWidget *button,
+ MousepadSearchBar *search_bar);
+static void mousepad_search_bar_match_case_toggled (GtkWidget *button,
+ MousepadSearchBar *search_bar);
+static gboolean mousepad_search_bar_highlight_timeout (gpointer user_data);
+static void mousepad_search_bar_highlight_timeout_destroy (gpointer user_data);
+static void mousepad_search_bar_nothing_found (MousepadSearchBar *search_bar,
+ gboolean nothing_found);
+
+
+enum
+{
+ HIDE_BAR,
+ FIND_STRING,
+ HIGHLIGHT_ALL,
+ LAST_SIGNAL,
+};
+
+
+struct _MousepadSearchBarClass
+{
+ GtkToolbarClass __parent__;
+};
+
+struct _MousepadSearchBar
+{
+ GtkToolbar __parent__;
+
+ /* text entry */
+ GtkWidget *entry;
+ GtkToolItem *next;
+ GtkToolItem *previous;
+
+ /* if something was found */
+ guint nothing_found : 1;
+
+ /* settings */
+ guint highlight_all : 1;
+ guint match_case : 1;
+
+ /* timeout for highlighting while typing */
+ guint highlight_id;
+};
+
+
+
+static GObjectClass *mousepad_search_bar_parent_class;
+static guint search_bar_signals[LAST_SIGNAL];
+
+
+
+GtkWidget *
+mousepad_search_bar_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_SEARCH_BAR,
+ "toolbar-style", GTK_TOOLBAR_BOTH_HORIZ,
+ "icon-size", TOOL_BAR_ICON_SIZE,
+ NULL);
+}
+
+
+
+GType
+mousepad_search_bar_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_TOOLBAR,
+ I_("MousepadSearchBar"),
+ sizeof (MousepadSearchBarClass),
+ (GClassInitFunc) mousepad_search_bar_class_init,
+ sizeof (MousepadSearchBar),
+ (GInstanceInitFunc) mousepad_search_bar_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_search_bar_class_init (MousepadSearchBarClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkBindingSet *binding_set;
+
+ mousepad_search_bar_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_search_bar_finalize;
+
+ /* signals */
+ search_bar_signals[HIDE_BAR] =
+ g_signal_new (I_("hide-bar"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ search_bar_signals[FIND_STRING] =
+ g_signal_new (I_("find-string"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ _mousepad_marshal_BOOLEAN__STRING_FLAGS,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_STRING, MOUSEPAD_TYPE_SEARCH_FLAGS);
+
+ search_bar_signals[HIGHLIGHT_ALL] =
+ g_signal_new (I_("highlight-all"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ _mousepad_marshal_BOOLEAN__STRING_FLAGS,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_STRING, MOUSEPAD_TYPE_SEARCH_FLAGS);
+
+ /* setup key bindings for the search bar */
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "hide-bar", 0);
+
+ /* style to hide the shadow around the toolbar and to add a 2px space between the label
+ * and the icon in a toolbar button */
+ gtk_rc_parse_string ("style \"mousepad-search-bar-style\"{GtkToolbar::shadow-type=GTK_SHADOW_NONE}\n"
+ "class\"MousepadSearchBar\"style\"mousepad-search-bar-style\"\n"
+ "style \"mousepad-button-style\"{GtkToolButton::icon-spacing=2}\n"
+ "widget \"MousepadWindow.*.Gtk*ToolButton\" style \"mousepad-button-style\"\n");
+}
+
+
+
+static void
+mousepad_search_bar_init (MousepadSearchBar *search_bar)
+{
+ GtkWidget *label, *image, *check, *menuitem;
+ GtkToolItem *item;
+
+ /* init variables */
+ search_bar->nothing_found = FALSE;
+ search_bar->highlight_id = 0;
+
+ /* the close button */
+ item = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE);
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+ g_signal_connect_swapped (G_OBJECT (item), "clicked",
+ G_CALLBACK (mousepad_search_hide_clicked), search_bar);
+
+ /* the find label */
+ item = gtk_tool_item_new ();
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+
+ label = gtk_label_new_with_mnemonic (_("Fi_nd:"));
+ gtk_container_add (GTK_CONTAINER (item), label);
+ gtk_misc_set_padding (GTK_MISC (label), 2, 0);
+ gtk_widget_show (label);
+
+ /* the entry field */
+ item = gtk_tool_item_new ();
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+
+ search_bar->entry = gtk_entry_new ();
+ gtk_container_add (GTK_CONTAINER (item), search_bar->entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), search_bar->entry);
+ gtk_widget_show (search_bar->entry);
+ g_signal_connect (G_OBJECT (search_bar->entry), "changed",
+ G_CALLBACK (mousepad_search_bar_entry_changed), search_bar);
+
+ /* next button */
+ image = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, TOOL_BAR_ICON_SIZE);
+ gtk_widget_show (image);
+
+ item = gtk_tool_button_new (image, _("_Next"));
+ gtk_tool_item_set_is_important (item, TRUE);
+ gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (item), TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+ g_signal_connect_swapped (G_OBJECT (item), "clicked",
+ G_CALLBACK (mousepad_search_bar_find_next), search_bar);
+
+ /* previous button */
+ image = gtk_image_new_from_stock (GTK_STOCK_GO_UP, TOOL_BAR_ICON_SIZE);
+ gtk_widget_show (image);
+
+ search_bar->previous = item = gtk_tool_button_new (image, _("_Previous"));
+ gtk_tool_item_set_is_important (item, TRUE);
+ gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (item), TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+ g_signal_connect_swapped (G_OBJECT (item), "clicked",
+ G_CALLBACK (mousepad_search_bar_find_previous), search_bar);
+
+ /* highlight all */
+ item = (GtkToolItem *) gtk_toggle_tool_button_new ();
+ gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), GTK_STOCK_SELECT_ALL);
+ gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), _("Highlight _All"));
+ gtk_tool_item_set_is_important (item, TRUE);
+ gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (item), TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+ g_signal_connect (G_OBJECT (item), "clicked",
+ G_CALLBACK (mousepad_search_bar_highlight_toggled), search_bar);
+
+ /* check button for case sensitive, including the proxy menu item */
+ item = gtk_tool_item_new ();
+ gtk_toolbar_insert (GTK_TOOLBAR (search_bar), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+
+ check = gtk_check_button_new_with_mnemonic (_("Mat_ch Case"));
+ gtk_container_add (GTK_CONTAINER (item), check);
+ gtk_widget_show (check);
+ g_signal_connect (G_OBJECT (check), "toggled",
+ G_CALLBACK (mousepad_search_bar_match_case_toggled), search_bar);
+
+ menuitem = gtk_check_menu_item_new_with_mnemonic (_("Mat_ch Case"));
+ gtk_tool_item_set_proxy_menu_item (item, "case-sensitive", menuitem);
+ exo_mutual_binding_new (G_OBJECT (check), "active", G_OBJECT (menuitem), "active");
+ gtk_widget_show (menuitem);
+}
+
+
+
+static void
+mousepad_search_bar_finalize (GObject *object)
+{
+ MousepadSearchBar *search_bar = MOUSEPAD_SEARCH_BAR (object);
+
+ /* stop a running highlight timeout */
+ if (search_bar->highlight_id != 0)
+ g_source_remove (search_bar->highlight_id);
+
+ (*G_OBJECT_CLASS (mousepad_search_bar_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_search_bar_find_string (MousepadSearchBar *search_bar,
+ MousepadSearchFlags flags)
+{
+ const gchar *string;
+ gboolean result;
+
+ /* append the insensitive flags when needed */
+ if (!search_bar->match_case)
+ flags |= MOUSEPAD_SEARCH_CASE_INSENSITIVE;
+
+ /* get the entry string */
+ string = gtk_entry_get_text (GTK_ENTRY (search_bar->entry));
+ if (string != NULL && *string != '\0')
+ {
+ /* send the signal and wait for the result */
+ g_signal_emit (G_OBJECT (search_bar), search_bar_signals[FIND_STRING], 0,
+ string, flags, &result);
+ }
+ else
+ {
+ result = TRUE;
+ }
+
+ /* change the entry style */
+ mousepad_search_bar_nothing_found (search_bar, !result);
+}
+
+
+
+static void
+mousepad_search_hide_clicked (MousepadSearchBar *search_bar)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* emit the signal */
+ g_signal_emit (G_OBJECT (search_bar), search_bar_signals[HIDE_BAR], 0);
+}
+
+
+
+static void
+mousepad_search_bar_entry_changed (GtkWidget *entry,
+ MousepadSearchBar *search_bar)
+{
+ /* stop a running highlight timeout */
+ if (search_bar->highlight_id != 0)
+ g_source_remove (search_bar->highlight_id);
+
+ if (search_bar->highlight_all)
+ {
+ /* start a new highlight timeout */
+ search_bar->highlight_id = g_timeout_add_full (G_PRIORITY_LOW, HIGHTLIGHT_TIMEOUT,
+ mousepad_search_bar_highlight_timeout, search_bar,
+ mousepad_search_bar_highlight_timeout_destroy);
+ }
+
+ /* find */
+ mousepad_search_bar_find_string (search_bar, 0);
+}
+
+
+
+static void
+mousepad_search_bar_highlight_toggled (GtkWidget *button,
+ MousepadSearchBar *search_bar)
+{
+ gboolean active;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* get the state of the toggle button */
+ active = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (button));
+
+ /* stop a running highlight timeout if the button is inactive*/
+ if (search_bar->highlight_id != 0 && !active)
+ g_source_remove (search_bar->highlight_id);
+
+ /* save the state */
+ search_bar->highlight_all = active;
+
+ /* invoke the highlight function to update the buffer */
+ search_bar->highlight_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_search_bar_highlight_timeout,
+ search_bar, mousepad_search_bar_highlight_timeout_destroy);
+}
+
+
+
+static void
+mousepad_search_bar_match_case_toggled (GtkWidget *button,
+ MousepadSearchBar *search_bar)
+{
+ gboolean active;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* get the state of the toggle button */
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+ /* save the state */
+ search_bar->match_case = active;
+}
+
+
+
+static gboolean
+mousepad_search_bar_highlight_timeout (gpointer user_data)
+{
+ MousepadSearchBar *search_bar = MOUSEPAD_SEARCH_BAR (user_data);
+ const gchar *string = NULL;
+ gboolean dummy;
+ MousepadSearchFlags flags;
+
+ GDK_THREADS_ENTER ();
+
+ /* append the insensitive case flag if needed */
+ if (!search_bar->match_case)
+ flags |= MOUSEPAD_SEARCH_CASE_INSENSITIVE;
+
+ /* get the string if highlighting is enabled */
+ if (search_bar->highlight_all)
+ {
+ /* get the entry string */
+ string = gtk_entry_get_text (GTK_ENTRY (search_bar->entry));
+ if (string == NULL || *string == '\0')
+ string = NULL;
+ }
+
+ /* send the signal and wait for the result */
+ g_signal_emit (G_OBJECT (search_bar), search_bar_signals[HIGHLIGHT_ALL], 0,
+ string, flags, &dummy);
+
+ GDK_THREADS_LEAVE ();
+
+ /* stop the timeout */
+ return FALSE;
+}
+
+
+
+static void
+mousepad_search_bar_highlight_timeout_destroy (gpointer user_data)
+{
+ MOUSEPAD_SEARCH_BAR (user_data)->highlight_id = 0;
+}
+
+
+
+static void
+mousepad_search_bar_nothing_found (MousepadSearchBar *search_bar,
+ gboolean nothing_found)
+{
+ const GdkColor red = {0, 0xffff, 0x6666, 0x6666};
+ const GdkColor white = {0, 0xffff, 0xffff, 0xffff};
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* only update the style if really needed */
+ if (search_bar->nothing_found != nothing_found)
+ {
+ /* (re)set the base and font color */
+ gtk_widget_modify_base (search_bar->entry, GTK_STATE_NORMAL, nothing_found ? &red : NULL);
+ gtk_widget_modify_text (search_bar->entry, GTK_STATE_NORMAL, nothing_found ? &white : NULL);
+
+ search_bar->nothing_found = nothing_found;
+ }
+}
+
+
+
+void
+mousepad_search_bar_focus (MousepadSearchBar *search_bar)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* focus the entry field */
+ gtk_widget_grab_focus (search_bar->entry);
+}
+
+
+
+void
+mousepad_search_bar_find_next (MousepadSearchBar *search_bar)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* find */
+ mousepad_search_bar_find_string (search_bar, MOUSEPAD_SEARCH_FORWARDS);
+}
+
+
+
+void
+mousepad_search_bar_find_previous (MousepadSearchBar *search_bar)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SEARCH_BAR (search_bar));
+
+ /* find backwards */
+ mousepad_search_bar_find_string (search_bar, MOUSEPAD_SEARCH_BACKWARDS);
+}
diff --git a/mousepad/mousepad-search-bar.h b/mousepad/mousepad-search-bar.h
new file mode 100644
index 0000000..8e36034
--- /dev/null
+++ b/mousepad/mousepad-search-bar.h
@@ -0,0 +1,47 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 __MOUSEPAD_SEARCH_BAR_H__
+#define __MOUSEPAD_SEARCH_BAR_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_SEARCH_BAR (mousepad_search_bar_get_type ())
+#define MOUSEPAD_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_SEARCH_BAR, MousepadSearchBar))
+#define MOUSEPAD_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_SEARCH_BAR, MousepadSearchBarClass))
+#define MOUSEPAD_IS_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_SEARCH_BAR))
+#define MOUSEPAD_IS_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_SEARCH_BAR))
+#define MOUSEPAD_SEARCH_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_SEARCH_BAR, MousepadSearchBarClass))
+
+typedef struct _MousepadSearchBarClass MousepadSearchBarClass;
+typedef struct _MousepadSearchBar MousepadSearchBar;
+
+GType mousepad_search_bar_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_search_bar_new (void);
+
+void mousepad_search_bar_focus (MousepadSearchBar *search_bar);
+
+void mousepad_search_bar_find_next (MousepadSearchBar *search_bar);
+
+void mousepad_search_bar_find_previous (MousepadSearchBar *search_bar);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_SEARCH_BAR_H__ */
diff --git a/mousepad/mousepad-statusbar.c b/mousepad/mousepad-statusbar.c
new file mode 100644
index 0000000..43a879a
--- /dev/null
+++ b/mousepad/mousepad-statusbar.c
@@ -0,0 +1,184 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-statusbar.h>
+
+static void mousepad_statusbar_class_init (MousepadStatusbarClass *klass);
+static void mousepad_statusbar_init (MousepadStatusbar *statusbar);
+static void mousepad_statusbar_finalize (GObject *object);
+
+struct _MousepadStatusbarClass
+{
+ GtkHBoxClass __parent__;
+};
+
+struct _MousepadStatusbar
+{
+ GtkHBox __parent__;
+
+ /* the three statusbar labels */
+ GtkWidget *label;
+ GtkWidget *position;
+ GtkWidget *overwrite;
+};
+
+
+
+static GObjectClass *mousepad_statusbar_parent_class;
+
+
+
+GtkWidget *
+mousepad_statusbar_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_STATUSBAR, NULL);
+}
+
+
+
+GType
+mousepad_statusbar_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_HBOX,
+ I_("MousepadStatusbar"),
+ sizeof (MousepadStatusbarClass),
+ (GClassInitFunc) mousepad_statusbar_class_init,
+ sizeof (MousepadStatusbar),
+ (GInstanceInitFunc) mousepad_statusbar_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_statusbar_class_init (MousepadStatusbarClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ mousepad_statusbar_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_statusbar_finalize;
+}
+
+
+
+static void
+mousepad_statusbar_init (MousepadStatusbar *statusbar)
+{
+ GtkWidget *frame;
+
+ /* spacing between the 3 frames */
+ gtk_box_set_spacing (GTK_BOX (statusbar), 3);
+
+ /* tooltip entry */
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start (GTK_BOX (statusbar), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ statusbar->label = gtk_label_new (NULL);
+ gtk_label_set_single_line_mode (GTK_LABEL (statusbar->label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (statusbar->label), 2, 2);
+ gtk_label_set_ellipsize (GTK_LABEL (statusbar->label), PANGO_ELLIPSIZE_END);
+ gtk_container_add (GTK_CONTAINER (frame), statusbar->label);
+ gtk_widget_show (statusbar->label);
+
+ /* line and column numbers */
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start (GTK_BOX (statusbar), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ statusbar->position = gtk_label_new (NULL);
+ gtk_container_add (GTK_CONTAINER (frame), statusbar->position);
+ gtk_misc_set_padding (GTK_MISC (statusbar->position), 2, 2);
+ gtk_widget_show (statusbar->position);
+
+ /* overwrite */
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start (GTK_BOX (statusbar), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ statusbar->overwrite = gtk_label_new (NULL);
+ gtk_container_add (GTK_CONTAINER (frame), statusbar->overwrite);
+ gtk_misc_set_padding (GTK_MISC (statusbar->overwrite), 2, 2);
+ gtk_widget_show (statusbar->overwrite);
+}
+
+
+
+static void
+mousepad_statusbar_finalize (GObject *object)
+{
+ (*G_OBJECT_CLASS (mousepad_statusbar_parent_class)->finalize) (object);
+}
+
+
+
+void
+mousepad_statusbar_set_text (MousepadStatusbar *statusbar,
+ const gchar *text)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_STATUSBAR (statusbar));
+
+ /* set the label text */
+ gtk_label_set_text (GTK_LABEL (statusbar->label), text);
+}
+
+
+
+void
+mousepad_statusbar_set_cursor_position (MousepadStatusbar *statusbar,
+ gint line,
+ gint column)
+{
+ gchar *string;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_STATUSBAR (statusbar));
+
+ string = g_strdup_printf (_("Line %d Col %d"), line, column);
+ gtk_label_set_text (GTK_LABEL (statusbar->position), string);
+ g_free (string);
+}
+
+
+
+void
+mousepad_statusbar_set_overwrite (MousepadStatusbar *statusbar,
+ gboolean overwrite)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_STATUSBAR (statusbar));
+
+ gtk_label_set_text (GTK_LABEL (statusbar->overwrite), overwrite ? _("OVR") : _("INS"));
+}
diff --git a/mousepad/mousepad-statusbar.h b/mousepad/mousepad-statusbar.h
new file mode 100644
index 0000000..f83b47f
--- /dev/null
+++ b/mousepad/mousepad-statusbar.h
@@ -0,0 +1,51 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 __MOUSEPAD_STATUSBAR_H__
+#define __MOUSEPAD_STATUSBAR_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_STATUSBAR (mousepad_statusbar_get_type ())
+#define MOUSEPAD_STATUSBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_STATUSBAR, MousepadStatusbar))
+#define MOUSEPAD_STATUSBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_STATUSBAR, MousepadStatusbarClass))
+#define MOUSEPAD_IS_STATUSBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_STATUSBAR))
+#define MOUSEPAD_IS_STATUSBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_STATUSBAR))
+#define MOUSEPAD_STATUSBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_STATUSBAR, MousepadStatusbarClass))
+
+typedef struct _MousepadStatusbarClass MousepadStatusbarClass;
+typedef struct _MousepadStatusbar MousepadStatusbar;
+
+GType mousepad_statusbar_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_statusbar_new (void);
+
+void mousepad_statusbar_set_text (MousepadStatusbar *statusbar,
+ const gchar *text);
+
+void mousepad_statusbar_set_cursor_position (MousepadStatusbar *statusbar,
+ gint line,
+ gint column);
+
+void mousepad_statusbar_set_overwrite (MousepadStatusbar *statusbar,
+ gboolean overwrite);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_STATUSBAR_H__ */
diff --git a/mousepad/mousepad-tab-label.c b/mousepad/mousepad-tab-label.c
deleted file mode 100644
index 0a8042f..0000000
--- a/mousepad/mousepad-tab-label.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
- *
- * 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 <mousepad/mousepad-private.h>
-#include <mousepad/mousepad-preferences.h>
-#include <mousepad/mousepad-tab-label.h>
-
-static void mousepad_tab_label_class_init (MousepadTabLabelClass *klass);
-static void mousepad_tab_label_init (MousepadTabLabel *window);
-static void mousepad_tab_label_finalize (GObject *object);
-static void mousepad_tab_label_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void mousepad_tab_label_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void mousepad_tab_label_close_tab (GtkWidget *widget,
- MousepadTabLabel *label);
-
-
-enum
-{
- PROP_0,
- PROP_TITLE,
- PROP_TOOLTIP,
-};
-
-enum
-{
- CLOSE_TAB,
- LAST_SIGNAL,
-};
-
-struct _MousepadTabLabelClass
-{
- GtkHBoxClass __parent__;
-
- /* signals */
- void (*close_tab) (MousepadTabLabel *label);
-};
-
-struct _MousepadTabLabel
-{
- GtkHBox __parent__;
-
- MousepadPreferences *preferences;
-
- GtkTooltips *tooltips;
- GtkWidget *ebox;
- GtkWidget *label;
-};
-
-
-static GObjectClass *mousepad_tab_label_parent_class;
-static guint label_signals[LAST_SIGNAL];
-
-
-
-GtkWidget *
-mousepad_tab_label_new (void)
-{
- return g_object_new (MOUSEPAD_TYPE_TAB_LABEL, NULL);
-}
-
-
-
-GType
-mousepad_tab_label_get_type (void)
-{
- static GType type = G_TYPE_INVALID;
-
- if (G_UNLIKELY (type == G_TYPE_INVALID))
- {
- type = g_type_register_static_simple (GTK_TYPE_HBOX,
- I_("MousepadTabLabel"),
- sizeof (MousepadTabLabelClass),
- (GClassInitFunc) mousepad_tab_label_class_init,
- sizeof (MousepadTabLabel),
- (GInstanceInitFunc) mousepad_tab_label_init,
- 0);
- }
-
- return type;
-}
-
-
-
-static void
-mousepad_tab_label_class_init (MousepadTabLabelClass *klass)
-{
- GObjectClass *gobject_class;
-
- mousepad_tab_label_parent_class = g_type_class_peek_parent (klass);
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->finalize = mousepad_tab_label_finalize;
- gobject_class->get_property = mousepad_tab_label_get_property;
- gobject_class->set_property = mousepad_tab_label_set_property;
-
- g_object_class_install_property (gobject_class,
- PROP_TITLE,
- g_param_spec_string ("title",
- "title",
- "title",
- NULL,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_TOOLTIP,
- g_param_spec_string ("tooltip",
- "tooltip",
- "tooltip",
- NULL,
- EXO_PARAM_READWRITE));
-
- label_signals[CLOSE_TAB] =
- g_signal_new ("close-tab",
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MousepadTabLabelClass, close_tab),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-
-
-static void
-mousepad_tab_label_init (MousepadTabLabel *label)
-{
- GtkWidget *button;
- GtkWidget *image;
-
- label->preferences = mousepad_preferences_get ();
-
- label->tooltips = gtk_tooltips_new ();
- g_object_ref (G_OBJECT (label->tooltips));
- gtk_object_sink (GTK_OBJECT (label->tooltips));
-
- gtk_widget_push_composite_child ();
-
- label->ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, NULL);
- GTK_WIDGET_SET_FLAGS (label->ebox, GTK_NO_WINDOW);
- gtk_box_pack_start (GTK_BOX (label), label->ebox, TRUE, TRUE, 0);
- gtk_widget_show (label->ebox);
-
- label->label = g_object_new (GTK_TYPE_LABEL,
- "selectable", FALSE,
- "xalign", 0.0, NULL);
- gtk_container_add (GTK_CONTAINER (label->ebox), label->label);
- gtk_widget_show (label->label);
-
- button = gtk_button_new ();
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
- gtk_container_set_border_width (GTK_CONTAINER (button), 0);
- gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
- GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_DEFAULT|GTK_CAN_FOCUS);
- gtk_tooltips_set_tip (label->tooltips, button, _("Close this tab"), NULL);
- gtk_box_pack_start (GTK_BOX (label), button, FALSE, FALSE, 0);
- exo_binding_new (G_OBJECT (label->preferences), "misc-tab-close-buttons", G_OBJECT (button), "visible");
-
- image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
- gtk_container_add (GTK_CONTAINER (button), image);
- gtk_widget_show (image);
-
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (mousepad_tab_label_close_tab), label);
-
- gtk_widget_pop_composite_child ();
-}
-
-
-
-static void
-mousepad_tab_label_finalize (GObject *object)
-{
- MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
-
- g_object_unref (G_OBJECT (label->preferences));
- g_object_unref (G_OBJECT (label->tooltips));
-
- (*G_OBJECT_CLASS (mousepad_tab_label_parent_class)->finalize) (object);
-}
-
-
-
-static void
-mousepad_tab_label_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
-
- switch (prop_id)
- {
- case PROP_TITLE:
- g_object_get_property (G_OBJECT (label->label), "label", value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
-mousepad_tab_label_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
- const gchar *title;
-
- switch (prop_id)
- {
- case PROP_TITLE:
- title = g_value_get_string (value);
- gtk_label_set_text (GTK_LABEL (label->label), title);
- break;
-
- case PROP_TOOLTIP:
- title = g_value_get_string (value);
- gtk_tooltips_set_tip (label->tooltips, label->ebox, title, NULL);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static void
-mousepad_tab_label_close_tab (GtkWidget *widget,
- MousepadTabLabel *label)
-{
- g_signal_emit (G_OBJECT (label), label_signals[CLOSE_TAB], 0);
-}
diff --git a/mousepad/mousepad-tab-label.h b/mousepad/mousepad-tab-label.h
deleted file mode 100644
index 1ce64d5..0000000
--- a/mousepad/mousepad-tab-label.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
- *
- * 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 __MOUSEPAD_TAB_LABEL_H__
-#define __MOUSEPAD_TAB_LABEL_H__
-
-G_BEGIN_DECLS
-
-#define MOUSEPAD_TYPE_TAB_LABEL (mousepad_tab_label_get_type ())
-#define MOUSEPAD_TAB_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabel))
-#define MOUSEPAD_TAB_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabelClass))
-#define MOUSEPAD_IS_TAB_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_TAB_LABEL))
-#define MOUSEPAD_IS_TAB_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_TAB_LABEL))
-#define MOUSEPAD_TAB_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabelClass))
-
-typedef struct _MousepadTabLabelClass MousepadTabLabelClass;
-typedef struct _MousepadTabLabel MousepadTabLabel;
-
-GType mousepad_tab_label_get_type (void) G_GNUC_CONST;
-
-GtkWidget *mousepad_tab_label_new (void);
-
-G_END_DECLS
-
-#endif /* !__MOUSEPAD_TAB_LABEL_H__ */
diff --git a/mousepad/mousepad-types.h b/mousepad/mousepad-types.h
new file mode 100644
index 0000000..a1aa178
--- /dev/null
+++ b/mousepad/mousepad-types.h
@@ -0,0 +1,34 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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 __MOUSEPAD_TYPES_H__
+#define __MOUSEPAD_TYPES_H__
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ MOUSEPAD_SEARCH_CASE_INSENSITIVE = 1 << 1,
+ MOUSEPAD_SEARCH_FORWARDS = 1 << 2,
+ MOUSEPAD_SEARCH_BACKWARDS = 1 << 3,
+} MousepadSearchFlags;
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_TYPES_H__ */
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index b0c181d..ed70907 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -64,8 +64,8 @@ struct _MousepadView
GtkTextView __parent__;
/* settings */
- gboolean auto_indent;
- gboolean line_numbers;
+ guint auto_indent : 1;
+ guint line_numbers : 1;
};
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
index 9c2e2d0..25b4096 100644
--- a/mousepad/mousepad-window-ui.xml
+++ b/mousepad/mousepad-window-ui.xml
@@ -55,10 +55,11 @@
<menuitem action="font" />
<separator />
<menuitem action="statusbar" />
- <separator />
+ </menu>
+
+ <menu action="document-menu">
<menuitem action="word-wrap" />
<menuitem action="line-numbers" />
- <separator />
<menuitem action="auto-indent" />
</menu>
@@ -73,4 +74,13 @@
<menuitem action="about" />
</menu>
</menubar>
+
+ <popup action="tab-menu">
+ <menuitem action="save-file" />
+ <menuitem action="save-file-as" />
+ <separator />
+ <menuitem action="reload" />
+ <separator />
+ <menuitem action="close-tab" />
+ </popup>
</ui>
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index 9debbd7..66af452 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -32,19 +32,24 @@
#include <unistd.h>
#endif
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-types.h>
#include <mousepad/mousepad-application.h>
+#include <mousepad/mousepad-exo.h>
+#include <mousepad/mousepad-document.h>
#include <mousepad/mousepad-dialogs.h>
#include <mousepad/mousepad-preferences.h>
-#include <mousepad/mousepad-private.h>
-#include <mousepad/mousepad-file.h>
-#include <mousepad/mousepad-screen.h>
-#include <mousepad/mousepad-view.h>
-#include <mousepad/mousepad-tab-label.h>
+#include <mousepad/mousepad-search-bar.h>
+#include <mousepad/mousepad-statusbar.h>
#include <mousepad/mousepad-window.h>
#include <mousepad/mousepad-window-ui.h>
+#define WINDOW_SPACING 3
+
+
+
/* class functions */
static void mousepad_window_class_init (MousepadWindowClass *klass);
static void mousepad_window_init (MousepadWindow *window);
@@ -72,48 +77,67 @@ static gboolean mousepad_window_save_geometry_timer (gpointer
static void mousepad_window_save_geometry_timer_destroy (gpointer user_data);
/* window functions */
-static MousepadScreen *mousepad_window_get_active (MousepadWindow *window);
static gboolean mousepad_window_save (MousepadWindow *window,
- MousepadScreen *screen,
+ MousepadDocument *document,
gboolean force_save_as);
static void mousepad_window_add (MousepadWindow *window,
- MousepadScreen *screen);
-static gboolean mousepad_window_close_screen (MousepadWindow *window,
- MousepadScreen *screen);
+ MousepadDocument *document);
+static gboolean mousepad_window_close_document (MousepadWindow *window,
+ MousepadDocument *document);
static void mousepad_window_set_title (MousepadWindow *window,
- MousepadScreen *screen);
+ MousepadDocument *document);
/* notebook signals */
static void mousepad_window_page_notified (GtkNotebook *notebook,
GParamSpec *pspec,
MousepadWindow *window);
static void mousepad_window_tab_removed (GtkNotebook *notebook,
- MousepadScreen *screen,
+ MousepadDocument *document,
MousepadWindow *window);
static void mousepad_window_page_reordered (GtkNotebook *notebook,
GtkNotebookPage *page,
guint page_num,
MousepadWindow *window);
+static void mousepad_window_tab_popup_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data);
+static gboolean mousepad_window_tab_popup (GtkNotebook *notebook,
+ GdkEventButton *event,
+ MousepadWindow *window);
-/* screen signals */
-static void mousepad_window_notify_title (MousepadScreen *screen,
+/* document signals */
+static void mousepad_window_notify_title (MousepadDocument *document,
GParamSpec *pspec,
MousepadWindow *window);
-static void mousepad_window_modified_changed (MousepadScreen *screen,
+static void mousepad_window_modified_changed (MousepadDocument *document,
+ MousepadWindow *window);
+static void mousepad_window_cursor_changed (MousepadDocument *document,
+ guint line,
+ guint column,
+ MousepadWindow *window);
+static void mousepad_window_overwrite_changed (MousepadDocument *document,
+ gboolean overwrite,
MousepadWindow *window);
-static void mousepad_window_selection_changed (MousepadScreen *screen,
+static void mousepad_window_selection_changed (MousepadDocument *document,
gboolean selected,
MousepadWindow *window);
/* menu updaters */
static void mousepad_window_update_actions (MousepadWindow *window);
+static gboolean mousepad_window_update_gomenu_idle (gpointer user_data);
+static void mousepad_window_update_gomenu_idle_destroy (gpointer user_data);
static void mousepad_window_update_gomenu (MousepadWindow *window);
/* recent functions */
static void mousepad_window_recent_add (MousepadWindow *window,
const gchar *filename);
+static gchar *mousepad_window_recent_escape_underscores (const gchar *str);
static gint mousepad_window_recent_sort (GtkRecentInfo *a,
GtkRecentInfo *b);
+static gboolean mousepad_window_recent_menu_idle (gpointer user_data);
+static void mousepad_window_recent_menu_idle_destroy (gpointer user_data);
static void mousepad_window_recent_menu (MousepadWindow *window);
static void mousepad_window_recent_clear (MousepadWindow *window);
@@ -150,10 +174,26 @@ static void mousepad_window_action_delete (GtkAction
MousepadWindow *window);
static void mousepad_window_action_select_all (GtkAction *action,
MousepadWindow *window);
+static void mousepad_window_action_find (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_find_next (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_find_previous (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_replace (GtkAction *action,
+ MousepadWindow *window);
static void mousepad_window_action_jump_to (GtkAction *action,
MousepadWindow *window);
static void mousepad_window_action_select_font (GtkAction *action,
MousepadWindow *window);
+static void mousepad_window_action_statusbar (GtkToggleAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_word_wrap (GtkToggleAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_line_numbers (GtkToggleAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_auto_indent (GtkToggleAction *action,
+ MousepadWindow *window);
static void mousepad_window_action_prev_tab (GtkAction *action,
MousepadWindow *window);
static void mousepad_window_action_next_tab (GtkAction *action,
@@ -164,7 +204,8 @@ static void mousepad_window_action_about (GtkAction
MousepadWindow *window);
/* miscellaneous actions */
-static void mousepad_window_button_close_tab (MousepadScreen *screen);
+static void mousepad_window_button_close_tab (MousepadDocument *document,
+ MousepadWindow *window);
static gboolean mousepad_window_delete_event (MousepadWindow *window,
GdkEvent *event);
@@ -180,8 +221,12 @@ struct _MousepadWindow
{
GtkWindow __parent__;
+ /* mousepad preferences */
MousepadPreferences *preferences;
+ /* the current active document */
+ MousepadDocument *active;
+
/* closures for the menu callbacks */
GClosure *menu_item_selected_closure;
GClosure *menu_item_deselected_closure;
@@ -198,11 +243,18 @@ struct _MousepadWindow
GtkRecentManager *recent_manager;
/* main window widgets */
+ GtkWidget *table;
GtkWidget *notebook;
+ GtkWidget *container;
+ GtkWidget *search_bar;
GtkWidget *statusbar;
/* support to remember window geometry */
- gint save_geometry_timer_id;
+ guint save_geometry_timer_id;
+
+ /* idle update functions for the recent and go menu */
+ guint update_recent_menu_id;
+ guint update_go_menu_id;
};
@@ -233,15 +285,17 @@ static const GtkActionEntry action_entries[] =
{ "select-all", GTK_STOCK_SELECT_ALL, N_("Select _All"), NULL, N_("Select the entire document"), G_CALLBACK (mousepad_window_action_select_all), },
{ "search-menu", NULL, N_("_Search"), NULL, NULL, NULL, },
- { "find", GTK_STOCK_FIND, N_("_Find"), NULL, N_("Search for text"), NULL, },
- { "find-next", NULL, N_("Find _Next"), NULL, N_("Search forwards for the same text"), NULL, },
- { "find-previous", NULL, N_("Find _Previous"), NULL, N_("Search backwards for the same text"), NULL, },
- { "replace", GTK_STOCK_FIND_AND_REPLACE, N_("_Replace"), NULL, N_("Search for and replace text"), NULL, },
+ { "find", GTK_STOCK_FIND, N_("_Find"), NULL, N_("Search for text"), G_CALLBACK (mousepad_window_action_find), },
+ { "find-next", NULL, N_("Find _Next"), NULL, N_("Search forwards for the same text"), G_CALLBACK (mousepad_window_action_find_next), },
+ { "find-previous", NULL, N_("Find _Previous"), NULL, N_("Search backwards for the same text"), G_CALLBACK (mousepad_window_action_find_previous), },
+ { "replace", GTK_STOCK_FIND_AND_REPLACE, N_("_Replace"), NULL, N_("Search for and replace text"), G_CALLBACK (mousepad_window_action_replace), },
{ "jump-to", GTK_STOCK_JUMP_TO, N_("_Jump To"), NULL, N_("Go to a specific line"), G_CALLBACK (mousepad_window_action_jump_to), },
{ "view-menu", NULL, N_("_View"), NULL, NULL, NULL, },
{ "font", GTK_STOCK_SELECT_FONT, N_("_Font"), NULL, N_("Change the editor font"), G_CALLBACK (mousepad_window_action_select_font), },
+ { "document-menu", NULL, N_("_Document"), NULL, NULL, NULL, },
+
{ "go-menu", NULL, N_("_Go"), NULL, },
{ "back", GTK_STOCK_GO_BACK, N_("Back"), NULL, N_("Select the previous tab"), G_CALLBACK (mousepad_window_action_prev_tab), },
{ "forward", GTK_STOCK_GO_FORWARD, N_("Forward"), NULL, N_("Select the next tab"), G_CALLBACK (mousepad_window_action_next_tab), },
@@ -252,10 +306,10 @@ static const GtkActionEntry action_entries[] =
static const GtkToggleActionEntry toggle_action_entries[] =
{
- { "statusbar", NULL, N_("_Statusbar"), NULL, N_("Change the visibility of the statusbar"), NULL, FALSE, },
- { "word-wrap", NULL, N_("_Word Wrap"), NULL, N_("Toggle breaking lines in between words"), NULL, FALSE, },
- { "line-numbers", NULL, N_("_Line Numbers"), NULL, N_("Change the visibility of the line numbers"), NULL, FALSE, },
- { "auto-indent", NULL, N_("_Auto Indent"), NULL, N_("Toggle automatic line indentation"), NULL, FALSE, },
+ { "statusbar", NULL, N_("_Statusbar"), NULL, N_("Change the visibility of the statusbar"), G_CALLBACK (mousepad_window_action_statusbar), FALSE, },
+ { "word-wrap", NULL, N_("_Word Wrap"), NULL, N_("Toggle breaking lines in between words"), G_CALLBACK (mousepad_window_action_word_wrap), FALSE, },
+ { "line-numbers", NULL, N_("_Line Numbers"), NULL, NULL, G_CALLBACK (mousepad_window_action_line_numbers), FALSE, },
+ { "auto-indent", NULL, N_("_Auto Indent"), NULL, NULL, G_CALLBACK (mousepad_window_action_auto_indent), FALSE, },
};
@@ -264,7 +318,6 @@ static GObjectClass *mousepad_window_parent_class;
static gboolean lock_menu_updates = FALSE;
-
GtkWidget *
mousepad_window_new (void)
{
@@ -311,18 +364,28 @@ mousepad_window_class_init (MousepadWindowClass *klass)
}
+
static void
mousepad_window_init (MousepadWindow *window)
{
GtkAccelGroup *accel_group;
GtkWidget *menubar;
- GtkWidget *vbox;
GtkWidget *label;
GtkWidget *separator;
GtkWidget *ebox;
GtkAction *action;
gint width, height;
+ gboolean visible;
+ /* initialize stuff */
+ window->save_geometry_timer_id = 0;
+ window->update_recent_menu_id = 0;
+ window->update_go_menu_id = 0;
+ window->search_bar = NULL;
+ window->statusbar = NULL;
+ window->active = NULL;
+
+ /* add the preferences to the window */
window->preferences = mousepad_preferences_get ();
/* allocate a closure for the menu_item_selected() callback */
@@ -335,7 +398,7 @@ mousepad_window_init (MousepadWindow *window)
g_closure_ref (window->menu_item_deselected_closure);
g_closure_sink (window->menu_item_deselected_closure);
- /* signal for monitoring */
+ /* signal for handling the window delete event */
g_signal_connect (G_OBJECT (window), "delete-event",
G_CALLBACK (mousepad_window_delete_event), NULL);
@@ -354,16 +417,7 @@ mousepad_window_init (MousepadWindow *window)
gtk_action_group_add_actions (window->window_actions, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
gtk_action_group_add_toggle_actions (window->window_actions, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
- /* create mutual bindings for the toggle buttons */
- action = gtk_action_group_get_action (window->window_actions, "line-numbers");
- exo_mutual_binding_new (G_OBJECT (window->preferences), "line-numbers", G_OBJECT (action), "active");
- action = gtk_action_group_get_action (window->window_actions, "auto-indent");
- exo_mutual_binding_new (G_OBJECT (window->preferences), "auto-indent", G_OBJECT (action), "active");
- action = gtk_action_group_get_action (window->window_actions, "statusbar");
- exo_mutual_binding_new (G_OBJECT (window->preferences), "statusbar", G_OBJECT (action), "active");
- action = gtk_action_group_get_action (window->window_actions, "word-wrap");
- exo_mutual_binding_new (G_OBJECT (window->preferences), "word-wrap", G_OBJECT (action), "active");
-
+ /* create the ui manager and connect proxy signals for the statusbar */
window->ui_manager = gtk_ui_manager_new ();
g_signal_connect (G_OBJECT (window->ui_manager), "connect-proxy", G_CALLBACK (mousepad_window_connect_proxy), window);
g_signal_connect (G_OBJECT (window->ui_manager), "disconnect-proxy", G_CALLBACK (mousepad_window_disconnect_proxy), window);
@@ -375,7 +429,7 @@ mousepad_window_init (MousepadWindow *window)
window->recent_actions = gtk_action_group_new ("RecentActions");
gtk_ui_manager_insert_action_group (window->ui_manager, window->recent_actions, -1);
g_signal_connect_swapped (G_OBJECT (window->recent_manager), "changed",
- G_CALLBACK (mousepad_window_recent_menu), window);
+ G_CALLBACK (mousepad_window_recent_menu), window);
/* create the recent menu */
mousepad_window_recent_menu (window);
@@ -388,12 +442,12 @@ mousepad_window_init (MousepadWindow *window)
accel_group = gtk_ui_manager_get_accel_group (window->ui_manager);
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (window), vbox);
- gtk_widget_show (vbox);
+ window->table = gtk_table_new (6, 1, FALSE);
+ gtk_container_add (GTK_CONTAINER (window), window->table);
+ gtk_widget_show (window->table);
menubar = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu");
- gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
+ gtk_table_attach (GTK_TABLE (window->table), menubar, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (menubar);
/* check if we need to add the root warning */
@@ -407,7 +461,7 @@ mousepad_window_init (MousepadWindow *window)
/* add the box for the root warning */
ebox = gtk_event_box_new ();
gtk_widget_set_name (ebox, "root-warning");
- gtk_box_pack_start (GTK_BOX (vbox), ebox, FALSE, FALSE, 0);
+ gtk_table_attach (GTK_TABLE (window->table), ebox, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (ebox);
/* add the label with the root warning */
@@ -417,7 +471,7 @@ mousepad_window_init (MousepadWindow *window)
gtk_widget_show (label);
separator = gtk_hseparator_new ();
- gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
+ gtk_table_attach (GTK_TABLE (window->table), separator, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (separator);
}
@@ -438,14 +492,18 @@ mousepad_window_init (MousepadWindow *window)
G_CALLBACK (mousepad_window_tab_removed), window);
g_signal_connect (G_OBJECT (window->notebook), "page-reordered",
G_CALLBACK (mousepad_window_page_reordered), window);
+ g_signal_connect (G_OBJECT (window->notebook), "button-press-event",
+ G_CALLBACK (mousepad_window_tab_popup), window);
- gtk_box_pack_start (GTK_BOX (vbox), window->notebook, TRUE, TRUE, 0);
+ /* append and show the notebook */
+ gtk_table_attach (GTK_TABLE (window->table), window->notebook, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_table_set_row_spacing (GTK_TABLE (window->table), 2, WINDOW_SPACING);
gtk_widget_show (window->notebook);
- /* create the statusbar */
- window->statusbar = g_object_new (GTK_TYPE_STATUSBAR, NULL);
- gtk_box_pack_start (GTK_BOX (vbox), window->statusbar, FALSE, FALSE, 0);
- exo_binding_new (G_OBJECT (window->preferences), "statusbar", G_OBJECT (window->statusbar), "visible");
+ /* check if we should display the statusbar by default */
+ g_object_get (G_OBJECT (window->preferences), "last-statusbar-visible", &visible, NULL);
+ action = gtk_action_group_get_action (window->window_actions, "statusbar");
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
}
@@ -456,7 +514,7 @@ mousepad_window_dispose (GObject *object)
MousepadWindow *window = MOUSEPAD_WINDOW (object);
/* destroy the save geometry timer source */
- if (G_UNLIKELY (window->save_geometry_timer_id > 0))
+ if (G_UNLIKELY (window->save_geometry_timer_id != 0))
g_source_remove (window->save_geometry_timer_id);
(*G_OBJECT_CLASS (mousepad_window_parent_class)->dispose) (object);
@@ -469,6 +527,14 @@ mousepad_window_finalize (GObject *object)
{
MousepadWindow *window = MOUSEPAD_WINDOW (object);
+ /* cancel a scheduled recent menu update */
+ if (G_UNLIKELY (window->update_recent_menu_id != 0))
+ g_source_remove (window->update_recent_menu_id);
+
+ /* cancel a scheduled go menu update */
+ if (G_UNLIKELY (window->update_go_menu_id != 0))
+ g_source_remove (window->update_go_menu_id);
+
/* drop our references on the menu_item_selected()/menu_item_deselected() closures */
g_closure_unref (window->menu_item_deselected_closure);
g_closure_unref (window->menu_item_selected_closure);
@@ -558,23 +624,24 @@ mousepad_window_menu_item_selected (GtkWidget *menu_item,
{
GtkAction *action;
gchar *tooltip;
- gint id;
/* we can only display tooltips if we have a statusbar */
if (G_LIKELY (window->statusbar != NULL))
{
- /* determine the action for the menu item */
+ /* get the action from the menu item */
action = g_object_get_data (G_OBJECT (menu_item), I_("gtk-action"));
- if (G_UNLIKELY (action == NULL))
- return;
-
- /* determine the tooltip from the action */
- g_object_get (G_OBJECT (action), "tooltip", &tooltip, NULL);
- if (G_LIKELY (tooltip != NULL))
+ if (G_LIKELY (action))
{
- id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
- gtk_statusbar_push (GTK_STATUSBAR (window->statusbar), id, tooltip);
- g_free (tooltip);
+ /* read the tooltip from the action, if there is one */
+ g_object_get (G_OBJECT (action), "tooltip", &tooltip, NULL);
+ if (G_LIKELY (tooltip != NULL))
+ {
+ /* show the tooltip */
+ mousepad_statusbar_set_text (MOUSEPAD_STATUSBAR (window->statusbar), tooltip);
+
+ /* cleanup */
+ g_free (tooltip);
+ }
}
}
}
@@ -585,14 +652,11 @@ static void
mousepad_window_menu_item_deselected (GtkWidget *menu_item,
MousepadWindow *window)
{
- gint id;
-
/* we can only undisplay tooltips if we have a statusbar */
if (G_LIKELY (window->statusbar != NULL))
{
- /* drop the last tooltip from the statusbar */
- id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
- gtk_statusbar_pop (GTK_STATUSBAR (window->statusbar), id);
+ /* hide the tip from the statusbar */
+ mousepad_statusbar_set_text (MOUSEPAD_STATUSBAR (window->statusbar), NULL);
}
}
@@ -654,27 +718,11 @@ mousepad_window_save_geometry_timer_destroy (gpointer user_data)
/**
* Mousepad Window Functions
**/
-static MousepadScreen *
-mousepad_window_get_active (MousepadWindow *window)
-{
- GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
- gint page_num;
-
- page_num = gtk_notebook_get_current_page (notebook);
-
- if (G_LIKELY (page_num >= 0))
- return MOUSEPAD_SCREEN (gtk_notebook_get_nth_page (notebook, page_num));
- else
- return NULL;
-}
-
-
-
gboolean
mousepad_window_open_tab (MousepadWindow *window,
const gchar *filename)
{
- GtkWidget *screen;
+ GtkWidget *document;
GError *error = NULL;
gboolean succeed = TRUE;
gint npages = 0, i;
@@ -687,15 +735,15 @@ mousepad_window_open_tab (MousepadWindow *window,
/* walk though the tabs */
for (i = 0; i < npages; i++)
{
- screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
+ document = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
- if (G_LIKELY (screen != NULL))
+ if (G_LIKELY (document != NULL))
{
/* get the filename */
- opened_filename = mousepad_screen_get_filename (MOUSEPAD_SCREEN (screen));
+ opened_filename = mousepad_document_get_filename (MOUSEPAD_DOCUMENT (document));
/* see if the file is already opened */
- if (exo_str_is_equal (filename, opened_filename))
+ if (opened_filename && strcmp (filename, opened_filename))
{
/* switch to the tab */
gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
@@ -706,22 +754,22 @@ mousepad_window_open_tab (MousepadWindow *window,
}
}
- /* new screen */
- screen = mousepad_screen_new ();
+ /* new document */
+ document = mousepad_document_new ();
if (filename)
- /* load the file content in the screen */
- succeed = mousepad_screen_open_file (MOUSEPAD_SCREEN (screen), filename, &error);
+ /* load the file content in the document */
+ succeed = mousepad_document_open_file (MOUSEPAD_DOCUMENT (document), filename, &error);
if (G_LIKELY (succeed))
{
- /* add the screen to the notebook and connect some signals */
- mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+ /* add the document to the notebook and connect some signals */
+ mousepad_window_add (window, MOUSEPAD_DOCUMENT (document));
}
else
{
- /* something went wrong, remove the screen */
- gtk_widget_destroy (GTK_WIDGET (screen));
+ /* something went wrong, remove the document */
+ gtk_widget_destroy (GTK_WIDGET (document));
/* show the warning */
mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
@@ -733,18 +781,18 @@ mousepad_window_open_tab (MousepadWindow *window,
-void
+gboolean
mousepad_window_open_files (MousepadWindow *window,
const gchar *working_directory,
gchar **filenames)
{
- gint n;
+ gint n, npages;
gchar *filename = NULL;
- _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
- _mousepad_return_if_fail (working_directory != NULL);
- _mousepad_return_if_fail (filenames != NULL);
- _mousepad_return_if_fail (*filenames != NULL);
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+ _mousepad_return_val_if_fail (working_directory != NULL, FALSE);
+ _mousepad_return_val_if_fail (filenames != NULL, FALSE);
+ _mousepad_return_val_if_fail (*filenames != NULL, FALSE);
/* block menu updates */
lock_menu_updates = TRUE;
@@ -775,28 +823,35 @@ mousepad_window_open_files (MousepadWindow *window,
/* allow menu updates again */
lock_menu_updates = FALSE;
+ /* check if there were tabs opened, if not we return false and in
+ * window-application we open an empty tab */
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+ if (G_UNLIKELY (npages == 0))
+ return FALSE;
+
/* update the menus */
mousepad_window_recent_menu (window);
mousepad_window_update_gomenu (window);
+
+ return TRUE;
}
static gboolean
-mousepad_window_save (MousepadWindow *window,
- MousepadScreen *screen,
- gboolean force_save_as)
+mousepad_window_save (MousepadWindow *window,
+ MousepadDocument *document,
+ gboolean force_save_as)
{
gchar *new_filename = NULL;
const gchar *filename;
gboolean succeed = FALSE;
GError *error = NULL;
const gchar *message;
- gint mtime;
gint action = MOUSEPAD_RESPONSE_OVERWRITE;
/* get the current filename */
- filename = mousepad_screen_get_filename (screen);
+ filename = mousepad_document_get_filename (document);
if (force_save_as || filename == NULL)
{
@@ -806,7 +861,7 @@ mousepad_window_save (MousepadWindow *window,
if (new_filename)
{
/* try the save the file */
- succeed = mousepad_screen_save_file (screen, new_filename, &error);
+ succeed = mousepad_document_save_file (document, new_filename, &error);
/* the warnings message for save as */
message = _("Failed to save the document as another file");
@@ -814,9 +869,9 @@ mousepad_window_save (MousepadWindow *window,
if (succeed)
{
/* set the filename */
- mousepad_screen_set_filename (screen, new_filename);
+ mousepad_document_set_filename (document, new_filename);
- /* add the item to the recent menu */
+ /* add the new document to the recent menu */
mousepad_window_recent_add (window, new_filename);
}
@@ -826,19 +881,16 @@ mousepad_window_save (MousepadWindow *window,
}
else
{
- /* get the mtime */
- mtime = mousepad_screen_get_mtime (screen);
-
/* check if the file has been modified externally, if so ask the user if
* he or she wants to overwrite/reload or cancel the action */
- if (G_UNLIKELY (mousepad_file_get_externally_modified (filename, mtime)))
+ if (G_UNLIKELY (mousepad_document_get_externally_modified (document)))
action = mousepad_dialogs_ask_overwrite (GTK_WINDOW (window), filename);
switch (action)
{
case MOUSEPAD_RESPONSE_OVERWRITE:
/* save the file */
- succeed = mousepad_screen_save_file (screen, filename, &error);
+ succeed = mousepad_document_save_file (document, filename, &error);
/* the warning message for save */
message = _("Failed to save the document");
@@ -846,7 +898,7 @@ mousepad_window_save (MousepadWindow *window,
case MOUSEPAD_RESPONSE_RELOAD:
/* reload the document */
- succeed = mousepad_screen_reload (screen, &error);
+ succeed = mousepad_document_reload (document, &error);
/* the warning message for save */
message = _("Failed to reload the document");
@@ -871,45 +923,38 @@ mousepad_window_save (MousepadWindow *window,
static void
-mousepad_window_add (MousepadWindow *window,
- MousepadScreen *screen)
+mousepad_window_add (MousepadWindow *window,
+ MousepadDocument *document)
{
- GtkWidget *label;
- gboolean always_show_tabs;
- gint page, npages;
- MousepadScreen *active;
+ GtkWidget *label;
+ gboolean always_show_tabs;
+ gboolean word_wrap;
+ gint page, npages;
+ MousepadDocument *active;
_mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- /* connect some bindings to the screen */
- exo_binding_new (G_OBJECT (window->preferences), "line-numbers", G_OBJECT (screen), "line-numbers");
- exo_binding_new (G_OBJECT (window->preferences), "word-wrap", G_OBJECT (screen), "word-wrap");
- exo_binding_new (G_OBJECT (window->preferences), "auto-indent", G_OBJECT (screen), "auto-indent");
- exo_binding_new (G_OBJECT (window->preferences), "font-name", G_OBJECT (screen), "font-name");
-
- label = mousepad_tab_label_new ();
- gtk_widget_show (label);
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
- /* add the window to the screen */
- g_object_set_data (G_OBJECT (screen), I_("mousepad-window"), window);
+ /* conect an exo binding to set the widget font */
+ exo_binding_new (G_OBJECT (window->preferences), "font-name", G_OBJECT (document), "font-name");
- /* connect some bindings and signals to the tab label */
- exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (label), "title");
- exo_binding_new (G_OBJECT (screen), "filename", G_OBJECT (label), "tooltip");
- g_signal_connect_swapped (G_OBJECT (label), "close-tab", G_CALLBACK (mousepad_window_button_close_tab), screen);
- g_signal_connect (G_OBJECT (screen), "notify::title", G_CALLBACK (mousepad_window_notify_title), window);
+ /* create the tab label */
+ label = mousepad_document_get_tab_label (document);
- g_signal_connect (G_OBJECT (screen), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
- g_signal_connect (G_OBJECT (screen), "modified-changed", G_CALLBACK (mousepad_window_modified_changed), window);
+ /* signals for the document */
+ g_signal_connect (G_OBJECT (document), "close-tab", G_CALLBACK (mousepad_window_button_close_tab), window);
+ g_signal_connect (G_OBJECT (document), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
+ g_signal_connect (G_OBJECT (document), "modified-changed", G_CALLBACK (mousepad_window_modified_changed), window);
+ g_signal_connect (G_OBJECT (document), "cursor-changed", G_CALLBACK (mousepad_window_cursor_changed), window);
+ g_signal_connect (G_OBJECT (document), "overwrite-changed", G_CALLBACK (mousepad_window_overwrite_changed), window);
+ g_signal_connect (G_OBJECT (document), "notify::title", G_CALLBACK (mousepad_window_notify_title), window);
- /* insert the page */
+ /* insert the page right from the active tab */
page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
- page = gtk_notebook_insert_page (GTK_NOTEBOOK (window->notebook),
- GTK_WIDGET (screen), label, page + 1);
+ page = gtk_notebook_insert_page (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (document), label, page + 1);
/* allow tab reordering */
- gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), TRUE);
+ gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (document), TRUE);
/* check if we should always display tabs */
g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL);
@@ -921,41 +966,44 @@ mousepad_window_add (MousepadWindow *window,
/* don't focus the notebook */
GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
+ /* set the wrapping mode */
+ g_object_get (G_OBJECT (window->preferences), "word-wrap", &word_wrap, NULL);
+ mousepad_document_set_word_wrap (document, word_wrap);
+
/* rebuild the go menu */
mousepad_window_update_gomenu (window);
- /* show the screen */
- gtk_widget_show (GTK_WIDGET (screen));
+ /* show the document */
+ gtk_widget_show (GTK_WIDGET (document));
/* get the active tab */
- active = mousepad_window_get_active (window);
+ active = window->active;
/* switch to the new tab */
gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page);
- /* destroy the (old) active tab if it's empty
- * and the new tab is not */
+ /* destroy the previous tab if it was not modified, untitled and the new tab is not untitled */
if (active != NULL &&
- mousepad_screen_get_modified (active) == FALSE &&
- mousepad_screen_get_filename (active) == NULL &&
- mousepad_screen_get_filename (screen) != NULL)
+ mousepad_document_get_modified (active) == FALSE &&
+ mousepad_document_get_filename (active) == NULL &&
+ mousepad_document_get_filename (document) != NULL)
gtk_widget_destroy (GTK_WIDGET (active));
}
static gboolean
-mousepad_window_close_screen (MousepadWindow *window,
- MousepadScreen *screen)
+mousepad_window_close_document (MousepadWindow *window,
+ MousepadDocument *document)
{
gint response;
gboolean succeed = FALSE;
_mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
/* check if the document needs to be saved */
- if (mousepad_screen_get_modified (screen))
+ if (mousepad_document_get_modified (document))
{
/* run the dialog */
response = mousepad_dialogs_save_changes (GTK_WINDOW (window));
@@ -963,26 +1011,26 @@ mousepad_window_close_screen (MousepadWindow *window,
switch (response)
{
case MOUSEPAD_RESPONSE_DONT_SAVE:
- /* don't save, only destroy the screen */
+ /* don't save, only destroy the document */
succeed = TRUE;
break;
case MOUSEPAD_RESPONSE_CANCEL:
/* we do nothing */
break;
case MOUSEPAD_RESPONSE_SAVE:
- succeed = mousepad_window_save (window, screen, FALSE);
+ succeed = mousepad_window_save (window, document, FALSE);
break;
}
}
else
{
- /* no changes in the screen, safe to destroy it */
+ /* no changes in the document, safe to destroy it */
succeed = TRUE;
}
- /* destroy the screen */
+ /* destroy the document */
if (succeed)
- gtk_widget_destroy (GTK_WIDGET (screen));
+ gtk_widget_destroy (GTK_WIDGET (document));
return succeed;
}
@@ -990,24 +1038,20 @@ mousepad_window_close_screen (MousepadWindow *window,
static void
-mousepad_window_set_title (MousepadWindow *window,
- MousepadScreen *screen)
+mousepad_window_set_title (MousepadWindow *window,
+ MousepadDocument *document)
{
gchar *string;
const gchar *title;
gboolean show_full_path;
- GtkTextView *textview;
-
- /* get the active textview */
- textview = mousepad_screen_get_text_view (screen);
/* whether to show the full path in the window title */
g_object_get (G_OBJECT (window->preferences), "misc-show-full-path-in-title", &show_full_path, NULL);
/* the window title */
- title = mousepad_screen_get_title (screen, show_full_path);
+ title = mousepad_document_get_title (document, show_full_path);
- if (!gtk_text_view_get_editable (textview))
+ if (G_UNLIKELY (mousepad_document_get_readonly (document)))
{
string = g_strdup_printf ("%s [%s] - %s",
title, _("Read Only"), PACKAGE_NAME);
@@ -1015,11 +1059,11 @@ mousepad_window_set_title (MousepadWindow *window,
else
{
string = g_strdup_printf ("%s%s - %s",
- mousepad_screen_get_modified (screen) ? "*" : "",
+ mousepad_document_get_modified (document) ? "*" : "",
title, PACKAGE_NAME);
}
- /* get the window title */
+ /* set the window title */
gtk_window_set_title (GTK_WINDOW (window), string);
/* cleanup */
@@ -1036,23 +1080,40 @@ mousepad_window_page_notified (GtkNotebook *notebook,
GParamSpec *pspec,
MousepadWindow *window)
{
- MousepadScreen *screen;
+ gint page_num;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+ /* get the notebook */
+ notebook = GTK_NOTEBOOK (window->notebook);
+
+ /* get the current page */
+ page_num = gtk_notebook_get_current_page (notebook);
+
+ if (G_LIKELY (page_num >= 0))
+ window->active = MOUSEPAD_DOCUMENT (gtk_notebook_get_nth_page (notebook, page_num));
+ else
+ window->active = NULL;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
+ if (G_LIKELY (window->active != NULL))
{
- mousepad_window_set_title (window, screen);
+ /* set the window title */
+ mousepad_window_set_title (window, window->active);
+ /* update the menu actions */
mousepad_window_update_actions (window);
+
+ /* update the statusbar */
+ mousepad_document_send_statusbar_signals (window->active);
}
}
static void
-mousepad_window_tab_removed (GtkNotebook *notebook,
- MousepadScreen *screen,
- MousepadWindow *window)
+mousepad_window_tab_removed (GtkNotebook *notebook,
+ MousepadDocument *document,
+ MousepadWindow *window)
{
gboolean always_show_tabs;
gint npages;
@@ -1078,7 +1139,7 @@ mousepad_window_tab_removed (GtkNotebook *notebook,
/* rebuild the go menu */
mousepad_window_update_gomenu (window);
- /* update all screen sensitive actions */
+ /* update all document sensitive actions */
mousepad_window_update_actions (window);
}
}
@@ -1097,37 +1158,132 @@ mousepad_window_page_reordered (GtkNotebook *notebook,
+static void
+mousepad_window_tab_popup_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
+{
+ GtkWidget *widget = GTK_WIDGET (user_data);
+
+ gdk_window_get_origin (widget->window, x, y);
+
+ *x += widget->allocation.x;
+ *y += widget->allocation.y + widget->allocation.height;
+
+ *push_in = TRUE;
+}
+
+static gboolean
+mousepad_window_tab_popup (GtkNotebook *notebook,
+ GdkEventButton *event,
+ MousepadWindow *window)
+{
+ GtkWidget *page, *label;
+ GtkWidget *menu;
+ guint page_num = 0;
+ gint x_root;
+
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+ {
+ /* walk through the tabs and look for the tab under the cursor */
+ while ((page = gtk_notebook_get_nth_page (notebook, page_num)) != NULL)
+ {
+ label = gtk_notebook_get_tab_label (notebook, page);
+
+ /* get the origin of the label */
+ gdk_window_get_origin (label->window, &x_root, NULL);
+ x_root = x_root + label->allocation.x;
+
+ /* check if the cursor is inside this label */
+ if (event->x_root >= x_root && event->x_root <= (x_root + label->allocation.width))
+ {
+ /* switch to this tab */
+ gtk_notebook_set_current_page (notebook, page_num);
+
+ /* get the menu */
+ menu = gtk_ui_manager_get_widget (window->ui_manager, "/tab-menu");
+
+ /* show it */
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+ mousepad_window_tab_popup_position, label,
+ event->button, event->time);
+
+ /* we succeed */
+ return TRUE;
+ }
+
+ /* try the next tab */
+ ++page_num;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
/**
- * Screen Signals Functions
+ * Document Signals Functions
**/
static void
-mousepad_window_notify_title (MousepadScreen *screen,
- GParamSpec *pspec,
- MousepadWindow *window)
+mousepad_window_notify_title (MousepadDocument *document,
+ GParamSpec *pspec,
+ MousepadWindow *window)
{
- mousepad_window_set_title (window, screen);
+ mousepad_window_set_title (window, document);
}
static void
-mousepad_window_modified_changed (MousepadScreen *screen,
- MousepadWindow *window)
+mousepad_window_modified_changed (MousepadDocument *document,
+ MousepadWindow *window)
{
_mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ mousepad_window_set_title (window, document);
+}
- /* TODO: set the tab label color */
- mousepad_window_set_title (window, screen);
+
+static void
+mousepad_window_cursor_changed (MousepadDocument *document,
+ guint line,
+ guint column,
+ MousepadWindow *window)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* set the new statusbar position */
+ if (G_LIKELY (window->statusbar))
+ mousepad_statusbar_set_cursor_position (MOUSEPAD_STATUSBAR (window->statusbar), line, column);
}
static void
-mousepad_window_selection_changed (MousepadScreen *screen,
- gboolean selected,
- MousepadWindow *window)
+mousepad_window_overwrite_changed (MousepadDocument *document,
+ gboolean overwrite,
+ MousepadWindow *window)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+ /* set the new overwrite mode in the statusbar */
+ if (G_LIKELY (window->statusbar))
+ mousepad_statusbar_set_overwrite (MOUSEPAD_STATUSBAR (window->statusbar), overwrite);
+}
+
+
+
+static void
+mousepad_window_selection_changed (MousepadDocument *document,
+ gboolean selected,
+ MousepadWindow *window)
{
GtkAction *action;
@@ -1149,15 +1305,14 @@ mousepad_window_selection_changed (MousepadScreen *screen,
static void
mousepad_window_update_actions (MousepadWindow *window)
{
- GtkAction *action;
- GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
- MousepadScreen *screen;
- GtkTextView *textview;
- GtkTextBuffer *buffer;
- gboolean cycle_tabs;
- gint n_pages;
- gint page_num;
- gboolean selected;
+ GtkAction *action;
+ GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
+ MousepadDocument *document;
+ gboolean cycle_tabs;
+ gint n_pages;
+ gint page_num;
+ gboolean has_selection;
+ gboolean active;
/* determine the number of pages */
n_pages = gtk_notebook_get_n_pages (notebook);
@@ -1166,15 +1321,11 @@ mousepad_window_update_actions (MousepadWindow *window)
action = gtk_action_group_get_action (window->window_actions, "close-tab");
gtk_action_set_sensitive (action, (n_pages > 1));
- /* update the actions for the current terminal screen */
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
+ /* update the actions for the current document */
+ document = window->active;
+ if (G_LIKELY (document != NULL))
{
- page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (screen));
-
- /* get the textview and the buffer from the screen */
- textview = mousepad_screen_get_text_view (screen);
- buffer = mousepad_screen_get_text_buffer (screen);
+ page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (document));
/* whether we cycle tabs */
g_object_get (G_OBJECT (window->preferences), "misc-cycle-tabs", &cycle_tabs, NULL);
@@ -1186,14 +1337,29 @@ mousepad_window_update_actions (MousepadWindow *window)
gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1 ) || (page_num < n_pages - 1));
action = gtk_action_group_get_action (window->window_actions, "save-file");
- gtk_action_set_sensitive (action, gtk_text_view_get_editable (textview));
+ gtk_action_set_sensitive (action, !mousepad_document_get_readonly (document));
+
+ action = gtk_action_group_get_action (window->window_actions, "reload");
+ gtk_action_set_sensitive (action, mousepad_document_get_filename (document) != NULL);
+
+ active = mousepad_document_get_word_wrap (document);
+ action = gtk_action_group_get_action (window->window_actions, "word-wrap");
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
+
+ active = mousepad_document_get_line_numbers (document);
+ action = gtk_action_group_get_action (window->window_actions, "line-numbers");
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
+
+ active = mousepad_document_get_auto_indent (document);
+ action = gtk_action_group_get_action (window->window_actions, "auto-indent");
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
/* set the sensitivity of the selection actions */
- g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
- mousepad_window_selection_changed (screen, selected, window);
+ has_selection = mousepad_document_get_has_selection (document);
+ mousepad_window_selection_changed (document, has_selection, window);
/* active this tab in the go menu */
- action = g_object_get_data (G_OBJECT (screen), I_("go-menu-action"));
+ action = g_object_get_data (G_OBJECT (document), I_("go-menu-action"));
if (G_LIKELY (action != NULL))
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
}
@@ -1202,10 +1368,11 @@ mousepad_window_update_actions (MousepadWindow *window)
-static void
-mousepad_window_update_gomenu (MousepadWindow *window)
+static gboolean
+mousepad_window_update_gomenu_idle (gpointer user_data)
{
- GtkWidget *screen;
+ GtkWidget *document;
+ MousepadWindow *window = MOUSEPAD_WINDOW (user_data);
gint npages;
gint n;
gchar name[15];
@@ -1213,15 +1380,13 @@ mousepad_window_update_gomenu (MousepadWindow *window)
GtkRadioAction *action;
GSList *group = NULL;
GList *actions, *li;
- static guint merge_id = 0;
+ static guint ui_merge_id = 0;
- /* leave when we're updating multiple files */
- if (lock_menu_updates)
- return;
+ GDK_THREADS_ENTER ();
/* remove the old merge */
- if (merge_id != 0)
- gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
+ if (ui_merge_id != 0)
+ gtk_ui_manager_remove_ui (window->ui_manager, ui_merge_id);
/* drop all the previous actions from the action group */
actions = gtk_action_group_list_actions (window->gomenu_actions);
@@ -1230,29 +1395,29 @@ mousepad_window_update_gomenu (MousepadWindow *window)
g_list_free (actions);
/* create a new merge id */
- merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
+ ui_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
/* walk through the notebook pages */
npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
for (n = 0; n < npages; ++n)
{
- screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n);
+ document = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n);
/* create a new action name */
g_snprintf (name, sizeof (name), "document-%d", n);
/* create the radio action */
action = gtk_radio_action_new (name, NULL, NULL, NULL, n);
- exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (action), "label");
- exo_binding_new (G_OBJECT (screen), "filename", G_OBJECT (action), "tooltip");
+ exo_binding_new (G_OBJECT (document), "title", G_OBJECT (action), "label");
+ exo_binding_new (G_OBJECT (document), "filename", G_OBJECT (action), "tooltip");
gtk_radio_action_set_group (action, group);
group = gtk_radio_action_get_group (action);
g_signal_connect (G_OBJECT (action), "activate",
G_CALLBACK (mousepad_window_action_goto), window->notebook);
- /* connect the action to the screen to we can easily active it when the user toggled the tabs */
- g_object_set_data (G_OBJECT (screen), I_("go-menu-action"), action);
+ /* connect the action to the document to we can easily active it when the user switched from tab */
+ g_object_set_data (G_OBJECT (document), I_("go-menu-action"), action);
if (G_LIKELY (n < 9))
{
@@ -1272,13 +1437,39 @@ mousepad_window_update_gomenu (MousepadWindow *window)
g_object_unref (G_OBJECT (action));
/* add the action to the go menu */
- gtk_ui_manager_add_ui (window->ui_manager, merge_id,
+ gtk_ui_manager_add_ui (window->ui_manager, ui_merge_id,
"/main-menu/go-menu/placeholder-go-items",
name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
}
/* make sure the ui is up2date to avoid flickering */
gtk_ui_manager_ensure_update (window->ui_manager);
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+
+
+static void
+mousepad_window_update_gomenu_idle_destroy (gpointer user_data)
+{
+ MOUSEPAD_WINDOW (user_data)->update_go_menu_id = 0;
+}
+
+
+
+static void
+mousepad_window_update_gomenu (MousepadWindow *window)
+{
+ /* leave when we're updating multiple files or there is this an idle function pending */
+ if (lock_menu_updates && window->update_go_menu_id != 0)
+ return;
+
+ /* schedule a go menu update */
+ window->update_go_menu_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_window_update_gomenu_idle,
+ window, mousepad_window_update_gomenu_idle_destroy);
}
@@ -1292,7 +1483,7 @@ mousepad_window_recent_add (MousepadWindow *window,
{
GtkRecentData info;
gchar *uri;
- static gchar *groups[2] = { PACKAGE_NAME, NULL };
+ static gchar *groups[] = { PACKAGE_NAME, NULL, };
_mousepad_return_if_fail (filename != NULL);
@@ -1318,6 +1509,40 @@ mousepad_window_recent_add (MousepadWindow *window,
+static gchar *
+mousepad_window_recent_escape_underscores (const gchar *str)
+{
+ GString *result;
+ gssize length;
+ const gchar *end, *next;
+
+ length = strlen (str);
+ result = g_string_sized_new (length);
+
+ end = str + length;
+
+ while (str != end)
+ {
+ next = g_utf8_next_char (str);
+
+ switch (*str)
+ {
+ case '_':
+ g_string_append (result, "__");
+ break;
+ default:
+ g_string_append_len (result, str, next - str);
+ break;
+ }
+
+ str = next;
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+
+
static gint
mousepad_window_recent_sort (GtkRecentInfo *a,
GtkRecentInfo *b)
@@ -1327,26 +1552,25 @@ mousepad_window_recent_sort (GtkRecentInfo *a,
-static void
-mousepad_window_recent_menu (MousepadWindow *window)
+static gboolean
+mousepad_window_recent_menu_idle (gpointer user_data)
{
- static guint merge_id = 0;
- GList *items, *li, *actions;
- GList *filtered = NULL;
- GtkRecentInfo *info;
- const gchar *display_name;
- gchar *uri_display;
- gchar *tooltip, *name, *label;
- GtkAction *action;
- gint n;
+ MousepadWindow *window = MOUSEPAD_WINDOW (user_data);
+ static guint ui_merge_id = 0;
+ GList *items, *li, *actions;
+ GList *filtered = NULL;
+ GtkRecentInfo *info;
+ const gchar *display_name;
+ gchar *uri_display;
+ gchar *tooltip, *name, *label;
+ GtkAction *action;
+ gint n;
- /* leave when we're updating multiple files */
- if (lock_menu_updates)
- return;
+ GDK_THREADS_ENTER ();
/* unmerge the ui controls from the previous update */
- if (merge_id != 0)
- gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
+ if (ui_merge_id != 0)
+ gtk_ui_manager_remove_ui (window->ui_manager, ui_merge_id);
/* drop all the previous actions from the action group */
actions = gtk_action_group_list_actions (window->recent_actions);
@@ -1355,7 +1579,7 @@ mousepad_window_recent_menu (MousepadWindow *window)
g_list_free (actions);
/* create a new merge id */
- merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
+ ui_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
/* get all the items in the manager */
items = gtk_recent_manager_get_items (window->recent_manager);
@@ -1387,7 +1611,7 @@ mousepad_window_recent_menu (MousepadWindow *window)
/* get the name of the item and escape the underscores */
display_name = gtk_recent_info_get_display_name (info);
- label = exo_str_replace (display_name, "_", "__");
+ label = mousepad_window_recent_escape_underscores (display_name);
/* create the tooltip with an utf-8 valid version of the filename */
uri_display = gtk_recent_info_get_uri_display (info);
@@ -1410,7 +1634,7 @@ mousepad_window_recent_menu (MousepadWindow *window)
gtk_action_group_add_action (window->recent_actions, action);
/* add the action to the menu */
- gtk_ui_manager_add_ui (window->ui_manager, merge_id,
+ gtk_ui_manager_add_ui (window->ui_manager, ui_merge_id,
"/main-menu/file-menu/recent-menu/placeholder-recent-items",
name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
@@ -1434,9 +1658,37 @@ mousepad_window_recent_menu (MousepadWindow *window)
/* make sure the ui is up2date to avoid flickering */
gtk_ui_manager_ensure_update (window->ui_manager);
+
+ GDK_THREADS_LEAVE ();
+
+ /* stop the idle function */
+ return FALSE;
}
+
+static void
+mousepad_window_recent_menu_idle_destroy (gpointer user_data)
+{
+ MOUSEPAD_WINDOW (user_data)->update_recent_menu_id = 0;
+}
+
+
+
+static void
+mousepad_window_recent_menu (MousepadWindow *window)
+{
+ /* leave when we're updating multiple files or there is this an idle function pending */
+ if (lock_menu_updates && window->update_recent_menu_id != 0)
+ return;
+
+ /* schedule a recent menu update */
+ window->update_recent_menu_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_window_recent_menu_idle,
+ window, mousepad_window_recent_menu_idle_destroy);
+}
+
+
+
static void
mousepad_window_recent_clear (MousepadWindow *window)
{
@@ -1460,7 +1712,7 @@ mousepad_window_recent_clear (MousepadWindow *window)
/* get the uri of the recent item */
uri = gtk_recent_info_get_uri (info);
- /* try to remove it, if it fails, break the loop */
+ /* try to remove it, if it fails, break the loop to avoid multiple errors */
if (G_UNLIKELY (gtk_recent_manager_remove_item (window->recent_manager, uri, &error) == FALSE))
break;
}
@@ -1556,7 +1808,7 @@ mousepad_window_action_open_file (GtkAction *action,
}
/* free the list */
- g_slist_free(filenames);
+ g_slist_free (filenames);
/* allow menu updates again */
lock_menu_updates = FALSE;
@@ -1573,8 +1825,8 @@ mousepad_window_action_open_file (GtkAction *action,
static void
-mousepad_window_action_open_recent (GtkAction *action,
- MousepadWindow *window)
+mousepad_window_action_open_recent (GtkAction *action,
+ MousepadWindow *window)
{
const gchar *uri;
gchar *filename;
@@ -1613,7 +1865,6 @@ mousepad_window_action_open_recent (GtkAction *action,
-
static void
mousepad_window_action_clear_recent (GtkAction *action,
MousepadWindow *window)
@@ -1641,13 +1892,13 @@ static void
mousepad_window_action_save_file (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
+ MousepadDocument *document;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
+ document = window->active;
+ if (G_LIKELY (document != NULL))
{
/* save the file */
- mousepad_window_save (window, screen, FALSE);
+ mousepad_window_save (window, document, FALSE);
}
}
@@ -1657,13 +1908,13 @@ static void
mousepad_window_action_save_file_as (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
+ MousepadDocument *document;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
+ document = window->active;
+ if (G_LIKELY (document != NULL))
{
/* save the file */
- if (mousepad_window_save (window, screen, TRUE))
+ if (mousepad_window_save (window, document, TRUE))
{
/* make sure save-file is sensitive */
action = gtk_action_group_get_action (window->window_actions, "save-file");
@@ -1678,16 +1929,16 @@ static void
mousepad_window_action_reload (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
- GError *error = NULL;
- const gchar *message;
- gint response = MOUSEPAD_RESPONSE_RELOAD;
+ MousepadDocument *document;
+ GError *error = NULL;
+ const gchar *message;
+ gint response = MOUSEPAD_RESPONSE_RELOAD;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
+ document = window->active;
+ if (G_LIKELY (document != NULL))
{
/* ask what to do when the document still has modifications */
- if (mousepad_screen_get_modified (screen))
+ if (mousepad_document_get_modified (document))
response = mousepad_dialogs_ask_reload (GTK_WINDOW (window));
switch (response)
@@ -1699,11 +1950,11 @@ mousepad_window_action_reload (GtkAction *action,
case MOUSEPAD_RESPONSE_SAVE_AS:
/* try to save the document, break when this went wrong, else
* fall-though and try to reload the document */
- if (!mousepad_window_save (window, screen, TRUE))
+ if (!mousepad_window_save (window, document, TRUE))
break;
case MOUSEPAD_RESPONSE_RELOAD:
- if (!mousepad_screen_reload (screen, &error))
+ if (!mousepad_document_reload (document, &error))
message = _("Failed to reload the document");
break;
}
@@ -1722,11 +1973,11 @@ static void
mousepad_window_action_close_tab (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
+ MousepadDocument *document;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- mousepad_window_close_screen (window, screen);
+ document = window->active;
+ if (G_LIKELY (document != NULL))
+ mousepad_window_close_document (window, document);
}
@@ -1736,7 +1987,7 @@ mousepad_window_action_close (GtkAction *action,
MousepadWindow *window)
{
gint npages, i;
- GtkWidget *screen;
+ GtkWidget *document;
/* get the number of page in the notebook */
npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) - 1;
@@ -1748,15 +1999,15 @@ mousepad_window_action_close (GtkAction *action,
* when all the tabs are closed */
for (i = npages; i >= 0; --i)
{
- screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
+ document = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
- if (G_LIKELY (screen != NULL))
+ if (G_LIKELY (document != NULL))
{
/* switch to the tab we're going to close */
gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
/* ask user what to do, break when he/she hits the cancel button */
- if (!mousepad_window_close_screen (window, MOUSEPAD_SCREEN (screen)))
+ if (!mousepad_window_close_document (window, MOUSEPAD_DOCUMENT (document)))
{
/* allow updates again */
lock_menu_updates = FALSE;
@@ -1797,30 +2048,8 @@ static void
mousepad_window_action_cut (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
- GtkTextBuffer *buffer;
- GtkClipboard *clipboard;
- GtkTextView *textview;
-
- /* get the active screen */
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- /* get the clipboard, textview and the buffer */
- buffer = mousepad_screen_get_text_buffer (screen);
- textview = mousepad_screen_get_text_view (screen);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (textview), GDK_SELECTION_CLIPBOARD);
-
- /* cut the text */
- gtk_text_buffer_cut_clipboard (buffer, clipboard,
- gtk_text_view_get_editable (textview));
-
- /* scroll to visible area */
- gtk_text_view_scroll_to_mark (textview,
- gtk_text_buffer_get_insert (buffer),
- MOUSEPAD_SCROLL_MARGIN,
- FALSE, 0.0, 0.0);
- }
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_cut_selection (window->active);
}
@@ -1829,20 +2058,8 @@ static void
mousepad_window_action_copy (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
- GtkTextBuffer *buffer;
- GtkClipboard *clipboard;
-
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- /* get the buffer and clipboard */
- buffer = mousepad_screen_get_text_buffer (screen);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
-
- /* copy the selected text */
- gtk_text_buffer_copy_clipboard (buffer, clipboard);
- }
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_copy_selection (window->active);
}
@@ -1851,29 +2068,8 @@ static void
mousepad_window_action_paste (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
- GtkTextBuffer *buffer;
- GtkClipboard *clipboard;
- GtkTextView *textview;
-
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- /* get the buffer and the clipboard */
- buffer = mousepad_screen_get_text_buffer (screen);
- textview = mousepad_screen_get_text_view (screen);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (textview), GDK_SELECTION_CLIPBOARD);
-
- /* paste the clipboard content */
- gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL,
- gtk_text_view_get_editable (textview));
-
- /* scroll to visible area */
- gtk_text_view_scroll_to_mark (textview,
- gtk_text_buffer_get_insert (buffer),
- MOUSEPAD_SCROLL_MARGIN,
- FALSE, 0.0, 0.0);
- }
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_paste_clipboard (window->active);
}
@@ -1882,27 +2078,8 @@ static void
mousepad_window_action_delete (GtkAction *action,
MousepadWindow *window)
{
- MousepadScreen *screen;
- GtkTextBuffer *buffer;
- GtkTextView *textview;
-
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- /* get the buffer */
- buffer = mousepad_screen_get_text_buffer (screen);
- textview = mousepad_screen_get_text_view (screen);
-
- /* delete the selected text */
- gtk_text_buffer_delete_selection (buffer, TRUE,
- gtk_text_view_get_editable (textview));
-
- /* scroll to visible area */
- gtk_text_view_scroll_to_mark (textview,
- gtk_text_buffer_get_insert (buffer),
- MOUSEPAD_SCROLL_MARGIN,
- FALSE, 0.0, 0.0);
- }
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_delete_selection (window->active);
}
@@ -1911,65 +2088,131 @@ static void
mousepad_window_action_select_all (GtkAction *action,
MousepadWindow *window)
{
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_select_all (window->active);
+}
- MousepadScreen *screen;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- /* get the buffer */
- buffer = mousepad_screen_get_text_buffer (screen);
- /* get the start and end iter */
- gtk_text_buffer_get_bounds (buffer, &start, &end);
+static void
+mousepad_window_hide_search_bar (MousepadWindow *window)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+ /* hide the search bar */
+ gtk_widget_hide (window->search_bar);
+ gtk_table_set_row_spacing (GTK_TABLE (window->table), 3, 0);
+
+ /* focus the active document's text view */
+ if (G_LIKELY (window->active))
+ mousepad_document_focus_textview (window->active);
+}
+
+
+
+static gboolean
+mousepad_window_find_string (MousepadWindow *window,
+ const gchar *string,
+ MousepadSearchFlags flags)
+{
+ gboolean found;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+
+ found = mousepad_document_find (window->active, string, flags);
+
+ return found;
+}
+
+static gboolean
+mousepad_window_highlight_all (MousepadWindow *window,
+ const gchar *string,
+ MousepadSearchFlags flags)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+
+ /* hightlight all the occurences in the active document */
+ mousepad_document_highlight_all (window->active, string, flags);
+
+ return FALSE;
+}
- /* select everything between those iters */
- gtk_text_buffer_select_range (buffer, &start, &end);
+static void
+mousepad_window_action_find (GtkAction *action,
+ MousepadWindow *window)
+{
+ if (G_UNLIKELY (window->search_bar == NULL))
+ {
+ /* create a new toolbar */
+ window->search_bar = mousepad_search_bar_new ();
+ gtk_table_attach (GTK_TABLE (window->table), window->search_bar, 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+
+ /* connect signals to the search bar */
+ g_signal_connect_swapped (G_OBJECT (window->search_bar), "hide-bar", G_CALLBACK (mousepad_window_hide_search_bar), window);
+ g_signal_connect_swapped (G_OBJECT (window->search_bar), "find-string", G_CALLBACK (mousepad_window_find_string), window);
+ g_signal_connect_swapped (G_OBJECT (window->search_bar), "highlight-all", G_CALLBACK (mousepad_window_highlight_all), window);
}
+
+ /* show the search bar and give some space to the table */
+ gtk_widget_show (window->search_bar);
+ gtk_table_set_row_spacing (GTK_TABLE (window->table), 3, WINDOW_SPACING);
+
+ /* focus the search entry */
+ mousepad_search_bar_focus (MOUSEPAD_SEARCH_BAR (window->search_bar));
}
static void
-mousepad_window_action_jump_to (GtkAction *action,
+mousepad_window_action_find_next (GtkAction *action,
+ MousepadWindow *window)
+{
+ /* only find the next occurence when the search bar is initialized */
+ if (G_LIKELY (window->search_bar != NULL))
+ mousepad_search_bar_find_next (MOUSEPAD_SEARCH_BAR (window->search_bar));
+}
+
+
+
+static void
+mousepad_window_action_find_previous (GtkAction *action,
+ MousepadWindow *window)
+{
+ /* only find the previous occurence when the search bar is initialized */
+ if (G_LIKELY (window->search_bar != NULL))
+ mousepad_search_bar_find_previous (MOUSEPAD_SEARCH_BAR (window->search_bar));
+}
+
+
+
+static void
+mousepad_window_action_replace (GtkAction *action,
MousepadWindow *window)
{
- GtkTextBuffer *buffer;
- MousepadScreen *screen;
- gint current_line, last_line, line;
- GtkTextIter iter;
- /* get the active screen */
- screen = mousepad_window_get_active (window);
- if (G_LIKELY (screen != NULL))
- {
- buffer = mousepad_screen_get_text_buffer (screen);
+}
+
- /* get the current line number */
- gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
- current_line = gtk_text_iter_get_line (&iter) + 1;
- /* get the last line number */
- gtk_text_buffer_get_end_iter (buffer, &iter);
- last_line = gtk_text_iter_get_line (&iter) + 1;
+static void
+mousepad_window_action_jump_to (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadDocument *document;
+ gint current_line, last_line, line;
+
+ /* get the active document */
+ document = window->active;
+ if (G_LIKELY (document != NULL))
+ {
+ /* get the current and last line number */
+ mousepad_document_line_numbers (document, ¤t_line, &last_line);
/* run the jump to dialog and wait for the response */
line = mousepad_dialogs_jump_to (GTK_WINDOW (window), current_line, last_line);
if (G_LIKELY (line > 0))
- {
- /* jump to the line */
- gtk_text_buffer_get_iter_at_line (buffer, &iter, line-1);
- gtk_text_buffer_place_cursor (buffer, &iter);
-
- /* scroll to visible area */
- gtk_text_view_scroll_to_mark (mousepad_screen_get_text_view (screen),
- gtk_text_buffer_get_insert (buffer),
- MOUSEPAD_SCROLL_MARGIN,
- FALSE, 0.0, 0.0);
- }
+ mousepad_document_jump_to_line (document, line);
}
}
@@ -2010,6 +2253,91 @@ mousepad_window_action_select_font (GtkAction *action,
static void
+mousepad_window_action_statusbar (GtkToggleAction *action,
+ MousepadWindow *window)
+{
+ gboolean active;
+ MousepadDocument *document;
+
+ /* determine the new state of the action */
+ active = gtk_toggle_action_get_active (action);
+
+ /* check if we should drop the statusbar */
+ if (!active && window->statusbar != NULL)
+ {
+ /* just get rid of the statusbar */
+ gtk_widget_destroy (window->statusbar);
+ window->statusbar = NULL;
+ }
+ else if (active && window->statusbar == NULL)
+ {
+ /* setup a new statusbar */
+ window->statusbar = mousepad_statusbar_new ();
+ gtk_table_attach (GTK_TABLE (window->table), window->statusbar, 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (window->statusbar);
+
+ /* set the statsbar text */
+ document = window->active;
+ if (document != NULL)
+ mousepad_document_send_statusbar_signals (document);
+ }
+
+ /* set the spacing above the statusbar */
+ gtk_table_set_row_spacing (GTK_TABLE (window->table), 4, active ? WINDOW_SPACING : 0);
+
+ /* remember the setting */
+ g_object_set (G_OBJECT (window->preferences), "last-statusbar-visible", active, NULL);
+}
+
+
+
+static void
+mousepad_window_action_word_wrap (GtkToggleAction *action,
+ MousepadWindow *window)
+{
+ gboolean word_wrap;
+
+ word_wrap = gtk_toggle_action_get_active (action);
+
+ /* store this as the last used wrap mode */
+ g_object_set (G_OBJECT (window->preferences), "word-wrap", word_wrap, NULL);
+
+ /* set the wrapping mode of the current document */
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_set_word_wrap (window->active, word_wrap);
+}
+
+
+
+static void
+mousepad_window_action_line_numbers (GtkToggleAction *action,
+ MousepadWindow *window)
+{
+ gboolean line_numbers;
+
+ line_numbers = gtk_toggle_action_get_active (action);
+
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_set_line_numbers (window->active, line_numbers);
+}
+
+
+
+static void
+mousepad_window_action_auto_indent (GtkToggleAction *action,
+ MousepadWindow *window)
+{
+ gboolean auto_indent;
+
+ auto_indent = gtk_toggle_action_get_active (action);
+
+ if (G_LIKELY (window->active != NULL))
+ mousepad_document_set_auto_indent (window->active, auto_indent);
+}
+
+
+
+static void
mousepad_window_action_prev_tab (GtkAction *action,
MousepadWindow *window)
{
@@ -2066,22 +2394,25 @@ mousepad_window_action_about (GtkAction *action,
}
+
/**
* Miscellaneous Actions
**/
static void
-mousepad_window_button_close_tab (MousepadScreen *screen)
+mousepad_window_button_close_tab (MousepadDocument *document,
+ MousepadWindow *window)
{
- MousepadWindow *window;
+ gint page_num;
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+ _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
- /* get the mousepad window of this screen */
- window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
+ /* switch to the tab we're going to close */
+ page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (document));
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
- /* close the screen */
- if (G_LIKELY (window != NULL))
- mousepad_window_close_screen (window, screen);
+ /* close the document */
+ mousepad_window_close_document (window, document);
}
@@ -2098,3 +2429,20 @@ mousepad_window_delete_event (MousepadWindow *window,
}
+
+void
+mousepad_gtk_set_tooltip (GtkWidget *widget,
+ const gchar *tooltip)
+{
+ static GtkTooltips *tooltips = NULL;
+
+ _mousepad_return_if_fail (GTK_IS_WIDGET (widget));
+
+ /* allocate the shared tooltips on-demand */
+ if (G_UNLIKELY (tooltips == NULL))
+ tooltips = gtk_tooltips_new ();
+
+ /* setup the tooltip for the widget */
+ gtk_tooltips_set_tip (tooltips, widget, tooltip, NULL);
+}
+
diff --git a/mousepad/mousepad-window.h b/mousepad/mousepad-window.h
index 951d020..2324bc0 100644
--- a/mousepad/mousepad-window.h
+++ b/mousepad/mousepad-window.h
@@ -39,10 +39,13 @@ GtkWidget *mousepad_window_new (void);
gboolean mousepad_window_open_tab (MousepadWindow *window,
const gchar *filename);
-void mousepad_window_open_files (MousepadWindow *window,
+gboolean mousepad_window_open_files (MousepadWindow *window,
const gchar *working_directory,
gchar **filenames);
+void mousepad_gtk_set_tooltip (GtkWidget *widget,
+ const gchar *string);
+
G_END_DECLS
#endif /* !__MOUSEPAD_WINDOW_H__ */
More information about the Xfce4-commits
mailing list