[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, &current_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