[Xfce4-commits] <mousepad:master> * mousepad/mousepad-dialogs.{c, h}: New file for the dialogs so the mousepad-window file becomes more readable. * mousepad/mousepad-window.c: Split some function and reorder them a bit. * mousepad/mousepad-window.c: The items in the go menu now have the filename as statusbar tooltip. * mousepad/mousepad-window.c: Check if the file is externally modified before writing. If it is, ask the user what to do. * mousepad/main.c, mousepad/mousepad-dbus.{c, h}, mousepad/mousepad-dbus-infos.xml: Support for terminating a running mousepad instance (that is connected to dbus), using mousepad -q. * mousepad/*: Add function destriptions for Erik (and others) :-).

Nick Schermer noreply at xfce.org
Sat May 5 21:30:08 CEST 2012


Updating branch refs/heads/master
         to b5178ab96dc4dd424f9ce884529a67e95731e145 (commit)
       from 5263c479394dbb5a6bc0b892806f11a629bd81f4 (commit)

commit b5178ab96dc4dd424f9ce884529a67e95731e145
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Mar 3 12:07:46 2007 +0000

    	* mousepad/mousepad-dialogs.{c,h}: New file for the dialogs
    	  so the mousepad-window file becomes more readable.
    	* mousepad/mousepad-window.c: Split some function and reorder
    	  them a bit.
    	* mousepad/mousepad-window.c: The items in the go menu now have
    	  the filename as statusbar tooltip.
    	* mousepad/mousepad-window.c: Check if the file is externally modified
    	  before writing. If it is, ask the user what to do.
    	* mousepad/main.c, mousepad/mousepad-dbus.{c,h},
    	  mousepad/mousepad-dbus-infos.xml: Support for terminating a running
    	  mousepad instance (that is connected to dbus), using mousepad -q.
    	* mousepad/*: Add function destriptions for Erik (and others) :-).
    
    (Old svn revision: 25069)

 ChangeLog                        |   15 +
 TODO                             |    2 +
 configure.in.in                  |    1 +
 mousepad/Makefile.am             |    4 +
 mousepad/main.c                  |   29 +-
 mousepad/mousepad-application.c  |   62 +++-
 mousepad/mousepad-dbus-infos.xml |   44 ++
 mousepad/mousepad-dbus.c         |  192 ++++++--
 mousepad/mousepad-dbus.h         |   27 +-
 mousepad/mousepad-dialogs.c      |  333 +++++++++++++
 mousepad/mousepad-dialogs.h      |   48 ++
 mousepad/mousepad-file.c         |   69 +++-
 mousepad/mousepad-file.h         |   35 +-
 mousepad/mousepad-preferences.c  |  138 +++++-
 mousepad/mousepad-screen.c       |   16 +-
 mousepad/mousepad-screen.h       |    4 +-
 mousepad/mousepad-view.c         |  118 ++++-
 mousepad/mousepad-window.c       |  975 +++++++++++++++++---------------------
 18 files changed, 1426 insertions(+), 686 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 65840c5..15b27bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-02-19	Nick Schermer <nick at xfce.org>
+
+	* mousepad/mousepad-dialogs.{c,h}: New file for the dialogs
+	  so the mousepad-window file becomes more readable.
+	* mousepad/mousepad-window.c: Split some function and reorder
+	  them a bit.
+	* mousepad/mousepad-window.c: The items in the go menu now have
+	  the filename as statusbar tooltip.
+	* mousepad/mousepad-window.c: Check if the file is externally modified
+	  before writing. If it is, ask the user what to do.
+	* mousepad/main.c, mousepad/mousepad-dbus.{c,h},
+	  mousepad/mousepad-dbus-infos.xml: Support for terminating a running
+	  mousepad instance (that is connected to dbus), using mousepad -q.
+	* mousepad/*: Add function destriptions for Erik (and others) :-).
+
 2007-02-18	Nick Schermer <nick at xfce.org>
 
 	* mousepad/mousepad-window.c: Improve the menu tooltips.
diff --git a/TODO b/TODO
index 6cb57fe..e64fc10 100644
--- a/TODO
+++ b/TODO
@@ -2,6 +2,8 @@
   - 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.
 
 - Text View
   - Search and Replace. Maybe also text highlighting.
diff --git a/configure.in.in b/configure.in.in
index dbf3aba..2e629ec 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -87,6 +87,7 @@ dnl ***********************************
 dnl *** Check for required packages ***
 dnl ***********************************
 XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.2])
+XDT_CHECK_PACKAGE([PCRE], [libpcre], [6.0])
 XDT_CHECK_PACKAGE([GLIB], [glib-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])
diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
index 08a4384..5f31e7c 100644
--- a/mousepad/Makefile.am
+++ b/mousepad/Makefile.am
@@ -19,6 +19,8 @@ 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						\
@@ -36,6 +38,7 @@ mousepad_SOURCES =							\
 
 mousepad_CFLAGS =							\
 	$(EXO_CFLAGS)							\
+	$(PCRE_CFLAGS)							\
 	$(GTHREAD_CFLAGS)						\
 	$(PLATFORM_CFLAGS)
 
@@ -46,6 +49,7 @@ mousepad_LDFLAGS =							\
 
 mousepad_LDADD =							\
 	$(EXO_LIBS)							\
+	$(PCRE_LIBS)							\
 	$(GTHREAD_LIBS)
 
 if HAVE_DBUS
diff --git a/mousepad/main.c b/mousepad/main.c
index d7102d8..b88bd15 100644
--- a/mousepad/main.c
+++ b/mousepad/main.c
@@ -41,6 +41,7 @@ static gchar    **filenames = NULL;
 static gboolean   opt_version = FALSE;
 #ifdef HAVE_DBUS
 static gboolean   opt_disable_server = FALSE;
+static gboolean   opt_quit = FALSE;
 #endif
 
 
@@ -49,9 +50,10 @@ static gboolean   opt_disable_server = FALSE;
 static GOptionEntry option_entries[] =
 {
 #ifdef HAVE_DBUS
-  { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_ ("Do not register with the D-BUS session message bus"), NULL, },
+  { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_("Do not register with the D-BUS session message bus"), NULL, },
+  { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit a running Mousepad instance"), NULL, },
 #endif
-  { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_ ("Print version information and exit"), NULL, },
+  { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL, },
   { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, NULL },
   { NULL, },
 };
@@ -62,11 +64,12 @@ gint
 main (gint argc, gchar **argv)
 {
   MousepadApplication *application;
+  GError              *error = NULL;
+  gchar               *working_directory;
+
 #ifdef HAVE_DBUS
   MousepadDBusService *dbus_service;
 #endif
-  GError              *error = NULL;
-  gchar               *working_directory;
 
   /* translation domain */
   xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
@@ -114,6 +117,22 @@ main (gint argc, gchar **argv)
       return EXIT_SUCCESS;
     }
 
+#ifdef HAVE_DBUS
+  /* check if we need to terminate a running Mousepad instance */
+  if (G_UNLIKELY (opt_quit))
+    {
+      /* try to terminate whatever is running */
+      if (!mousepad_dbus_client_terminate (&error))
+        {
+          g_error ("Failed to terminate a running instance: %s\n", error->message);
+          g_error_free (error);
+          return EXIT_FAILURE;
+        }
+
+      return EXIT_SUCCESS;
+    }
+#endif /* !HAVE_DBUS */
+
   /* get the current working directory */
   working_directory = g_get_current_dir ();
 
@@ -150,7 +169,7 @@ main (gint argc, gchar **argv)
   /* create a new mousepad application */
   application = mousepad_application_get ();
 
-  /* open an empty window or the files */
+  /* open an empty window (with an empty document or the files) */
   mousepad_application_open_window (application, NULL, working_directory, filenames);
 
   /* cleanup */
diff --git a/mousepad/mousepad-application.c b/mousepad/mousepad-application.c
index 755348b..da88720 100644
--- a/mousepad/mousepad-application.c
+++ b/mousepad/mousepad-application.c
@@ -44,6 +44,7 @@ struct _MousepadApplication
 {
   GObject  __parent__;
 
+  /* internal list of all the opened windows */
   GList   *windows;
 };
 
@@ -53,6 +54,16 @@ static GObjectClass *mousepad_application_parent_class;
 
 
 
+/**
+ * mousepad_application_get:
+ *
+ * Returns the global shared #MousepadApplication instance.
+ * This method takes a reference on the global instance
+ * for the caller, so you must call g_object_unref()
+ * on it when done.
+ *
+ * Return value: the shared #MousepadApplication instance.
+ **/
 MousepadApplication*
 mousepad_application_get (void)
 {
@@ -72,10 +83,6 @@ mousepad_application_get (void)
 
 
 
-static GObjectClass *mousepad_application_parent_class;
-
-
-
 GType
 mousepad_application_get_type (void)
 {
@@ -116,7 +123,7 @@ mousepad_application_init (MousepadApplication *application)
   gchar *path;
 
   /* check if we have a saved accel map */
-  path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm");
+  path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, PACKAGE_NAME "/accels.scm");
   if (G_LIKELY (path != NULL))
     {
       /* load the accel map */
@@ -135,7 +142,7 @@ mousepad_application_finalize (GObject *object)
   gchar               *path;
 
   /* save the current accel map */
-  path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm", TRUE);
+  path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, PACKAGE_NAME "/accels.scm", TRUE);
   if (G_LIKELY (path != NULL))
     {
       /* save the accel map */
@@ -143,6 +150,7 @@ mousepad_application_finalize (GObject *object)
       g_free (path);
     }
 
+  /* destroy the windows if they are still opened */
   for (li = application->windows; li != NULL; li = li->next)
     {
       g_signal_handlers_disconnect_by_func (G_OBJECT (li->data), G_CALLBACK (mousepad_application_window_destroyed), application);
@@ -156,6 +164,16 @@ mousepad_application_finalize (GObject *object)
 
 
 
+/**
+ * mousepad_application_get_windows:
+ * @application: A #MousepadApplication.
+ *
+ * Returns a list of #MousepadWindows currently registered by the
+ * #MousepadApplication. The returned list is owned by the caller and
+ * must be freed using g_list_free().
+ *
+ * Return value: the list of regular #MousepadWindows in @application.
+ **/
 GList*
 mousepad_application_get_windows (MousepadApplication *application)
 {
@@ -173,6 +191,14 @@ mousepad_application_get_windows (MousepadApplication *application)
 
 
 
+/**
+ * mousepad_application_has_windows:
+ * @application : a #MousepadApplication.
+ *
+ * Returns %TRUE if @application controls atleast one window.
+ *
+ * Return value: %TRUE if @application controls atleast one window.
+ **/
 gboolean
 mousepad_application_has_windows (MousepadApplication *application)
 {
@@ -183,6 +209,19 @@ mousepad_application_has_windows (MousepadApplication *application)
 
 
 
+/**
+ * mousepad_application_open_window:
+ * @application       : A #MousepadApplication.
+ * @screen            : The #GdkScreen on which to open the window or %NULL
+ *                      to open on the default screen.
+ * @working_directory : The default working directory for this window.
+ * @filenames         : A list of filenames we try to open in tabs. The file names
+ *                      can either be absolute paths, supported URIs or relative file
+ *                      names to @working_directory or %NULL for an untitled document.
+ *
+ * Opens a new Mousepad window and tries to open all the file names in tabs. If
+ * @filename is %NULL an empty Untiled documenten will be opened in the window.
+ **/
 void
 mousepad_application_open_window (MousepadApplication  *application,
                                   GdkScreen            *screen,
@@ -210,6 +249,8 @@ mousepad_application_open_window (MousepadApplication  *application,
   else
     mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
 
+  /* TODO: check if there are actually some tabs in the window, if not, open an empty tab */
+
   /* connect to the "destroy" signal */
   g_signal_connect (G_OBJECT (window), "destroy",
                     G_CALLBACK (mousepad_application_window_destroyed), application);
@@ -222,6 +263,15 @@ mousepad_application_open_window (MousepadApplication  *application,
 
 
 
+/**
+ * mousepad_application_window_destroyed:
+ * @window      : The window that has been destroyed.
+ * @application : A #MousepadApplication.
+ *
+ * This function removes @window from the registed windows in @application.
+ * When there are no more windows left in @application, the application is
+ * terminated.
+ **/
 static void
 mousepad_application_window_destroyed (GtkWidget           *window,
                                        MousepadApplication *application)
diff --git a/mousepad/mousepad-dbus-infos.xml b/mousepad/mousepad-dbus-infos.xml
index 27fa116..4787ba8 100644
--- a/mousepad/mousepad-dbus-infos.xml
+++ b/mousepad/mousepad-dbus-infos.xml
@@ -1,15 +1,59 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
+<!--
+   $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
+-->
+
 <node name="/org/xfce/Mousepad">
 
+  <!--
+    org.xfce.Thunar
+
+    The Mousepad specific interface, which provides Mousepad specific methods.
+
+    This inferface is internally used by Mousepad and should not be used externally.
+  -->
   <interface name="org.xfce.Mousepad">
     <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="mousepad_dbus_service" />
 
+    <!--
+      LaunchFiles (working-directory : STRING, filenames : ARRAY OF STRING : VOID
+
+      working-directory : the directory, relative to which filenames should
+                          be interpreted.
+      filenames         : an array of file names to launch. The file names may
+                          be either file:-URIs, absolute paths or paths relative
+                          to the working-directory.
+    -->
     <method name="LaunchFiles">
       <arg direction="in" name="working-directory" type="s" />
       <arg direction="in" name="filenames" type="as" />
     </method>
 
+    <!--
+      Terminate () : VOID
+
+      Tells a running Mousepad instance to terminate immediately.
+    -->
+    <method name="Terminate">
+    </method>
+
   </interface>
 
 </node>
diff --git a/mousepad/mousepad-dbus.c b/mousepad/mousepad-dbus.c
index 9c6f6bd..1b7288a 100644
--- a/mousepad/mousepad-dbus.c
+++ b/mousepad/mousepad-dbus.c
@@ -38,13 +38,18 @@
 
 
 
-static void      mousepad_dbus_service_class_init     (MousepadDBusServiceClass  *klass);
-static void      mousepad_dbus_service_init           (MousepadDBusService       *dbus_service);
-static void      mousepad_dbus_service_finalize       (GObject                   *object);
-static gboolean  mousepad_dbus_service_launch_files   (MousepadDBusService       *dbus_service,
-                                                       const gchar               *working_directory,
-                                                       gchar                    **filenames,
-                                                       GError                   **error);
+#define MOUSEPAD_DBUS_PATH      "/org/xfce/Mousepad"
+#define MOUSEPAD_DBUS_INTERFACE "org.xfce.Mousepad"
+
+
+
+static void      mousepad_dbus_service_class_init    (MousepadDBusServiceClass  *klass);
+static void      mousepad_dbus_service_init          (MousepadDBusService       *dbus_service);
+static void      mousepad_dbus_service_finalize      (GObject                   *object);
+static gboolean  mousepad_dbus_service_launch_files  (MousepadDBusService       *dbus_service,
+                                                      const gchar               *working_directory,
+                                                      gchar                    **filenames,
+                                                      GError                   **error);
 
 
 
@@ -116,10 +121,11 @@ mousepad_dbus_service_init (MousepadDBusService *dbus_service)
   if (G_LIKELY (dbus_service->connection != NULL))
     {
       /* register the /org/xfce/TextEditor object for Mousepad */
-      dbus_g_connection_register_g_object (dbus_service->connection, "/org/xfce/Mousepad", G_OBJECT (dbus_service));
+      dbus_g_connection_register_g_object (dbus_service->connection, MOUSEPAD_DBUS_PATH, G_OBJECT (dbus_service));
 
       /* request the org.xfce.Mousepad name for Mousepad */
-      dbus_bus_request_name (dbus_g_connection_get_connection (dbus_service->connection), "org.xfce.Mousepad", DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
+      dbus_bus_request_name (dbus_g_connection_get_connection (dbus_service->connection),
+                             MOUSEPAD_DBUS_INTERFACE, DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
     }
   else
     {
@@ -152,6 +158,20 @@ mousepad_dbus_service_finalize (GObject *object)
 
 
 
+/**
+ * mousepad_dbus_service_launch_files:
+ * @dbus_service      : A #MousepadDBusService.
+ * @working_directory : The default working directory for this window.
+ * @filenames         : A list of filenames we try to open in tabs. The file names
+ *                      can either be absolute paths, supported URIs or relative file
+ *                      names to @working_directory or %NULL for an untitled document.
+ * @error             : Return location for errors, not used atm.
+ *
+ * This function is activated by DBus (service) and opens a new window in this instance of
+ * Mousepad.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
 static gboolean
 mousepad_dbus_service_launch_files (MousepadDBusService  *dbus_service,
                                     const gchar          *working_directory,
@@ -164,8 +184,10 @@ mousepad_dbus_service_launch_files (MousepadDBusService  *dbus_service,
   _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
   _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
+  /* get the default screen */
   screen = gdk_screen_get_default ();
 
+  /* open a mousepad window */
   application = mousepad_application_get ();
   mousepad_application_open_window (application, screen, working_directory, filenames);
   g_object_unref (G_OBJECT (application));
@@ -175,19 +197,46 @@ mousepad_dbus_service_launch_files (MousepadDBusService  *dbus_service,
 
 
 
-gboolean
-mousepad_dbus_client_launch_files (gchar       **filenames,
-                                   const gchar  *working_directory,
-                                   GError      **error)
+/**
+ * mousepad_dbus_service_terminate:
+ * @dbus_service : A #MousepadDBusService.
+ * @error        : Return location for errors, not used atm.
+ *
+ * This function quits this instance of Mousepad.
+ *
+ * Return value: %TRUE on success.
+ **/
+static gboolean
+mousepad_dbus_service_terminate (MousepadDBusService  *dbus_service,
+                                 GError              **error)
+{
+  /* leave the Gtk main loop as soon as possible */
+  gtk_main_quit ();
+
+  /* we cannot fail */
+  return TRUE;
+}
+
+
+
+/**
+ * mousepad_dbus_client_send:
+ * @message : A #DBusMessage.
+ * @error   : Return location for errors or %NULL.
+ *
+ * This function sends the DBus message and should avoid
+ * code duplication in the functions below.
+ *
+ * Return value: %TRUE on succeed or %FALSE if @error is set.
+ **/
+static gboolean
+mousepad_dbus_client_send (DBusMessage  *message,
+                           GError      **error)
 {
   DBusConnection *connection;
-  DBusMessage    *message;
   DBusMessage    *result;
   DBusError       derror;
 
-  _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
-  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
   dbus_error_init (&derror);
 
   /* try to connect to the session bus */
@@ -199,34 +248,22 @@ mousepad_dbus_client_launch_files (gchar       **filenames,
       return FALSE;
     }
 
-  /* generate the message */
-  message = dbus_message_new_method_call ("org.xfce.Mousepad", "/org/xfce/Mousepad",
-                                          "org.xfce.Mousepad", "LaunchFiles");
-  dbus_message_set_auto_start (message, FALSE);
-  dbus_message_append_args (message,
-                            DBUS_TYPE_STRING, &working_directory,
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, filenames ? g_strv_length (filenames) : 0,
-                            DBUS_TYPE_INVALID);
-
   /* send the message */
   result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror);
 
-  /* release ref */
-  dbus_message_unref (message);
-
   /* check if no reply was received */
   if (result == NULL)
     {
-#ifndef NDEBUG
-      /* set the error when debug is enabled */
-      dbus_set_g_error (error, &derror);
-#endif
+      /* check if there was just no instance running */
+      if (!dbus_error_has_name (&derror, DBUS_ERROR_NAME_HAS_NO_OWNER))
+        dbus_set_g_error (error, &derror);
+
       dbus_error_free (&derror);
       return FALSE;
     }
 
   /* but maybe we received an error */
-  if (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR)
+  if (G_UNLIKELY (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR))
     {
       dbus_set_error_from_message (&derror, result);
       dbus_set_g_error (error, &derror);
@@ -243,5 +280,90 @@ mousepad_dbus_client_launch_files (gchar       **filenames,
 
 
 
-#include <mousepad/mousepad-dbus-infos.h>
+/**
+ * mousepad_dbus_client_terminate:
+ * @error : Return location for errors or %NULL.
+ *
+ * Function called from this instance of the application and tries to invoke
+ * with an already running instance and ties to quit it.
+ * The mousepad_dbus_service_terminate function is activated in the running instance.
+ *
+ * Return value: %TRUE on success.
+ **/
+gboolean
+mousepad_dbus_client_terminate (GError **error)
+{
+  DBusMessage *message;
 
+  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  /* generate the message */
+  message = dbus_message_new_method_call (MOUSEPAD_DBUS_INTERFACE, MOUSEPAD_DBUS_PATH,
+                                          MOUSEPAD_DBUS_INTERFACE, "Terminate");
+  dbus_message_set_auto_start (message, FALSE);
+
+
+  /* send the message */
+  mousepad_dbus_client_send (message, error);
+
+  /* unref the message */
+  dbus_message_unref (message);
+
+  /* we return false if an error was set */
+  return (error != NULL);
+}
+
+
+
+/**
+ * mousepad_dbus_client_launch_files:
+ * @filenames         : A list of filenames we try to open in tabs. The file names
+ *                      can either be absolute paths, supported URIs or relative file
+ *                      names to @working_directory or %NULL for an untitled document.
+ * @working_directory : Working directory for the new Mousepad window.
+ * @error             : Return location for errors or %NULL.
+ *
+ * This function is called within this instance and tries to connect a running instance
+ * of Mousepad via DBus. The function mousepad_dbus_service_launch_files is activated in the
+ * running instance.
+ *
+ * Return value: %TRUE on success.
+ **/
+gboolean
+mousepad_dbus_client_launch_files (gchar       **filenames,
+                                   const gchar  *working_directory,
+                                   GError      **error)
+{
+  DBusMessage *message;
+  guint        length = 0;
+  gboolean     succeed;
+
+  _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
+  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  /* get the length of the filesname string */
+  if (filenames)
+    length = g_strv_length (filenames);
+
+  /* generate the message */
+  message = dbus_message_new_method_call (MOUSEPAD_DBUS_INTERFACE, MOUSEPAD_DBUS_PATH,
+                                          MOUSEPAD_DBUS_INTERFACE, "LaunchFiles");
+  dbus_message_set_auto_start (message, FALSE);
+  dbus_message_append_args (message,
+                            DBUS_TYPE_STRING, &working_directory,
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, length,
+                            DBUS_TYPE_INVALID);
+
+  /* send the message */
+  succeed = mousepad_dbus_client_send (message, error);
+
+  /* unref the message */
+  dbus_message_unref (message);
+
+  return succeed;
+}
+
+
+
+/* include the dbus glue generated by dbus-binding-tool */
+#include <mousepad/mousepad-dbus-infos.h>
diff --git a/mousepad/mousepad-dbus.h b/mousepad/mousepad-dbus.h
index 50e5866..d02bef6 100644
--- a/mousepad/mousepad-dbus.h
+++ b/mousepad/mousepad-dbus.h
@@ -25,19 +25,20 @@ 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))
-#define MOUSEPAD_IS_DBUS_SERVICE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DBUS_SERVICE))
-#define MOUSEPAD_IS_DBUS_SERVICE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DBUS_BRIGDE))
-#define MOUSEPAD_DBUS_SERVICE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
-
-GType     mousepad_dbus_service_get_type (void) G_GNUC_CONST;
-
-gboolean
-mousepad_dbus_client_launch_files (gchar       **filenames,
-                                   const gchar  *working_directory,
-                                   GError      **error);
+#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))
+#define MOUSEPAD_IS_DBUS_SERVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DBUS_SERVICE))
+#define MOUSEPAD_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DBUS_BRIGDE))
+#define MOUSEPAD_DBUS_SERVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
+
+GType     mousepad_dbus_service_get_type    (void) G_GNUC_CONST;
+
+gboolean  mousepad_dbus_client_terminate    (GError      **error);
+
+gboolean  mousepad_dbus_client_launch_files (gchar       **filenames,
+                                             const gchar  *working_directory,
+                                             GError      **error);
 
 G_END_DECLS
 
diff --git a/mousepad/mousepad-dialogs.c b/mousepad/mousepad-dialogs.c
new file mode 100644
index 0000000..dbd9f5c
--- /dev/null
+++ b/mousepad/mousepad-dialogs.c
@@ -0,0 +1,333 @@
+/* $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-file.h>
+
+
+
+static GtkWidget *
+mousepad_dialogs_image_button (const gchar *stock_id,
+                               const gchar *label)
+{
+  GtkWidget *button, *image;
+
+  image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
+  gtk_widget_show (image);
+
+  button = gtk_button_new_with_mnemonic (label);
+  gtk_button_set_image (GTK_BUTTON (button), image);
+  gtk_widget_show (button);
+
+  return button;
+}
+
+
+
+void
+mousepad_dialogs_show_about (GtkWindow *parent)
+{
+  static const gchar *authors[] =
+  {
+    "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."),
+                         "copyright", _("Copyright \302\251 2004-2007 Xfce Development Team"),
+                         "destroy-with-parent", TRUE,
+                         "license", XFCE_LICENSE_GPL,
+                         "logo-icon-name", PACKAGE_NAME,
+                         "name", PACKAGE_NAME,
+                         "version", PACKAGE_VERSION,
+                         "translator-credits", _("translator-credits"),
+                         "website", "http://www.xfce.org/projects/mousepad",
+                         NULL);
+}
+
+
+
+void
+mousepad_dialogs_show_error (GtkWindow    *parent,
+                             const GError *error,
+                             const gchar  *message)
+{
+  GtkWidget *dialog;
+
+  /* create the warning dialog */
+  dialog = gtk_message_dialog_new (parent,
+                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_ERROR,
+                                   GTK_BUTTONS_CLOSE,
+                                   "%s.", message);
+
+  /* set secondary text if an error is provided */
+  if (G_LIKELY (error != NULL))
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
+
+  /* display the dialog */
+  gtk_dialog_run (GTK_DIALOG (dialog));
+
+  /* cleanup */
+  gtk_widget_destroy (dialog);
+}
+
+
+
+gint
+mousepad_dialogs_jump_to (GtkWindow *parent,
+                          gint       current_line,
+                          gint       last_line)
+{
+  GtkWidget     *dialog;
+  GtkWidget     *hbox;
+  GtkWidget     *label;
+  GtkWidget     *button;
+  GtkAdjustment *adjustment;
+  gint           line_number = 0;
+
+  /* build the dialog */
+  dialog = gtk_dialog_new_with_buttons (_("Jump To"),
+                                        parent,
+                                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_JUMP_TO, GTK_RESPONSE_OK,
+                                        NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+  hbox = gtk_hbox_new (FALSE, 8);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
+  gtk_widget_show (hbox);
+
+  label = gtk_label_new_with_mnemonic (_("_Line number:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  /* the spin button adjustment */
+  adjustment = (GtkAdjustment *) gtk_adjustment_new (current_line, 1, last_line, 1, 10, 0);
+
+  /* the spin button */
+  button = gtk_spin_button_new (adjustment, 1, 0);
+  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
+  gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
+  gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
+  gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
+  gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
+
+  /* run the dialog */
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    line_number = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button));
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
+
+  return line_number;
+}
+
+
+
+gboolean
+mousepad_dialogs_clear_recent (GtkWindow *parent)
+{
+  GtkWidget *dialog;
+  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?"));
+
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                            _("This will only remove the items from the "
+                                              "history owned by Mousepad."));
+
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_CLEAR, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+  /* popup the dialog */
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    succeed = TRUE;
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
+
+  return succeed;
+}
+
+
+
+gboolean
+mousepad_dialogs_save_changes (GtkWindow *parent)
+{
+  GtkWidget *dialog;
+  gint       response;
+
+  /* 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."));
+
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+                                mousepad_dialogs_image_button (GTK_STOCK_DELETE, _("_Don't Save")),
+                                GTK_RESPONSE_REJECT);
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+  /* run the dialog and wait for a response */
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
+
+  return response;
+}
+
+
+
+static GtkFileChooserConfirmation
+mousepad_dialogs_save_as_callback (GtkFileChooser *dialog)
+{
+  gchar                      *filename;
+  GError                     *error = NULL;
+  GtkFileChooserConfirmation  result;
+
+  /* get the filename */
+  filename = gtk_file_chooser_get_filename (dialog);
+
+  if (mousepad_file_is_writable (filename, &error))
+    {
+      /* show the normal confirmation dialog */
+      result = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
+    }
+  else
+    {
+      /* tell the user he cannot write to this file */
+      mousepad_dialogs_show_error (GTK_WINDOW (dialog), error, _("Permission denied"));
+      g_error_free (error);
+
+      /* the user doesn't have permission to write to the file */
+      result = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
+    }
+
+  /* cleanup */
+  g_free (filename);
+
+  return result;
+}
+
+
+
+gchar *
+mousepad_dialogs_save_as (GtkWindow   *parent,
+                          const gchar *filename)
+{
+  gchar     *new_filename = NULL;
+  GtkWidget *dialog;
+
+  dialog = gtk_file_chooser_dialog_new (_("Save As"),
+                                        parent,
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+                                        NULL);
+  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+  /* we check if the user is allowed to write to the file */
+  g_signal_connect (G_OBJECT (dialog), "confirm-overwrite",
+                    G_CALLBACK (mousepad_dialogs_save_as_callback), NULL);
+
+  /* set the current filename */
+  if (filename != NULL)
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), filename);
+
+  /* run the dialog */
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    new_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
+
+  return new_filename;
+}
+
+
+
+gboolean
+mousepad_dialogs_ask_overwrite (GtkWindow   *parent,
+                                const gchar *filename)
+{
+  GtkWidget *dialog;
+  gboolean   overwrite = FALSE;
+
+  dialog = gtk_message_dialog_new (parent,
+                                   GTK_DIALOG_MODAL
+                                   | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_QUESTION,
+                                   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);
+
+  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+                                mousepad_dialogs_image_button (GTK_STOCK_SAVE, _("_Overwrite")),
+                                GTK_RESPONSE_OK);
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+                                mousepad_dialogs_image_button (GTK_STOCK_REFRESH, _("_Reload")),
+                                GTK_RESPONSE_REJECT);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    overwrite = TRUE;
+
+  gtk_widget_destroy (dialog);
+
+  return overwrite;
+}
diff --git a/mousepad/mousepad-dialogs.h b/mousepad/mousepad-dialogs.h
new file mode 100644
index 0000000..b6f0310
--- /dev/null
+++ b/mousepad/mousepad-dialogs.h
@@ -0,0 +1,48 @@
+/* $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_DIALOGS_H__
+#define __MOUSEPAD_DIALOGS_H__
+
+G_BEGIN_DECLS
+
+void      mousepad_dialogs_show_about    (GtkWindow    *parent);
+
+
+void      mousepad_dialogs_show_error    (GtkWindow    *parent,
+                                          const GError *error,
+                                          const gchar  *message);
+
+gint      mousepad_dialogs_jump_to       (GtkWindow    *parent,
+                                          gint          current_line,
+                                          gint          last_line);
+
+gboolean  mousepad_dialogs_clear_recent  (GtkWindow    *parent);
+
+gint      mousepad_dialogs_save_changes  (GtkWindow    *parent);
+
+gchar    *mousepad_dialogs_save_as       (GtkWindow    *parent,
+                                          const gchar  *filename);
+
+gboolean  mousepad_dialogs_ask_overwrite (GtkWindow    *parent,
+                                          const gchar  *filename);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_DIALOGS_H__ */
diff --git a/mousepad/mousepad-file.c b/mousepad/mousepad-file.c
index 6854fa6..389ee6e 100644
--- a/mousepad/mousepad-file.c
+++ b/mousepad/mousepad-file.c
@@ -54,25 +54,31 @@
 #include <mousepad/mousepad-file.h>
 
 
-
+/**
+ * mousepad_file_get_externally_modified:
+ * @filename : The filename we're going to check.
+ * @mtime    : The last modification time of the document.
+ *
+ * Returns whether a file has been modified after @mtime. If
+ * no file was found it returns %FALSE.
+ *
+ * Return value: %TRUE is the file exists and has been modified.
+ **/
 gboolean
-mousepad_file_get_externally_modified (const gchar  *filename,
-                                       gint          mtime,
-                                       GError      **error)
+mousepad_file_get_externally_modified (const gchar *filename,
+                                       gint         mtime)
 {
   gint         fd;
   struct stat  statb;
   gboolean     modified = FALSE;
 
-  _mousepad_return_val_if_fail (filename != NULL, FALSE);
-  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  _mousepad_return_val_if_fail (filename != NULL, TRUE);
 
   /* open the file for reading */
   fd = open (filename, O_RDONLY);
   if (G_UNLIKELY (fd < 0))
     {
-      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
-                   _("Failed to open \"%s\" for reading"), filename);
+      /* files probably doesn't exists, so we can safely write */
       return FALSE;
     }
 
@@ -88,6 +94,21 @@ mousepad_file_get_externally_modified (const gchar  *filename,
 
 
 
+/**
+ * mousepad_file_save_data:
+ * @filename  : The filename of the document.
+ * @data      : The content of the editor. This string should
+ *              already been converted to the correct encoding.
+ * @bytes     : The length of @data.
+ * @new_mtime : Return location for the file's modification
+ *              time after a succesfull write.
+ * @error     : Return location for errors or %NULL.
+ *
+ * Try to save the @data to @filename. This function does not
+ * check if the document has been modified externally.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
 gboolean
 mousepad_file_save_data (const gchar  *filename,
                          const gchar  *data,
@@ -188,6 +209,26 @@ failed:
 
 
 
+/**
+ * mousepad_file_read_to_buffer:
+ * @filename  : The filename of the destination file.
+ * @buffer    : A #GtkTextBuffer where we can insert the
+ *              content of @filename.
+ * @new_mtime : Return location of the file's modification time
+ *              after a succesfull read.
+ * @readonly  : Return location if we're only allowed to write
+ *              the file. %TRUE if the user is not allowed to write
+ *              to the file.
+ * @error     : Return location of errors or %NULL.
+ *
+ * This function reads the content of a file and inserts it directly
+ * in a #GtkTextBuffer. We don't return a string to avoid string duplication.
+ *
+ * If the user has support for MMAP and the size of the file is below 8MB, we
+ * use MMAP to speedup the file reading a bit.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
 gboolean
 mousepad_file_read_to_buffer (const gchar    *filename,
                               GtkTextBuffer  *buffer,
@@ -280,6 +321,18 @@ failed:
 
 
 
+/**
+ * mousepad_file_is_writable:
+ * @filename : The filename to check.
+ * @error    : Return location of errors or %NULL.
+ *
+ * Check if a user is allowed to write to a file. This function
+ * is used in the save as dialog to warn the user if he or she
+ * has permissions to write (before actually closing the
+ * dialog).
+ *
+ * Return value: %TRUE is the user is allowed to write the @filename.
+ **/
 gboolean
 mousepad_file_is_writable (const gchar  *filename,
                            GError      **error)
diff --git a/mousepad/mousepad-file.h b/mousepad/mousepad-file.h
index cabfda8..8ffcfd4 100644
--- a/mousepad/mousepad-file.h
+++ b/mousepad/mousepad-file.h
@@ -22,24 +22,23 @@
 
 G_BEGIN_DECLS
 
-gboolean   mousepad_file_get_externally_modified   (const gchar    *filename,
-                                                    gint            mtime,
-                                                    GError        **error);
-
-gboolean   mousepad_file_save_data                 (const gchar    *filename,
-                                                    const gchar    *data,
-                                                    gsize           bytes,
-                                                    gint           *new_mtime,
-                                                    GError        **error);
-
-gboolean   mousepad_file_read_to_buffer            (const gchar    *filename,
-                                                    GtkTextBuffer  *buffer,
-                                                    gint           *new_mtime,
-                                                    gboolean       *readonly,
-                                                    GError        **error);
-
-gboolean   mousepad_file_is_writable               (const gchar    *filename,
-                                                    GError        **error);
+gboolean  mousepad_file_get_externally_modified  (const gchar    *filename,
+                                                  gint            mtime);
+
+gboolean  mousepad_file_save_data                (const gchar    *filename,
+                                                  const gchar    *data,
+                                                  gsize           bytes,
+                                                  gint           *new_mtime,
+                                                  GError        **error);
+
+gboolean  mousepad_file_read_to_buffer           (const gchar    *filename,
+                                                  GtkTextBuffer  *buffer,
+                                                  gint           *new_mtime,
+                                                  gboolean       *readonly,
+                                                  GError        **error);
+
+gboolean  mousepad_file_is_writable              (const gchar    *filename,
+                                                  GError        **error);
 
 G_END_DECLS
 
diff --git a/mousepad/mousepad-preferences.c b/mousepad/mousepad-preferences.c
index c3707c6..c5ec45f 100644
--- a/mousepad/mousepad-preferences.c
+++ b/mousepad/mousepad-preferences.c
@@ -80,7 +80,7 @@ static void     mousepad_preferences_set_property       (GObject
                                                          const GValue             *value,
                                                          GParamSpec               *pspec);
 static void     mousepad_preferences_queue_store        (MousepadPreferences      *preferences);
-static gboolean mousepad_preferences_load_idle          (gpointer                  user_data);
+static gboolean mousepad_preferences_load               (MousepadPreferences      *preferences);
 static gboolean mousepad_preferences_store_idle         (gpointer                  user_data);
 static void     mousepad_preferences_store_idle_destroy (gpointer                  user_data);
 
@@ -93,10 +93,10 @@ struct _MousepadPreferences
 {
   GObject  __parent__;
 
+  /* all the properties stored in the Object */
   GValue   values[N_PROPERTIES];
 
-  gboolean loading_in_progress;
-
+  /* idle save timer id */
   gint     store_idle_id;
 };
 
@@ -105,7 +105,14 @@ struct _MousepadPreferences
 static GObjectClass *mousepad_preferences_parent_class;
 
 
-
+/**
+ * transform_string_to_boolean:
+ * @const GValue : String #GValue.
+ * @GValue       : Return location for a #GValue boolean.
+ *
+ * Converts a string into a boolean. This is used when
+ * converting the XfceRc values.
+ **/
 static void
 transform_string_to_boolean (const GValue *src,
                              GValue       *dst)
@@ -115,6 +122,13 @@ transform_string_to_boolean (const GValue *src,
 
 
 
+/**
+ * transform_string_to_int:
+ * @const GValue : String #GValue.
+ * @GValue       : Return location for a #GValue integer.
+ *
+ * Converts a string into a number.
+ **/
 static void
 transform_string_to_int (const GValue *src,
                          GValue       *dst)
@@ -164,6 +178,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
   if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_INT))
     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",
@@ -172,6 +191,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          FALSE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:font-name
+   *
+   * The font name and size used in the text view. If this value is
+   * %NULL, the system font will be used.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_FONT_NAME,
                                    g_param_spec_string ("font-name",
@@ -180,6 +205,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                         NULL,
                                                         EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:last-window-height
+   *
+   * The last known height of a #MousepadWindow, which will be used as
+   * default height for newly created windows.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_LAST_WINDOW_HEIGHT,
                                    g_param_spec_int ("last-window-height",
@@ -188,6 +219,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                      1, G_MAXINT, 480,
                                                      EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:last-window-width
+   *
+   * The last known width of a #MousepadWindow, which will be used as
+   * default width for newly created windows.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_LAST_WINDOW_WIDTH,
                                    g_param_spec_int ("last-window-width",
@@ -196,6 +233,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                      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",
@@ -204,6 +246,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          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",
@@ -212,6 +259,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          TRUE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:word-wrap
+   *
+   * Whether word wrapping is enabled.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_WORD_WRAP,
                                    g_param_spec_boolean ("word-wrap",
@@ -220,6 +272,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          FALSE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:misc-always-show-tabs
+   *
+   * Whether tabs are always visible. By default the tabs are hidden
+   * when there is only 1 screen opened.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_MISC_ALWAYS_SHOW_TABS,
                                    g_param_spec_boolean ("misc-always-show-tabs",
@@ -228,6 +286,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          FALSE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:misc-cycle-tabs
+   *
+   * Whether to cycle tabs with the back and forward buttons in the go menu.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_MISC_CYCLE_TABS,
                                    g_param_spec_boolean ("misc-cycle-tabs",
@@ -236,6 +299,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          FALSE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:misc-show-full-path-in-title
+   *
+   * Whether to show the full file name path in the window title.
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_MISC_SHOW_FULL_PATH_IN_TITLE,
                                    g_param_spec_boolean ("misc-show-full-path-in-title",
@@ -244,6 +312,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          FALSE,
                                                          EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:misc-recent-menu-limit
+   *
+   * The number of items in the recent menu,
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_MISC_RECENT_MENU_LIMIT,
                                    g_param_spec_int ("misc-recent-menu-limit",
@@ -252,6 +325,15 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                      1, G_MAXINT, 10,
                                                      EXO_PARAM_READWRITE));
 
+  /**
+   * MousepadPreferences:misc-remember-geometry
+   *
+   * Whether Mousepad should remember the size of windows and apply this
+   * to newly created windows. If %TRUE the width and height are
+   * saved to "last-window-width" and "last-window-height". If
+   * %FALSE the user may specify the start size in "last-window-with"
+   * and "last-window-height".
+   **/
   g_object_class_install_property (gobject_class,
                                    PROP_MISC_REMEMBER_GEOMETRY,
                                    g_param_spec_boolean ("misc-remember-geometry",
@@ -260,6 +342,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          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",
@@ -275,7 +362,7 @@ static void
 mousepad_preferences_init (MousepadPreferences *preferences)
 {
   /* load the settings */
-  mousepad_preferences_load_idle (preferences);
+  mousepad_preferences_load (preferences);
 }
 
 
@@ -345,7 +432,7 @@ mousepad_preferences_set_property (GObject      *object,
 static void
 mousepad_preferences_queue_store (MousepadPreferences *preferences)
 {
-  if (preferences->store_idle_id == 0 && !preferences->loading_in_progress)
+  if (preferences->store_idle_id == 0)
     {
       preferences->store_idle_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_preferences_store_idle,
                                                     preferences, mousepad_preferences_store_idle_destroy);
@@ -387,23 +474,22 @@ property_name_to_option_name (const gchar *property_name)
 
 
 static gboolean
-mousepad_preferences_load_idle (gpointer user_data)
+mousepad_preferences_load (MousepadPreferences *preferences)
 {
-  MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (user_data);
-  const gchar         *string;
-  GParamSpec         **specs;
-  GParamSpec          *spec;
-  XfceRc              *rc;
-  GValue               dst = { 0, };
-  GValue               src = { 0, };
-  gchar               *option;
-  guint                nspecs;
-  guint                n;
+  const gchar  *string;
+  GParamSpec  **specs;
+  GParamSpec   *spec;
+  XfceRc       *rc;
+  GValue        dst = { 0, };
+  GValue        src = { 0, };
+  gchar        *option;
+  guint         nspecs;
+  guint         n;
 
   rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", TRUE);
   if (G_UNLIKELY (rc == NULL))
     {
-      g_warning ("Failed to load mousepad preferences.");
+      g_warning ("Failed to load the preferences. Unable to open \"~/.config/Mousepad/mousepadrc\"");
       return FALSE;
     }
 
@@ -411,8 +497,6 @@ mousepad_preferences_load_idle (gpointer user_data)
 
   xfce_rc_set_group (rc, "Configuration");
 
-  preferences->loading_in_progress = TRUE;
-
   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (preferences), &nspecs);
 
   for (n = 0; n < nspecs; ++n)
@@ -449,8 +533,6 @@ mousepad_preferences_load_idle (gpointer user_data)
     }
   g_free (specs);
 
-  preferences->loading_in_progress = FALSE;
-
   xfce_rc_close (rc);
 
   g_object_thaw_notify (G_OBJECT (preferences));
@@ -477,7 +559,7 @@ mousepad_preferences_store_idle (gpointer user_data)
   rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", FALSE);
   if (G_UNLIKELY (rc == NULL))
     {
-      g_warning ("Failed to store mousepad preferences.");
+      g_warning ("Failed to store the preferences. Unable to open \"~/.config/Mousepad/mousepadrc\"");
       return FALSE;
     }
 
@@ -533,6 +615,16 @@ mousepad_preferences_store_idle_destroy (gpointer user_data)
 
 
 
+/**
+ * mousepad_preferences_get:
+ *
+ * Queries the global #MousepadPreferences instance, which is shared
+ * by all modules. The function automatically takes a reference
+ * for the caller, so you'll need to call g_object_unref() when
+ * you're done with it.
+ *
+ * Return value: the global #MousepadPreferences instance.
+ **/
 MousepadPreferences*
 mousepad_preferences_get (void)
 {
diff --git a/mousepad/mousepad-screen.c b/mousepad/mousepad-screen.c
index 4e281b7..1ac53a3 100644
--- a/mousepad/mousepad-screen.c
+++ b/mousepad/mousepad-screen.c
@@ -458,6 +458,7 @@ mousepad_screen_open_file (MousepadScreen  *screen,
 
 gboolean
 mousepad_screen_save_file (MousepadScreen  *screen,
+                           const gchar     *filename,
                            GError         **error)
 {
   gchar         *content;
@@ -470,7 +471,7 @@ mousepad_screen_save_file (MousepadScreen  *screen,
 
   _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 (screen->filename != NULL, FALSE);
+  _mousepad_return_val_if_fail (filename != NULL, FALSE);
 
   /* get the buffer */
   buffer = mousepad_screen_get_text_buffer (screen);
@@ -495,7 +496,7 @@ mousepad_screen_save_file (MousepadScreen  *screen,
 
       if (G_LIKELY (converted != NULL))
         {
-          succeed = mousepad_file_save_data (screen->filename, converted, bytes,
+          succeed = mousepad_file_save_data (filename, converted, bytes,
                                              &new_mtime, error);
 
           /* cleanup */
@@ -553,18 +554,11 @@ mousepad_screen_get_filename (MousepadScreen *screen)
 
 
 gboolean
-mousepad_screen_get_externally_modified (MousepadScreen  *screen,
-                                         GError         **error)
+mousepad_screen_get_mtime (MousepadScreen *screen)
 {
-  gboolean modified;
-
   _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
-  _mousepad_return_val_if_fail (screen->filename != NULL, FALSE);
-
-  /* check if the file has been modified */
-  modified = mousepad_file_get_externally_modified (screen->filename, screen->mtime, error);
 
-  return modified;
+  return screen->mtime;
 }
 
 
diff --git a/mousepad/mousepad-screen.h b/mousepad/mousepad-screen.h
index 9017424..c7274bc 100644
--- a/mousepad/mousepad-screen.h
+++ b/mousepad/mousepad-screen.h
@@ -46,6 +46,7 @@ gboolean        mousepad_screen_open_file                (MousepadScreen  *scree
                                                           GError         **error);
 
 gboolean        mousepad_screen_save_file                (MousepadScreen  *screen,
+                                                          const gchar     *filename,
                                                           GError         **error);
 
 const gchar    *mousepad_screen_get_title                (MousepadScreen  *screen,
@@ -53,8 +54,7 @@ const gchar    *mousepad_screen_get_title                (MousepadScreen  *scree
 
 const gchar    *mousepad_screen_get_filename             (MousepadScreen  *screen);
 
-gboolean        mousepad_screen_get_externally_modified  (MousepadScreen  *screen,
-                                                          GError         **error);
+gboolean        mousepad_screen_get_mtime                (MousepadScreen  *screen);
 
 GtkTextView    *mousepad_screen_get_text_view            (MousepadScreen  *screen);
 
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index d4f3ce0..b0c181d 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -32,25 +32,25 @@
 
 
 
-static void            mousepad_view_class_init               (MousepadViewClass  *klass);
-static void            mousepad_view_init                     (MousepadView       *view);
-static void            mousepad_view_finalize                 (GObject            *object);
-static gboolean        mousepad_view_key_press_event          (GtkWidget          *widget,
-                                                               GdkEventKey        *event);
-static void            mousepad_view_indent_lines             (MousepadView       *view,
-                                                               GtkTextIter        *start,
-                                                               GtkTextIter        *end,
-                                                               gboolean            indent);
-static gchar          *mousepad_view_compute_indentation      (MousepadView       *view,
-                                                               GtkTextIter        *iter);
-static gint            mousepad_view_expose                   (GtkWidget          *widget,
-                                                               GdkEventExpose     *event);
-static void            mousepad_view_get_lines                (GtkTextView        *text_view,
-                                                               gint                first_y,
-                                                               gint                last_y,
-                                                               GArray            **pixels,
-                                                               GArray            **numbers,
-                                                               gint               *countp);
+static void      mousepad_view_class_init           (MousepadViewClass  *klass);
+static void      mousepad_view_init                 (MousepadView       *view);
+static void      mousepad_view_finalize             (GObject            *object);
+static gboolean  mousepad_view_key_press_event      (GtkWidget          *widget,
+                                                     GdkEventKey        *event);
+static void      mousepad_view_indent_lines         (MousepadView       *view,
+                                                     GtkTextIter        *start,
+                                                     GtkTextIter        *end,
+                                                     gboolean            indent);
+static gchar    *mousepad_view_compute_indentation  (MousepadView       *view,
+                                                     GtkTextIter        *iter);
+static gint      mousepad_view_expose               (GtkWidget          *widget,
+                                                     GdkEventExpose     *event);
+static void      mousepad_view_get_lines            (GtkTextView        *text_view,
+                                                     gint                first_y,
+                                                     gint                last_y,
+                                                     GArray            **pixels,
+                                                     GArray            **numbers,
+                                                     gint               *countp);
 
 
 
@@ -63,6 +63,7 @@ struct _MousepadView
 {
   GtkTextView  __parent__;
 
+  /* settings */
   gboolean     auto_indent;
   gboolean     line_numbers;
 };
@@ -128,6 +129,18 @@ mousepad_view_finalize (GObject *object)
 
 
 
+/**
+ * mousepad_view_key_press_event:
+ * @widget : A #GtkWidget.
+ * @event  : A #GdkEventKey
+ *
+ * This function is triggered when the user pressed a key in the
+ * #MousepadView. It checks if we need to auto indent the new line
+ * or when multiple lines are selected we (un)indent all of them.
+ *
+ * Return value: %TRUE if we handled the event, else we trigger the
+ *               parent class so Gtk can handle the event.
+ **/
 static gboolean
 mousepad_view_key_press_event (GtkWidget   *widget,
                                GdkEventKey *event)
@@ -210,6 +223,18 @@ mousepad_view_key_press_event (GtkWidget   *widget,
 
 
 
+/**
+ * mousepad_view_indent_lines:
+ * @view   : A #MousepadView
+ * @start  : The start #GtkTextIter of the selection.
+ * @end    : The end #GtkTextIter of the selection
+ * @indent : Whether we need to indent or unindent the
+ *           selected lines.
+ *
+ * This function (un)indents the selected lines. It simply walks
+ * from the start line number to the end line number and prepends
+ * or removed a tab (or the tab width in spaces).
+ **/
 static void
 mousepad_view_indent_lines (MousepadView *view,
                             GtkTextIter  *start,
@@ -309,6 +334,19 @@ mousepad_view_indent_lines (MousepadView *view,
 
 
 
+/**
+ * mousepad_view_compute_indentation:
+ * @view : A #MousepadView.
+ * @iter : The #GtkTextIter of the previous line.
+ *
+ * This function is used to get the tabs and spaces we need to
+ * append when auto indentation is enabled. If scans the line of
+ * @iter and returns a slice of the tabs and spaces before the
+ * first character or line end.
+ *
+ * Return value: A string of tabs and spaces or %NULL when the
+ *               previous line has no tabs or spaces before the text.
+ **/
 static gchar *
 mousepad_view_compute_indentation (MousepadView *view,
                                    GtkTextIter  *iter)
@@ -356,6 +394,21 @@ mousepad_view_compute_indentation (MousepadView *view,
 
 
 
+/**
+ * mousepad_view_get_lines:
+ * @text_view : A #GtkTextView
+ * @first_y   : The first y location of the visible #GtkTextView window.
+ * @last_y    : The last y location of the visible #GtkTextView window.
+ * @pixels    : Return location for the #GArray with the y location
+ *              in pixels we need to draw line numbers.
+ * @numbers   : Return location for the #GArray with all the visible
+ *              line numbers.
+ * @countp    : Return location for the number of lines visible between
+ *              @first_y and @last_y.
+ *
+ * This function returns two arrays with the lines number and there draw
+ * location of the visible text view window.
+ **/
 static void
 mousepad_view_get_lines (GtkTextView  *text_view,
                          gint          first_y,
@@ -428,6 +481,17 @@ mousepad_view_get_lines (GtkTextView  *text_view,
 
 
 
+/**
+ * mousepad_view_expose:
+ * @widget : A textview widget.
+ * @event  : A #GdkEventExpose event.
+ *
+ * This function draws the line numbers in the GTK_TEXT_WINDOW_LEFT window
+ * when it receives an expose event. At the end of the function we always
+ * return the expose_event of the parent class so Gtk can draw the text.
+ *
+ * Return value: The return value of the parent_class.
+ **/
 static gboolean
 mousepad_view_expose (GtkWidget      *widget,
                       GdkEventExpose *event)
@@ -520,6 +584,14 @@ mousepad_view_expose (GtkWidget      *widget,
 
 
 
+/**
+ * mousepad_view_set_show_line_numbers:
+ * @view    : A #MousepadView
+ * @visible : Boolean whether we show or hide the line
+ *            numbers.
+ *
+ * Whether line numbers are visible in the @view.
+ **/
 void
 mousepad_view_set_show_line_numbers (MousepadView *view,
                                      gboolean      visible)
@@ -543,6 +615,14 @@ mousepad_view_set_show_line_numbers (MousepadView *view,
 
 
 
+/**
+ * mousepad_view_set_auto_indent:
+ * @view    : A #MousepadView
+ * @visible : Boolean whether we enable or disable
+ *            auto indentation.
+ *
+ * Whether we enable auto indentation.
+ **/
 void
 mousepad_view_set_auto_indent (MousepadView *view,
                                gboolean      enable)
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index 126fa88..b5bf592 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -25,11 +25,15 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 #include <mousepad/mousepad-application.h>
+#include <mousepad/mousepad-dialogs.h>
 #include <mousepad/mousepad-preferences.h>
 #include <mousepad/mousepad-private.h>
 #include <mousepad/mousepad-file.h>
@@ -41,12 +45,15 @@
 
 
 
+/* class functions */
 static void              mousepad_window_class_init                   (MousepadWindowClass    *klass);
 static void              mousepad_window_init                         (MousepadWindow         *window);
 static void              mousepad_window_dispose                      (GObject                *object);
 static void              mousepad_window_finalize                     (GObject                *object);
 static gboolean          mousepad_window_configure_event              (GtkWidget              *widget,
                                                                        GdkEventConfigure      *event);
+
+/* statusbar tooltips */
 static void              mousepad_window_connect_proxy                (GtkUIManager           *manager,
                                                                        GtkAction              *action,
                                                                        GtkWidget              *proxy,
@@ -59,25 +66,24 @@ static void              mousepad_window_menu_item_selected           (GtkWidget
                                                                        MousepadWindow         *window);
 static void              mousepad_window_menu_item_deselected         (GtkWidget              *menu_item,
                                                                        MousepadWindow         *window);
+
+/* save windows geometry */
 static gboolean          mousepad_window_save_geometry_timer          (gpointer                user_data);
 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_as                      (MousepadWindow         *window,
-                                                                       MousepadScreen         *screen);
+static gboolean          mousepad_window_save                         (MousepadWindow         *window,
+                                                                       MousepadScreen         *screen,
+                                                                       gboolean                force_save_as);
 static void              mousepad_window_add                          (MousepadWindow         *window,
                                                                        MousepadScreen         *screen);
 static gboolean          mousepad_window_close_screen                 (MousepadWindow         *window,
                                                                        MousepadScreen         *screen);
-static gint              mousepad_window_sort_recent_items            (GtkRecentInfo          *a,
-                                                                       GtkRecentInfo          *b);
-static void              mousepad_window_recent_menu                  (MousepadWindow         *window);
-static void              mousepad_window_add_recent                   (MousepadWindow         *window,
-                                                                       const gchar            *filename);
 static void              mousepad_window_set_title                    (MousepadWindow         *window,
                                                                        MousepadScreen         *screen);
-static void              mousepad_window_notify_title                 (MousepadScreen         *screen,
-                                                                       GParamSpec             *pspec,
-                                                                       MousepadWindow         *window);
+
+/* notebook signals */
 static void              mousepad_window_page_notified                (GtkNotebook            *notebook,
                                                                        GParamSpec             *pspec,
                                                                        MousepadWindow         *window);
@@ -88,14 +94,30 @@ static void              mousepad_window_page_reordered               (GtkNotebo
                                                                        GtkNotebookPage        *page,
                                                                        guint                   page_num,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_error_dialog                 (GtkWindow              *window,
-                                                                       GError                 *error,
-                                                                       const gchar            *message);
-static void              mousepad_window_update_actions               (MousepadWindow         *window);
-static void              mousepad_window_go_menu                      (MousepadWindow         *window);
+
+/* screen signals */
+static void              mousepad_window_notify_title                 (MousepadScreen         *screen,
+                                                                       GParamSpec             *pspec,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_modified_changed             (MousepadScreen         *screen,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_selection_changed            (MousepadScreen         *screen,
                                                                        gboolean                selected,
                                                                        MousepadWindow         *window);
+
+/* menu updaters */
+static void              mousepad_window_update_actions               (MousepadWindow         *window);
+static void              mousepad_window_update_gomenu                (MousepadWindow         *window);
+
+/* recent functions */
+static void              mousepad_window_recent_add                   (MousepadWindow         *window,
+                                                                       const gchar            *filename);
+static gint              mousepad_window_recent_sort                  (GtkRecentInfo          *a,
+                                                                       GtkRecentInfo          *b);
+static void              mousepad_window_recent_menu                  (MousepadWindow         *window);
+static void              mousepad_window_recent_clear                 (MousepadWindow         *window);
+
+/* actions */
 static void              mousepad_window_action_open_new_window       (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_open_file             (GtkAction              *action,
@@ -110,9 +132,6 @@ static void              mousepad_window_action_save_file_as          (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_close_tab             (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_button_close_tab             (MousepadScreen         *screen);
-static gboolean          mousepad_window_delete_event                 (MousepadWindow         *window,
-                                                                       GdkEvent               *event);
 static void              mousepad_window_action_close                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_close_all_windows     (GtkAction              *action,
@@ -137,9 +156,16 @@ static void              mousepad_window_action_prev_tab              (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_next_tab              (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_goto                  (GtkRadioAction         *action,
+                                                                       GtkNotebook            *notebook);
 static void              mousepad_window_action_about                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
 
+/* miscellaneous actions */
+static void              mousepad_window_button_close_tab             (MousepadScreen         *screen);
+static gboolean          mousepad_window_delete_event                 (MousepadWindow         *window,
+                                                                       GdkEvent               *event);
+
 
 
 
@@ -346,7 +372,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);
@@ -488,6 +514,9 @@ mousepad_window_configure_event (GtkWidget         *widget,
 
 
 
+/**
+ * Statusbar Tooltip Functions
+ **/
 static void
 mousepad_window_connect_proxy (GtkUIManager   *manager,
                                GtkAction      *action,
@@ -566,6 +595,9 @@ mousepad_window_menu_item_deselected (GtkWidget      *menu_item,
 
 
 
+/**
+ * Save Geometry Functions
+ **/
 static gboolean
 mousepad_window_save_geometry_timer (gpointer user_data)
 {
@@ -616,6 +648,9 @@ mousepad_window_save_geometry_timer_destroy (gpointer user_data)
 
 
 
+/**
+ * Mousepad Window Functions
+ **/
 static MousepadScreen *
 mousepad_window_get_active (MousepadWindow *window)
 {
@@ -671,19 +706,22 @@ mousepad_window_open_tab (MousepadWindow *window,
   /* new screen */
   screen = mousepad_screen_new ();
 
-  /* load a file, if there is any */
   if (filename)
+    /* load the file content in the screen */
     succeed = mousepad_screen_open_file (MOUSEPAD_SCREEN (screen), filename, &error);
 
   if (G_LIKELY (succeed))
-    mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+    {
+      /* add the screen to the notebook and connect some signals */
+      mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+    }
   else
     {
       /* something went wrong, remove the screen */
       gtk_widget_destroy (GTK_WIDGET (screen));
 
       /* show the warning */
-      mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to open file"));
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
       g_error_free (error);
     }
 
@@ -712,7 +750,7 @@ mousepad_window_open_files (MousepadWindow  *window,
   for (n = 0; filenames[n] != NULL; ++n)
     {
       /* check if the filename looks like an uri */
-      if (g_strstr_len (filenames[n], 5, "file:"))
+      if (strncmp (filenames[n], "file:", 5) == 0)
         {
           /* convert the uri to an absolute filename */
           filename = g_filename_from_uri (filenames[n], NULL, NULL);
@@ -736,95 +774,76 @@ mousepad_window_open_files (MousepadWindow  *window,
 
   /* update the menus */
   mousepad_window_recent_menu (window);
-  mousepad_window_go_menu (window);
+  mousepad_window_update_gomenu (window);
 }
 
 
 
-static GtkFileChooserConfirmation
-mousepad_window_save_as_callback (GtkFileChooser *dialog)
+static gboolean
+mousepad_window_save (MousepadWindow  *window,
+                      MousepadScreen  *screen,
+                      gboolean         force_save_as)
 {
-  gchar                      *filename;
-  GError                     *error = NULL;
-  GtkFileChooserConfirmation  result;
+  gchar       *new_filename = NULL;
+  const gchar *filename;
+  gboolean     succeed = FALSE;
+  GError      *error = NULL;
+  const gchar *message;
+  gint         mtime;
 
-  /* get the filename */
-  filename = gtk_file_chooser_get_filename (dialog);
+  /* get the current filename */
+  filename = mousepad_screen_get_filename (screen);
 
-  if (mousepad_file_is_writable (filename, &error))
+  if (force_save_as || filename == NULL)
     {
-      /* show the normal confirmation dialog */
-      result = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
-    }
-  else
-    {
-      /* tell the user he cannot write to this file */
-      mousepad_window_error_dialog (GTK_WINDOW (dialog), error, _("Permission denied"));
-      g_error_free (error);
-
-      /* the user doesn't have permission to write to the file */
-      result = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
-    }
-
-  /* cleanup */
-  g_free (filename);
-
-  return result;
-}
+      /* get the new filename */
+      new_filename = mousepad_dialogs_save_as (GTK_WINDOW (window), filename);
 
+      if (new_filename)
+        {
+          /* try the save the file */
+          succeed = mousepad_screen_save_file (screen, new_filename, &error);
 
+          /* the warnings message for save as */
+          message = _("Failed to save the document as another file");
 
-static gboolean
-mousepad_window_save_as (MousepadWindow *window,
-                         MousepadScreen *screen)
-{
-  GtkWidget   *dialog;
-  gboolean     succeed = FALSE;
-  gchar       *filename;
+          if (succeed)
+            {
+              /* set the filename */
+              mousepad_screen_set_filename (screen, new_filename);
 
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+              /* add the item to the recent menu */
+              mousepad_window_recent_add (window, new_filename);
+            }
 
-  dialog = gtk_file_chooser_dialog_new (_("Save As"),
-                                        GTK_WINDOW (window),
-                                        GTK_FILE_CHOOSER_ACTION_SAVE,
-                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
-                                        NULL);
-  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
-  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-
-  /* we check if the user is allowed to write to the file */
-  g_signal_connect (G_OBJECT (dialog), "confirm-overwrite",
-                                G_CALLBACK (mousepad_window_save_as_callback), NULL);
-
-  /* set the current file, or the temp name */
-  if (mousepad_screen_get_filename (screen) != NULL)
-    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_filename (screen));
+          /* cleanup */
+          g_free (new_filename);
+        }
+    }
   else
-    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_title (screen, FALSE));
-
-  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
     {
-      /* get the filename the user has selected */
-      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+      /* get the mtime */
+      mtime = mousepad_screen_get_mtime (screen);
 
-      if (G_LIKELY (filename != NULL))
+      /* check if the file has been modified externally, if so ask the user if
+       * he or she wants to overwrite the file */
+      if (mousepad_file_get_externally_modified (filename, mtime) == FALSE ||
+          mousepad_dialogs_ask_overwrite (GTK_WINDOW (window), filename) == TRUE)
         {
-          /* set the filename */
-          mousepad_screen_set_filename (screen, filename);
-
-          /* cleanup */
-          g_free (filename);
+          /* save the file */
+          succeed = mousepad_screen_save_file (screen, filename, &error);
 
-          /* it worked */
-          succeed = TRUE;
+          /* the warning message for save */
+          message = _("Failed to save the document");
         }
     }
 
-  /* destroy the dialog */
-  gtk_widget_destroy (dialog);
+  /* display the error */
+  if (G_UNLIKELY (error))
+    {
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, message);
+      g_error_free (error);
+    }
 
   return succeed;
 }
@@ -832,18 +851,6 @@ mousepad_window_save_as (MousepadWindow *window,
 
 
 static void
-mousepad_window_modified_changed (MousepadScreen *screen,
-                                  MousepadWindow *window)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
-  _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
-  mousepad_window_set_title (window, screen);
-}
-
-
-
-static void
 mousepad_window_add (MousepadWindow *window,
                      MousepadScreen *screen)
 {
@@ -895,7 +902,7 @@ mousepad_window_add (MousepadWindow *window,
   GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
 
   /* rebuild the go menu */
-  mousepad_window_go_menu (window);
+  mousepad_window_update_gomenu (window);
 
   /* show the screen */
   gtk_widget_show (GTK_WIDGET (screen));
@@ -921,10 +928,8 @@ static gboolean
 mousepad_window_close_screen (MousepadWindow *window,
                               MousepadScreen *screen)
 {
-  GtkWidget *dialog;
   gint       response;
   gboolean   succeed = FALSE;
-  GError    *error = NULL;
 
   _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
   _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
@@ -932,28 +937,12 @@ mousepad_window_close_screen (MousepadWindow *window,
   /* check if the document needs to be saved */
   if (mousepad_screen_get_modified (screen))
     {
-      /* create the question dialog */
-      dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                       GTK_MESSAGE_QUESTION,
-                                       GTK_BUTTONS_NONE,
-                                       _("Do you want to save changes to this\ndocument before closing?"));
-      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                                _("If you don't save, your changes will be lost."));
-      gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                              _("_Don't Save"), GTK_RESPONSE_HELP,
-                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                              GTK_STOCK_SAVE, GTK_RESPONSE_OK,
-                              NULL);
-      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-
       /* run the dialog */
-      response = gtk_dialog_run (GTK_DIALOG (dialog));
-      gtk_widget_destroy (dialog);
+      response = mousepad_dialogs_save_changes (GTK_WINDOW (window));
 
       switch (response)
         {
-          case GTK_RESPONSE_HELP:
+          case GTK_RESPONSE_REJECT:
             /* don't save, only destroy the screen */
             succeed = TRUE;
             break;
@@ -961,17 +950,7 @@ mousepad_window_close_screen (MousepadWindow *window,
             /* we do nothing */
             break;
           case GTK_RESPONSE_OK:
-            /* save the screen */
-            if (mousepad_screen_get_filename (screen) == NULL)
-              {
-                /* file has no name yet, save as */
-                if (mousepad_window_save_as (window, screen))
-                  succeed = mousepad_screen_save_file (screen, &error);
-              }
-            else
-              {
-                succeed = mousepad_screen_save_file (screen, &error);
-              }
+            succeed = mousepad_window_save (window, screen, FALSE);
             break;
         }
     }
@@ -983,168 +962,11 @@ mousepad_window_close_screen (MousepadWindow *window,
 
   /* destroy the screen */
   if (succeed)
-    {
-      gtk_widget_destroy (GTK_WIDGET (screen));
-    }
-  else if (error != NULL)
-    {
-      /* something went wrong with saving the file */
-      mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
-      g_error_free (error);
-    }
+    gtk_widget_destroy (GTK_WIDGET (screen));
 
   return succeed;
 }
 
-static gint
-mousepad_window_sort_recent_items (GtkRecentInfo *a,
-                                   GtkRecentInfo *b)
-{
-  return (gtk_recent_info_get_modified (a) < gtk_recent_info_get_modified (b));
-}
-
-static void
-mousepad_window_recent_menu (MousepadWindow *window)
-{
-  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;
-
-  /* leave when we're updating multiple files */
-  if (lock_menu_updates)
-    return;
-
-  /* unmerge the ui controls from the previous update */
-  if (merge_id != 0)
-    gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
-
-  /* drop all the previous actions from the action group */
-  actions = gtk_action_group_list_actions (window->recent_actions);
-  for (li = actions; li != NULL; li = li->next)
-    gtk_action_group_remove_action (window->recent_actions, li->data);
-  g_list_free (actions);
-
-  /* create a new merge id */
-  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);
-
-  /* walk through the items in the manager */
-  for (li = items; li != NULL; li = li->next)
-    {
-      /* check if the item is in the Mousepad group */
-      if (!gtk_recent_info_has_group (li->data, PACKAGE_NAME))
-        continue;
-
-      /* append the item */
-      filtered = g_list_prepend (filtered, li->data);
-    }
-
-  /* sort the filtered items */
-  filtered = g_list_sort (filtered, (GCompareFunc) mousepad_window_sort_recent_items);
-
-  /* get the recent menu limit number */
-  g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-limit", &n, NULL);
-
-  /* append the items to the menu */
-  for (li = filtered; n > 0 && li != NULL; li = li->next, --n)
-    {
-      info = li->data;
-
-      /* create the action name */
-      name = g_strdup_printf ("recent-info-%d", n);
-
-      /* 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, "_", "__");
-
-      /* create the tooltip with an utf-8 valid version of the filename */
-      uri_display = gtk_recent_info_get_uri_display (info);
-      tooltip = g_strdup_printf (_("Open '%s'"), uri_display);
-      g_free (uri_display);
-
-      /* create the action */
-      action = gtk_action_new (name, label, tooltip, NULL);
-
-      /* cleanup */
-      g_free (tooltip);
-      g_free (label);
-
-      /* add the info data and connect a menu signal */
-      g_object_set_data_full (G_OBJECT (action), I_("gtk-recent-info"), gtk_recent_info_ref (info), (GDestroyNotify) gtk_recent_info_unref);
-      g_signal_connect (G_OBJECT (action), "activate",
-			G_CALLBACK (mousepad_window_action_open_recent), window);
-
-      /* add the action to the recent actions group */
-      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,
-                             "/main-menu/file-menu/recent-menu/placeholder-recent-items",
-                             name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
-
-      /* cleanup */
-      g_free (name);
-    }
-
-  /* show or hide the not 'available' action */
-  action = gtk_action_group_get_action (window->window_actions, "no-recent-items");
-  gtk_action_set_visible (action, (filtered == NULL));
-  gtk_action_set_sensitive (action, FALSE);
-
-  /* set the sensitivity of the clear button */
-  action = gtk_action_group_get_action (window->window_actions, "clear-recent");
-  gtk_action_set_sensitive (action, (filtered != NULL));
-
-  /* cleanup */
-  g_list_free (filtered);
-  g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
-  g_list_free (items);
-
-  /* make sure the ui is up2date to avoid flickering */
-  gtk_ui_manager_ensure_update (window->ui_manager);
-}
-
-
-
-
-static void
-mousepad_window_add_recent (MousepadWindow *window,
-                            const gchar    *filename)
-{
-  GtkRecentData       info;
-  gchar              *uri;
-  static gchar       *groups[2] = { PACKAGE_NAME, NULL };
-
-  _mousepad_return_if_fail (filename != NULL);
-
-  /* create the recent data */
-  info.display_name = NULL;
-  info.description  = NULL;
-  info.mime_type    = "text/plain";
-  info.app_name     = PACKAGE_NAME;
-  info.app_exec     = PACKAGE " %u";
-  info.groups       = groups;
-  info.is_private   = FALSE;
-
-  /* create an uri from the filename */
-  uri = g_filename_to_uri (filename, NULL, NULL);
-
-  /* add it */
-  if (G_LIKELY (uri != NULL))
-    {
-      gtk_recent_manager_add_full (window->recent_manager, uri, &info);
-      g_free (uri);
-    }
-}
-
 
 
 static void
@@ -1186,16 +1008,9 @@ mousepad_window_set_title (MousepadWindow *window,
 
 
 
-static void
-mousepad_window_notify_title (MousepadScreen *screen,
-                              GParamSpec     *pspec,
-                              MousepadWindow *window)
-{
-  mousepad_window_set_title (window, screen);
-}
-
-
-
+/**
+ * Notebook Signal Functions
+ **/
 static void
 mousepad_window_page_notified (GtkNotebook    *notebook,
                                GParamSpec     *pspec,
@@ -1241,7 +1056,7 @@ mousepad_window_tab_removed (GtkNotebook    *notebook,
       GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
 
       /* rebuild the go menu */
-      mousepad_window_go_menu (window);
+      mousepad_window_update_gomenu (window);
 
       /* update all screen sensitive actions */
       mousepad_window_update_actions (window);
@@ -1257,38 +1072,34 @@ mousepad_window_page_reordered (GtkNotebook     *notebook,
                                 MousepadWindow  *window)
 {
   /* update the go menu */
-  mousepad_window_go_menu (window);
+  mousepad_window_update_gomenu (window);
 }
 
 
+
+/**
+ * Screen Signals Functions
+ **/
 static void
-mousepad_window_error_dialog (GtkWindow   *window,
-                              GError      *error,
-                              const gchar *message)
+mousepad_window_notify_title (MousepadScreen *screen,
+                              GParamSpec     *pspec,
+                              MousepadWindow *window)
 {
-  GtkWidget   *dialog;
-
-  _mousepad_return_if_fail (GTK_IS_WINDOW (window));
-
-  /* create the warning dialog */
-  dialog = gtk_message_dialog_new (window,
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_ERROR,
-                                   GTK_BUTTONS_CLOSE,
-                                   message);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+  mousepad_window_set_title (window, screen);
+}
 
-  /* set the message from GError */
-  if (G_LIKELY (error && error->message))
-    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                              error->message);
 
-  /* run the dialog */
-  gtk_dialog_run (GTK_DIALOG (dialog));
 
-  /* destroy it */
-  gtk_widget_destroy (dialog);
+static void
+mousepad_window_modified_changed (MousepadScreen *screen,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+  /* TODO: set the tab label color */
 
+  mousepad_window_set_title (window, screen);
 }
 
 
@@ -1312,19 +1123,21 @@ mousepad_window_selection_changed (MousepadScreen *screen,
 
 
 
+/**
+ * Menu Update Functions
+ **/
 static void
 mousepad_window_update_actions (MousepadWindow *window)
 {
-  GtkAction        *action;
-  GtkNotebook      *notebook = GTK_NOTEBOOK (window->notebook);
-  MousepadScreen   *screen;
-  GtkTextView      *textview;
-  GtkTextBuffer    *buffer;
-  GtkWidget        *goitem;
-  gboolean          cycle_tabs;
-  gint              n_pages;
-  gint              page_num;
-  gboolean          selected;
+  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;
 
   /* determine the number of pages */
   n_pages = gtk_notebook_get_n_pages (notebook);
@@ -1339,9 +1152,11 @@ mousepad_window_update_actions (MousepadWindow *window)
     {
       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);
 
+      /* whether we cycle tabs */
       g_object_get (G_OBJECT (window->preferences), "misc-cycle-tabs", &cycle_tabs, NULL);
 
       action = gtk_action_group_get_action (window->window_actions, "back");
@@ -1353,30 +1168,22 @@ mousepad_window_update_actions (MousepadWindow *window)
       action = gtk_action_group_get_action (window->window_actions, "save-file");
       gtk_action_set_sensitive (action, gtk_text_view_get_editable (textview));
 
+      /* set the sensitivity of the selection actions */
       g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
       mousepad_window_selection_changed (screen, selected, window);
 
-      /* update the "Go" menu */
-      goitem = g_object_get_data (G_OBJECT (screen), "go-menu-item");
-      if (G_LIKELY (goitem != NULL))
-        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (goitem), TRUE);
+      /* active this tab in the go menu */
+      action = g_object_get_data (G_OBJECT (screen), I_("go-menu-action"));
+      if (G_LIKELY (action != NULL))
+        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
     }
 }
 
 
-static void
-mousepad_window_action_goto (GtkRadioAction *action,
-                             GtkNotebook    *notebook)
-{
-  gint page = gtk_radio_action_get_current_value (action);
-
-  gtk_notebook_set_current_page (notebook, page);
-}
-
 
 
 static void
-mousepad_window_go_menu (MousepadWindow *window)
+mousepad_window_update_gomenu (MousepadWindow *window)
 {
   GtkWidget      *screen;
   gint            npages;
@@ -1418,13 +1225,14 @@ mousepad_window_go_menu (MousepadWindow *window)
       /* 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");
       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-item"), action);
+      g_object_set_data (G_OBJECT (screen), I_("go-menu-action"), action);
 
       if (G_LIKELY (n < 9))
         {
@@ -1454,8 +1262,210 @@ mousepad_window_go_menu (MousepadWindow *window)
 }
 
 
+
+/**
+ * Funtions for managing the recent files
+ **/
+static void
+mousepad_window_recent_add (MousepadWindow *window,
+                            const gchar    *filename)
+{
+  GtkRecentData  info;
+  gchar         *uri;
+  static gchar  *groups[2] = { PACKAGE_NAME, NULL };
+
+  _mousepad_return_if_fail (filename != NULL);
+
+  /* create the recent data */
+  info.display_name = NULL;
+  info.description  = NULL;
+  info.mime_type    = "text/plain";
+  info.app_name     = PACKAGE_NAME;
+  info.app_exec     = PACKAGE " %u";
+  info.groups       = groups;
+  info.is_private   = FALSE;
+
+  /* create an uri from the filename */
+  uri = g_filename_to_uri (filename, NULL, NULL);
+
+  /* add it */
+  if (G_LIKELY (uri != NULL))
+    {
+      gtk_recent_manager_add_full (window->recent_manager, uri, &info);
+      g_free (uri);
+    }
+}
+
+
+
+static gint
+mousepad_window_recent_sort (GtkRecentInfo *a,
+                             GtkRecentInfo *b)
+{
+  return (gtk_recent_info_get_modified (a) < gtk_recent_info_get_modified (b));
+}
+
+
+
+static void
+mousepad_window_recent_menu (MousepadWindow *window)
+{
+  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;
+
+  /* leave when we're updating multiple files */
+  if (lock_menu_updates)
+    return;
+
+  /* unmerge the ui controls from the previous update */
+  if (merge_id != 0)
+    gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
+
+  /* drop all the previous actions from the action group */
+  actions = gtk_action_group_list_actions (window->recent_actions);
+  for (li = actions; li != NULL; li = li->next)
+    gtk_action_group_remove_action (window->recent_actions, li->data);
+  g_list_free (actions);
+
+  /* create a new merge id */
+  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);
+
+  /* walk through the items in the manager and pick the ones that or in the mousepad group */
+  for (li = items; li != NULL; li = li->next)
+    {
+      /* check if the item is in the Mousepad group */
+      if (!gtk_recent_info_has_group (li->data, PACKAGE_NAME))
+        continue;
+
+      /* append the item */
+      filtered = g_list_prepend (filtered, li->data);
+    }
+
+  /* sort the filtered items by modification date */
+  filtered = g_list_sort (filtered, (GCompareFunc) mousepad_window_recent_sort);
+
+  /* get the recent menu limit number */
+  g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-limit", &n, NULL);
+
+  /* append the items to the menu */
+  for (li = filtered; n > 0 && li != NULL; li = li->next, --n)
+    {
+      info = li->data;
+
+      /* create the action name */
+      name = g_strdup_printf ("recent-info-%d", n);
+
+      /* 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, "_", "__");
+
+      /* create the tooltip with an utf-8 valid version of the filename */
+      uri_display = gtk_recent_info_get_uri_display (info);
+      tooltip = g_strdup_printf (_("Open '%s'"), uri_display);
+      g_free (uri_display);
+
+      /* create the action */
+      action = gtk_action_new (name, label, tooltip, NULL);
+
+      /* cleanup */
+      g_free (tooltip);
+      g_free (label);
+
+      /* add the info data and connect a menu signal */
+      g_object_set_data_full (G_OBJECT (action), I_("gtk-recent-info"), gtk_recent_info_ref (info), (GDestroyNotify) gtk_recent_info_unref);
+      g_signal_connect (G_OBJECT (action), "activate",
+                        G_CALLBACK (mousepad_window_action_open_recent), window);
+
+      /* add the action to the recent actions group */
+      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,
+                             "/main-menu/file-menu/recent-menu/placeholder-recent-items",
+                             name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+
+      /* cleanup */
+      g_free (name);
+    }
+
+  /* set the visibility of the 'No items found' action */
+  action = gtk_action_group_get_action (window->window_actions, "no-recent-items");
+  gtk_action_set_visible (action, (filtered == NULL));
+  gtk_action_set_sensitive (action, FALSE);
+
+  /* set the sensitivity of the clear button */
+  action = gtk_action_group_get_action (window->window_actions, "clear-recent");
+  gtk_action_set_sensitive (action, (filtered != NULL));
+
+  /* cleanup */
+  g_list_free (filtered);
+  g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+  g_list_free (items);
+
+  /* make sure the ui is up2date to avoid flickering */
+  gtk_ui_manager_ensure_update (window->ui_manager);
+}
+
+
+static void
+mousepad_window_recent_clear (MousepadWindow *window)
+{
+  GList         *items, *li;
+  const gchar   *uri;
+  GError        *error = NULL;
+  GtkRecentInfo *info;
+
+  /* get all the items in the manager */
+  items = gtk_recent_manager_get_items (window->recent_manager);
+
+  /* walk through the items */
+  for (li = items; li != NULL; li = li->next)
+    {
+      info = li->data;
+
+      /* check if the item is in the Mousepad group */
+      if (!gtk_recent_info_has_group (info, PACKAGE_NAME))
+        continue;
+
+      /* get the uri of the recent item */
+      uri = gtk_recent_info_get_uri (info);
+
+      /* try to remove it, if it fails, break the loop */
+      if (G_UNLIKELY (gtk_recent_manager_remove_item (window->recent_manager, uri, &error) == FALSE))
+        break;
+     }
+
+  /* cleanup */
+  g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+  g_list_free (items);
+
+  /* print a warning is there is one */
+  if (G_UNLIKELY (error != NULL))
+    {
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error,
+                                   _("Failed to remove an item from the recent history"));
+      g_error_free (error);
+    }
+}
+
+
+
 /**
  * Menu Actions
+ *
+ * All those function should be sorted by the menu structure so it's
+ * easy to find a function. They should also use the other window
+ * functions as much as possible to avoid code duplication.
  **/
 static void
 mousepad_window_action_open_new_window (GtkAction      *action,
@@ -1519,7 +1529,7 @@ mousepad_window_action_open_file (GtkAction      *action,
           mousepad_window_open_tab (window, filename);
 
           /* add to the recent files */
-          mousepad_window_add_recent (window, filename);
+          mousepad_window_recent_add (window, filename);
 
           /* cleanup */
           g_free (filename);
@@ -1533,7 +1543,7 @@ mousepad_window_action_open_file (GtkAction      *action,
 
       /* update the menus */
       mousepad_window_recent_menu (window);
-      mousepad_window_go_menu (window);
+      mousepad_window_update_gomenu (window);
     }
 
   /* destroy dialog */
@@ -1588,60 +1598,14 @@ static void
 mousepad_window_action_clear_recent (GtkAction      *action,
                                      MousepadWindow *window)
 {
-  GtkWidget         *dialog;
-  GtkRecentInfo     *info;
-  GList             *items, *li;
-  const gchar       *uri;
-  GError            *error = NULL;
-
-  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_QUESTION,
-                                   GTK_BUTTONS_NONE,
-                                   _("Are you sure you want to clear\nthe Recent History?"));
-  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                            _("This will only remove the items from the history owned by Mousepad."));
-  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                          GTK_STOCK_CLEAR, GTK_RESPONSE_OK,
-                          NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
-
-  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+  /* ask the user if he or she really want to clear the history */
+  if (mousepad_dialogs_clear_recent (GTK_WINDOW (window)))
     {
       /* avoid updating the menu */
       lock_menu_updates = TRUE;
 
-      /* get all the items in the manager */
-      items = gtk_recent_manager_get_items (window->recent_manager);
-
-      /* walk through the items */
-      for (li = items; li != NULL; li = li->next)
-        {
-          info = li->data;
-
-          /* check if the item is in the Mousepad group */
-          if (gtk_recent_info_has_group (info, PACKAGE_NAME))
-            {
-              /* get the uri of the recent item */
-              uri = gtk_recent_info_get_uri (info);
-
-              /* try to remove it, if it fails, break the loop */
-              if (G_UNLIKELY (gtk_recent_manager_remove_item (window->recent_manager, uri, &error) == FALSE))
-                {
-                  mousepad_window_error_dialog (GTK_WINDOW (window), error,
-                                                _("Failed to remove an item from the recent history"));
-                  g_error_free (error);
-
-                  /* stop removing to prevent multiple warnings */
-                  break;
-                }
-            }
-        }
-
-      /* cleanup */
-      g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
-      g_list_free (items);
+      /* clear the recent history */
+      mousepad_window_recent_clear (window);
 
       /* allow menu updates again */
       lock_menu_updates = FALSE;
@@ -1649,9 +1613,6 @@ mousepad_window_action_clear_recent (GtkAction      *action,
       /* update the recent menu */
       mousepad_window_recent_menu (window);
     }
-
-  /* destroy the dialog */
-  gtk_widget_destroy (dialog);
 }
 
 
@@ -1661,26 +1622,12 @@ mousepad_window_action_save_file (GtkAction      *action,
                                   MousepadWindow *window)
 {
   MousepadScreen *screen;
-  GError         *error = NULL;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
-      if (mousepad_screen_get_filename (screen) != NULL)
-        mousepad_screen_save_file (screen, &error);
-      else
-        {
-          if (mousepad_window_save_as (window, screen))
-            mousepad_screen_save_file (screen, &error);
-        }
-
-      /* check for errors */
-      if (G_UNLIKELY (error != NULL))
-        {
-          mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
-          g_error_free (error);
-        }
+      /* save the file */
+      mousepad_window_save (window, screen, FALSE);
     }
 }
 
@@ -1691,25 +1638,12 @@ mousepad_window_action_save_file_as (GtkAction      *action,
                                      MousepadWindow *window)
 {
   MousepadScreen *screen;
-  GError         *error = NULL;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
-      /* popup the save as dialog, if that worked, save the file, if
-       * that worked too, add the (new) file to the recent menu */
-      if (mousepad_window_save_as (window, screen))
-        if (mousepad_screen_save_file (screen, &error))
-          mousepad_window_add_recent (window, mousepad_screen_get_filename (screen));
-
-      /* check for errors */
-      if (G_UNLIKELY (error != NULL))
-        {
-          mousepad_window_error_dialog (GTK_WINDOW (window), error,  _("Failed to save file as"));
-          g_error_free (error);
-        }
-      else
+      /* save the file */
+      if (mousepad_window_save (window, screen, TRUE))
         {
           /* make sure save-file is sensitive */
           action = gtk_action_group_get_action (window->window_actions, "save-file");
@@ -1727,7 +1661,6 @@ mousepad_window_action_close_tab (GtkAction      *action,
   MousepadScreen *screen;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     mousepad_window_close_screen (window, screen);
 }
@@ -1735,36 +1668,6 @@ mousepad_window_action_close_tab (GtkAction      *action,
 
 
 static void
-mousepad_window_button_close_tab (MousepadScreen *screen)
-{
-  MousepadWindow *window;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
-  /* get the mousepad window of this screen */
-  window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
-
-  /* close the screen */
-  if (G_LIKELY (window != NULL))
-    mousepad_window_close_screen (window, screen);
-}
-
-
-
-static gboolean
-mousepad_window_delete_event (MousepadWindow *window,
-                              GdkEvent       *event)
-{
-  /* try to close the windows */
-  mousepad_window_action_close (NULL, window);
-
-  /* we will close the window when it's time */
-  return TRUE;
-}
-
-
-
-static void
 mousepad_window_action_close (GtkAction      *action,
                               MousepadWindow *window)
 {
@@ -1795,7 +1698,7 @@ mousepad_window_action_close (GtkAction      *action,
               lock_menu_updates = FALSE;
 
               /* update the go menu */
-              mousepad_window_go_menu (window);
+              mousepad_window_update_gomenu (window);
 
               break;
             }
@@ -1837,7 +1740,6 @@ mousepad_window_action_cut (GtkAction      *action,
 
   /* get the active screen */
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
       /* get the clipboard, textview and the buffer */
@@ -1868,10 +1770,9 @@ mousepad_window_action_copy (GtkAction      *action,
   GtkClipboard   *clipboard;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
-      /* get the buffer, textview and the clipboard */
+      /* get the buffer and clipboard */
       buffer = mousepad_screen_get_text_buffer (screen);
       clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
 
@@ -1892,7 +1793,6 @@ mousepad_window_action_paste (GtkAction      *action,
   GtkTextView    *textview;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
       /* get the buffer and the clipboard */
@@ -1923,7 +1823,6 @@ mousepad_window_action_delete (GtkAction      *action,
   GtkTextView    *textview;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
       /* get the buffer */
@@ -1954,7 +1853,6 @@ mousepad_window_action_select_all (GtkAction      *action,
   GtkTextIter     start, end;
 
   screen = mousepad_window_get_active (window);
-
   if (G_LIKELY (screen != NULL))
     {
       /* get the buffer */
@@ -1974,68 +1872,32 @@ static void
 mousepad_window_action_jump_to (GtkAction      *action,
                                 MousepadWindow *window)
 {
-  GtkWidget      *dialog;
-  GtkWidget      *hbox, *label, *button;
   GtkTextBuffer  *buffer;
   MousepadScreen *screen;
-  gint            num, num_max;
+  gint            current_line, last_line, line;
   GtkTextIter     iter;
-  GtkAdjustment   *adjustment;
-
 
+  /* 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));
-      num = gtk_text_iter_get_line (&iter) + 1;
+      current_line = gtk_text_iter_get_line (&iter) + 1;
 
       /* get the last line number */
       gtk_text_buffer_get_end_iter (buffer, &iter);
-      num_max = gtk_text_iter_get_line (&iter) + 1;
-
-      /* build the dialog */
-      dialog = gtk_dialog_new_with_buttons (_("Jump To"),
-                                            GTK_WINDOW (window),
-                                            GTK_DIALOG_MODAL
-                                            | GTK_DIALOG_DESTROY_WITH_PARENT
-                                            | GTK_DIALOG_NO_SEPARATOR,
-                                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                            GTK_STOCK_JUMP_TO, GTK_RESPONSE_OK,
-                                            NULL);
-      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-      gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-
-      hbox = gtk_hbox_new (FALSE, 8);
-      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
-      gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
-      gtk_widget_show (hbox);
-
-      label = gtk_label_new_with_mnemonic (_("_Line number:"));
-      gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-      gtk_widget_show (label);
-
-      /* the spin button adjustment */
-      adjustment = (GtkAdjustment *) gtk_adjustment_new (num, 1, num_max, 1, 10, 0);
+      last_line = gtk_text_iter_get_line (&iter) + 1;
 
-      /* the spin button */
-      button = gtk_spin_button_new (adjustment, 1, 0);
-      gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
-      gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
-      gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
-      gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
-      gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
-      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-      gtk_widget_show (button);
+      /* run the jump to dialog and wait for the response */
+      line = mousepad_dialogs_jump_to (GTK_WINDOW (window), current_line, last_line);
 
-      if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+      if (G_LIKELY (line > 0))
         {
           /* jump to the line */
-          num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button)) - 1;
-          gtk_text_buffer_get_iter_at_line (buffer, &iter, num);
+          gtk_text_buffer_get_iter_at_line (buffer, &iter, line-1);
           gtk_text_buffer_place_cursor (buffer, &iter);
 
           /* scroll to visible area */
@@ -2044,9 +1906,6 @@ mousepad_window_action_jump_to (GtkAction      *action,
                                         MOUSEPAD_SCROLL_MARGIN,
                                         FALSE, 0.0, 0.0);
         }
-
-      /* destroy the dialog */
-      gtk_widget_destroy (dialog);
     }
 }
 
@@ -2123,31 +1982,55 @@ mousepad_window_action_next_tab (GtkAction      *action,
 
 
 static void
+mousepad_window_action_goto (GtkRadioAction *action,
+                             GtkNotebook    *notebook)
+{
+  /* get the page number from the action value */
+  gint page = gtk_radio_action_get_current_value (action);
+
+  /* set the page */
+  gtk_notebook_set_current_page (notebook, page);
+}
+
+
+
+static void
 mousepad_window_action_about (GtkAction      *action,
                               MousepadWindow *window)
 {
-  static const gchar *authors[] =
-  {
-    "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 (GTK_WINDOW (window),
-                         "authors", authors,
-                         "comments", _("Mousepad is a fast text editor for the Xfce Desktop Environment."),
-                         "copyright", _("Copyright \302\251 2004-2007 Xfce Development Team"),
-                         "destroy-with-parent", TRUE,
-                         "license", XFCE_LICENSE_GPL,
-                         "logo-icon-name", PACKAGE_NAME,
-                         "name", PACKAGE_NAME,
-                         "version", PACKAGE_VERSION,
-                         "translator-credits", _("translator-credits"),
-                         "website", "http://www.xfce.org/projects/mousepad",
-                         NULL);
+  mousepad_dialogs_show_about (GTK_WINDOW (window));
 }
 
+
+/**
+ * Miscellaneous Actions
+ **/
+static void
+mousepad_window_button_close_tab (MousepadScreen *screen)
+{
+  MousepadWindow *window;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+  /* get the mousepad window of this screen */
+  window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
+
+  /* close the screen */
+  if (G_LIKELY (window != NULL))
+    mousepad_window_close_screen (window, screen);
+}
+
+
+
+static gboolean
+mousepad_window_delete_event (MousepadWindow *window,
+                              GdkEvent       *event)
+{
+  /* try to close the windows */
+  mousepad_window_action_close (NULL, window);
+
+  /* we will close the window when all the tabs are closed */
+  return TRUE;
+}
+
+


More information about the Xfce4-commits mailing list