Updating branch refs/heads/master
         to ec1234c58d36457576ea554ac2fd5885da962fd7 (commit)
       from fe666120450ea8df11059d60c0bcdb806d3d5426 (commit)

commit ec1234c58d36457576ea554ac2fd5885da962fd7
Author: Nick Schermer <n...@xfce.org>
Date:   Wed Apr 11 08:22:46 2007 +0000

        * mousepad/mousepad-{document,window,statusbar}: You can now click the 
OVR
          text in the statusbar to toggle the overwrite mode.
        * mousepad/mousepad-{document,window,undo}: Initial version of an undo
          manager. This is not finished yet, but it's a start.
        * mousepad/Makefile.am, mousepad/mousepad-csource.pl: Remove my perl 
script
          because it has some problems. Use exo-csource instead.
        * Remove some empty object functions.
    
    (Old svn revision: 25514)

 ChangeLog                       |   10 +
 configure.in.in                 |   11 +
 mousepad/Makefile.am            |   17 +-
 mousepad/mousepad-csource.pl    |   90 ------
 mousepad/mousepad-document.c    |  138 +++++++++-
 mousepad/mousepad-document.h    |   11 +
 mousepad/mousepad-private.h     |    1 +
 mousepad/mousepad-search-bar.c  |    9 +-
 mousepad/mousepad-statusbar.c   |   72 ++++-
 mousepad/mousepad-undo.c        |  592 +++++++++++++++++++++++++++++++++++++++
 mousepad/mousepad-undo.h        |   57 ++++
 mousepad/mousepad-view.c        |   24 +--
 mousepad/mousepad-window-ui.xml |    2 +
 mousepad/mousepad-window.c      |   92 ++++++-
 14 files changed, 984 insertions(+), 142 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f4f4ef9..2e8dbf5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-04-xx     Nick Schermer <n...@xfce.org>
+       * mousepad/mousepad-{document,window,statusbar}: You can now click the 
OVR
+         text in the statusbar to toggle the overwrite mode.
+       * mousepad/mousepad-{document,window,undo}: Initial version of an undo
+         manager. This is not finished yet, but it's a start.
+       * mousepad/Makefile.am, mousepad/mousepad-csource.pl: Remove my perl 
script
+         because it has some problems. Use exo-csource instead.
+       * Remove some empty object functions.
+
+
 2007-04-06     Nick Schermer <n...@xfce.org>
        * mousepad/mousepad-document.c: Fix segfault from previous commit.
        * mousepad/mousepad-document.c: Fix bug in searching backwards, we have 
to
diff --git a/configure.in.in b/configure.in.in
index 272e528..4ae2f42 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -110,6 +110,12 @@ XDT_CHECK_OPTIONAL_PACKAGE([LIBSTARTUP_NOTIFICATION],
                            [0.4], [startup-notification],
                            [startup notification library])
 
+dnl *******************************************************
+dnl *** Optional support for unix print support in GTK+ ***
+dnl *******************************************************
+XDT_CHECK_OPTIONAL_PACKAGE([GTK_UNIX_PRINT], [gtk+-unix-print-2.0],
+                           [2.10.0], [gtk_unix_print], [GTK+ Unix print 
support])
+
 dnl *************************
 dnl *** Check for gtk-doc ***
 dnl *************************
@@ -234,4 +240,9 @@ echo "* Startup Notification:      yes"
 else
 echo "* Startup Notification:      no"
 fi
+if test x"$GTK_UNIX_PRINT_FOUND" = x"yes"; then
+echo "* GTK+ Unix Print Support:   yes"
+else
+echo "* GTK+ Unix Print Support:   no"
+fi
 echo
diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
index 429aa9f..9ec9015 100644
--- a/mousepad/Makefile.am
+++ b/mousepad/Makefile.am
@@ -46,13 +46,15 @@ mousepad_SOURCES =                                          
                \
        mousepad-statusbar.h                                                    
\
        mousepad-view.c                                                         
\
        mousepad-view.h                                                         
\
+       mousepad-undo.c                                                         
\
+       mousepad-undo.h                                                         
\
        mousepad-window.c                                                       
\
        mousepad-window.h                                                       
\
        mousepad-window-ui.h
 
 mousepad_CFLAGS =                                                              
\
        $(GTK_CFLAGS)                                                           
\
-       $(LIBXFCE4UTIL_CFLAGS) \
+       $(LIBXFCE4UTIL_CFLAGS)                                                  
\
        $(GMODULE_CFLAGS)                                                       
\
        $(GTHREAD_CFLAGS)                                                       
\
        $(PLATFORM_CFLAGS)
@@ -63,7 +65,7 @@ mousepad_LDFLAGS =                                            
                \
 
 mousepad_LDADD =                                                               
\
        $(GTK_LIBS)                                                             
\
-       $(LIBXFCE4UTIL_LIBS) \
+       $(LIBXFCE4UTIL_LIBS)                                                    
\
        $(GMODULE_LIBS)                                                         
\
        $(GTHREAD_LIBS)
 
@@ -83,6 +85,14 @@ mousepad_LDADD +=                                            
                \
        $(DBUS_LIBS)
 endif
 
+if HAVE_GTK_UNIX_PRINT
+mousepad_CFLAGS +=                                                             
\
+       $(GTK_UNIX_PRINT_CFLAGS)
+
+mousepad_LDADD +=                                                              
\
+       $(GTK_UNIX_PRINT_LIBS)
+endif
+
 if MAINTAINER_MODE
 CLEANFILES =                                                                   
\
        xgen-mmc                                                                
\
@@ -106,7 +116,7 @@ mousepad-dbus-infos.h: $(srcdir)/mousepad-dbus-infos.xml 
Makefile
 endif
 
 mousepad-window-ui.h: Makefile $(srcdir)/mousepad-window-ui.xml
-       $(PERL) $(srcdir)/mousepad-csource.pl mousepad_window_ui < 
$(srcdir)/mousepad-window-ui.xml > mousepad-window-ui.h
+       exo-csource --static --name=mousepad_window_ui 
$(srcdir)/mousepad-window-ui.xml > mousepad-window-ui.h
 
 mousepad-enum-types.h: stamp-mousepad-enum-types.h
        @true
@@ -150,7 +160,6 @@ mousepad-marshal.c: mousepad-marshal.list Makefile
 endif
 
 EXTRA_DIST =                                                                   
\
-       mousepad-csource.pl                                                     
\
        mousepad-dbus-infos.xml                                                 
\
        mousepad-marshal.list                                                   
\
        mousepad-window-ui.xml
diff --git a/mousepad/mousepad-csource.pl b/mousepad/mousepad-csource.pl
deleted file mode 100755
index 71bd2f9..0000000
--- a/mousepad/mousepad-csource.pl
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env perl -w
-#
-# $Id$
-#
-# Copyright (c) 2007 Nick Schermer <n...@xfce.org>
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the Free
-# Software Foundation; either version 2 of the License, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-# Place, Suite 330, Boston, MA  02111-1307  USA
-#
-
-if ($#ARGV < 0)
-  {
-    print ("No variable name defined. Exiting...");
-    exit;
-  }
-
-# get the variable name
-my $varname = $ARGV[0];
-shift;
-
-# init
-my $max_column = 70;
-my $result;
-my $line ;
-
-# walk though the lines, strip when and append the result
-while (<>)
-  {
-    # ignore empty lines
-    next if /^\s*$/;
-
-    # skip comments
-    if ($_ =~ '<!--')
-      {
-        $in_comment = 1;
-      }
-
-    if ($in_comment)
-      {
-        if ($_ =~ '-->')
-          {
-            $in_comment = 0;
-          }
-        next;
-      }
-
-    $line = $_;
-
-    # strip the code before and after the xml block
-    $line =~ s/.*</</g;
-    $line =~ s/>.*\n/>/g;
-
-    # append the striped line to the result
-    $result .= $line;
-  }
-
-# start of the file
-print  "static const unsigned int ". $varname ."_length = ". length ($result) 
.";\n\n".
-       "#ifdef __SUNPRO_C\n".
-       "#pragma align 4 (". $varname .")\n".
-       "#endif\n".
-       "#ifdef __GNUC__\n".
-       "static const char ". $varname ."[] __attribute__ ((__aligned__ (4))) 
=\n".
-       "#else\n".
-       "static const char ". $varname ."[] =\n".
-       "#endif\n".
-       "{\n";
-
-# escape the comments
-$result =~ s/\"/\\"/g;
-
-# print the content of the xml file
-for ($i = 0; $i < length ($result); $i = $i + $max_column)
-  {
-    print "  \"" . substr ($result, $i, $max_column) . "\"\n";
-  }
-
-# close
-print  "};\n\n";
diff --git a/mousepad/mousepad-document.c b/mousepad/mousepad-document.c
index 5802f1c..035db81 100644
--- a/mousepad/mousepad-document.c
+++ b/mousepad/mousepad-document.c
@@ -40,17 +40,20 @@
 #include <mousepad/mousepad-file.h>
 #include <mousepad/mousepad-marshal.h>
 #include <mousepad/mousepad-view.h>
+#include <mousepad/mousepad-undo.h>
 #include <mousepad/mousepad-window.h>
 
 
 
-#define DEFAULT_SEARCH_FLAGS  (GTK_TEXT_SEARCH_VISIBLE_ONLY | 
GTK_TEXT_SEARCH_TEXT_ONLY)
-
-
-
 static void      mousepad_document_class_init              
(MousepadDocumentClass  *klass);
 static void      mousepad_document_init                    (MousepadDocument   
    *document);
 static void      mousepad_document_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,
@@ -74,7 +77,6 @@ static void      mousepad_document_tab_button_clicked      
(GtkWidget
                                                             MousepadDocument   
    *document);
 
 
-
 enum
 {
   CLOSE_TAB,
@@ -82,6 +84,8 @@ enum
   MODIFIED_CHANGED,
   CURSOR_CHANGED,
   OVERWRITE_CHANGED,
+  CAN_UNDO,
+  CAN_REDO,
   LAST_SIGNAL,
 };
 
@@ -98,6 +102,9 @@ struct _MousepadDocument
   GtkTextView       *textview;
   GtkTextBuffer     *buffer;
 
+  /* the undo manager */
+  MousepadUndo      *undo;
+
   /* the highlight tag */
   GtkTextTag        *tag;
 
@@ -205,6 +212,22 @@ mousepad_document_class_init (MousepadDocumentClass *klass)
                   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);
 }
 
 
@@ -226,6 +249,15 @@ mousepad_document_init (MousepadDocument *document)
   /* create a textbuffer */
   document->buffer = gtk_text_buffer_new (NULL);
 
+  /* 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);
 
@@ -243,6 +275,8 @@ mousepad_document_init (MousepadDocument *document)
                     G_CALLBACK (mousepad_document_notify_cursor_position), 
document);
   g_signal_connect (G_OBJECT (document->textview), "notify::overwrite",
                     G_CALLBACK (mousepad_document_toggle_overwrite), document);
+  g_signal_connect (G_OBJECT (document->textview), "populate-popup",
+                    G_CALLBACK (mousepad_undo_populate_popup), document->undo);
 }
 
 
@@ -256,6 +290,9 @@ mousepad_document_finalize (GObject *object)
   g_free (document->filename);
   g_free (document->display_name);
 
+  /* release the undo manager */
+  g_object_unref (G_OBJECT (document->undo));
+
   /* release our reference from the buffer */
   g_object_unref (G_OBJECT (document->buffer));
 
@@ -265,6 +302,32 @@ mousepad_document_finalize (GObject *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)
 {
@@ -507,6 +570,17 @@ mousepad_document_set_line_numbers (MousepadDocument 
*document,
 
 
 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);
+}
+
+
+
+void
 mousepad_document_set_word_wrap (MousepadDocument *document,
                                  gboolean          word_wrap)
 {
@@ -557,6 +631,9 @@ mousepad_document_open_file (MousepadDocument  *document,
   /* 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,
@@ -583,6 +660,9 @@ mousepad_document_open_file (MousepadDocument  *document,
       succeed = TRUE;
     }
 
+  /* unlock the undo manager */
+  mousepad_undo_unlock (document->undo);
+
   /* and we're done */
   gtk_text_buffer_end_user_action (document->buffer);
 
@@ -973,6 +1053,26 @@ mousepad_document_get_externally_modified 
(MousepadDocument *document)
 
 
 
+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)
 {
@@ -1145,3 +1245,31 @@ mousepad_document_get_auto_indent (MousepadDocument 
*document)
 
   return document->auto_indent;
 }
+
+
+
+void
+mousepad_document_undo (MousepadDocument *document)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+  /* undo */
+  mousepad_undo_do_undo (document->undo);
+
+  /* scroll to visible area */
+  mousepad_document_scroll_to_visible_area (document);
+}
+
+
+
+void
+mousepad_document_redo (MousepadDocument *document)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+  /* redo */
+  mousepad_undo_do_redo (document->undo);
+
+  /* scroll to visible area */
+  mousepad_document_scroll_to_visible_area (document);
+}
diff --git a/mousepad/mousepad-document.h b/mousepad/mousepad-document.h
index c390a91..fe4ba64 100644
--- a/mousepad/mousepad-document.h
+++ b/mousepad/mousepad-document.h
@@ -57,6 +57,9 @@ void            mousepad_document_set_auto_indent          
(MousepadDocument
 void            mousepad_document_set_line_numbers         (MousepadDocument   
 *document,
                                                             gboolean           
  line_numbers);
 
+void            mousepad_document_set_overwrite            (MousepadDocument   
 *document,
+                                                            gboolean           
  overwrite);
+
 void            mousepad_document_set_word_wrap            (MousepadDocument   
 *document,
                                                             gboolean           
  word_wrap);
 
@@ -97,6 +100,10 @@ void            mousepad_document_line_numbers             
(MousepadDocument
 
 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);
@@ -116,6 +123,10 @@ gboolean        mousepad_document_get_line_numbers         
(MousepadDocument
 
 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__ */
diff --git a/mousepad/mousepad-private.h b/mousepad/mousepad-private.h
index e0455b4..b70e0de 100644
--- a/mousepad/mousepad-private.h
+++ b/mousepad/mousepad-private.h
@@ -21,6 +21,7 @@
 #ifndef __MOUSEPAD_PRIVATE_H__
 #define __MOUSEPAD_PRIVATE_H__
 
+#include <glib-object.h>
 #include <gtk/gtk.h>
 #include <libxfce4util/libxfce4util.h>
 
diff --git a/mousepad/mousepad-search-bar.c b/mousepad/mousepad-search-bar.c
index 46e197c..a0dc8e2 100644
--- a/mousepad/mousepad-search-bar.c
+++ b/mousepad/mousepad-search-bar.c
@@ -445,9 +445,12 @@ mousepad_search_bar_match_case_toggled (GtkWidget         
*button,
   /* save the setting */
   g_object_set (G_OBJECT (search_bar->preferences), "last-match-case", active, 
NULL);
 
-  /* invoke the highlight function to update the buffer */
-  search_bar->highlight_id = g_idle_add_full (G_PRIORITY_LOW, 
mousepad_search_bar_highlight_timeout,
-                                              search_bar, 
mousepad_search_bar_highlight_timeout_destroy);
+  if (search_bar->highlight_all)
+    {
+      /* invoke the highlight function to update the buffer */
+      search_bar->highlight_id = g_idle_add_full (G_PRIORITY_LOW, 
mousepad_search_bar_highlight_timeout,
+                                                  search_bar, 
mousepad_search_bar_highlight_timeout_destroy);
+    }
 }
 
 
diff --git a/mousepad/mousepad-statusbar.c b/mousepad/mousepad-statusbar.c
index 43a879a..e75b0b1 100644
--- a/mousepad/mousepad-statusbar.c
+++ b/mousepad/mousepad-statusbar.c
@@ -24,9 +24,21 @@
 #include <mousepad/mousepad-private.h>
 #include <mousepad/mousepad-statusbar.h>
 
+
+
 static void              mousepad_statusbar_class_init                
(MousepadStatusbarClass *klass);
 static void              mousepad_statusbar_init                      
(MousepadStatusbar      *statusbar);
-static void              mousepad_statusbar_finalize                  (GObject 
               *object);
+static gboolean          mousepad_statusbar_overwrite_clicked         
(GtkWidget              *widget,
+                                                                       
GdkEventButton         *event,
+                                                                       
MousepadStatusbar      *statusbar);
+
+
+
+enum
+{
+  ENABLE_OVERWRITE,
+  LAST_SIGNAL,
+};
 
 struct _MousepadStatusbarClass
 {
@@ -37,6 +49,9 @@ struct _MousepadStatusbar
 {
   GtkHBox             __parent__;
 
+  /* whether overwrite is enabled */
+  guint               overwrite_enabled : 1;
+
   /* the three statusbar labels */
   GtkWidget          *label;
   GtkWidget          *position;
@@ -45,7 +60,7 @@ struct _MousepadStatusbar
 
 
 
-static GObjectClass *mousepad_statusbar_parent_class;
+static guint statusbar_signals[LAST_SIGNAL];
 
 
 
@@ -83,10 +98,15 @@ mousepad_statusbar_class_init (MousepadStatusbarClass 
*klass)
 {
   GObjectClass *gobject_class;
 
-  mousepad_statusbar_parent_class = g_type_class_peek_parent (klass);
-
   gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = mousepad_statusbar_finalize;
+
+  statusbar_signals[ENABLE_OVERWRITE] =
+    g_signal_new (I_("enable-overwrite"),
+                  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);
 }
 
 
@@ -94,7 +114,7 @@ mousepad_statusbar_class_init (MousepadStatusbarClass *klass)
 static void
 mousepad_statusbar_init (MousepadStatusbar *statusbar)
 {
-  GtkWidget *frame;
+  GtkWidget *frame, *ebox;
 
   /* spacing between the 3 frames */
   gtk_box_set_spacing (GTK_BOX (statusbar), 3);
@@ -108,7 +128,7 @@ mousepad_statusbar_init (MousepadStatusbar *statusbar)
   statusbar->label = gtk_label_new (NULL);
   gtk_label_set_single_line_mode (GTK_LABEL (statusbar->label), TRUE);
   gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.5);
-  gtk_misc_set_padding (GTK_MISC (statusbar->label), 2, 2);
+  gtk_misc_set_padding (GTK_MISC (statusbar->label), 4, 2);
   gtk_label_set_ellipsize (GTK_LABEL (statusbar->label), PANGO_ELLIPSIZE_END);
   gtk_container_add (GTK_CONTAINER (frame), statusbar->label);
   gtk_widget_show (statusbar->label);
@@ -121,7 +141,7 @@ mousepad_statusbar_init (MousepadStatusbar *statusbar)
 
   statusbar->position = gtk_label_new (NULL);
   gtk_container_add (GTK_CONTAINER (frame), statusbar->position);
-  gtk_misc_set_padding (GTK_MISC (statusbar->position), 2, 2);
+  gtk_misc_set_padding (GTK_MISC (statusbar->position), 4, 2);
   gtk_widget_show (statusbar->position);
 
   /* overwrite */
@@ -130,18 +150,38 @@ mousepad_statusbar_init (MousepadStatusbar *statusbar)
   gtk_box_pack_start (GTK_BOX (statusbar), frame, FALSE, FALSE, 0);
   gtk_widget_show (frame);
 
-  statusbar->overwrite = gtk_label_new (NULL);
-  gtk_container_add (GTK_CONTAINER (frame), statusbar->overwrite);
-  gtk_misc_set_padding (GTK_MISC (statusbar->overwrite), 2, 2);
+  ebox = gtk_event_box_new ();
+  gtk_container_add (GTK_CONTAINER (frame), ebox);
+  gtk_widget_show (ebox);
+  g_signal_connect (G_OBJECT (ebox), "button-press-event",
+                    G_CALLBACK (mousepad_statusbar_overwrite_clicked), 
statusbar);
+
+  statusbar->overwrite = gtk_label_new (_("OVR"));
+  gtk_container_add (GTK_CONTAINER (ebox), statusbar->overwrite);
+  gtk_misc_set_padding (GTK_MISC (statusbar->overwrite), 4, 2);
   gtk_widget_show (statusbar->overwrite);
 }
 
 
 
-static void
-mousepad_statusbar_finalize (GObject *object)
+static gboolean
+mousepad_statusbar_overwrite_clicked (GtkWidget         *widget,
+                                      GdkEventButton    *event,
+                                      MousepadStatusbar *statusbar)
 {
-  (*G_OBJECT_CLASS (mousepad_statusbar_parent_class)->finalize) (object);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_STATUSBAR (statusbar), FALSE);
+
+  /* only respond on the left button click */
+  if (event->type != GDK_BUTTON_PRESS || event->button != 1)
+    return FALSE;
+
+  /* swap the startusbar state */
+  statusbar->overwrite_enabled = !statusbar->overwrite_enabled;
+
+  /* send the signal */
+  g_signal_emit (G_OBJECT (statusbar), statusbar_signals[ENABLE_OVERWRITE], 0, 
statusbar->overwrite_enabled);
+
+  return TRUE;
 }
 
 
@@ -180,5 +220,7 @@ mousepad_statusbar_set_overwrite (MousepadStatusbar 
*statusbar,
 {
   _mousepad_return_if_fail (MOUSEPAD_IS_STATUSBAR (statusbar));
 
-  gtk_label_set_text (GTK_LABEL (statusbar->overwrite), overwrite ? _("OVR") : 
_("INS"));
+  gtk_widget_set_sensitive (statusbar->overwrite, overwrite);
+
+  statusbar->overwrite_enabled = overwrite;
 }
diff --git a/mousepad/mousepad-undo.c b/mousepad/mousepad-undo.c
new file mode 100644
index 0000000..874538f
--- /dev/null
+++ b/mousepad/mousepad-undo.c
@@ -0,0 +1,592 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <n...@xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-undo.h>
+
+
+
+/* maximum number of steps in the undo manager */
+#define MAX_UNDO_STEPS 50
+
+
+
+typedef struct _MousepadUndoInfo   MousepadUndoInfo;
+typedef enum   _MousepadUndoAction MousepadUndoAction;
+
+enum
+{
+  CAN_UNDO,
+  CAN_REDO,
+  LAST_SIGNAL
+};
+
+enum _MousepadUndoAction
+{
+  INSERT,
+  DELETE,
+};
+
+struct _MousepadUndoClass
+{
+  GObjectClass __parent__;
+};
+
+struct _MousepadUndo
+{
+  GObject  __parent__;
+
+  /* the text buffer we're monitoring */
+  GtkTextBuffer      *buffer;
+
+  /* whether the undo monitor is locked */
+  guint               locked;
+
+  /* list of undo steps */
+  GSList             *steps;
+
+  /* position in the steps list */
+  gint                steps_position;
+
+  /* the buffer of the active step */
+  GString            *step_buffer;
+
+  /* the info of the active step */
+  MousepadUndoAction  step_action;
+  gint                step_start;
+  gint                step_end;
+
+  /* whether we can undo and redo */
+  guint               can_undo : 1;
+  guint               can_redo : 1;
+};
+
+struct _MousepadUndoInfo
+{
+  /* the action of the undo step */
+  MousepadUndoAction  action;
+
+  /* the deleted or inserted string */
+  gchar              *string;
+
+  /* the start and end position in the buffer */
+  gint                start;
+  gint                end;
+};
+
+
+
+static void  mousepad_undo_class_init       (MousepadUndoClass  *klass);
+static void  mousepad_undo_init             (MousepadUndo       *undo);
+static void  mousepad_undo_finalize         (GObject            *object);
+static void  mousepad_undo_free_step        (MousepadUndoInfo   *info);
+static void  mousepad_undo_preform_step     (MousepadUndo       *undo,
+                                             gboolean            undo_step);
+static void  mousepad_undo_new_step         (MousepadUndo       *undo);
+static void  mousepad_undo_insert_text      (GtkTextBuffer      *buffer,
+                                             GtkTextIter        *pos,
+                                             const gchar        *text,
+                                             gint                length,
+                                             MousepadUndo       *undo);
+static void  mousepad_undo_delete_range     (GtkTextBuffer      *buffer,
+                                             GtkTextIter        *start_iter,
+                                             GtkTextIter        *end_iter,
+                                             MousepadUndo       *undo);
+
+
+
+static GObjectClass *mousepad_undo_parent_class;
+static guint         undo_signals[LAST_SIGNAL];
+
+
+
+GType
+mousepad_undo_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            I_("MousepadUndo"),
+                                            sizeof (MousepadUndoClass),
+                                            (GClassInitFunc) 
mousepad_undo_class_init,
+                                            sizeof (MousepadUndo),
+                                            (GInstanceInitFunc) 
mousepad_undo_init,
+                                            0);
+    }
+
+  return type;
+}
+
+
+
+static void
+mousepad_undo_class_init (MousepadUndoClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  mousepad_undo_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = mousepad_undo_finalize;
+
+  undo_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);
+
+  undo_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);
+}
+
+
+
+static void
+mousepad_undo_init (MousepadUndo *undo)
+{
+  /* reset some variabled */
+  undo->locked = 0;
+  undo->steps = NULL;
+  undo->steps_position = 0;
+
+  /* we can't undo or redo */
+  undo->can_undo = FALSE;
+  undo->can_redo = FALSE;
+
+  /* allocate the string buffer (we prealloc 15 characters to avoid mulitple 
reallocations ) */
+  undo->step_buffer = g_string_sized_new (15);
+}
+
+
+
+static void
+mousepad_undo_finalize (GObject *object)
+{
+  MousepadUndo *undo = MOUSEPAD_UNDO (object);
+  GSList       *li;
+
+  /* cleanup the undo steps */
+  for (li = undo->steps; li != NULL; li = li->next)
+    mousepad_undo_free_step (li->data);
+
+  /* free the list */
+  g_slist_free (undo->steps);
+
+  /* cleanup the monitor step */
+  g_string_free (undo->step_buffer, TRUE);
+
+  /* release the undo reference from the buffer */
+  g_object_unref (G_OBJECT (undo->buffer));
+
+  (*G_OBJECT_CLASS (mousepad_undo_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_undo_free_step (MousepadUndoInfo *info)
+{
+  /* free the string */
+  g_free (info->string);
+
+  /* free the slice */
+  g_slice_free (MousepadUndoInfo, info);
+}
+
+
+
+static void
+mousepad_undo_preform_step (MousepadUndo *undo,
+                            gboolean      undo_step)
+{
+  MousepadUndoInfo   *info;
+  MousepadUndoAction  action;
+  GtkTextIter         start_iter, end_iter;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_UNDO (undo));
+
+  /* prevent undo updates */
+  mousepad_undo_lock (undo);
+
+  /* flush the undo buffer */
+  mousepad_undo_new_step (undo);
+  undo->step_start = undo->step_end = 0;
+
+  /* decrease the position counter if we're going to undo */
+  if (undo_step)
+    undo->steps_position--;
+
+  /* get the step we're going to undo */
+  info = g_slist_nth_data (undo->steps, undo->steps_position);
+
+  if (G_LIKELY (info))
+    {
+      /* get the action */
+      action = info->action;
+
+      /* swap the action if we're going to undo */
+      if (!undo_step)
+        action = (action == INSERT ? DELETE : INSERT);
+
+      /* get the start iter position */
+      gtk_text_buffer_get_iter_at_offset (undo->buffer, &start_iter, 
info->start);
+
+      switch (action)
+        {
+          case INSERT:
+            /* get the end iter */
+            gtk_text_buffer_get_iter_at_offset (undo->buffer, &end_iter, 
info->end);
+
+            /* delete the inserted text */
+            gtk_text_buffer_delete (undo->buffer, &start_iter, &end_iter);
+
+            break;
+
+          case DELETE:
+            /* insert the deleted text */
+            gtk_text_buffer_insert (undo->buffer, &start_iter, info->string, 
-1);
+
+            break;
+
+          default:
+            _mousepad_assert_not_reached ();
+        }
+
+      /* set the cursor, we scroll to the cursor in mousepad-document */
+      gtk_text_buffer_place_cursor (undo->buffer, &start_iter);
+
+      /* increase the position counter if we did a redo */
+      if (!undo_step)
+        undo->steps_position++;
+    }
+
+  /* set the can_undo boolean */
+  undo->can_undo = (undo->steps_position > 0);
+  undo->can_redo = (undo->steps_position < g_slist_length (undo->steps));
+
+  /* emit the can-undo and can-redo signals */
+  g_signal_emit (G_OBJECT (undo), undo_signals[CAN_UNDO], 0, undo->can_undo);
+  g_signal_emit (G_OBJECT (undo), undo_signals[CAN_REDO], 0, undo->can_redo);
+
+  /* remove our lock */
+  mousepad_undo_unlock (undo);
+}
+
+
+
+static void
+mousepad_undo_new_step (MousepadUndo *undo)
+{
+  MousepadUndoInfo *info;
+  gint              i;
+  GSList           *item;
+
+  /* leave when there is nothing todo */
+  if (undo->step_start == 0 && undo->step_end == 0)
+    return;
+
+  /* allocate the slice */
+  info = g_slice_new0 (MousepadUndoInfo);
+
+  /* set the info */
+  info->string = g_strdup (undo->step_buffer->str);
+  info->action = undo->step_action;
+  info->start = undo->step_start;
+  info->end = undo->step_end;
+
+  /* append to the steps list */
+  undo->steps = g_slist_append (undo->steps, info);
+
+  /* set the list position */
+  undo->steps_position = g_slist_length (undo->steps);
+
+  /* erase the buffer */
+  undo->step_buffer = g_string_erase (undo->step_buffer, 0, -1);
+
+  /* check the list length */
+  if (G_UNLIKELY (g_slist_length (undo->steps) > MAX_UNDO_STEPS))
+    for (i = g_slist_length (undo->steps); i > MAX_UNDO_STEPS; i--)
+      {
+        /* get the first item in the list */
+        item = g_slist_nth (undo->steps, 0);
+
+        /* cleanup the data */
+        mousepad_undo_free_step (item->data);
+
+        /* delete the node in the list */
+        undo->steps = g_slist_delete_link (undo->steps, item);
+      }
+}
+
+
+
+static void
+mousepad_undo_handle_step (const gchar        *text,
+                           gint                start,
+                           gint                end,
+                           MousepadUndoAction  action,
+                           MousepadUndo       *undo)
+{
+  gboolean create_new_step = FALSE;
+
+  /* check if we need to update whether we can undo */
+  if (undo->can_undo != TRUE)
+    {
+      undo->can_undo = TRUE;
+
+      /* emit the can-undo signal */
+      g_signal_emit (G_OBJECT (undo), undo_signals[CAN_UNDO], 0, 
undo->can_undo);
+    }
+
+  /* check if we need to create a new step after we appended the data */
+  if (ABS (end - start) == 1)
+    {
+      switch (g_utf8_get_char (text))
+        {
+          case ' ':
+          case '\t':
+          case '\n':
+            create_new_step = TRUE;
+            break;
+        }
+    }
+
+  /* try to append to the active step */
+  if (undo->step_action == action
+      && action == INSERT
+      && undo->step_end == start)
+    {
+      /* append the inserted string */
+      undo->step_buffer = g_string_append_len (undo->step_buffer, text, (start 
- end));
+
+      /* update the end position */
+      undo->step_end = end;
+    }
+  else if (undo->step_action == action
+           && action == DELETE
+           && undo->step_start == end)
+    {
+      /* prepend the deleted text */
+      undo->step_buffer = g_string_prepend_len (undo->step_buffer, text, (end 
- start));
+
+      /* update the start position */
+      undo->step_start = start;
+    }
+  else
+    {
+      /* we really need a new step */
+      create_new_step = TRUE;
+    }
+
+  /* create a new step if needed */
+  if (create_new_step)
+    {
+      /* create step */
+      mousepad_undo_new_step (undo);
+
+      /* set the new info */
+      undo->step_buffer = g_string_append_len (undo->step_buffer, text, ABS 
(start - end));
+      undo->step_action = action;
+      undo->step_start = start;
+      undo->step_end = end;
+    }
+}
+
+
+
+static void
+mousepad_undo_insert_text (GtkTextBuffer *buffer,
+                           GtkTextIter   *pos,
+                           const gchar   *text,
+                           gint           length,
+                           MousepadUndo  *undo)
+{
+  gint start, end;
+
+  /* quit when the undo manager is locked */
+  if (undo->locked)
+    return;
+
+  /* get the start and end position */
+  start = gtk_text_iter_get_offset (pos);
+  end = start + length;
+
+  /* append the changes */
+  mousepad_undo_handle_step (text, start, end, INSERT, undo);
+}
+
+
+
+static void
+mousepad_undo_delete_range (GtkTextBuffer *buffer,
+                            GtkTextIter   *start_iter,
+                            GtkTextIter   *end_iter,
+                            MousepadUndo  *undo)
+{
+  gint   start, end;
+  gchar *text;
+
+  /* quit when the undo manager is locked */
+  if (undo->locked)
+    return;
+
+  /* get the start and end position */
+  start = gtk_text_iter_get_offset (start_iter);
+  end = gtk_text_iter_get_offset (end_iter);
+
+  /* get the deleted string */
+  text = gtk_text_buffer_get_slice (buffer, start_iter, end_iter, FALSE);
+
+  /* append the changes */
+  mousepad_undo_handle_step (text, start, end, DELETE, undo);
+
+  /* cleanup */
+  g_free (text);
+}
+
+
+
+MousepadUndo *
+mousepad_undo_new (GtkTextBuffer *buffer)
+{
+  MousepadUndo *undo;
+
+  _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+  /* create the undo object */
+  undo = g_object_new (MOUSEPAD_TYPE_UNDO, NULL);
+
+  /* set the buffer (we also take a reference) */
+  undo->buffer = g_object_ref (G_OBJECT (buffer));
+
+  /* connect signals to the buffer so we can monitor it */
+  g_signal_connect (G_OBJECT (buffer), "insert-text", G_CALLBACK 
(mousepad_undo_insert_text), undo);
+  g_signal_connect (G_OBJECT (buffer), "delete-range", G_CALLBACK 
(mousepad_undo_delete_range), undo);
+
+  return undo;
+}
+
+
+
+void
+mousepad_undo_lock (MousepadUndo *undo)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_UNDO (undo));
+
+  /* increase the lock count */
+  undo->locked++;
+}
+
+
+
+void
+mousepad_undo_unlock (MousepadUndo *undo)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_UNDO (undo));
+  _mousepad_return_if_fail (undo->locked > 0);
+
+  /* decrease the lock count */
+  undo->locked--;
+}
+
+
+
+void
+mousepad_undo_do_undo (MousepadUndo *undo)
+{
+  /* run the undo step */
+  mousepad_undo_preform_step (undo, TRUE);
+}
+
+
+
+void
+mousepad_undo_do_redo (MousepadUndo *undo)
+{
+  /* run the redo step */
+  mousepad_undo_preform_step (undo, FALSE);
+}
+
+
+
+gboolean
+mousepad_undo_can_undo (MousepadUndo *undo)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_UNDO (undo), FALSE);
+
+  return undo->can_undo;
+}
+
+
+
+gboolean
+mousepad_undo_can_redo (MousepadUndo *undo)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_UNDO (undo), FALSE);
+
+  return undo->can_redo;
+}
+
+
+
+void
+mousepad_undo_populate_popup (GtkTextView  *textview,
+                              GtkMenu      *menu,
+                              MousepadUndo *undo)
+{
+  GtkWidget *item;
+  gboolean   editable;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_UNDO (undo));
+
+  /* whether the textview is editable */
+  editable = gtk_text_view_get_editable (textview);
+
+  /* separator */
+  item = gtk_separator_menu_item_new ();
+  gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show (item);
+
+  /* redo item */
+  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_REDO, NULL);
+  gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+  gtk_widget_set_sensitive (item, editable && mousepad_undo_can_redo (undo));
+  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK 
(mousepad_undo_do_redo), undo);
+  gtk_widget_show (item);
+
+  /* undo item */
+  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_UNDO, NULL);
+  gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+  gtk_widget_set_sensitive (item, editable && mousepad_undo_can_undo (undo));
+  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK 
(mousepad_undo_do_undo), undo);
+  gtk_widget_show (item);
+}
diff --git a/mousepad/mousepad-undo.h b/mousepad/mousepad-undo.h
new file mode 100644
index 0000000..86ce9ae
--- /dev/null
+++ b/mousepad/mousepad-undo.h
@@ -0,0 +1,57 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <n...@xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MOUSEPAD_UNDO_H__
+#define __MOUSEPAD_UNDO_H__
+
+G_BEGIN_DECLS
+
+typedef struct _MousepadUndoClass MousepadUndoClass;
+typedef struct _MousepadUndo      MousepadUndo;
+
+#define MOUSEPAD_TYPE_UNDO            (mousepad_undo_get_type ())
+#define MOUSEPAD_UNDO(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
MOUSEPAD_TYPE_UNDO, MousepadUndo))
+#define MOUSEPAD_UNDO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
MOUSEPAD_TYPE_UNDO, MousepadUndoClass))
+#define MOUSEPAD_IS_UNDO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
MOUSEPAD_TYPE_UNDO))
+#define MOUSEPAD_IS_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
MOUSEPAD_TYPE_UNDO))
+#define MOUSEPAD_UNDO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
MOUSEPAD_TYPE_UNDO, MousepadUndoClass))
+
+GType          mousepad_undo_get_type        (void) G_GNUC_CONST;
+
+MousepadUndo  *mousepad_undo_new             (GtkTextBuffer *buffer);
+
+void           mousepad_undo_lock            (MousepadUndo  *undo);
+
+void           mousepad_undo_unlock          (MousepadUndo  *undo);
+
+void           mousepad_undo_do_undo         (MousepadUndo  *undo);
+
+void           mousepad_undo_do_redo         (MousepadUndo  *undo);
+
+gboolean       mousepad_undo_can_undo        (MousepadUndo  *undo);
+
+gboolean       mousepad_undo_can_redo        (MousepadUndo  *undo);
+
+void           mousepad_undo_populate_popup  (GtkTextView   *textview,
+                                              GtkMenu       *menu,
+                                              MousepadUndo  *undo);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_UNDO_H__ */
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index ed70907..cc6afd7 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -33,8 +33,6 @@
 
 
 static void      mousepad_view_class_init           (MousepadViewClass  
*klass);
-static void      mousepad_view_init                 (MousepadView       *view);
-static void      mousepad_view_finalize             (GObject            
*object);
 static gboolean  mousepad_view_key_press_event      (GtkWidget          
*widget,
                                                      GdkEventKey        
*event);
 static void      mousepad_view_indent_lines         (MousepadView       *view,
@@ -86,7 +84,7 @@ mousepad_view_get_type (void)
                                             sizeof (MousepadViewClass),
                                             (GClassInitFunc) 
mousepad_view_class_init,
                                             sizeof (MousepadView),
-                                            (GInstanceInitFunc) 
mousepad_view_init,
+                                            NULL,
                                             0);
     }
 
@@ -98,14 +96,10 @@ mousepad_view_get_type (void)
 static void
 mousepad_view_class_init (MousepadViewClass *klass)
 {
-  GObjectClass   *gobject_class;
   GtkWidgetClass *widget_class;
 
   mousepad_view_parent_class = g_type_class_peek_parent (klass);
 
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = mousepad_view_finalize;
-
   widget_class = GTK_WIDGET_CLASS (klass);
   widget_class->key_press_event = mousepad_view_key_press_event;
   widget_class->expose_event = mousepad_view_expose;
@@ -113,22 +107,6 @@ mousepad_view_class_init (MousepadViewClass *klass)
 
 
 
-static void
-mousepad_view_init (MousepadView *view)
-{
-  /* empty */
-}
-
-
-
-static void
-mousepad_view_finalize (GObject *object)
-{
-  (*G_OBJECT_CLASS (mousepad_view_parent_class)->finalize) (object);
-}
-
-
-
 /**
  * mousepad_view_key_press_event:
  * @widget : A #GtkWidget.
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
index 25b4096..1477e41 100644
--- a/mousepad/mousepad-window-ui.xml
+++ b/mousepad/mousepad-window-ui.xml
@@ -25,6 +25,8 @@
       <separator />
       <menuitem action="reload" />
       <separator />
+      <menuitem action="print-document" />
+      <separator />
       <menuitem action="close-tab" />
       <menuitem action="close-window" />
       <menuitem action="close-all-windows" />
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index 8779309..14affd9 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -85,6 +85,8 @@ static gboolean          mousepad_window_close_document       
        (MousepadW
                                                                        
MousepadDocument       *document);
 static void              mousepad_window_set_title                    
(MousepadWindow         *window,
                                                                        
MousepadDocument       *document);
+static void              mousepad_window_toggle_overwrite             
(MousepadWindow         *window,
+                                                                       
gboolean                overwrite);
 
 /* notebook signals */
 static void              mousepad_window_page_notified                
(GtkNotebook            *notebook,
@@ -119,6 +121,10 @@ static void              mousepad_window_overwrite_changed 
           (MousepadD
 static void              mousepad_window_selection_changed            
(MousepadDocument       *document,
                                                                        
gboolean                selected,
                                                                        
MousepadWindow         *window);
+static void              mousepad_window_can_undo                     
(MousepadWindow         *window,
+                                                                       
gboolean                can_undo);
+static void              mousepad_window_can_redo                     
(MousepadWindow         *window,
+                                                                       
gboolean                can_redo);
 
 /* menu updaters */
 static void              mousepad_window_update_actions               
(MousepadWindow         *window);
@@ -152,6 +158,8 @@ static void              
mousepad_window_action_save_file_as          (GtkAction
                                                                        
MousepadWindow         *window);
 static void              mousepad_window_action_reload                
(GtkAction              *action,
                                                                        
MousepadWindow         *window);
+static void              mousepad_window_action_print                 
(GtkAction              *action,
+                                                                       
MousepadWindow         *window);
 static void              mousepad_window_action_close_tab             
(GtkAction              *action,
                                                                        
MousepadWindow         *window);
 static void              mousepad_window_action_close                 
(GtkAction              *action,
@@ -160,6 +168,10 @@ static void              
mousepad_window_action_close_all_windows     (GtkAction
                                                                        
MousepadWindow         *window);
 static void              mousepad_window_action_open_new_tab          
(GtkAction              *action,
                                                                        
MousepadWindow         *window);
+static void              mousepad_window_action_undo                  
(GtkAction              *action,
+                                                                       
MousepadWindow         *window);
+static void              mousepad_window_action_redo                  
(GtkAction              *action,
+                                                                       
MousepadWindow         *window);
 static void              mousepad_window_action_cut                   
(GtkAction              *action,
                                                                        
MousepadWindow         *window);
 static void              mousepad_window_action_copy                  
(GtkAction              *action,
@@ -267,13 +279,14 @@ static const GtkActionEntry action_entries[] =
     { "save-file", GTK_STOCK_SAVE, N_("_Save"), NULL, N_("Save the current 
file"), G_CALLBACK (mousepad_window_action_save_file), },
     { "save-file-as", GTK_STOCK_SAVE_AS, N_("Save _As"), NULL, N_("Save 
current document as another file"), G_CALLBACK 
(mousepad_window_action_save_file_as), },
     { "reload", GTK_STOCK_REFRESH, N_("Re_load"), NULL, N_("Reload this 
document."), G_CALLBACK (mousepad_window_action_reload), },
+    { "print-document", GTK_STOCK_PRINT, N_("_Print"), "<control>P", N_("Prin 
the current page"), G_CALLBACK (mousepad_window_action_print), },
     { "close-tab", GTK_STOCK_CLOSE, N_("C_lose Tab"), "<control>W", N_("Close 
the current file"), G_CALLBACK (mousepad_window_action_close_tab), },
     { "close-window", GTK_STOCK_QUIT, N_("_Close Window"), "<control>Q", 
N_("Quit the program"), G_CALLBACK (mousepad_window_action_close), },
     { "close-all-windows", NULL, N_("Close _All Windows"), 
"<control><shift>W", N_("Close all Mousepad windows"), G_CALLBACK 
(mousepad_window_action_close_all_windows), },
 
   { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL, },
-    { "undo", GTK_STOCK_UNDO, N_("_Undo"), NULL, N_("Undo the last action"), 
NULL, },
-    { "redo", GTK_STOCK_REDO, N_("_Redo"), NULL, N_("Redo the last undone 
action"), NULL, },
+    { "undo", GTK_STOCK_UNDO, N_("_Undo"), "<control>Z", N_("Undo the last 
action"), G_CALLBACK (mousepad_window_action_undo), },
+    { "redo", GTK_STOCK_REDO, N_("_Redo"), "<control>Y", N_("Redo the last 
undone action"), G_CALLBACK (mousepad_window_action_redo), },
     { "cut", GTK_STOCK_CUT, N_("Cu_t"), NULL, N_("Cut the selection"), 
G_CALLBACK (mousepad_window_action_cut), },
     { "copy", GTK_STOCK_COPY, N_("_Copy"), NULL, N_("Copy the selection"), 
G_CALLBACK (mousepad_window_action_copy), },
     { "paste", GTK_STOCK_PASTE, N_("_Paste"), NULL, N_("Paste the clipboard"), 
G_CALLBACK (mousepad_window_action_paste), },
@@ -953,6 +966,8 @@ mousepad_window_add (MousepadWindow   *window,
   g_signal_connect (G_OBJECT (document), "modified-changed", G_CALLBACK 
(mousepad_window_modified_changed), window);
   g_signal_connect (G_OBJECT (document), "cursor-changed", G_CALLBACK 
(mousepad_window_cursor_changed), window);
   g_signal_connect (G_OBJECT (document), "overwrite-changed", G_CALLBACK 
(mousepad_window_overwrite_changed), window);
+  g_signal_connect_swapped (G_OBJECT (document), "can-undo", G_CALLBACK 
(mousepad_window_can_undo), window);
+  g_signal_connect_swapped (G_OBJECT (document), "can-redo", G_CALLBACK 
(mousepad_window_can_redo), window);
 
   /* insert the page right from the active tab */
   page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
@@ -1077,6 +1092,18 @@ mousepad_window_set_title (MousepadWindow   *window,
 
 
 
+static void
+mousepad_window_toggle_overwrite (MousepadWindow *window,
+                                  gboolean        overwrite)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  if (G_LIKELY (window->active))
+    mousepad_document_set_overwrite (window->active, overwrite);
+}
+
+
+
 /**
  * Notebook Signal Functions
  **/
@@ -1294,6 +1321,30 @@ mousepad_window_selection_changed (MousepadDocument 
*document,
 
 
 
+static void
+mousepad_window_can_undo (MousepadWindow *window,
+                          gboolean        can_undo)
+{
+  GtkAction *action;
+
+  action = gtk_action_group_get_action (window->window_actions, "undo");
+  gtk_action_set_sensitive (action, can_undo);
+}
+
+
+
+static void
+mousepad_window_can_redo (MousepadWindow *window,
+                          gboolean        can_redo)
+{
+  GtkAction *action;
+
+  action = gtk_action_group_get_action (window->window_actions, "redo");
+  gtk_action_set_sensitive (action, can_redo);
+}
+
+
+
 /**
  * Menu Update Functions
  **/
@@ -1349,6 +1400,10 @@ mousepad_window_update_actions (MousepadWindow *window)
       action = gtk_action_group_get_action (window->window_actions, 
"auto-indent");
       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
 
+      /* set the sensitivity of the undo and redo actions */
+      mousepad_window_can_undo (window, mousepad_document_get_can_undo 
(document));
+      mousepad_window_can_redo (window, mousepad_document_get_can_redo 
(document));
+
       /* set the sensitivity of the selection actions */
       has_selection = mousepad_document_get_has_selection (document);
       mousepad_window_selection_changed (document, has_selection, window);
@@ -1981,6 +2036,15 @@ mousepad_window_action_reload (GtkAction      *action,
 
 
 static void
+mousepad_window_action_print (GtkAction      *action,
+                              MousepadWindow *window)
+{
+
+}
+
+
+
+static void
 mousepad_window_action_close_tab (GtkAction      *action,
                                   MousepadWindow *window)
 {
@@ -2056,6 +2120,26 @@ mousepad_window_action_close_all_windows (GtkAction      
*action,
 
 
 static void
+mousepad_window_action_undo (GtkAction      *action,
+                             MousepadWindow *window)
+{
+  if (G_LIKELY (window->active != NULL))
+    mousepad_document_undo (window->active);
+}
+
+
+
+static void
+mousepad_window_action_redo (GtkAction      *action,
+                             MousepadWindow *window)
+{
+  if (G_LIKELY (window->active != NULL))
+    mousepad_document_redo (window->active);
+}
+
+
+
+static void
 mousepad_window_action_cut (GtkAction      *action,
                             MousepadWindow *window)
 {
@@ -2300,6 +2384,10 @@ mousepad_window_action_statusbar (GtkToggleAction 
*action,
       gtk_table_attach (GTK_TABLE (window->table), window->statusbar, 0, 1, 5, 
6, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
       gtk_widget_show (window->statusbar);
 
+      /* overwrite toggle signal */
+      g_signal_connect_swapped (G_OBJECT (window->statusbar), 
"enable-overwrite",
+                                G_CALLBACK (mousepad_window_toggle_overwrite), 
window);
+
       /* set the statsbar text */
       document = window->active;
       if (document != NULL)
_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
https://mail.xfce.org/mailman/listinfo/xfce4-commits

Reply via email to