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