[Xfce4-commits] r26134 - in mousepad/branches/nick_0_3: . mousepad po

Nick Schermer nick at xfce.org
Tue Oct 16 22:01:37 CEST 2007


Author: nick
Date: 2007-10-16 20:01:37 +0000 (Tue, 16 Oct 2007)
New Revision: 26134

Added:
   mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.c
   mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.h
   mousepad/branches/nick_0_3/mousepad/mousepad-print.c
   mousepad/branches/nick_0_3/mousepad/mousepad-print.h
   mousepad/branches/nick_0_3/mousepad/mousepad-replace-dialog.c
   mousepad/branches/nick_0_3/mousepad/mousepad-replace-dialog.h
   mousepad/branches/nick_0_3/mousepad/mousepad-util.c
   mousepad/branches/nick_0_3/mousepad/mousepad-util.h
Removed:
   mousepad/branches/nick_0_3/mousepad/mousepad-types.h
Modified:
   mousepad/branches/nick_0_3/ChangeLog
   mousepad/branches/nick_0_3/NEWS
   mousepad/branches/nick_0_3/TODO
   mousepad/branches/nick_0_3/configure.in.in
   mousepad/branches/nick_0_3/mousepad/Makefile.am
   mousepad/branches/nick_0_3/mousepad/main.c
   mousepad/branches/nick_0_3/mousepad/mousepad-application.c
   mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.c
   mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.h
   mousepad/branches/nick_0_3/mousepad/mousepad-document.c
   mousepad/branches/nick_0_3/mousepad/mousepad-document.h
   mousepad/branches/nick_0_3/mousepad/mousepad-file.c
   mousepad/branches/nick_0_3/mousepad/mousepad-file.h
   mousepad/branches/nick_0_3/mousepad/mousepad-marshal.list
   mousepad/branches/nick_0_3/mousepad/mousepad-preferences.c
   mousepad/branches/nick_0_3/mousepad/mousepad-private.h
   mousepad/branches/nick_0_3/mousepad/mousepad-search-bar.c
   mousepad/branches/nick_0_3/mousepad/mousepad-search-bar.h
   mousepad/branches/nick_0_3/mousepad/mousepad-statusbar.c
   mousepad/branches/nick_0_3/mousepad/mousepad-statusbar.h
   mousepad/branches/nick_0_3/mousepad/mousepad-undo.c
   mousepad/branches/nick_0_3/mousepad/mousepad-undo.h
   mousepad/branches/nick_0_3/mousepad/mousepad-view.c
   mousepad/branches/nick_0_3/mousepad/mousepad-view.h
   mousepad/branches/nick_0_3/mousepad/mousepad-window-ui.xml
   mousepad/branches/nick_0_3/mousepad/mousepad-window.c
   mousepad/branches/nick_0_3/mousepad/mousepad-window.h
   mousepad/branches/nick_0_3/po/POTFILES.in
   mousepad/branches/nick_0_3/po/mousepad.pot
Log:
* Diffstat:
  38 files changed, 5987 insertions(+), 3632 deletions(-)

* mousepad/mousepad-dialogs.c: Set the correct default return
  in the jump dialog.
* mousepad/mousepad-replace-{dialog,window,preferences}.{c,h}:
  Implement the new replace dialog.
* Remove options from the type-ahead bar, it was too bloated
  and those options are now available in the replace dialog.
* mousepad/mousepad-document.c: The MousepadDocument now holds
  utf-8 valid names, the MousepadFile the real filename.
* mousepad/mousepad-window.c: Full tab dnd (detach) with
  Gtk+ 2.12.
* mousepad/mousepad-encoding-dialog.{c,h}: Add a encoding dialog.
  This dialog should help users to find the right encoding for a
  document.
* mousepad/mousepad-print.{c,h}: Initial version of a basic 
  printing support. Needs some big improvement tho.
* mousepad/mousepad-statusbar: Fix issues with some theme engines
  that paint a line above the statusbar (instead of a frame).
* mousepad/mousepad-window.c: A window is now destoyed when it 
  contains no tabs, previously this caused some segfaults with the
  tab dnd code, but this is all fixed now.
* mousepad/mousepad-preferences.c: The option names are now stored
  in the nick name of the pspec. With debug build this name is
  compared with the option name from spec name to check for typos.
* mousepad/mousepad-view.c: Options for 'insert tab as spaces' and
  settings the tab size. This also needed a rewrite of the
  indentation code, which ended up much cleaner.
* mousepad/mousepad-view.c: Big speed improvements in the vertical
  selction code.
* mousepad/mousepad-view.c: Cleanups in the clipboard code and move
  code from mousepad-document to mousepad-view.
* mousepad/mousepad-{window,search-bar}.c: Handle clipboard actions
  properly when the search bar is focused.
* A lot of code cleanups, bug fixes, polishing and stuff I can't
  remember after 5 months ;).


Modified: mousepad/branches/nick_0_3/ChangeLog
===================================================================
--- mousepad/branches/nick_0_3/ChangeLog	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/ChangeLog	2007-10-16 20:01:37 UTC (rev 26134)
@@ -1,3 +1,40 @@
+2007-10-16      Nick Schermer <nick at xfce.org>
+	* mousepad/mousepad-dialogs.c: Set the correct default return
+	  in the jump dialog.
+	* mousepad/mousepad-replace-{dialog,window,preferences}.{c,h}:
+	  Implement the new replace dialog.
+	* Remove options from the type-ahead bar, it was too bloated
+	  and those options are now available in the replace dialog.
+	* mousepad/mousepad-document.c: The MousepadDocument now holds
+	  utf-8 valid names, the MousepadFile the real filename.
+	* mousepad/mousepad-window.c: Full tab dnd (detach) with
+	  Gtk+ 2.12.
+	* mousepad/mousepad-encoding-dialog.{c,h}: Add a encoding dialog.
+	  This dialog should help users to find the right encoding for a
+	  document.
+	* mousepad/mousepad-print.{c,h}: Initial version of a basic 
+	  printing support. Needs some big improvement tho.
+	* mousepad/mousepad-statusbar: Fix issues with some theme engines
+	  that paint a line above the statusbar (instead of a frame).
+	* mousepad/mousepad-window.c: A window is now destoyed when it 
+	  contains no tabs, previously this caused some segfaults with the
+	  tab dnd code, but this is all fixed now.
+	* mousepad/mousepad-preferences.c: The option names are now stored
+	  in the nick name of the pspec. With debug build this name is
+	  compared with the option name from spec name to check for typos.
+	* mousepad/mousepad-view.c: Options for 'insert tab as spaces' and
+	  settings the tab size. This also needed a rewrite of the
+	  indentation code, which ended up much cleaner.
+	* mousepad/mousepad-view.c: Big speed improvements in the vertical
+	  selction code.
+	* mousepad/mousepad-view.c: Cleanups in the clipboard code and move
+	  code from mousepad-document to mousepad-view.
+	* mousepad/mousepad-{window,search-bar}.c: Handle clipboard actions
+	  properly when the search bar is focused.
+	* A lot of code cleanups, bug fixes, polishing and stuff I can't
+	  remember after 5 months ;).
+
+
 2007-05-22	Nick Schermer <nick at xfce.org
 	* *.*: Remove copyright lines.
 

Modified: mousepad/branches/nick_0_3/NEWS
===================================================================
--- mousepad/branches/nick_0_3/NEWS	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/NEWS	2007-10-16 20:01:37 UTC (rev 26134)
@@ -1,27 +1,30 @@
 0.3.0
 =====
-- A complete rewrite of Mousepad. The code is now written in GOjects 
-  where possible so we have a solid base for further development.
-- Run multiple windows in one instance. We also invoke a running
-  instance with DBus (optional), this is needed for tab DND between
-  windows.
-- Support for multiple tabs in one window.
-- Load multiple files at once from both the open dialog and the command
-  line.
-- Type-ahead find and highlight feature like Firefox.
-- Support for editable menu accelerators.
-- Reimplemented recent file support. You can cleanup the Mousepad history
-  and a file is removed from the history when Mousepad was unable to open
-  it.
-- Various hidden settings.
-- Statusbar with cursor location and whether overwrite is actived.
-- Mousepad depends on GTK+ 2.10.
-- Save button is now default response in the dialog (Bug #2941).
-- No font is set as long the user has not defined any (Bug #2720).
-- No compiler warnings (Bug #1697).
-- Windows geometry is now properly saved (Bug #2945).
-- Hidden option to show to full path in the window title (Bug #2896).
-- Basic command line options (Bug #2397).
-- The MousepadPreferences object uses XfceRc for saving the 
-  settings (Bug #2786).
-- No crashes when there is no rc file (Bug #2784).
+Highlights:
+    - A complete rewrite of Mousepad. The code is now written in GOjects
+      where possible so we have a solid base for further development.
+    - Run multiple windows in one instance. We also invoke a running
+      instance with DBus (optional), this is needed for tab DND between
+      windows.
+    - Support for multiple tabs in one window.
+    - Load multiple files at once from both the open dialog and the command
+      line.
+    - Type-ahead find and highlight feature like Firefox.
+    - Support for editable menu accelerators.
+    - Reimplemented recent file support. You can cleanup the Mousepad history
+      and a file is removed from the history when Mousepad was unable to open
+      it.
+    - Various hidden settings.
+    - Statusbar with cursor location and whether overwrite is actived.
+    - Mousepad depends on GTK+ 2.10.
+
+Bug fixes:
+    - Save button is now default response in the dialog (Bug #2941).
+    - No font is set as long the user has not defined any (Bug #2720).
+    - No compiler warnings (Bug #1697).
+    - Windows geometry is now properly saved (Bug #2945).
+    - Hidden option to show the full path in the window title (Bug #2896).
+    - Basic command line options (Bug #2397).
+    - The MousepadPreferences object uses XfceRc for saving the
+      settings (Bug #2786).
+    - No segfault when there is no rc file (Bug #2784).

Modified: mousepad/branches/nick_0_3/TODO
===================================================================
--- mousepad/branches/nick_0_3/TODO	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/TODO	2007-10-16 20:01:37 UTC (rev 26134)
@@ -8,60 +8,44 @@
 
 Interface
 =========
-- Dialog when closing multiple (modified) tabs. Maybe not needed
-  since we ask the use what to do when a modified file is closed.
 - Tab font color when the file is modified or read only.
 - Test the application with a screen reader and add Atk objects
   where needed.
 - Cleanup the menus and make them consistent. For example: we're
   using both file and document atm. The name of the Go menu should
   also be changed to something more descriptive.
-- You can't use the Ctrl - v/c/x buttons in the type-ahead bar
-  because they are 'registered' by the textview/ui.
-- When hitting the enter button in the jump dialog, we should jump.
-- Replace dialog. This dialog should also provide a find button so
-  there is an alternative for the type-ahead feature.
-- Maybe a match whole word option.
+- Make the mnemonic's consistent all over the application and make
+  sure they don't conflict inside a dialog/window.
+- Check the search and replace code for bugs.
+- Add option to disable the search feedback in the replace dialog
+  (highlight, count matches, type-ahead). This can slow down mousepad
+  with large text files.
 
 
+Undo
+====
+- Need to fix a couple of issues here. I'm not really satisfied with
+  it right now.
+
+
 Code
 ====
-- Cleanup mousepad-document.h. The order of the functions is a mess.
 - Check for code duplication and make sure the comments are worth
   reading.
 
 
-Text View
-=========
-- Tabs as spaces option.
-
-
-Undo Manager
-============
-- Replace g_list_append with g_list_prepend in the undo manager. See
-  glib manual why.
-- We erase the GString in the undo manager, but this buffer will be
-  (very) large when a large bunch of text is deleted. Maybe not a big
-  problem, but we could shrink it after erasing.
-- Let the undo manager handle multiple steps (mostly for vertical
-  selection cut/delete).
-
-
 Saving and loading
 ==================
 - Save All option.
-- Support for encoding. Only UTF-8 is supported for testing.
-- The filenames used in the title and tooltips are not UTF-8 safe.
-  We also have to make sure _ characters in a filename do not
-  result in mnemonic labels.
 - Check if the file is externally modified when switching tabs.
+- Cleanup and improve encoding support and order the encoding types.
 
 
 Other
 =====
-- Implement Gtk print support.
 - We need a cool Mousepad logo.
 - Write documentation.
+- Session manager support.
 
 
 Testing and polishing

Modified: mousepad/branches/nick_0_3/configure.in.in
===================================================================
--- mousepad/branches/nick_0_3/configure.in.in	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/configure.in.in	2007-10-16 20:01:37 UTC (rev 26134)
@@ -69,32 +69,9 @@
 dnl **********************************
 dnl *** Check for standard headers ***
 dnl **********************************
-AC_CHECK_HEADERS([ctype.h errno.h fcntl.h memory.h stdlib.h string.h \
-                  sys/mman.h sys/types.h sys/stat.h time.h unistd.h])
+AC_CHECK_HEADERS([errno.h fcntl.h memory.h math.h stdlib.h string.h \
+                  sys/types.h sys/stat.h time.h unistd.h])
 
-dnl ************************************
-dnl *** Check for standard functions ***
-dnl ************************************
-AC_FUNC_MMAP()
-AC_CHECK_FUNCS([posix_madvise])
-
-dnl ******************************************
-dnl *** Linux/glibc specified work-arounds ***
-dnl ******************************************
-AC_MSG_CHECKING([whether we need _BSD_SOURCE and _XOPEN_SOURCE])
-AC_TRY_LINK([#include <features.h>],
-[
-  if (__GLIBC_PREREQ (2, 0));
-],
-[
-  AC_DEFINE([_XOPEN_SOURCE], [600], [Required to unbreak glibc])
-  AC_DEFINE([_BSD_SOURCE], [1], [Required to unbreak glibc])
-  AC_MSG_RESULT([yes])
-],
-[
-  AC_MSG_RESULT([no])
-])
-
 dnl ******************************
 dnl *** Check for i18n support ***
 dnl ******************************

Modified: mousepad/branches/nick_0_3/mousepad/Makefile.am
===================================================================
--- mousepad/branches/nick_0_3/mousepad/Makefile.am	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/Makefile.am	2007-10-16 20:01:37 UTC (rev 26134)
@@ -10,22 +10,17 @@
 	-DG_LOG_DOMAIN=\"Mousepad\"						\
 	-DLIBEXECDIR=\"$(libexecdir)\"						\
 	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"					\
+	-DG_DISABLE_DEPRECATED							\
 	$(PLATFORM_CPPFLAGS)
 
 bin_PROGRAMS = 									\
 	mousepad
 
-mousepad_headers = 								\
-	mousepad-types.h
-
 mousepad_built_sources =							\
-	mousepad-enum-types.c							\
-	mousepad-enum-types.h							\
 	mousepad-marshal.c							\
 	mousepad-marshal.h
 
 mousepad_SOURCES =								\
-	$(mousepad_headers)							\
 	$(mousepad_built_sources)						\
 	$(mousepad_dbus_sources)						\
 	main.c									\
@@ -35,11 +30,17 @@
 	mousepad-dialogs.h							\
 	mousepad-document.c							\
 	mousepad-document.h							\
+	mousepad-encoding-dialog.c						\
+	mousepad-encoding-dialog.h						\
 	mousepad-file.c								\
 	mousepad-file.h								\
 	mousepad-preferences.c							\
 	mousepad-preferences.h							\
+	mousepad-print.c							\
+	mousepad-print.h							\
 	mousepad-private.h							\
+	mousepad-replace-dialog.c						\
+	mousepad-replace-dialog.h						\
 	mousepad-search-bar.c							\
 	mousepad-search-bar.h							\
 	mousepad-statusbar.c							\
@@ -48,6 +49,8 @@
 	mousepad-view.h								\
 	mousepad-undo.c								\
 	mousepad-undo.h								\
+	mousepad-util.c								\
+	mousepad-util.h								\
 	mousepad-window.c							\
 	mousepad-window.h							\
 	mousepad-window-ui.h
@@ -96,14 +99,11 @@
 if MAINTAINER_MODE
 CLEANFILES =									\
 	xgen-mmc								\
-	xgen-mmh								\
-	xgen-metc								\
-	xgen-meth
+	xgen-mmh
 
 DISTCLEANFILES =								\
 	$(mousepad_built_sources)                                       	\
 	stamp-mousepad-marshal.h						\
-	stamp-mousepad-enum-types.h						\
 	mousepad-window-ui.h
 
 BUILT_SOURCES =									\
@@ -118,31 +118,9 @@
 mousepad-window-ui.h: Makefile $(srcdir)/mousepad-window-ui.xml
 	exo-csource --strip-comments --strip-content --static --name=mousepad_window_ui $(srcdir)/mousepad-window-ui.xml > mousepad-window-ui.h
 
-mousepad-enum-types.h: stamp-mousepad-enum-types.h
-	@true
-stamp-mousepad-enum-types.h: $(mousepad_headers) Makefile
-	( cd $(srcdir) && glib-mkenums \
-		--fhead "#ifndef __MOUSEPAD_ENUM_TYPES_H__\n#define __MOUSEPAD_ENUM_TYPES_H__\n#include <glib-object.h>\nG_BEGIN_DECLS\n" \
-		--fprod "/* enumerations from \"@filename@\" */\n" \
-		--vhead "GType @enum_name at _get_type (void) G_GNUC_CONST;\n#define MOUSEPAD_TYPE_ at ENUMSHORT@ (@enum_name at _get_type())\n" \
-		--ftail "G_END_DECLS\n\n#endif /* !__MOUSEPAD_ENUM_TYPES_H__ */" \
-		$(mousepad_headers) ) >> xgen-meth \
-	&& ( cmp -s xgen-meth mousepad-enum-types.h || cp xgen-meth mousepad-enum-types.h ) \
-	&& rm -f xgen-meth \
-	&& echo timestamp > $(@F)
-mousepad-enum-types.c: $(mousepad_headers) Makefile
-	( cd $(srcdir) && glib-mkenums \
-		--fhead "#include <mousepad/mousepad-enum-types.h>\n#include <mousepad/mousepad-types.h>" \
-		--fprod "\n/* enumerations from \"@filename@\" */" \
-		--vhead "GType\n at enum_name@_get_type (void)\n{\n\tstatic GType type = 0;\n\tif (type == 0) {\n\tstatic const G at Type@Value values[] = {"\
-		--vprod "\t{ @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
-		--vtail "\t{ 0, NULL, NULL }\n\t};\n\ttype = g_ at type@_register_static (\"@EnumName@\", values);\n  }\n\treturn type;\n}\n" \
-		$(mousepad_headers) ) >> xgen-metc \
-	&& cp xgen-metc mousepad-enum-types.c \
-	&& rm -f xgen-metc
-
 mousepad-marshal.h: stamp-mousepad-marshal.h
 	@true
+
 stamp-mousepad-marshal.h: mousepad-marshal.list Makefile
 	( cd $(srcdir) && glib-genmarshal \
 		--prefix=_mousepad_marshal \

Modified: mousepad/branches/nick_0_3/mousepad/main.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/main.c	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/main.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -64,7 +64,6 @@
   MousepadApplication *application;
   GError              *error = NULL;
   gchar               *working_directory;
-
 #ifdef HAVE_DBUS
   MousepadDBusService *dbus_service;
 #endif
@@ -80,24 +79,24 @@
   g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
 #endif
 
-  /* initialize the GThread system */
+  /* initialize the gthread system */
   if (G_LIKELY (!g_thread_supported ()))
     g_thread_init (NULL);
 
-  /* initialize Gtk+ */
+  /* initialize gtk+ */
   if (!gtk_init_with_args (&argc, &argv, _("[FILES...]"), option_entries, GETTEXT_PACKAGE, &error))
     {
       /* check if we have an error message */
       if (G_LIKELY (error == NULL))
         {
-          /* no error message, the GUI initialization failed */
+          /* no error message, the gui initialization failed */
           g_error ("%s", _("Failed to open display."));
         }
       else
         {
-           /* print the error message */
-           g_error ("%s", error->message);
-           g_error_free (error);
+          /* print the error message */
+          g_error ("%s", error->message);
+          g_error_free (error);
         }
 
       return EXIT_FAILURE;

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-application.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-application.c	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-application.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -21,8 +21,8 @@
 
 #include <mousepad/mousepad-private.h>
 #include <mousepad/mousepad-application.h>
-#include <mousepad/mousepad-types.h>
 #include <mousepad/mousepad-document.h>
+#include <mousepad/mousepad-replace-dialog.h>
 #include <mousepad/mousepad-window.h>
 
 
@@ -35,6 +35,8 @@
 static GtkWidget  *mousepad_application_create_window             (MousepadApplication        *application);
 static void        mousepad_application_new_window_with_document  (MousepadWindow             *existing,
                                                                    MousepadDocument           *document,
+                                                                   gint                        x,
+                                                                   gint                        y,
                                                                    MousepadApplication        *application);
 static void        mousepad_application_new_window                (MousepadWindow             *existing,
                                                                    MousepadApplication        *application);
@@ -126,6 +128,8 @@
     {
       /* load the accel map */
       gtk_accel_map_load (path);
+
+      /* cleanup */
       g_free (path);
     }
 }
@@ -139,12 +143,19 @@
   GSList              *li;
   gchar               *path;
 
+  /* flush the history items of the replace dialog
+   * this is a bit of an ugly place, but cleaning on a window close
+   * isn't a good option eighter */
+  mousepad_replace_dialog_history_clean ();
+
   /* save the current accel map */
   path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, PACKAGE_NAME G_DIR_SEPARATOR_S "accels.scm", TRUE);
   if (G_LIKELY (path != NULL))
     {
       /* save the accel map */
       gtk_accel_map_save (path);
+
+      /* cleanup */
       g_free (path);
     }
 
@@ -155,6 +166,7 @@
       gtk_widget_destroy (GTK_WIDGET (li->data));
     }
 
+  /* cleanup the list of windows */
   g_slist_free (application->windows);
 
   (*G_OBJECT_CLASS (mousepad_application_parent_class)->finalize) (object);
@@ -230,6 +242,8 @@
 static void
 mousepad_application_new_window_with_document (MousepadWindow      *existing,
                                                MousepadDocument    *document,
+                                               gint                 x,
+                                               gint                 y,
                                                MousepadApplication *application)
 {
   GtkWidget *window;
@@ -247,9 +261,13 @@
   if (G_LIKELY (screen != NULL))
     gtk_window_set_screen (GTK_WINDOW (window), screen);
 
+  /* move the window on valid cooridinates */
+  if (x > -1 && y > -1)
+    gtk_window_move (GTK_WINDOW (window), x, y);
+
   /* create an empty document if no document was send */
   if (document == NULL)
-    document = MOUSEPAD_DOCUMENT (mousepad_document_new ());
+    document = mousepad_document_new ();
 
   /* add the document to the new window */
   mousepad_window_add (MOUSEPAD_WINDOW (window), document);
@@ -265,7 +283,7 @@
                                  MousepadApplication *application)
 {
   /* trigger new document function */
-  mousepad_application_new_window_with_document (existing, NULL, application);
+  mousepad_application_new_window_with_document (existing, NULL, -1, -1, application);
 }
 
 
@@ -297,7 +315,7 @@
   if (succeed == FALSE)
     {
       /* create a new document */
-      document = MOUSEPAD_DOCUMENT (mousepad_document_new ());
+      document = mousepad_document_new ();
 
       /* add the document to the new window */
       mousepad_window_add (MOUSEPAD_WINDOW (window), document);

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.c	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -21,36 +21,17 @@
 
 #include <mousepad/mousepad-private.h>
 #include <mousepad/mousepad-dialogs.h>
-#include <mousepad/mousepad-file.h>
+#include <mousepad/mousepad-util.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[] =
   {
-    "Benedikt Meurer <benny at xfce.org>",
-    "Erik Harrison <erikharrison at xfce.org>",
     "Nick Schermer <nick at xfce.org>",
+    "Erik Harrison <erikharrison at xfce.org>",
     NULL,
   };
 
@@ -58,7 +39,6 @@
   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,
@@ -117,7 +97,7 @@
                                         GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
                                         GTK_STOCK_JUMP_TO, MOUSEPAD_RESPONSE_JUMP_TO,
                                         NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_JUMP_TO);
   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
   hbox = gtk_hbox_new (FALSE, 8);
@@ -161,28 +141,25 @@
   GtkWidget *image;
   gboolean   succeed = FALSE;
 
-  /* the dialog icon */
-  image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_DIALOG);
-  gtk_widget_show (image);
-
   /* create the question dialog */
   dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
-                                   _("Remove all entries from the document history?"));
-
+                                   _("Remove all entries from the documents history?"));
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                           GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
                           GTK_STOCK_CLEAR, MOUSEPAD_RESPONSE_CLEAR,
                           NULL);
-
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Clear Document History"));
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Clear Documents History"));
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
-  gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
-
   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                            _("Clearing the document history will permanently "
+                                            _("Clearing the documents history will permanently "
                                               "remove all currently listed entries."));
 
+  /* the dialog icon */
+  image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_DIALOG);
+  gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
+  gtk_widget_show (image);
+
   /* popup the dialog */
   if (gtk_dialog_run (GTK_DIALOG (dialog)) == MOUSEPAD_RESPONSE_CLEAR)
     succeed = TRUE;
@@ -212,7 +189,7 @@
                                    _("Do you want to save the changes before closing?"));
 
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_dialogs_image_button (GTK_STOCK_DELETE, _("_Don't Save")),
+                                mousepad_util_image_button (GTK_STOCK_DELETE, _("_Don't Save")),
                                 MOUSEPAD_RESPONSE_DONT_SAVE);
 
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
@@ -238,76 +215,6 @@
 
 
 
-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;
-}
-
-
-
 gint
 mousepad_dialogs_ask_overwrite (GtkWindow   *parent,
                                 const gchar *filename)
@@ -328,10 +235,10 @@
 
   gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL);
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_dialogs_image_button (GTK_STOCK_SAVE, _("_Overwrite")),
+                                mousepad_util_image_button (GTK_STOCK_SAVE, _("_Overwrite")),
                                 MOUSEPAD_RESPONSE_OVERWRITE);
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_dialogs_image_button (GTK_STOCK_REFRESH, _("_Reload")),
+                                mousepad_util_image_button (GTK_STOCK_REFRESH, _("_Reload")),
                                 MOUSEPAD_RESPONSE_RELOAD);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
 
@@ -365,7 +272,7 @@
                           GTK_STOCK_SAVE_AS, MOUSEPAD_RESPONSE_SAVE_AS,
                           NULL);
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_dialogs_image_button (GTK_STOCK_REFRESH, _("_Reload")),
+                                mousepad_util_image_button (GTK_STOCK_REFRESH, _("_Reload")),
                                 MOUSEPAD_RESPONSE_RELOAD);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
 

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.h
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.h	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-dialogs.h	2007-10-16 20:01:37 UTC (rev 26134)
@@ -20,39 +20,44 @@
 
 G_BEGIN_DECLS
 
+/* dialog responses */
 enum {
   MOUSEPAD_RESPONSE_CANCEL,
   MOUSEPAD_RESPONSE_CLEAR,
+  MOUSEPAD_RESPONSE_CLOSE,
   MOUSEPAD_RESPONSE_DONT_SAVE,
+  MOUSEPAD_RESPONSE_FIND,
   MOUSEPAD_RESPONSE_JUMP_TO,
   MOUSEPAD_RESPONSE_OVERWRITE,
   MOUSEPAD_RESPONSE_RELOAD,
+  MOUSEPAD_RESPONSE_REPLACE,
   MOUSEPAD_RESPONSE_SAVE,
   MOUSEPAD_RESPONSE_SAVE_AS,
+  MOUSEPAD_RESPONSE_CHECK_ENTRY
 };
 
-void      mousepad_dialogs_show_about    (GtkWindow    *parent);
+GtkWidget *mousepad_dialogs_image_button (const gchar *stock_id,
+                                          const gchar *label);
 
+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);
+void       mousepad_dialogs_show_error    (GtkWindow    *parent,
+                                           const GError *error,
+                                           const gchar  *message);
 
-gboolean  mousepad_dialogs_clear_recent  (GtkWindow    *parent);
+gint       mousepad_dialogs_jump_to       (GtkWindow    *parent,
+                                           gint          current_line,
+                                           gint          last_line);
 
-gint      mousepad_dialogs_save_changes  (GtkWindow    *parent);
+gboolean   mousepad_dialogs_clear_recent  (GtkWindow    *parent);
 
-gchar    *mousepad_dialogs_save_as       (GtkWindow    *parent,
-                                          const gchar  *filename);
+gint       mousepad_dialogs_save_changes  (GtkWindow    *parent);
 
-gint      mousepad_dialogs_ask_overwrite (GtkWindow    *parent,
-                                          const gchar  *filename);
+gint       mousepad_dialogs_ask_overwrite (GtkWindow    *parent,
+                                           const gchar  *filename);
 
-gint      mousepad_dialogs_ask_reload    (GtkWindow    *parent);
+gint       mousepad_dialogs_ask_reload    (GtkWindow    *parent);
 
 G_END_DECLS
 

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-document.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-document.c	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-document.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -28,32 +28,25 @@
 #ifdef HAVE_TIME_H
 #include <time.h>
 #endif
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
 
 #include <mousepad/mousepad-private.h>
-#include <mousepad/mousepad-types.h>
+#include <mousepad/mousepad-util.h>
 #include <mousepad/mousepad-document.h>
-#include <mousepad/mousepad-file.h>
 #include <mousepad/mousepad-marshal.h>
 #include <mousepad/mousepad-view.h>
 #include <mousepad/mousepad-undo.h>
+#include <mousepad/mousepad-preferences.h>
 #include <mousepad/mousepad-window.h>
 
 
 
+#define MOUSEPAD_DOCUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOUSEPAD_TYPE_DOCUMENT, MousepadDocumentPrivate))
+
+
+
 static void      mousepad_document_class_init              (MousepadDocumentClass  *klass);
 static void      mousepad_document_init                    (MousepadDocument       *document);
 static void      mousepad_document_finalize                (GObject                *object);
-static void      mousepad_document_emit_can_undo           (MousepadUndo           *undo,
-                                                            gboolean                can_undo,
-                                                            MousepadDocument       *document);
-static void      mousepad_document_emit_can_redo           (MousepadUndo           *undo,
-                                                            gboolean                can_redo,
-                                                            MousepadDocument       *document);
-static void      mousepad_document_modified_changed        (GtkTextBuffer          *buffer,
-                                                            MousepadDocument       *document);
 static void      mousepad_document_notify_has_selection    (GtkTextBuffer          *buffer,
                                                             GParamSpec             *pspec,
                                                             MousepadDocument       *document);
@@ -71,14 +64,8 @@
                                                             guint                   info,
                                                             guint                   time,
                                                             MousepadDocument       *document);
-static void      mousepad_document_scroll_to_visible_area  (MousepadDocument       *document);
-static gboolean  mousepad_document_iter_search             (const GtkTextIter      *start,
-                                                            const gchar            *str,
-                                                            MousepadSearchFlags     flags,
-                                                            GtkTextIter            *match_start,
-                                                            GtkTextIter            *match_end,
-                                                            gboolean                forward_search);
-static void      mousepad_document_update_tab              (MousepadDocument       *document);
+static void      mousepad_document_filename_changed        (MousepadDocument       *document,
+                                                            const gchar            *filename);
 static void      mousepad_document_tab_button_clicked      (GtkWidget              *widget,
                                                             MousepadDocument       *document);
 
@@ -87,11 +74,8 @@
 {
   CLOSE_TAB,
   SELECTION_CHANGED,
-  MODIFIED_CHANGED,
   CURSOR_CHANGED,
   OVERWRITE_CHANGED,
-  CAN_UNDO,
-  CAN_REDO,
   LAST_SIGNAL,
 };
 
@@ -100,37 +84,20 @@
   GtkScrolledWindowClass __parent__;
 };
 
-struct _MousepadDocument
+struct _MousepadDocumentPrivate
 {
-  GtkScrolledWindow  __parent__;
+  GtkScrolledWindow __parent__;
 
-  /* text view */
-  GtkTextView       *textview;
-  GtkTextBuffer     *buffer;
-
-  /* the undo manager */
-  MousepadUndo      *undo;
-
-  /* the highlight tag */
-  GtkTextTag        *tag;
-
   /* the tab label and ebox */
-  GtkWidget         *ebox;
-  GtkWidget         *label;
+  GtkWidget           *ebox;
+  GtkWidget           *label;
 
-  /* absolute path of the file */
-  gchar             *filename;
+  /* utf-8 valid document names */
+  gchar               *utf8_filename;
+  gchar               *utf8_basename;
 
-  /* name of the file used for the titles */
-  gchar             *display_name;
-
-  /* last document modified time */
-  time_t             mtime;
-
   /* settings */
-  guint              word_wrap : 1;
-  guint              line_numbers : 1;
-  guint              auto_indent : 1;
+  guint                word_wrap : 1;
 };
 
 
@@ -140,7 +107,7 @@
 
 
 
-GtkWidget *
+MousepadDocument *
 mousepad_document_new (void)
 {
   return g_object_new (MOUSEPAD_TYPE_DOCUMENT, NULL);
@@ -174,6 +141,8 @@
 {
   GObjectClass *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (MousepadDocumentPrivate));
+
   mousepad_document_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
@@ -182,7 +151,7 @@
   document_signals[CLOSE_TAB] =
     g_signal_new (I_("close-tab"),
                   G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
+                  G_SIGNAL_NO_HOOKS,
                   0, NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -190,23 +159,15 @@
   document_signals[SELECTION_CHANGED] =
     g_signal_new (I_("selection-changed"),
                   G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
+                  G_SIGNAL_NO_HOOKS,
                   0, NULL, NULL,
                   g_cclosure_marshal_VOID__BOOLEAN,
                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
-  document_signals[MODIFIED_CHANGED] =
-    g_signal_new (I_("modified-changed"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__VOID,
-                  G_TYPE_NONE, 0);
-
   document_signals[CURSOR_CHANGED] =
     g_signal_new (I_("cursor-changed"),
                   G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
+                  G_SIGNAL_NO_HOOKS,
                   0, NULL, NULL,
                   _mousepad_marshal_VOID__UINT_UINT,
                   G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
@@ -214,26 +175,10 @@
   document_signals[OVERWRITE_CHANGED] =
     g_signal_new (I_("overwrite-changed"),
                   G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
+                  G_SIGNAL_NO_HOOKS,
                   0, NULL, NULL,
                   g_cclosure_marshal_VOID__BOOLEAN,
                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
-  document_signals[CAN_UNDO] =
-    g_signal_new (I_("can-undo"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__BOOLEAN,
-                  G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
-  document_signals[CAN_REDO] =
-    g_signal_new (I_("can-redo"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__BOOLEAN,
-                  G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 }
 
 
@@ -241,12 +186,18 @@
 static void
 mousepad_document_init (MousepadDocument *document)
 {
-  GtkTargetList *target_list;
+  GtkTargetList       *target_list;
+  gboolean             word_wrap, auto_indent, line_numbers, insert_spaces;
+  gchar               *font_name;
+  gint                 tab_width;
+  MousepadPreferences *preferences;
 
+  /* private structure */
+  document->priv = MOUSEPAD_DOCUMENT_GET_PRIVATE (document);
+
   /* initialize the variables */
-  document->filename     = NULL;
-  document->display_name = NULL;
-  document->mtime        = 0;
+  document->priv->utf8_filename = NULL;
+  document->priv->utf8_basename = NULL;
 
   /* setup the scolled window */
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (document), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
@@ -257,15 +208,15 @@
   /* create a textbuffer */
   document->buffer = gtk_text_buffer_new (NULL);
 
+  /* initialize the file */
+  document->file = mousepad_file_new (document->buffer);
+
+  /* connect signals to the file */
+  g_signal_connect_swapped (G_OBJECT (document->file), "filename-changed", G_CALLBACK (mousepad_document_filename_changed), document);
+
   /* initialize the undo manager */
   document->undo = mousepad_undo_new (document->buffer);
 
-  /* connect signals to the undo manager */
-  g_signal_connect (G_OBJECT (document->undo), "can-undo",
-                    G_CALLBACK (mousepad_document_emit_can_undo), document);
-  g_signal_connect (G_OBJECT (document->undo), "can-redo",
-                    G_CALLBACK (mousepad_document_emit_can_redo), document);
-
   /* create the highlight tag */
   document->tag = gtk_text_buffer_create_tag (document->buffer, NULL, "background", "#ffff78", NULL);
 
@@ -278,8 +229,34 @@
   target_list = gtk_drag_dest_get_target_list (GTK_WIDGET (document->textview));
   gtk_target_list_add_table (target_list, drop_targets, G_N_ELEMENTS (drop_targets));
 
+  /* preferences */
+  preferences = mousepad_preferences_get ();
+
+  /* read all the default settings */
+  g_object_get (G_OBJECT (preferences),
+                "view-word-wrap", &word_wrap,
+                "view-line-numbers", &line_numbers,
+                "view-auto-indent", &auto_indent,
+                "view-font-name", &font_name,
+                "view-tab-width", &tab_width,
+                "view-insert-spaces", &insert_spaces,
+                NULL);
+
+  /* release the preferences */
+  g_object_unref (G_OBJECT (preferences));
+
+  /* set all the settings */
+  mousepad_document_set_word_wrap (document, word_wrap);
+  mousepad_document_set_font (document, font_name);
+  mousepad_view_set_line_numbers (document->textview, line_numbers);
+  mousepad_view_set_auto_indent (document->textview, auto_indent);
+  mousepad_view_set_tab_width (document->textview, tab_width);
+  mousepad_view_set_insert_spaces (document->textview, insert_spaces);
+
+  /* cleanup */
+  g_free (font_name);
+
   /* attach signals to the text view and buffer */
-  g_signal_connect (G_OBJECT (document->buffer), "modified-changed", G_CALLBACK (mousepad_document_modified_changed), document);
   g_signal_connect (G_OBJECT (document->buffer), "notify::has-selection", G_CALLBACK (mousepad_document_notify_has_selection), document);
   g_signal_connect (G_OBJECT (document->buffer), "notify::cursor-position", G_CALLBACK (mousepad_document_notify_cursor_position), document);
   g_signal_connect (G_OBJECT (document->textview), "notify::overwrite", G_CALLBACK (mousepad_document_toggle_overwrite), document);
@@ -295,59 +272,23 @@
   MousepadDocument *document = MOUSEPAD_DOCUMENT (object);
 
   /* cleanup */
-  g_free (document->filename);
-  g_free (document->display_name);
+  g_free (document->priv->utf8_filename);
+  g_free (document->priv->utf8_basename);
 
   /* release the undo manager */
   g_object_unref (G_OBJECT (document->undo));
 
-  /* release our reference from the buffer */
+  /* release the file */
+  g_object_unref (G_OBJECT (document->file));
+
+  /* release the buffer reference */
   g_object_unref (G_OBJECT (document->buffer));
 
   (*G_OBJECT_CLASS (mousepad_document_parent_class)->finalize) (object);
 }
 
 
-
 static void
-mousepad_document_emit_can_undo (MousepadUndo     *undo,
-                                 gboolean          can_undo,
-                                 MousepadDocument *document)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-  /* emit the signal */
-  g_signal_emit (G_OBJECT (document), document_signals[CAN_UNDO], 0, can_undo);
-}
-
-
-
-static void
-mousepad_document_emit_can_redo (MousepadUndo     *undo,
-                                 gboolean          can_redo,
-                                 MousepadDocument *document)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-  /* emit the signal */
-  g_signal_emit (G_OBJECT (document), document_signals[CAN_REDO], 0, can_redo);
-}
-
-
-
-static void
-mousepad_document_modified_changed (GtkTextBuffer    *buffer,
-                                    MousepadDocument *document)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-  /* emit the signal */
-  g_signal_emit (G_OBJECT (document), document_signals[MODIFIED_CHANGED], 0);
-}
-
-
-
-static void
 mousepad_document_notify_has_selection (GtkTextBuffer    *buffer,
                                         GParamSpec       *pspec,
                                         MousepadDocument *document)
@@ -358,7 +299,7 @@
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
 
   /* check if we have selected text or not */
-  has_selection = mousepad_document_get_has_selection (document);
+  has_selection = mousepad_view_get_has_selection (document->textview);
 
   /* emit the signal */
   g_signal_emit (G_OBJECT (document), document_signals[SELECTION_CHANGED], 0, has_selection);
@@ -371,8 +312,9 @@
                                           GParamSpec       *pspec,
                                           MousepadDocument *document)
 {
-  GtkTextIter iter, start;
+  GtkTextIter iter;
   guint       line, column = 0;
+  gint        tab_width;
 
   _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
@@ -380,25 +322,17 @@
   /* get the current iter position */
   gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
 
-  /* get the current line numbr */
+  /* get the current line number */
   line = gtk_text_iter_get_line (&iter) + 1;
 
+  /* get the tab width */
+  tab_width = mousepad_view_get_tab_width (document->textview);
+
   /* get the column */
-  start = iter;
-  gtk_text_iter_set_line_offset (&start, 0);
+  column = mousepad_util_get_real_line_offset (&iter, tab_width) + 1;
 
-  while (!gtk_text_iter_equal (&start, &iter))
-    {
-      if (gtk_text_iter_get_char (&start) == '\t')
-        column += (8 - (column % 8));
-      else
-        ++column;
-
-      gtk_text_iter_forward_char (&start);
-    }
-
   /* emit the signal */
-  g_signal_emit (G_OBJECT (document), document_signals[CURSOR_CHANGED], 0, line, column + 1);
+  g_signal_emit (G_OBJECT (document), document_signals[CURSOR_CHANGED], 0, line, column);
 }
 
 
@@ -442,169 +376,51 @@
 
 
 static void
-mousepad_document_scroll_to_visible_area (MousepadDocument *document)
+mousepad_document_filename_changed (MousepadDocument *document,
+                                    const gchar      *filename)
 {
+  gchar *utf8_filename, *utf8_basename;
+
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (filename != NULL);
 
-  /* scroll to visible area */
-  gtk_text_view_scroll_to_mark (document->textview,
-                                gtk_text_buffer_get_insert (document->buffer),
-                                0.02, FALSE, 0.0, 0.0);
-}
+  /* convert the title into a utf-8 valid version for display */
+  utf8_filename = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
 
-
-
-gboolean
-mousepad_document_reload (MousepadDocument  *document,
-                          GError           **error)
-{
-  GtkTextIter  start, end;
-  gchar       *filename;
-  gboolean     succeed = FALSE;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  /* remove the content of the textview */
-  gtk_text_buffer_get_bounds (document->buffer, &start, &end);
-  gtk_text_buffer_delete (document->buffer, &start, &end);
-
-  /* we have to copy the filename, because mousepad_screen_open_file (resets) the name */
-  filename = g_strdup (document->filename);
-
-  /* reload the document */
-  succeed = mousepad_document_open_file (document, filename, error);
-
-  /* cleanup */
-  g_free (filename);
-
-  return succeed;
-}
-
-
-
-gboolean
-mousepad_document_save_file (MousepadDocument  *document,
-                             const gchar       *filename,
-                             GError           **error)
-{
-  gchar       *content;
-  gchar       *converted = NULL;
-  GtkTextIter  start, end;
-  gsize        bytes;
-  gint         new_mtime;
-  gboolean     succeed = FALSE;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-  _mousepad_return_val_if_fail (filename != NULL, FALSE);
-
-  /* get the textview content */
-  gtk_text_buffer_get_bounds (document->buffer, &start, &end);
-  content = gtk_text_buffer_get_slice (document->buffer, &start, &end, TRUE);
-
-  if (G_LIKELY (content != NULL))
+  if (G_LIKELY (utf8_filename))
     {
-      /* TODO: fix the file encoding here, basic utf8 for testing */
-      converted = g_convert (content,
-                             strlen (content),
-                             "UTF-8",
-                             "UTF-8",
-                             NULL,
-                             &bytes,
-                             error);
+      /* create the display name */
+      utf8_basename = g_filename_display_basename (utf8_filename);
 
-      /* cleanup */
-      g_free (content);
+      /* remove the old names */
+      g_free (document->priv->utf8_filename);
+      g_free (document->priv->utf8_basename);
 
-      if (G_LIKELY (converted != NULL))
+      /* set the new names */
+      document->priv->utf8_filename = utf8_filename;
+      document->priv->utf8_basename = utf8_basename;
+
+      /* update the tab label and tooltip */
+      if (G_UNLIKELY (document->priv->label))
         {
-          succeed = mousepad_file_save_data (filename, converted, bytes,
-                                             &new_mtime, error);
+          /* set the tab label */
+          gtk_label_set_text (GTK_LABEL (document->priv->label), utf8_basename);
 
-          /* cleanup */
-          g_free (converted);
-
-          /* saving work w/o problems */
-          if (G_LIKELY (succeed))
-            {
-              /* set the new mtime */
-              document->mtime = new_mtime;
-
-              /* nothing happend */
-              gtk_text_buffer_set_modified (document->buffer, FALSE);
-
-              /* we were allowed to write */
-              gtk_text_view_set_editable (document->textview, TRUE);
-
-              /* emit the modified-changed signal */
-              mousepad_document_modified_changed (NULL, document);
-            }
+          /* set the tab tooltip */
+          mousepad_util_set_tooltip (document->priv->ebox, utf8_filename);
         }
     }
-
-  return succeed;
 }
 
 
 
 void
-mousepad_document_set_filename (MousepadDocument *document,
-                                const gchar      *filename)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-  _mousepad_return_if_fail (filename != NULL);
-
-  /* cleanup the old names */
-  g_free (document->filename);
-  g_free (document->display_name);
-
-  /* create the new names */
-  document->filename = g_strdup (filename);
-  document->display_name = g_filename_display_basename (filename);
-
-  /* update the tab label and tooltip */
-  if (document->ebox && document->label)
-    mousepad_document_update_tab (document);
-}
-
-
-
-void
-mousepad_document_set_auto_indent (MousepadDocument *document,
-                                   gboolean          auto_indent)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-  /* store the setting */
-  document->auto_indent = auto_indent;
-
-  mousepad_view_set_auto_indent (MOUSEPAD_VIEW (document->textview), auto_indent);
-}
-
-
-
-void
-mousepad_document_set_line_numbers (MousepadDocument *document,
-                                    gboolean          line_numbers)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-  /* store the setting */
-  document->line_numbers = line_numbers;
-
-  mousepad_view_set_show_line_numbers (MOUSEPAD_VIEW (document->textview), line_numbers);
-}
-
-
-
-void
 mousepad_document_set_overwrite (MousepadDocument *document,
                                  gboolean          overwrite)
 {
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
 
-  gtk_text_view_set_overwrite (document->textview, overwrite);
+  gtk_text_view_set_overwrite (GTK_TEXT_VIEW (document->textview), overwrite);
 }
 
 
@@ -616,10 +432,10 @@
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
 
   /* store the setting */
-  document->word_wrap = word_wrap;
+  document->priv->word_wrap = word_wrap;
 
   /* set the wrapping mode */
-  gtk_text_view_set_wrap_mode (document->textview,
+  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (document->textview),
                                word_wrap ? GTK_WRAP_WORD : GTK_WRAP_NONE);
 }
 
@@ -635,6 +451,7 @@
 
   if (G_LIKELY (font_name))
     {
+      /* set the widget font */
       font_desc = pango_font_description_from_string (font_name);
       gtk_widget_modify_font (GTK_WIDGET (document->textview), font_desc);
       pango_font_description_free (font_desc);
@@ -643,418 +460,7 @@
 
 
 
-gboolean
-mousepad_document_open_file (MousepadDocument  *document,
-                             const gchar       *filename,
-                             GError           **error)
-{
-  GtkTextIter iter;
-  gboolean    succeed = FALSE;
-  gboolean    readonly;
-  gint        new_mtime;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-  _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-  _mousepad_return_val_if_fail (filename != NULL, FALSE);
-
-  /* we're going to add the file content */
-  gtk_text_buffer_begin_user_action (document->buffer);
-
-  /* lock the undo manager */
-  mousepad_undo_lock (document->undo);
-
-  /* insert the file content */
-  if (mousepad_file_read_to_buffer (filename,
-                                    document->buffer,
-                                    &new_mtime,
-                                    &readonly,
-                                    error))
-    {
-      /* set the new filename */
-      mousepad_document_set_filename (document, filename);
-
-      /* set the new mtime */
-      document->mtime = new_mtime;
-
-      /* whether the textview is editable */
-      gtk_text_view_set_editable (document->textview, !readonly);
-
-      /* move the cursors to the first place and pretend nothing happend */
-      gtk_text_buffer_get_start_iter (document->buffer, &iter);
-      gtk_text_buffer_place_cursor (document->buffer, &iter);
-      gtk_text_buffer_set_modified (document->buffer, FALSE);
-      gtk_text_view_scroll_to_iter (document->textview, &iter, 0, FALSE, 0, 0);
-
-      /* it worked out very well */
-      succeed = TRUE;
-    }
-
-  /* unlock the undo manager */
-  mousepad_undo_unlock (document->undo);
-
-  /* and we're done */
-  gtk_text_buffer_end_user_action (document->buffer);
-
-  return succeed;
-}
-
-
-
-
-static gboolean
-mousepad_document_iter_search (const GtkTextIter   *start,
-                               const gchar         *str,
-                               MousepadSearchFlags  flags,
-                               GtkTextIter         *match_start,
-                               GtkTextIter         *match_end,
-                               gboolean             search_forward)
-{
-  GtkTextIter iter, begin;
-  gunichar    iter_char, str_char;
-  gboolean    succeed = FALSE;
-  gboolean    continue_search;
-  guint       str_offset = 0;
-
-  _mousepad_return_val_if_fail (start != NULL, FALSE);
-
-  /* set the start iter */
-  iter = *start;
-
-  /* walk from the start to the end iter */
-  do
-    {
-      /* get the characters we're going to compare */
-      iter_char = gtk_text_iter_get_char (&iter);
-      str_char  = g_utf8_get_char (str);
-
-      /* convert the characters to lower case if needed */
-      if (flags & MOUSEPAD_SEARCH_CASE_INSENSITIVE)
-        {
-          iter_char = tolower (iter_char);
-          str_char  = tolower (str_char);
-        }
-
-      /* compare the two characters */
-      if (iter_char == str_char)
-        {
-          /* first character matched, set the begin iter */
-          if (str_offset == 0)
-            begin = iter;
-
-          /* get the next character and increase the offset counter */
-          str = g_utf8_next_char (str);
-          str_offset++;
-
-          /* we've hit the end of the search string, so we had a full match */
-          if (G_UNLIKELY (*str == '\0'))
-            {
-              if (G_LIKELY (search_forward))
-                {
-                  /* forward one character */
-                  gtk_text_iter_forward_char (&iter);
-
-                  /* check if we match a whole word */
-                  if (flags & MOUSEPAD_SEARCH_WHOLE_WORD
-                      && !(gtk_text_iter_starts_word (&begin)
-                           && gtk_text_iter_ends_word (&iter)))
-                    goto reset_match;
-                }
-              else
-                {
-                  /* 'backward' one character */
-                  gtk_text_iter_forward_char (&begin);
-
-                  /* check if we match a whole word */
-                  if (flags & MOUSEPAD_SEARCH_WHOLE_WORD
-                      && !(gtk_text_iter_starts_word (&iter)
-                           && gtk_text_iter_ends_word (&begin)))
-                    goto reset_match;
-                }
-
-              /* set the start and end iters */
-              *match_start = begin;
-              *match_end   = iter;
-
-              /* return true and break the loop */
-              succeed = TRUE;
-              break;
-            }
-        }
-      else if (G_UNLIKELY (str_offset > 0))
-        {
-          reset_match:
-          /* go back to the first character in the string */
-          for (;str_offset > 0; str_offset--)
-            str = g_utf8_prev_char (str);
-
-          /* reset the iter */
-          iter = begin;
-        }
-
-      /* jump to next iter in the buffer */
-      if (G_LIKELY (search_forward))
-        continue_search = gtk_text_iter_forward_char (&iter);
-      else
-        continue_search = gtk_text_iter_backward_char (&iter);
-    }
-  while (G_LIKELY (continue_search));
-
-  return succeed;
-}
-
-
-
-gboolean
-mousepad_document_find (MousepadDocument    *document,
-                        const gchar         *string,
-                        MousepadSearchFlags  flags)
-{
-  gboolean     found;
-  gboolean     already_wrapped = FALSE;
-  gchar       *reversed = NULL;
-  GtkTextIter  doc_start, doc_end;
-  GtkTextIter  sel_start, sel_end;
-  GtkTextIter  match_start, match_end;
-  GtkTextIter  start;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-  _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (document->buffer), FALSE);
-  _mousepad_return_val_if_fail (string && g_utf8_validate (string, -1, NULL), FALSE);
-
-  /* get the bounds */
-  gtk_text_buffer_get_bounds (document->buffer, &doc_start, &doc_end);
-  gtk_text_buffer_get_selection_bounds (document->buffer, &sel_start, &sel_end);
-
-  /* set the correct starting point for the search */
-  if (flags & MOUSEPAD_SEARCH_FORWARDS)
-    {
-      start = sel_end;
-    }
-  else
-    {
-      start = sel_start;
-
-      if (flags & MOUSEPAD_SEARCH_BACKWARDS)
-        {
-          /* the character is right of the iter, go one iter backwards */
-          gtk_text_iter_backward_char (&start);
-
-          /* reverse the search string */
-          reversed = g_utf8_strreverse (string, -1);
-        }
-    }
-
-search:
-  /* try to find the next occurence of the string */
-  if (flags & MOUSEPAD_SEARCH_BACKWARDS)
-    found = mousepad_document_iter_search (&start, reversed, flags, &match_start, &match_end, FALSE);
-  else
-    found = mousepad_document_iter_search (&start, string, flags, &match_start, &match_end, TRUE);
-
-  /* select the occurence */
-  if (found)
-    {
-      /* set the cursor in from of the matched iter */
-      gtk_text_buffer_place_cursor (document->buffer, &match_start);
-
-      /* select the match */
-      gtk_text_buffer_move_mark_by_name (document->buffer, "insert", &match_end);
-
-      /* scroll document so the cursor is visible */
-      mousepad_document_scroll_to_visible_area (document);
-    }
-  /* wrap around */
-  else if (flags & MOUSEPAD_SEARCH_WRAP_AROUND && already_wrapped == FALSE)
-    {
-      /* set the new start and end iter */
-      if (flags & MOUSEPAD_SEARCH_BACKWARDS)
-        start = doc_end;
-      else
-        start = doc_start;
-
-      /* set we did the wrap, so we don't end up in a loop */
-      already_wrapped = TRUE;
-
-      /* search again */
-      goto search;
-    }
-  else if (flags & MOUSEPAD_SEARCH_WRAP_AROUND)
-    {
-      /* nothing found, we already did the wrap, so just place the cursor where we started */
-      gtk_text_buffer_place_cursor (document->buffer, &sel_start);
-    }
-
-  /* cleanup */
-  g_free (reversed);
-
-  return found;
-}
-
-
-
 void
-mousepad_document_replace (MousepadDocument *document)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-
-
-}
-
-
-
-void
-mousepad_document_highlight_all (MousepadDocument    *document,
-                                 const gchar         *string,
-                                 MousepadSearchFlags  flags)
-{
-  GtkTextIter iter;
-  GtkTextIter doc_start, doc_end;
-  GtkTextIter match_start, match_end;
-  gboolean    found;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
-  _mousepad_return_if_fail (string ? g_utf8_validate (string, -1, NULL) : TRUE);
-
-  /* get the document bounds */
-  gtk_text_buffer_get_bounds (document->buffer, &doc_start, &doc_end);
-
-  /* remove all the highlight tags */
-  gtk_text_buffer_remove_tag (document->buffer, document->tag, &doc_start, &doc_end);
-
-  /* highlight the new string */
-  if (G_LIKELY (string != NULL && *string != '\0'))
-    {
-      /* set the iter to the beginning of the document */
-      iter = doc_start;
-
-      /* highlight all the occurences of the strings */
-      do
-        {
-          /* search for the next occurence of the string */
-          found = mousepad_document_iter_search (&iter, string, flags, &match_start, &match_end, TRUE);
-
-          if (G_LIKELY (found))
-            {
-              /* highlight the found occurence */
-              gtk_text_buffer_apply_tag (document->buffer, document->tag, &match_start, &match_end);
-
-              /* jump to the end of the highlighted string and continue searching */
-              iter = match_end;
-            }
-        }
-      while (found);
-    }
-}
-
-
-
-void
-mousepad_document_cut_selection (MousepadDocument *document)
-{
-  GtkClipboard *clipboard;
-  MousepadView *view = MOUSEPAD_VIEW (document->textview);
-
-  /* get the clipboard */
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
-
-  /* cut the text */
-  if (mousepad_view_get_vertical_selection (view))
-    mousepad_view_cut_clipboard (view, clipboard);
-  else
-    gtk_text_buffer_cut_clipboard (document->buffer, clipboard, gtk_text_view_get_editable (document->textview));
-
-  /* make sure the cursor is in the visible area */
-  mousepad_document_scroll_to_visible_area (document);
-}
-
-
-
-void
-mousepad_document_copy_selection (MousepadDocument *document)
-{
-  GtkClipboard *clipboard;
-  MousepadView *view = MOUSEPAD_VIEW (document->textview);
-
-  /* get the clipboard */
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
-
-  /* copy the selected text */
-  if (mousepad_view_get_vertical_selection (view))
-    mousepad_view_copy_clipboard (view, clipboard);
-  else
-    gtk_text_buffer_copy_clipboard (document->buffer, clipboard);
-}
-
-
-
-void
-mousepad_document_paste_clipboard (MousepadDocument *document)
-{
-  GtkClipboard *clipboard;
-
-  /* get the clipboard */
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
-
-  /* paste the clipboard content */
-  gtk_text_buffer_paste_clipboard (document->buffer, clipboard, NULL, gtk_text_view_get_editable (document->textview));
-
-  /* make sure the cursor is in the visible area */
-  mousepad_document_scroll_to_visible_area (document);
-}
-
-
-
-void
-mousepad_document_paste_column_clipboard (MousepadDocument *document)
-{
-  GtkClipboard *clipboard;
-  MousepadView *view = MOUSEPAD_VIEW (document->textview);
-
-  /* get the clipboard */
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (document->textview), GDK_SELECTION_CLIPBOARD);
-
-  /* past the clipboard text in a column */
-  mousepad_view_paste_column_clipboard (view, clipboard);
-
-  /* make sure the cursor is in the visible area */
-  mousepad_document_scroll_to_visible_area (document);
-}
-
-
-
-void
-mousepad_document_delete_selection (MousepadDocument *document)
-{
-  MousepadView *view = MOUSEPAD_VIEW (document->textview);
-
-  /* delete the selected text */
-  if (mousepad_view_get_vertical_selection (view))
-    mousepad_view_delete_selection (view);
-  else
-    gtk_text_buffer_delete_selection (document->buffer, TRUE, gtk_text_view_get_editable (document->textview));
-
-  /* make sure the cursor is in the visible area */
-  mousepad_document_scroll_to_visible_area (document);
-}
-
-
-
-void
-mousepad_document_select_all (MousepadDocument *document)
-{
-  GtkTextIter start, end;
-
-  /* get the start and end iter */
-  gtk_text_buffer_get_bounds (document->buffer, &start, &end);
-
-  /* select everything between those iters */
-  gtk_text_buffer_select_range (document->buffer, &start, &end);
-}
-
-
-
-void
 mousepad_document_focus_textview (MousepadDocument *document)
 {
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
@@ -1072,13 +478,14 @@
   GtkTextIter iter;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
 
   /* move the cursor */
-  gtk_text_buffer_get_iter_at_line (document->buffer, &iter, line_number-1);
+  gtk_text_buffer_get_iter_at_line (document->buffer, &iter, line_number - 1);
   gtk_text_buffer_place_cursor (document->buffer, &iter);
 
   /* make sure the cursor is in the visible area */
-  mousepad_document_scroll_to_visible_area (document);
+  mousepad_view_put_cursor_on_screen (document->textview);
 }
 
 
@@ -1092,7 +499,7 @@
   mousepad_document_notify_cursor_position (document->buffer, NULL, document);
 
   /* re-send the overwrite signal */
-  mousepad_document_toggle_overwrite (document->textview, NULL, document);
+  mousepad_document_toggle_overwrite (GTK_TEXT_VIEW (document->textview), NULL, document);
 }
 
 
@@ -1105,6 +512,7 @@
   GtkTextIter iter;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
 
   /* get the current line number */
   gtk_text_buffer_get_iter_at_mark (document->buffer, &iter, gtk_text_buffer_get_insert (document->buffer));
@@ -1118,79 +526,12 @@
 
 
 gboolean
-mousepad_document_get_externally_modified (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-  _mousepad_return_val_if_fail (document->filename != NULL, FALSE);
-
-  /* return whether the file has been externally modified */
-  return mousepad_file_get_externally_modified (document->filename, document->mtime);
-}
-
-
-
-gboolean
-mousepad_document_get_can_undo (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-
-  return mousepad_undo_can_undo (document->undo);
-}
-
-
-
-gboolean
-mousepad_document_get_can_redo (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-
-  return mousepad_undo_can_redo (document->undo);
-}
-
-
-
-const gchar *
-mousepad_document_get_filename (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), NULL);
-
-  return document->filename;
-}
-
-
-
-gboolean
-mousepad_document_get_has_selection (MousepadDocument *document)
-{
-  gboolean       has_selection;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-
-  /* check if we have selected text or not */
-  g_object_get (G_OBJECT (document->buffer), "has-selection", &has_selection, NULL);
-
-  return has_selection;
-}
-
-
-
-gboolean
-mousepad_document_get_modified (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-
-  /* return whether the buffer has been modified */
-  return gtk_text_buffer_get_modified (document->buffer);
-}
-
-
-
-gboolean
 mousepad_document_get_readonly (MousepadDocument *document)
 {
   _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+  _mousepad_return_val_if_fail (GTK_IS_TEXT_VIEW (document->textview), FALSE);
 
-  return !gtk_text_view_get_editable (document->textview);
+  return !gtk_text_view_get_editable (GTK_TEXT_VIEW (document->textview));
 }
 
 
@@ -1206,20 +547,16 @@
   gtk_widget_show (hbox);
 
   /* the ebox */
-  document->ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, "visible-window", FALSE, NULL);
-  gtk_box_pack_start (GTK_BOX (hbox), document->ebox, TRUE, TRUE, 0);
-  gtk_widget_show (document->ebox);
+  document->priv->ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, "visible-window", FALSE, NULL);
+  gtk_box_pack_start (GTK_BOX (hbox), document->priv->ebox, TRUE, TRUE, 0);
+  mousepad_util_set_tooltip (document->priv->ebox, document->priv->utf8_filename);
+  gtk_widget_show (document->priv->ebox);
 
   /* create the label */
-  document->label = g_object_new (GTK_TYPE_LABEL,
-                                 "selectable", FALSE,
-                                 "xalign", 0.0, NULL);
-  gtk_container_add (GTK_CONTAINER (document->ebox), document->label);
-  gtk_widget_show (document->label);
+  document->priv->label = gtk_label_new (mousepad_document_get_basename (document));
+  gtk_container_add (GTK_CONTAINER (document->priv->ebox), document->priv->label);
+  gtk_widget_show (document->priv->label);
 
-  /* update the tab and add signal to the ebox for a title update */
-  mousepad_document_update_tab (document);
-
   /* create the button */
   button = g_object_new (GTK_TYPE_BUTTON,
                          "relief", GTK_RELIEF_NONE,
@@ -1227,10 +564,9 @@
                          "border-width", 0,
                          "can-default", FALSE,
                          "can-focus", FALSE, NULL);
-  mousepad_gtk_set_tooltip (button, _("Close this tab"));
+  mousepad_util_set_tooltip (button, _("Close this tab"));
   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-  g_signal_connect (G_OBJECT (button), "clicked",
-                    G_CALLBACK (mousepad_document_tab_button_clicked), document);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (mousepad_document_tab_button_clicked), document);
   gtk_widget_show (button);
 
   /* button image */
@@ -1244,19 +580,6 @@
 
 
 static void
-mousepad_document_update_tab (MousepadDocument *document)
-{
-  /* set the tab label */
-  gtk_label_set_text (GTK_LABEL (document->label),
-                      mousepad_document_get_title (document, FALSE));
-
-  /* set the tab tooltip */
-  mousepad_gtk_set_tooltip (document->ebox, document->filename);
-}
-
-
-
-static void
 mousepad_document_tab_button_clicked (GtkWidget        *widget,
                                       MousepadDocument *document)
 {
@@ -1266,86 +589,71 @@
 
 
 const gchar *
-mousepad_document_get_title (MousepadDocument *document,
-                             gboolean          show_full_path)
+mousepad_document_get_basename (MousepadDocument *document)
 {
-  const gchar  *title;
-  static guint  untitled_counter = 0;
+  static gint untitled_counter = 0;
 
   _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), NULL);
 
-  if (G_UNLIKELY (show_full_path && document->filename))
+  /* check if there is a filename set */
+  if (document->priv->utf8_basename == NULL)
     {
-      /* return the filename */
-      title = document->filename;
+      /* create an unique untitled document name */
+      document->priv->utf8_basename = g_strdup_printf ("%s %d", _("Untitled"), ++untitled_counter);
     }
-  else
-    {
-      /* check if the document is still untitled, if so, fix it */
-      if (G_UNLIKELY (document->display_name == NULL))
-        document->display_name = g_strdup_printf ("%s %d", _("Untitled"), ++untitled_counter);
 
-      /* return the display_name */
-      title = document->display_name;
-    }
-
-  return title;
+  return document->priv->utf8_basename;
 }
 
 
 
-gboolean
-mousepad_document_get_word_wrap (MousepadDocument *document)
+const gchar *
+mousepad_document_get_filename (MousepadDocument *document)
 {
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), NULL);
 
-  return document->word_wrap;
+  return document->priv->utf8_filename;
 }
 
 
 
 gboolean
-mousepad_document_get_line_numbers (MousepadDocument *document)
+mousepad_document_get_word_wrap (MousepadDocument *document)
 {
   _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
 
-  return document->line_numbers;
+  return document->priv->word_wrap;
 }
 
 
 
-gboolean
-mousepad_document_get_auto_indent (MousepadDocument *document)
-{
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
-
-  return document->auto_indent;
-}
-
-
-
 void
-mousepad_document_undo (MousepadDocument *document)
+mousepad_document_get_font_information (MousepadDocument      *document,
+                                        PangoFontDescription **font_desc,
+                                        gint                  *font_height)
 {
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  PangoContext         *context;
+  PangoFontMetrics     *metrics;
+  PangoFontDescription *font;
 
-  /* undo */
-  mousepad_undo_do_undo (document->undo);
+  /* get the textview context */
+  context = gtk_widget_get_pango_context (GTK_WIDGET (document->textview));
 
-  /* scroll to visible area */
-  mousepad_document_scroll_to_visible_area (document);
-}
+  /* get the font description */
+  font = pango_context_get_font_description (context);
 
+  if (font_desc)
+    *font_desc = font;
 
+  if (G_LIKELY (font_height))
+    {
+      /* get metric information about the font */
+      metrics = pango_context_get_metrics (context, font, pango_context_get_language (context));
 
-void
-mousepad_document_redo (MousepadDocument *document)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+      /* calculate the real font height */
+      *font_height = (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)) / PANGO_SCALE;
 
-  /* redo */
-  mousepad_undo_do_redo (document->undo);
-
-  /* scroll to visible area */
-  mousepad_document_scroll_to_visible_area (document);
+      /* release the metrics */
+      pango_font_metrics_unref (metrics);
+    }
 }

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-document.h
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-document.h	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-document.h	2007-10-16 20:01:37 UTC (rev 26134)
@@ -20,10 +20,14 @@
 
 G_BEGIN_DECLS
 
-#include <mousepad/mousepad-types.h>
+#include <mousepad/mousepad-util.h>
+#include <mousepad/mousepad-file.h>
+#include <mousepad/mousepad-undo.h>
+#include <mousepad/mousepad-view.h>
 
-typedef struct _MousepadDocumentClass MousepadDocumentClass;
-typedef struct _MousepadDocument      MousepadDocument;
+typedef struct _MousepadDocumentPrivate MousepadDocumentPrivate;
+typedef struct _MousepadDocumentClass   MousepadDocumentClass;
+typedef struct _MousepadDocument        MousepadDocument;
 
 #define MOUSEPAD_SCROLL_MARGIN 0.02
 
@@ -34,101 +38,67 @@
 #define MOUSEPAD_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DOCUMENT))
 #define MOUSEPAD_DOCUMENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DOCUMENT, MousepadDocumentClass))
 
-GType           mousepad_document_get_type                 (void) G_GNUC_CONST;
+struct _MousepadDocument
+{
+  GtkScrolledWindow        __parent__;
 
-GtkWidget      *mousepad_document_new                      (void);
+  /* private structure */
+  MousepadDocumentPrivate *priv;
 
-gboolean        mousepad_document_reload                   (MousepadDocument    *document,
-                                                            GError             **error);
+  /* file */
+  MousepadFile            *file;
 
-gboolean        mousepad_document_save_file                (MousepadDocument    *document,
-                                                            const gchar         *filename,
-                                                            GError             **error);
+  /* undo manager */
+  MousepadUndo            *undo;
 
-void            mousepad_document_set_filename             (MousepadDocument    *document,
-                                                            const gchar         *filename);
+  /* text buffer */
+  GtkTextBuffer           *buffer;
 
-void            mousepad_document_set_font                 (MousepadDocument    *document,
-                                                            const gchar         *font_name);
+  /* text view */
+  MousepadView            *textview;
 
-void            mousepad_document_set_auto_indent          (MousepadDocument    *document,
-                                                            gboolean             auto_indent);
+  /* the highlight tag */
+  GtkTextTag              *tag;
+};
 
-void            mousepad_document_set_line_numbers         (MousepadDocument    *document,
-                                                            gboolean             line_numbers);
+GType             mousepad_document_get_type                 (void) G_GNUC_CONST;
 
-void            mousepad_document_set_overwrite            (MousepadDocument    *document,
-                                                            gboolean             overwrite);
+MousepadDocument *mousepad_document_new                      (void);
 
-void            mousepad_document_set_word_wrap            (MousepadDocument    *document,
-                                                            gboolean             word_wrap);
+void              mousepad_document_set_font                 (MousepadDocument      *document,
+                                                              const gchar           *font_name);
 
-gboolean        mousepad_document_open_file                (MousepadDocument    *document,
-                                                            const gchar         *filename,
-                                                            GError             **error);
+void              mousepad_document_set_overwrite            (MousepadDocument      *document,
+                                                              gboolean               overwrite);
 
-gboolean        mousepad_document_find                     (MousepadDocument    *document,
-                                                            const gchar         *string,
-                                                            MousepadSearchFlags  flags);
+void              mousepad_document_set_word_wrap            (MousepadDocument      *document,
+                                                              gboolean               word_wrap);
 
-void            mousepad_document_replace                  (MousepadDocument    *document);
+void              mousepad_document_focus_textview           (MousepadDocument      *document);
 
-void            mousepad_document_highlight_all            (MousepadDocument    *document,
-                                                            const gchar         *string,
-                                                            MousepadSearchFlags  flags);
+void              mousepad_document_jump_to_line             (MousepadDocument      *document,
+                                                              gint                   line_number);
 
-void            mousepad_document_cut_selection            (MousepadDocument    *document);;
+void              mousepad_document_send_statusbar_signals   (MousepadDocument      *document);
 
-void            mousepad_document_copy_selection           (MousepadDocument    *document);
+void              mousepad_document_line_numbers             (MousepadDocument      *document,
+                                                              gint                  *current_line,
+                                                              gint                  *last_line);
 
-void            mousepad_document_paste_clipboard          (MousepadDocument    *document);
+gboolean          mousepad_document_get_readonly             (MousepadDocument      *document);
 
-void            mousepad_document_paste_column_clipboard   (MousepadDocument    *document);
+GtkWidget        *mousepad_document_get_tab_label            (MousepadDocument      *document);
 
-void            mousepad_document_delete_selection         (MousepadDocument    *document);
+const gchar      *mousepad_document_get_basename             (MousepadDocument      *document);
 
-void            mousepad_document_select_all               (MousepadDocument    *document);
+const gchar      *mousepad_document_get_filename             (MousepadDocument      *document);
 
-void            mousepad_document_focus_textview           (MousepadDocument    *document);
+gboolean          mousepad_document_get_word_wrap            (MousepadDocument      *document);
 
-void            mousepad_document_jump_to_line             (MousepadDocument    *document,
-                                                            gint                 line_number);
+void              mousepad_document_get_font_information     (MousepadDocument      *document,
+                                                              PangoFontDescription **font_desc,
+                                                              gint                  *font_height);
 
-void            mousepad_document_send_statusbar_signals   (MousepadDocument    *document);
-
-void            mousepad_document_line_numbers             (MousepadDocument    *document,
-                                                            gint                *current_line,
-                                                            gint                *last_line);
-
-gboolean        mousepad_document_get_externally_modified  (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_can_undo             (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_can_redo             (MousepadDocument    *document);
-
-const gchar    *mousepad_document_get_filename             (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_has_selection        (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_modified             (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_readonly             (MousepadDocument    *document);
-
-GtkWidget      *mousepad_document_get_tab_label            (MousepadDocument    *document);
-
-const gchar    *mousepad_document_get_title                (MousepadDocument    *document,
-                                                            gboolean             show_full_path);
-
-gboolean        mousepad_document_get_word_wrap            (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_line_numbers         (MousepadDocument    *document);
-
-gboolean        mousepad_document_get_auto_indent          (MousepadDocument    *document);
-
-void            mousepad_document_undo                     (MousepadDocument    *document);
-
-void            mousepad_document_redo                     (MousepadDocument    *document);
-
 G_END_DECLS
 
 #endif /* !__MOUSEPAD_DOCUMENT_H__ */

Added: mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.c	                        (rev 0)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -0,0 +1,577 @@
+/* $Id$ */
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-document.h>
+#include <mousepad/mousepad-encoding-dialog.h>
+#include <mousepad/mousepad-preferences.h>
+#include <mousepad/mousepad-util.h>
+
+
+
+static void     mousepad_encoding_dialog_class_init             (MousepadEncodingDialogClass *klass);
+static void     mousepad_encoding_dialog_init                   (MousepadEncodingDialog      *dialog);
+static void     mousepad_encoding_dialog_finalize               (GObject                     *object);
+static gboolean mousepad_encoding_dialog_test_encodings_idle    (gpointer                     user_data);
+static void     mousepad_encoding_dialog_test_encodings_destroy (gpointer                     user_data);
+static void     mousepad_encoding_dialog_test_encodings         (MousepadEncodingDialog      *dialog);
+static void     mousepad_encoding_dialog_read_file              (MousepadEncodingDialog      *dialog,
+                                                                 const gchar                 *encoding);
+static void     mousepad_encoding_dialog_button_toggled         (GtkWidget                   *button,
+                                                                 MousepadEncodingDialog      *dialog);
+static void     mousepad_encoding_dialog_combo_changed          (GtkComboBox                 *combo,
+                                                                 MousepadEncodingDialog      *dialog);
+
+
+
+enum
+{
+  COLUMN_LABEL,
+  COLUMN_ID,
+  COLUMN_UNPRINTABLE,
+  N_COLUMNS
+};
+
+struct _MousepadEncodingDialogClass
+{
+  GtkDialogClass __parent__;
+};
+
+struct _MousepadEncodingDialog
+{
+  GtkDialog __parent__;
+
+  /* the file */
+  MousepadDocument *document;
+
+  /* encoding test idle id */
+  guint          encoding_id;
+
+  /* encoding test position */
+  gint           encoding_n;
+
+  /* ok button */
+  GtkWidget     *button_ok;
+
+  /* error label and box */
+  GtkWidget     *error_box;
+  GtkWidget     *error_label;
+
+  /* progressbar */
+  GtkWidget     *progress;
+
+  /* the three radio button */
+  GtkWidget     *radio_utf8;
+  GtkWidget     *radio_system;
+  GtkWidget     *radio_other;
+
+  /* other encodings combo box */
+  GtkListStore  *store;
+  GtkWidget     *combo;
+};
+
+
+
+static const gchar *encodings[] =
+{
+"ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6",
+"ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13",
+"ISO-8859-14", "ISO-8859-15", "ISO-8859-16",
+
+"ARMSCII-8",
+"ASCII",
+"BIG5",
+"BIG5-HKSCS",
+"BIG5-HKSCS:1999",
+"BIG5-HKSCS:2001",
+"C99", "IBM850", "CP862", "CP866", "CP874", "CP932", "CP936", "CP949", "CP950",
+"CP1133", "CP1250", "CP1251", "CP1252", "CP1253", "CP1254", "CP1255", "CP1256", "CP1257", "CP1258",
+"EUC-CN",
+"EUC-JP",
+"EUC-KR",
+"EUC-TW",
+"GB18030",
+"GBK",
+"Georgian-Academy",
+"Georgian-PS",
+"HP-ROMAN8",
+"HZ",
+"ISO-2022-CN",
+"ISO-2022-CN-EXT",
+"ISO-2022-JP",
+"ISO-2022-JP-1",
+"ISO-2022-JP-2",
+"ISO-2022-KR",
+
+
+
+"JAVA",
+"JOHAB",
+"KOI8-R",
+"KOI8-RU",
+"KOI8-T",
+"KOI8-U",
+"MacArabic",
+"MacCentralEurope",
+"MacCroatian",
+"MacGreek",
+"MacHebrew",
+"MacIceland",
+"Macintosh",
+"MacMacRoman",
+"MacRomania",
+"MacThai",
+"MacTurkish",
+"MacUkraine",
+"MacCyrillic",
+"MuleLao-1",
+"NEXTSTEP",
+"PT154",
+"SHIFT_JIS",
+"TCVN",
+"TIS-620,",
+"UCS-2",
+"UCS-2-INTERNAL",
+"UCS-2BE",
+"UCS-2LE",
+"UCS-4",
+"UCS-4-INTERNAL",
+"UCS-4BE",
+"UCS-4LE",
+"UTF-16",
+"UTF-16BE",
+"UTF-16LE",
+"UTF-32",
+"UTF-32BE",
+"UTF-32LE",
+"UTF-7",
+"UTF-8",
+"VISCII"
+};
+
+
+
+static GObjectClass *mousepad_encoding_dialog_parent_class;
+
+
+
+GType
+mousepad_encoding_dialog_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (GTK_TYPE_DIALOG,
+                                            I_("MousepadEncodingDialog"),
+                                            sizeof (MousepadEncodingDialogClass),
+                                            (GClassInitFunc) mousepad_encoding_dialog_class_init,
+                                            sizeof (MousepadEncodingDialog),
+                                            (GInstanceInitFunc) mousepad_encoding_dialog_init,
+                                            0);
+    }
+
+  return type;
+}
+
+
+
+static void
+mousepad_encoding_dialog_class_init (MousepadEncodingDialogClass *klass)
+{
+  GObjectClass   *gobject_class;
+
+  mousepad_encoding_dialog_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = mousepad_encoding_dialog_finalize;
+}
+
+
+
+static void
+mousepad_encoding_dialog_init (MousepadEncodingDialog *dialog)
+{
+  const gchar     *system_charset;
+  gchar           *system_label;
+  GtkWidget       *vbox, *hbox, *icon;
+  GtkCellRenderer *cell;
+
+  /* set some dialog properties */
+  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+  gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 350);
+
+  /* add buttons */
+  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+  dialog->button_ok = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+
+  /* create the header */
+  mousepad_util_dialog_header (GTK_DIALOG (dialog), _("The document was not UTF-8 valid"),
+                               _("Please select an encoding below."), GTK_STOCK_FILE);
+
+  /* dialog vbox */
+  vbox = gtk_vbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
+
+  hbox = gtk_hbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  /* encoding radio buttons */
+  dialog->radio_utf8 = gtk_radio_button_new_with_label (NULL, _("Default (UTF-8)"));
+  g_signal_connect (G_OBJECT (dialog->radio_utf8), "toggled", G_CALLBACK (mousepad_encoding_dialog_button_toggled), dialog);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_utf8, FALSE, FALSE, 0);
+  gtk_widget_show (dialog->radio_utf8);
+
+  g_get_charset (&system_charset);
+  system_label = g_strdup_printf ("%s (%s)", _("System"), system_charset);
+  dialog->radio_system = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (dialog->radio_utf8), system_label);
+  g_signal_connect (G_OBJECT (dialog->radio_system), "toggled", G_CALLBACK (mousepad_encoding_dialog_button_toggled), dialog);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_system, FALSE, FALSE, 0);
+  gtk_widget_show (dialog->radio_system);
+  g_free (system_label);
+
+  dialog->radio_other = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (dialog->radio_system), _("Other:"));
+  g_signal_connect (G_OBJECT (dialog->radio_other), "toggled", G_CALLBACK (mousepad_encoding_dialog_button_toggled), dialog);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_other, FALSE, FALSE, 0);
+
+  /* create store */
+  dialog->store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
+
+  /* combobox with other charsets */
+  dialog->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (dialog->store));
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->combo, TRUE, TRUE, 0);
+  g_signal_connect (G_OBJECT (dialog->combo), "changed", G_CALLBACK (mousepad_encoding_dialog_combo_changed), dialog);
+
+  /* text renderer for 1st column */
+  cell = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dialog->combo), cell, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (dialog->combo), cell, "text", COLUMN_LABEL, NULL);
+
+  /* progress bar */
+  dialog->progress = gtk_progress_bar_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->progress, TRUE, TRUE, 0);
+  gtk_progress_bar_set_text (GTK_PROGRESS_BAR (dialog->progress), "Testing encodings...");
+  gtk_widget_show (dialog->progress);
+
+  /* error box */
+  dialog->error_box = gtk_hbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (vbox), dialog->error_box, FALSE, FALSE, 0);
+
+  /* error icon */
+  icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_BUTTON);
+  gtk_box_pack_start (GTK_BOX (dialog->error_box), icon, FALSE, FALSE, 0);
+  gtk_widget_show (icon);
+
+  /* error label */
+  dialog->error_label = gtk_label_new (NULL);
+  gtk_box_pack_start (GTK_BOX (dialog->error_box), dialog->error_label, FALSE, FALSE, 0);
+  gtk_label_set_use_markup (GTK_LABEL (dialog->error_label), TRUE);
+  gtk_widget_show (dialog->error_label);
+
+  /* create text view */
+  dialog->document = mousepad_document_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (dialog->document), TRUE, TRUE, 0);
+  gtk_text_view_set_editable (GTK_TEXT_VIEW (dialog->document->textview), FALSE);
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (dialog->document->textview), FALSE);
+  mousepad_view_set_line_numbers (dialog->document->textview, FALSE);
+  mousepad_document_set_word_wrap (dialog->document, FALSE);
+  gtk_widget_show (GTK_WIDGET (dialog->document));
+
+  /* lock undo manager forever */
+  mousepad_undo_lock (dialog->document->undo);
+}
+
+
+
+static void
+mousepad_encoding_dialog_finalize (GObject *object)
+{
+  MousepadEncodingDialog *dialog = MOUSEPAD_ENCODING_DIALOG (object);
+
+  /* stop running timeout */
+  if (G_UNLIKELY (dialog->encoding_id))
+    g_source_remove (dialog->encoding_id);
+
+  /* clear and release store */
+  gtk_list_store_clear (dialog->store);
+  g_object_unref (G_OBJECT (dialog->store));
+
+  (*G_OBJECT_CLASS (mousepad_encoding_dialog_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+mousepad_encoding_dialog_test_encodings_idle (gpointer user_data)
+{
+  MousepadEncodingDialog *dialog = MOUSEPAD_ENCODING_DIALOG (user_data);
+  gdouble                 fraction;
+  gint                    unprintable, value;
+  const gchar            *encoding;
+  GtkTreeIter             iter, needle;
+
+  GDK_THREADS_ENTER ();
+
+  /* calculate the status */
+  fraction = (dialog->encoding_n + 1.00) / G_N_ELEMENTS (encodings);
+
+  /* set progress bar */
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (dialog->progress), fraction);
+
+  /* get the encoding */
+  encoding = encodings[dialog->encoding_n];
+
+  /* set an encoding */
+  unprintable = mousepad_file_test_encoding (dialog->document->file, encoding, NULL);
+
+  /* add the encoding to the combo box is the test succeed */
+  if (unprintable != -1)
+    {
+      /* get the first model iter, if there is one */
+      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->store), &needle))
+        {
+          while (TRUE)
+            {
+              /* get the column value */
+              gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), &needle, COLUMN_UNPRINTABLE, &value, -1);
+
+              /* insert before the item with a higher number of unprintable characters */
+              if (value > unprintable)
+                {
+                  gtk_list_store_insert_before (dialog->store, &iter, &needle);
+
+                  break;
+                }
+
+              /* leave when we reached the end of the tree */
+              if (gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->store), &needle) == FALSE)
+                goto append_to_list;
+            }
+        }
+      else
+        {
+          append_to_list:
+
+          /* append to the list */
+          gtk_list_store_append (dialog->store, &iter);
+        }
+
+      /* set the column data */
+      gtk_list_store_set (dialog->store, &iter,
+                          COLUMN_LABEL, encoding,
+                          COLUMN_ID, dialog->encoding_n,
+                          COLUMN_UNPRINTABLE, unprintable,
+                          -1);
+    }
+
+  /* advance offset */
+  dialog->encoding_n++;
+
+  /* show the widgets when we're done */
+  if (dialog->encoding_n == G_N_ELEMENTS (encodings))
+    {
+      /* select the first item */
+      gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combo), 0);
+
+      /* hide progress bar */
+      gtk_widget_hide (dialog->progress);
+
+      /* show the radio button and combo box */
+      gtk_widget_show (dialog->radio_other);
+      gtk_widget_show (dialog->combo);
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return (dialog->encoding_n < G_N_ELEMENTS (encodings));
+}
+
+
+
+static void
+mousepad_encoding_dialog_test_encodings_destroy (gpointer user_data)
+{
+  MOUSEPAD_ENCODING_DIALOG (user_data)->encoding_id = 0;
+}
+
+
+
+static void
+mousepad_encoding_dialog_test_encodings (MousepadEncodingDialog *dialog)
+{
+  if (G_LIKELY (dialog->encoding_id == 0))
+    {
+      /* reset counter */
+      dialog->encoding_n = 0;
+
+      /* start new idle function */
+      dialog->encoding_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, mousepad_encoding_dialog_test_encodings_idle,
+                                             dialog, mousepad_encoding_dialog_test_encodings_destroy);
+    }
+}
+
+
+
+static void
+mousepad_encoding_dialog_read_file (MousepadEncodingDialog *dialog,
+                                    const gchar            *encoding)
+{
+  GtkTextIter  start, end;
+  GError      *error = NULL;
+  gchar       *message;
+  gboolean     succeed;
+
+  /* clear buffer */
+  gtk_text_buffer_get_bounds (dialog->document->buffer, &start, &end);
+  gtk_text_buffer_delete (dialog->document->buffer, &start, &end);
+
+  /* set encoding */
+  mousepad_file_set_encoding (dialog->document->file, encoding);
+
+  /* try to open the file */
+  succeed = mousepad_file_open (dialog->document->file, &error);
+
+  /* set sensitivity of the ok button */
+  gtk_widget_set_sensitive (dialog->button_ok, succeed);
+
+  if (succeed)
+    {
+      /* no error, hide the box */
+      gtk_widget_hide (dialog->error_box);
+    }
+  else
+    {
+      /* format message */
+      message = g_strdup_printf ("<b>%s.</b>", error->message);
+
+      /* set the error label */
+      gtk_label_set_markup (GTK_LABEL (dialog->error_label), message);
+
+      /* cleanup */
+      g_free (message);
+
+      /* show the error box */
+      gtk_widget_show (dialog->error_box);
+
+      /* clear the error */
+      g_error_free (error);
+    }
+}
+
+
+
+static void
+mousepad_encoding_dialog_button_toggled (GtkWidget              *button,
+                                         MousepadEncodingDialog *dialog)
+{
+  const gchar *system_charset;
+
+  /* ignore inactive buttons */
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+    {
+      /* set sensitivity of the other combobox */
+      gtk_widget_set_sensitive (dialog->combo, (button == dialog->radio_other));
+
+      if (button == dialog->radio_utf8)
+        {
+          /* open the file */
+          mousepad_encoding_dialog_read_file (dialog, NULL);
+        }
+      else if (button == dialog->radio_system)
+        {
+          /* get the system charset */
+          g_get_charset (&system_charset);
+
+          /* open the file */
+          mousepad_encoding_dialog_read_file (dialog, system_charset);
+        }
+      else
+        {
+          /* poke function */
+          mousepad_encoding_dialog_combo_changed (GTK_COMBO_BOX (dialog->combo), dialog);
+        }
+    }
+}
+
+
+
+static void
+mousepad_encoding_dialog_combo_changed (GtkComboBox            *combo,
+                                        MousepadEncodingDialog *dialog)
+{
+  GtkTreeIter iter;
+  gint        id;
+
+  /* get the selected item */
+  if (GTK_WIDGET_SENSITIVE (combo) && gtk_combo_box_get_active_iter (combo, &iter))
+    {
+      /* get the id */
+      gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), &iter, COLUMN_ID, &id, -1);
+
+      /* open the file with other encoding */
+      mousepad_encoding_dialog_read_file (dialog, encodings[id]);
+    }
+}
+
+
+
+GtkWidget *
+mousepad_encoding_dialog_new (GtkWindow    *parent,
+                              MousepadFile *file)
+{
+  MousepadEncodingDialog *dialog;
+
+  _mousepad_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), NULL);
+
+  /* create the dialog */
+  dialog = g_object_new (MOUSEPAD_TYPE_ENCODING_DIALOG, NULL);
+
+  /* set parent window */
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+  /* set the filename */
+  mousepad_file_set_filename (dialog->document->file, mousepad_file_get_filename (file));
+
+  /* start with the system encoding */
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radio_system), TRUE);
+
+  /* queue idle function */
+  mousepad_encoding_dialog_test_encodings (dialog);
+
+  return GTK_WIDGET (dialog);
+}
+
+
+
+const gchar *
+mousepad_encoding_dialog_get_encoding (MousepadEncodingDialog *dialog)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_ENCODING_DIALOG (dialog), NULL);
+
+  return mousepad_file_get_encoding (dialog->document->file);
+}


Property changes on: mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.c
___________________________________________________________________
Name: keywords
   + Id

Added: mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.h
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.h	                        (rev 0)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.h	2007-10-16 20:01:37 UTC (rev 26134)
@@ -0,0 +1,42 @@
+/* $Id$ */
+/*
+ * 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_ENCODING_DIALOG_H__
+#define __MOUSEPAD_ENCODING_DIALOG_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_ENCODING_DIALOG            (mousepad_encoding_dialog_get_type ())
+#define MOUSEPAD_ENCODING_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_ENCODING_DIALOG, MousepadEncodingDialog))
+#define MOUSEPAD_ENCODING_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_ENCODING_DIALOG, MousepadEncodingDialogClass))
+#define MOUSEPAD_IS_ENCODING_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_ENCODING_DIALOG))
+#define MOUSEPAD_IS_ENCODING_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_ENCODING_DIALOG))
+#define MOUSEPAD_ENCODING_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_ENCODING_DIALOG, MousepadEncodingDialogClass))
+
+typedef struct _MousepadEncodingDialogClass MousepadEncodingDialogClass;
+typedef struct _MousepadEncodingDialog      MousepadEncodingDialog;
+
+GType        mousepad_encoding_dialog_get_type     (void) G_GNUC_CONST;
+
+GtkWidget   *mousepad_encoding_dialog_new          (GtkWindow              *parent,
+                                                    MousepadFile           *file);
+
+const gchar *mousepad_encoding_dialog_get_encoding (MousepadEncodingDialog *dialog);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_ENCODING_DIALOG_H__ */


Property changes on: mousepad/branches/nick_0_3/mousepad/mousepad-encoding-dialog.h
___________________________________________________________________
Name: keywords
   + Id

Modified: mousepad/branches/nick_0_3/mousepad/mousepad-file.c
===================================================================
--- mousepad/branches/nick_0_3/mousepad/mousepad-file.c	2007-10-15 19:36:09 UTC (rev 26133)
+++ mousepad/branches/nick_0_3/mousepad/mousepad-file.c	2007-10-16 20:01:37 UTC (rev 26134)
@@ -19,375 +19,627 @@
 #include <config.h>
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
 #endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 
+#include <glib.h>
+#include <glib/gstdio.h>
+
 #include <mousepad/mousepad-private.h>
 #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)
+#define MAX_ENCODING_CHECK_CHARS       (10000)
+#define MOUSEPAD_GET_LINE_END_CHARS(a) ((a) == MOUSEPAD_LINE_END_WIN32 ? "\r\n\0" : ((a) == MOUSEPAD_LINE_END_MAC ? "\r\0" : "\n\0"))
+
+
+enum
 {
-  gint         fd;
-  struct stat  statb;
-  gboolean     modified = FALSE;
+  EXTERNALLY_MODIFIED,
+  FILENAME_CHANGED,
+  LAST_SIGNAL
+};
 
-  _mousepad_return_val_if_fail (filename != NULL, TRUE);
+struct _MousepadFileClass
+{
+  GObjectClass __parent__;
+};
 
-  /* open the file for reading */
-  fd = open (filename, O_RDONLY);
-  if (G_UNLIKELY (fd < 0))
+struct _MousepadFile
+{
+  GObject             __parent__;
+
+  /* the text buffer this file belongs to */
+  GtkTextBuffer      *buffer;
+
+  /* filename */
+  gchar              *filename;
+
+  /* encoding of the file */
+  gchar              *encoding;
+
+  /* line ending of the file */
+  MousepadLineEnding  line_ending;
+
+  /* our last modification time */
+  gint                mtime;
+
+  /* if file is read-only */
+  guint               readonly : 1;
+};
+
+
+
+static void  mousepad_file_class_init       (MousepadFileClass  *klass);
+static void  mousepad_file_init             (MousepadFile       *file);
+static void  mousepad_file_finalize         (GObject            *object);
+
+
+
+static GObjectClass *mousepad_file_parent_class;
+static guint         file_signals[LAST_SIGNAL];
+
+
+
+GType
+mousepad_file_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
     {
-      /* files probably doesn't exists, so we can safely write */
-      return FALSE;
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            I_("MousepadFile"),
+                                            sizeof (MousepadFileClass),
+                                            (GClassInitFunc) mousepad_file_class_init,
+                                            sizeof (MousepadFile),
+                                            (GInstanceInitFunc) mousepad_file_init,
+                                            0);
     }
 
-  /* check if the file has been modified */
-  if (G_LIKELY (fstat (fd, &statb) == 0))
-    modified = (mtime > 0 && statb.st_mtime != mtime);
+  return type;
+}
 
-  /* close the file */
-  close (fd);
 
-  return modified;
+
+static void
+mousepad_file_class_init (MousepadFileClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  mousepad_file_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = mousepad_file_finalize;
+
+  file_signals[EXTERNALLY_MODIFIED] =
+    g_signal_new (I_("externally-modified"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_NO_HOOKS,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__BOOLEAN,
+                  G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+  file_signals[FILENAME_CHANGED] =
+    g_signal_new (I_("filename-changed"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_NO_HOOKS,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__STRING,
+                  G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 
 
-/**
- * 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.
- **/
+static void
+mousepad_file_init (MousepadFile *file)
+{
+  /* initialize */
+  file->filename    = NULL;
+  file->encoding    = NULL;
+  file->line_ending = MOUSEPAD_LINE_END_NONE;
+  file->readonly    = FALSE;
+  file->mtime       = 0;
+}
+
+
+
+static void
+mousepad_file_finalize (GObject *object)
+{
+  MousepadFile *file = MOUSEPAD_FILE (object);
+
+  /* cleanup */
+  g_free (file->filename);
+  g_free (file->encoding);
+
+  /* release the reference from the buffer */
+  g_object_unref (G_OBJECT (file->buffer));
+
+  (*G_OBJECT_CLASS (mousepad_file_parent_class)->finalize) (object);
+}
+
+
+
+MousepadFile *
+mousepad_file_new (GtkTextBuffer *buffer)
+{
+  MousepadFile *file;
+
+  _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+  file = g_object_new (MOUSEPAD_TYPE_FILE, NULL);
+
+  /* set the buffer */
+  file->buffer = g_object_ref (G_OBJECT (buffer));
+
+  return file;
+}
+
+
+
+void
+mousepad_file_set_filename (MousepadFile *file,
+                            const gchar  *filename)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_FILE (file));
+
+  /* free the old filename */
+  g_free (file->filename);
+
+  /* set the filename */
+  file->filename = g_strdup (filename);
+
+  /* send a signal that the name has been changed */
+  g_signal_emit (G_OBJECT (file), file_signals[FILENAME_CHANGED], 0, file->filename);
+}
+
+
+
+const gchar *
+mousepad_file_get_filename (MousepadFile *file)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), NULL);
+
+  return file->filename;
+}
+
+
+
+gchar *
+mousepad_file_get_uri (MousepadFile *file)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), NULL);
+
+  return g_filename_to_uri (file->filename, NULL, NULL);
+}
+
+
+
+void
+mousepad_file_set_encoding (MousepadFile *file,
+                            const gchar  *encoding)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_FILE (file));
+
+  /* cleanup */
+  g_free (file->encoding);
+
+  /* set new encoding */
+  file->encoding = g_strdup (encoding);
+}
+
+
+
+const gchar *
+mousepad_file_get_encoding (MousepadFile *file)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), NULL);
+
+  return file->encoding ? file->encoding : "UTF-8";
+}
+
+
+
+void
+mousepad_file_set_line_ending (MousepadFile       *file,
+                               MousepadLineEnding  line_ending)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_FILE (file));
+
+  file->line_ending = line_ending;
+}
+
+
+
+MousepadLineEnding
+mousepad_file_get_line_ending (MousepadFile *file)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), MOUSEPAD_LINE_END_NONE);
+
+  return file->line_ending;
+}
+
+
+
 gboolean
-mousepad_file_save_data (const gchar  *filename,
-                         const gchar  *data,
-                         gsize         bytes,
-                         gint         *new_mtime,
-                         GError      **error)
+mousepad_file_open (MousepadFile  *file,
+                    GError       **error)
 {
-  gint         fd;
+  GIOChannel  *channel;
+  GIOStatus    status;
+  gsize        length, terminator_pos;
+  gboolean     succeed = FALSE;
+  gchar       *string;
+  const gchar *line_term;
+  GtkTextIter  start, end;
   struct stat  statb;
-  gboolean     succeed = FALSE;
-  gint         n, m, l;
 
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_FILE (file), FALSE);
+  _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (file->buffer), FALSE);
   _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-  _mousepad_return_val_if_fail (filename != NULL, FALSE);
-  _mousepad_return_val_if_fail (data != NULL, FALSE);
+  _mousepad_return_val_if_fail (file->filename != NULL, FALSE);
 
-  /* try to create the file (this failes if it already exists) */
-  fd = open (filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
-  if (fd < 0)
+  /* check if the file exists */
+  if (g_file_test (file->filename, G_FILE_TEST_EXISTS) == FALSE)
+    return TRUE;
+
+  /* open the channel */
+  channel = g_io_channel_new_file (file->filename, "r", error);
+
+  if (G_LIKELY (channel))
     {
-      if (G_LIKELY (errno == EEXIST))
+      /* freeze notifications */
+      g_object_freeze_notify (G_OBJECT (file->buffer));
+
+      /* set the encoding of the channel */
+      if (file->encoding != NULL)
         {
-          /* try to open an existing file for reading */
-          fd = open (filename, O_RDWR);
-          if (G_UNLIKELY (fd < 0))
-            {
-              g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
-                           _("Failed to open \"%s\" for writing"), filename);
-              return FALSE;
-             }
+          /* set the encoding */
+          status = g_io_channel_set_encoding (channel, file->encoding, error);
+
+          if (G_UNLIKELY (status != G_IO_STATUS_NORMAL))
+            goto failed;
         }
-      else
+
+      /* get the iter at the beginning of the document */
+      gtk_text_buffer_get_start_iter (file->buffer, &end);
+
+      /* read the content of the file */
+      while (TRUE)
         {
-          /* failed to create a file */
-          g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                       _("Failed to create new file \"%s\""), filename);
-          return FALSE;
-        }
-    }
+          /* read the line */
+          status = g_io_channel_read_line (channel, &string, &length, &terminator_pos, error);
 
-  /* get the file information */
-  if (G_UNLIKELY (fstat (fd, &statb) != 0))
-    goto failed;
+          /* leave on problems */
+          if (G_UNLIKELY (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_EOF))
+            goto failed;
 
-  /* an extra check if we are allowed to write */
-  if (G_UNLIKELY ((statb.st_mode & 00222) == 0 && access (filename, W_OK) != 0))
-    {
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("You don't have permission to write to \"%s\""), filename);
-      goto failed;
-    }
+          if (G_LIKELY (string))
+            {
+              /* detect the line ending of the file */
+              if (length != terminator_pos
+                  && file->line_ending == MOUSEPAD_LINE_END_NONE)
+                {
+                  /* get the characters */
+                  line_term = string + terminator_pos;
 
-  /* make sure the document is empty and we're writing at the beginning of the file */
-  if (G_LIKELY (lseek (fd, 0, SEEK_SET) != -1))
-    if (G_UNLIKELY (ftruncate (fd, 0) != 0))
-      {
-        g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                     _("Failed to truncate \"%s\" before writing"), filename);
-        goto failed;
-      }
+                  if (strcmp (line_term, "\n") == 0)
+                    file->line_ending = MOUSEPAD_LINE_END_UNIX;
+                  else if (strcmp (line_term, "\r") == 0)
+                    file->line_ending = MOUSEPAD_LINE_END_MAC;
+                  else if (strcmp (line_term, "\r\n") == 0)
+                    file->line_ending = MOUSEPAD_LINE_END_WIN32;
+                  else
+                    g_warning (_("Unknown line ending detected (%s)"), line_term);
+                }
 
-  /* write the content to the file */
-  for (m = 0, n = bytes; m < n; )
-    {
-      /* write the data piece by piece */
-      l = write (fd, data + m, n - m);
+              /* make sure the string utf-8 valid */
+              if (G_UNLIKELY (g_utf8_validate (string, length, NULL) == FALSE))
+                {
+                  /* set an error */
+                  g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
+                               _("Converted string is not UTF-8 valid"));
 
-      if (G_UNLIKELY (l < 0))
-        {
-          /* just try again on EAGAIN/EINTR */
-          if (G_LIKELY (errno != EAGAIN && errno != EINTR))
-            {
-              g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                           _("Failed to write data to \"%s\""), filename);
-              goto failed;
+                  /* free string */
+                  g_free (string);
+
+                  goto failed;
+                }
+
+              /* insert the string in the buffer */
+              gtk_text_buffer_insert (file->buffer, &end, string, length);
+
+              /* cleanup */
+              g_free (string);
             }
+
+          /* break when we've reached the end of the file */
+          if (G_UNLIKELY (status == G_IO_STATUS_EOF))
+            break;
         }
-      else
+
+      /* done */
+      succeed = TRUE;
+
+      /* get the start iter */
+      gtk_text_buffer_get_start_iter (file->buffer, &start);
+
+      /* set the cursor to the beginning of the document */
+      gtk_text_buffer_place_cursor (file->buffer, &start);
+
+      /* check if we're allowed to write to the file */
+      if (G_LIKELY (g_lstat (file->filename, &statb) == 0) && access (file->filename, W_OK) == 0)
+        file->readonly = !((statb.st_mode & 00222) != 0);
+
+      failed:
+
+      /* empty the buffer if we did not succeed */
+      if (G_UNLIKELY (succeed == FALSE))
         {
-          /* advance the offset */
-          m += l;
+          gtk_text_buffer_get_bounds (file->buffer, &start, &end);
+          gtk_text_buffer_delete (file->buffer, &start, &end);
         }
-    }
 
-  /* re-stat the mtime */
-  if (G_UNLIKELY (fstat (fd, &statb) == 0))
-    *new_mtime = statb.st_mtime;
+      /* this does not count as a modified buffer */
+      gtk_text_buffer_set_modified (file->buffer, FALSE);
 
-  /* mm.. it seems everything worked fine */
-  succeed = TRUE;
+      /* thawn notifications */
+      g_object_thaw_notify (G_OBJECT (file->buffer));
 
-failed:
-  /* close the file */
-  close (fd);
+      /* close the channel and flush the write buffer */
+      g_io_channel_shutdown (channel, TRUE, NULL);
 
+      /* release the channel */
+      g_io_channel_unref (channel);
+    }
+
   return succeed;
 }
 
 
 
-/**
- * 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: %T