diff options
Diffstat (limited to 'third_party/undoview')
-rw-r--r-- | third_party/undoview/LICENSE | 165 | ||||
-rw-r--r-- | third_party/undoview/README.chromium | 9 | ||||
-rw-r--r-- | third_party/undoview/undo_manager.c | 1084 | ||||
-rw-r--r-- | third_party/undoview/undo_manager.h | 86 | ||||
-rw-r--r-- | third_party/undoview/undo_view.c | 83 | ||||
-rw-r--r-- | third_party/undoview/undo_view.h | 51 | ||||
-rw-r--r-- | third_party/undoview/undoview.gyp | 22 |
7 files changed, 1500 insertions, 0 deletions
diff --git a/third_party/undoview/LICENSE b/third_party/undoview/LICENSE new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/third_party/undoview/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/third_party/undoview/README.chromium b/third_party/undoview/README.chromium new file mode 100644 index 0000000..260d8e3 --- /dev/null +++ b/third_party/undoview/README.chromium @@ -0,0 +1,9 @@ +Name: undoview +URL: http://projects.gnome.org/gtksourceview/ + +This contains GtkUndoView, which is GtkTextView with undo/redo +support. The code to add the support is borrowed from GtkSourceView. +However since SV has a lot of other stuff we don't want, we borrow +only the undo support and add it to GtkTextView to create a +GtkUndoView. + diff --git a/third_party/undoview/undo_manager.c b/third_party/undoview/undo_manager.c new file mode 100644 index 0000000..9136b37 --- /dev/null +++ b/third_party/undoview/undo_manager.c @@ -0,0 +1,1084 @@ +/* + * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence + * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi + * Copyright (C) 2002-2005 Paolo Maggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <stdlib.h> +#include <string.h> + +#include "undo_manager.h" + +#define DEFAULT_MAX_UNDO_LEVELS 25 + +typedef struct _GtkSourceUndoAction GtkSourceUndoAction; +typedef struct _GtkSourceUndoInsertAction GtkSourceUndoInsertAction; +typedef struct _GtkSourceUndoDeleteAction GtkSourceUndoDeleteAction; + +typedef enum { + GTK_SOURCE_UNDO_ACTION_INSERT, + GTK_SOURCE_UNDO_ACTION_DELETE, +} GtkSourceUndoActionType; + +/* + * We use offsets instead of GtkTextIters because the last ones + * require to much memory in this context without giving us any advantage. + */ + +struct _GtkSourceUndoInsertAction { + gint pos; + gchar *text; + gint length; + gint chars; +}; + +struct _GtkSourceUndoDeleteAction { + gint start; + gint end; + gchar *text; + gboolean forward; +}; + +struct _GtkSourceUndoAction { + GtkSourceUndoActionType action_type; + + union { + GtkSourceUndoInsertAction insert; + GtkSourceUndoDeleteAction delete; + } action; + + gint order_in_group; + + /* It is TRUE whether the action can be merged with the following action. */ + guint mergeable : 1; + + /* It is TRUE whether the action is marked as "modified". + * An action is marked as "modified" if it changed the + * state of the buffer from "not modified" to "modified". Only the first + * action of a group can be marked as modified. + * There can be a single action marked as "modified" in the actions list. + */ + guint modified : 1; +}; + +/* INVALID is a pointer to an invalid action */ +#define INVALID ((void *) "IA") + +struct _GtkSourceUndoManagerPrivate { + GtkTextBuffer *document; + + GList* actions; + gint next_redo; + + gint actions_in_current_group; + + gint running_not_undoable_actions; + + gint num_of_groups; + + gint max_undo_levels; + + guint can_undo : 1; + guint can_redo : 1; + + /* It is TRUE whether, while undoing an action of the current group (with order_in_group > 1), + * the state of the buffer changed from "not modified" to "modified". + */ + guint modified_undoing_group : 1; + + /* Pointer to the action (in the action list) marked as "modified". + * It is NULL when no action is marked as "modified". + * It is INVALID when the action marked as "modified" has been removed + * from the action list (freeing the list or resizing it) */ + GtkSourceUndoAction *modified_action; +}; + +enum { + CAN_UNDO, + CAN_REDO, + LAST_SIGNAL +}; + +static void gtk_source_undo_manager_class_init(GtkSourceUndoManagerClass *klass); +static void gtk_source_undo_manager_init(GtkSourceUndoManager *um); +static void gtk_source_undo_manager_finalize(GObject *object); + +static void gtk_source_undo_manager_insert_text_handler(GtkTextBuffer *buffer, + GtkTextIter *pos, + const gchar *text, + gint length, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_delete_range_handler(GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_begin_user_action_handler(GtkTextBuffer *buffer, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_modified_changed_handler(GtkTextBuffer *buffer, + GtkSourceUndoManager *um); + +static void gtk_source_undo_manager_free_action_list(GtkSourceUndoManager *um); + +static void gtk_source_undo_manager_add_action(GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action); +static void gtk_source_undo_manager_free_first_n_actions(GtkSourceUndoManager *um, + gint n); +static void gtk_source_undo_manager_check_list_size(GtkSourceUndoManager *um); + +static gboolean gtk_source_undo_manager_merge_action(GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action); + +static GObjectClass *parent_class = NULL; +static guint undo_manager_signals [LAST_SIGNAL] = { 0 }; + +GType +gtk_source_undo_manager_get_type(void) { + static GType undo_manager_type = 0; + + if(undo_manager_type == 0) + { + static const GTypeInfo our_info = + { + sizeof(GtkSourceUndoManagerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_source_undo_manager_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GtkSourceUndoManager), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_source_undo_manager_init, + NULL /* value_table */ + }; + + undo_manager_type = g_type_register_static(G_TYPE_OBJECT, + "GtkSourceUndoManager", + &our_info, + 0); + } + + return undo_manager_type; +} + +static void +gtk_source_undo_manager_class_init(GtkSourceUndoManagerClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + object_class->finalize = gtk_source_undo_manager_finalize; + + klass->can_undo = NULL; + klass->can_redo = NULL; + + undo_manager_signals[CAN_UNDO] = + g_signal_new("can_undo", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkSourceUndoManagerClass, can_undo), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); + + undo_manager_signals[CAN_REDO] = + g_signal_new("can_redo", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkSourceUndoManagerClass, can_redo), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); +} + +static void +gtk_source_undo_manager_init(GtkSourceUndoManager *um) { + um->priv = g_new0(GtkSourceUndoManagerPrivate, 1); + + um->priv->actions = NULL; + um->priv->next_redo = 0; + + um->priv->can_undo = FALSE; + um->priv->can_redo = FALSE; + + um->priv->running_not_undoable_actions = 0; + + um->priv->num_of_groups = 0; + + um->priv->max_undo_levels = DEFAULT_MAX_UNDO_LEVELS; + + um->priv->modified_action = NULL; + + um->priv->modified_undoing_group = FALSE; +} + +static void +gtk_source_undo_manager_finalize(GObject *object) { + GtkSourceUndoManager *um; + + g_return_if_fail(object != NULL); + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(object)); + + um = GTK_SOURCE_UNDO_MANAGER(object); + + g_return_if_fail(um->priv != NULL); + + if(um->priv->actions != NULL) + gtk_source_undo_manager_free_action_list(um); + + g_signal_handlers_disconnect_by_func(G_OBJECT(um->priv->document), + G_CALLBACK(gtk_source_undo_manager_delete_range_handler), + um); + + g_signal_handlers_disconnect_by_func(G_OBJECT(um->priv->document), + G_CALLBACK(gtk_source_undo_manager_insert_text_handler), + um); + + g_signal_handlers_disconnect_by_func(G_OBJECT(um->priv->document), + G_CALLBACK(gtk_source_undo_manager_begin_user_action_handler), + um); + + g_signal_handlers_disconnect_by_func(G_OBJECT(um->priv->document), + G_CALLBACK(gtk_source_undo_manager_modified_changed_handler), + um); + + g_free(um->priv); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +GtkSourceUndoManager* +gtk_source_undo_manager_new(GtkTextBuffer* buffer) { + GtkSourceUndoManager *um; + + um = GTK_SOURCE_UNDO_MANAGER(g_object_new(GTK_SOURCE_TYPE_UNDO_MANAGER, NULL)); + + g_return_val_if_fail(um->priv != NULL, NULL); + um->priv->document = buffer; + + g_signal_connect(G_OBJECT(buffer), "insert_text", + G_CALLBACK(gtk_source_undo_manager_insert_text_handler), + um); + + g_signal_connect(G_OBJECT(buffer), "delete_range", + G_CALLBACK(gtk_source_undo_manager_delete_range_handler), + um); + + g_signal_connect(G_OBJECT(buffer), "begin_user_action", + G_CALLBACK(gtk_source_undo_manager_begin_user_action_handler), + um); + + g_signal_connect(G_OBJECT(buffer), "modified_changed", + G_CALLBACK(gtk_source_undo_manager_modified_changed_handler), + um); + return um; +} + +void +gtk_source_undo_manager_begin_not_undoable_action(GtkSourceUndoManager *um) { + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + ++um->priv->running_not_undoable_actions; +} + +static void +gtk_source_undo_manager_end_not_undoable_action_internal(GtkSourceUndoManager *um) { + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + g_return_if_fail(um->priv->running_not_undoable_actions > 0); + + --um->priv->running_not_undoable_actions; +} + +void +gtk_source_undo_manager_end_not_undoable_action(GtkSourceUndoManager *um) { + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + gtk_source_undo_manager_end_not_undoable_action_internal(um); + + if(um->priv->running_not_undoable_actions == 0) + { + gtk_source_undo_manager_free_action_list(um); + + um->priv->next_redo = -1; + + if(um->priv->can_undo) + { + um->priv->can_undo = FALSE; + g_signal_emit(G_OBJECT(um), + undo_manager_signals [CAN_UNDO], + 0, + FALSE); + } + + if(um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit(G_OBJECT(um), + undo_manager_signals [CAN_REDO], + 0, + FALSE); + } + } +} + +gboolean +gtk_source_undo_manager_can_undo(const GtkSourceUndoManager *um) { + g_return_val_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um), FALSE); + g_return_val_if_fail(um->priv != NULL, FALSE); + + return um->priv->can_undo; +} + +gboolean +gtk_source_undo_manager_can_redo(const GtkSourceUndoManager *um) { + g_return_val_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um), FALSE); + g_return_val_if_fail(um->priv != NULL, FALSE); + + return um->priv->can_redo; +} + +static void +set_cursor(GtkTextBuffer *buffer, gint cursor) { + GtkTextIter iter; + + /* Place the cursor at the requested position */ + gtk_text_buffer_get_iter_at_offset(buffer, &iter, cursor); + gtk_text_buffer_place_cursor(buffer, &iter); +} + +static void +insert_text(GtkTextBuffer *buffer, gint pos, const gchar *text, gint len) { + GtkTextIter iter; + + gtk_text_buffer_get_iter_at_offset(buffer, &iter, pos); + gtk_text_buffer_insert(buffer, &iter, text, len); +} + +static void +delete_text(GtkTextBuffer *buffer, gint start, gint end) { + GtkTextIter start_iter; + GtkTextIter end_iter; + + gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, start); + + if(end < 0) + gtk_text_buffer_get_end_iter(buffer, &end_iter); + else + gtk_text_buffer_get_iter_at_offset(buffer, &end_iter, end); + + gtk_text_buffer_delete(buffer, &start_iter, &end_iter); +} + +static gchar* +get_chars(GtkTextBuffer *buffer, gint start, gint end) { + GtkTextIter start_iter; + GtkTextIter end_iter; + + gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, start); + + if(end < 0) + gtk_text_buffer_get_end_iter(buffer, &end_iter); + else + gtk_text_buffer_get_iter_at_offset(buffer, &end_iter, end); + + return gtk_text_buffer_get_slice(buffer, &start_iter, &end_iter, TRUE); +} + +void +gtk_source_undo_manager_undo(GtkSourceUndoManager *um) { + GtkSourceUndoAction *undo_action; + gboolean modified = FALSE; + + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + g_return_if_fail(um->priv->can_undo); + + um->priv->modified_undoing_group = FALSE; + + gtk_source_undo_manager_begin_not_undoable_action(um); + + do + { + undo_action = g_list_nth_data(um->priv->actions, um->priv->next_redo + 1); + g_return_if_fail(undo_action != NULL); + + /* undo_action->modified can be TRUE only if undo_action->order_in_group <= 1 */ + g_return_if_fail((undo_action->order_in_group <= 1) || + ((undo_action->order_in_group > 1) && !undo_action->modified)); + + if(undo_action->order_in_group <= 1) + { + /* Set modified to TRUE only if the buffer did not change its state from + * "not modified" to "modified" undoing an action(with order_in_group > 1) + * in current group. */ + modified =(undo_action->modified && !um->priv->modified_undoing_group); + } + + switch(undo_action->action_type) + { + case GTK_SOURCE_UNDO_ACTION_DELETE: + insert_text( + um->priv->document, + undo_action->action.delete.start, + undo_action->action.delete.text, + strlen(undo_action->action.delete.text)); + + if(undo_action->action.delete.forward) + set_cursor( + um->priv->document, + undo_action->action.delete.start); + else + set_cursor( + um->priv->document, + undo_action->action.delete.end); + + break; + + case GTK_SOURCE_UNDO_ACTION_INSERT: + delete_text( + um->priv->document, + undo_action->action.insert.pos, + undo_action->action.insert.pos + + undo_action->action.insert.chars); + + set_cursor( + um->priv->document, + undo_action->action.insert.pos); + break; + + default: + /* Unknown action type. */ + g_return_if_reached(); + } + + ++um->priv->next_redo; + + } while(undo_action->order_in_group > 1); + + if(modified) + { + --um->priv->next_redo; + gtk_text_buffer_set_modified(um->priv->document, FALSE); + ++um->priv->next_redo; + } + + gtk_source_undo_manager_end_not_undoable_action_internal(um); + + um->priv->modified_undoing_group = FALSE; + + if(!um->priv->can_redo) + { + um->priv->can_redo = TRUE; + g_signal_emit(G_OBJECT(um), + undo_manager_signals [CAN_REDO], + 0, + TRUE); + } + + if(um->priv->next_redo >=(gint)(g_list_length(um->priv->actions) - 1)) + { + um->priv->can_undo = FALSE; + g_signal_emit(G_OBJECT(um), + undo_manager_signals [CAN_UNDO], + 0, + FALSE); + } +} + +void +gtk_source_undo_manager_redo(GtkSourceUndoManager *um) { + GtkSourceUndoAction *undo_action; + gboolean modified = FALSE; + + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + g_return_if_fail(um->priv->can_redo); + + undo_action = g_list_nth_data(um->priv->actions, um->priv->next_redo); + g_return_if_fail(undo_action != NULL); + + gtk_source_undo_manager_begin_not_undoable_action(um); + + do + { + if(undo_action->modified) + { + g_return_if_fail(undo_action->order_in_group <= 1); + modified = TRUE; + } + + --um->priv->next_redo; + + switch(undo_action->action_type) + { + case GTK_SOURCE_UNDO_ACTION_DELETE: + delete_text( + um->priv->document, + undo_action->action.delete.start, + undo_action->action.delete.end); + + set_cursor( + um->priv->document, + undo_action->action.delete.start); + + break; + + case GTK_SOURCE_UNDO_ACTION_INSERT: + set_cursor( + um->priv->document, + undo_action->action.insert.pos); + + insert_text( + um->priv->document, + undo_action->action.insert.pos, + undo_action->action.insert.text, + undo_action->action.insert.length); + + break; + + default: + /* Unknown action type */ + ++um->priv->next_redo; + g_return_if_reached(); + } + + if(um->priv->next_redo < 0) + undo_action = NULL; + else + undo_action = g_list_nth_data(um->priv->actions, um->priv->next_redo); + + } while((undo_action != NULL) &&(undo_action->order_in_group > 1)); + + if(modified) + { + ++um->priv->next_redo; + gtk_text_buffer_set_modified(um->priv->document, FALSE); + --um->priv->next_redo; + } + + gtk_source_undo_manager_end_not_undoable_action_internal(um); + + if(um->priv->next_redo < 0) + { + um->priv->can_redo = FALSE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_REDO], 0, FALSE); + } + + if(!um->priv->can_undo) + { + um->priv->can_undo = TRUE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_UNDO], 0, TRUE); + } +} + +static void +gtk_source_undo_action_free(GtkSourceUndoAction *action) { + if(action == NULL) + return; + + if(action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + g_free(action->action.insert.text); + else if(action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + g_free(action->action.delete.text); + else + g_return_if_reached(); + + g_free(action); +} + +static void +gtk_source_undo_manager_free_action_list(GtkSourceUndoManager *um) { + GList *l; + + l = um->priv->actions; + + while(l != NULL) + { + GtkSourceUndoAction *action = l->data; + + if(action->order_in_group == 1) + --um->priv->num_of_groups; + + if(action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free(action); + + l = g_list_next(l); + } + + g_list_free(um->priv->actions); + um->priv->actions = NULL; +} + +static void +gtk_source_undo_manager_insert_text_handler(GtkTextBuffer *buffer, + GtkTextIter *pos, + const gchar *text, + gint length, + GtkSourceUndoManager *um) { + GtkSourceUndoAction undo_action; + + if(um->priv->running_not_undoable_actions > 0) + return; + + undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT; + + undo_action.action.insert.pos = gtk_text_iter_get_offset(pos); + undo_action.action.insert.text =(gchar*) text; + undo_action.action.insert.length = length; + undo_action.action.insert.chars = g_utf8_strlen(text, length); + + if((undo_action.action.insert.chars > 1) ||(g_utf8_get_char(text) == '\n')) + + undo_action.mergeable = FALSE; + else + undo_action.mergeable = TRUE; + + undo_action.modified = FALSE; + + gtk_source_undo_manager_add_action(um, &undo_action); +} + +static void +gtk_source_undo_manager_delete_range_handler(GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end, + GtkSourceUndoManager *um) { + GtkSourceUndoAction undo_action; + GtkTextIter insert_iter; + + if(um->priv->running_not_undoable_actions > 0) + return; + + undo_action.action_type = GTK_SOURCE_UNDO_ACTION_DELETE; + + gtk_text_iter_order(start, end); + + undo_action.action.delete.start = gtk_text_iter_get_offset(start); + undo_action.action.delete.end = gtk_text_iter_get_offset(end); + + undo_action.action.delete.text = get_chars( + buffer, + undo_action.action.delete.start, + undo_action.action.delete.end); + + /* figure out if the user used the Delete or the Backspace key */ + gtk_text_buffer_get_iter_at_mark(buffer, &insert_iter, + gtk_text_buffer_get_insert(buffer)); + if(gtk_text_iter_get_offset(&insert_iter) <= undo_action.action.delete.start) + undo_action.action.delete.forward = TRUE; + else + undo_action.action.delete.forward = FALSE; + + if(((undo_action.action.delete.end - undo_action.action.delete.start) > 1) || + (g_utf8_get_char(undo_action.action.delete.text ) == '\n')) + undo_action.mergeable = FALSE; + else + undo_action.mergeable = TRUE; + + undo_action.modified = FALSE; + + gtk_source_undo_manager_add_action(um, &undo_action); + + g_free(undo_action.action.delete.text); + +} + +static void +gtk_source_undo_manager_begin_user_action_handler(GtkTextBuffer *buffer, GtkSourceUndoManager *um) { + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + if(um->priv->running_not_undoable_actions > 0) + return; + + um->priv->actions_in_current_group = 0; +} + +static void +gtk_source_undo_manager_add_action(GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action) { + GtkSourceUndoAction* action; + + if(um->priv->next_redo >= 0) + { + gtk_source_undo_manager_free_first_n_actions(um, um->priv->next_redo + 1); + } + + um->priv->next_redo = -1; + + if(!gtk_source_undo_manager_merge_action(um, undo_action)) + { + action = g_new(GtkSourceUndoAction, 1); + *action = *undo_action; + + if(action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + action->action.insert.text = g_strndup(undo_action->action.insert.text, undo_action->action.insert.length); + else if(action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + action->action.delete.text = g_strdup(undo_action->action.delete.text); + else + { + g_free(action); + g_return_if_reached(); + } + + ++um->priv->actions_in_current_group; + action->order_in_group = um->priv->actions_in_current_group; + + if(action->order_in_group == 1) + ++um->priv->num_of_groups; + + um->priv->actions = g_list_prepend(um->priv->actions, action); + } + + gtk_source_undo_manager_check_list_size(um); + + if(!um->priv->can_undo) + { + um->priv->can_undo = TRUE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_UNDO], 0, TRUE); + } + + if(um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_REDO], 0, FALSE); + } +} + +static void +gtk_source_undo_manager_free_first_n_actions(GtkSourceUndoManager *um, + gint n) { + gint i; + + if(um->priv->actions == NULL) + return; + + for(i = 0; i < n; i++) + { + GtkSourceUndoAction *action = g_list_first(um->priv->actions)->data; + + if(action->order_in_group == 1) + --um->priv->num_of_groups; + + if(action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free(action); + + um->priv->actions = g_list_delete_link(um->priv->actions, + um->priv->actions); + + if(um->priv->actions == NULL) + return; + } +} + +static void +gtk_source_undo_manager_check_list_size(GtkSourceUndoManager *um) { + gint undo_levels; + + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + undo_levels = gtk_source_undo_manager_get_max_undo_levels(um); + + if(undo_levels < 1) + return; + + if(um->priv->num_of_groups > undo_levels) + { + GtkSourceUndoAction *undo_action; + GList *last; + + last = g_list_last(um->priv->actions); + undo_action =(GtkSourceUndoAction*) last->data; + + do + { + GList *tmp; + + if(undo_action->order_in_group == 1) + --um->priv->num_of_groups; + + if(undo_action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free(undo_action); + + tmp = g_list_previous(last); + um->priv->actions = g_list_delete_link(um->priv->actions, last); + last = tmp; + g_return_if_fail(last != NULL); + + undo_action =(GtkSourceUndoAction*) last->data; + + } while((undo_action->order_in_group > 1) || + (um->priv->num_of_groups > undo_levels)); + } +} + +/** + * gtk_source_undo_manager_merge_action: + * @um: a #GtkSourceUndoManager. + * @undo_action: a #GtkSourceUndoAction. + * + * This function tries to merge the undo action at the top of + * the stack with a new undo action. So when we undo for example + * typing, we can undo the whole word and not each letter by itself. + * + * Return Value: %TRUE is merge was successful, %FALSE otherwise. + **/ +static gboolean +gtk_source_undo_manager_merge_action(GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action) { + GtkSourceUndoAction *last_action; + + g_return_val_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um), FALSE); + g_return_val_if_fail(um->priv != NULL, FALSE); + + if(um->priv->actions == NULL) + return FALSE; + + last_action =(GtkSourceUndoAction*) g_list_nth_data(um->priv->actions, 0); + + if(!last_action->mergeable) + return FALSE; + + if((!undo_action->mergeable) || + (undo_action->action_type != last_action->action_type)) + { + last_action->mergeable = FALSE; + return FALSE; + } + + if(undo_action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + { + if((last_action->action.delete.forward != undo_action->action.delete.forward) || + ((last_action->action.delete.start != undo_action->action.delete.start) && + (last_action->action.delete.start != undo_action->action.delete.end))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + if(last_action->action.delete.start == undo_action->action.delete.start) + { + gchar *str; + +#define L (last_action->action.delete.end - last_action->action.delete.start - 1) +#define g_utf8_get_char_at(p,i) g_utf8_get_char(g_utf8_offset_to_pointer((p),(i))) + + /* Deleted with the delete key */ + if((g_utf8_get_char(undo_action->action.delete.text) != ' ') && + (g_utf8_get_char(undo_action->action.delete.text) != '\t') && + ((g_utf8_get_char_at(last_action->action.delete.text, L) == ' ') || + (g_utf8_get_char_at(last_action->action.delete.text, L) == '\t'))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf("%s%s", last_action->action.delete.text, + undo_action->action.delete.text); + + g_free(last_action->action.delete.text); + last_action->action.delete.end +=(undo_action->action.delete.end - + undo_action->action.delete.start); + last_action->action.delete.text = str; + } + else + { + gchar *str; + + /* Deleted with the backspace key */ + if((g_utf8_get_char(undo_action->action.delete.text) != ' ') && + (g_utf8_get_char(undo_action->action.delete.text) != '\t') && + ((g_utf8_get_char(last_action->action.delete.text) == ' ') || + (g_utf8_get_char(last_action->action.delete.text) == '\t'))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf("%s%s", undo_action->action.delete.text, + last_action->action.delete.text); + + g_free(last_action->action.delete.text); + last_action->action.delete.start = undo_action->action.delete.start; + last_action->action.delete.text = str; + } + } + else if(undo_action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + { + gchar* str; + +#define I (last_action->action.insert.chars - 1) + + if((undo_action->action.insert.pos != + (last_action->action.insert.pos + last_action->action.insert.chars)) || + ((g_utf8_get_char(undo_action->action.insert.text) != ' ') && + (g_utf8_get_char(undo_action->action.insert.text) != '\t') && + ((g_utf8_get_char_at(last_action->action.insert.text, I) == ' ') || + (g_utf8_get_char_at(last_action->action.insert.text, I) == '\t'))) + ) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf("%s%s", last_action->action.insert.text, + undo_action->action.insert.text); + + g_free(last_action->action.insert.text); + last_action->action.insert.length += undo_action->action.insert.length; + last_action->action.insert.text = str; + last_action->action.insert.chars += undo_action->action.insert.chars; + + } + else + /* Unknown action inside undo merge encountered */ + g_return_val_if_reached(TRUE); + + return TRUE; +} + +gint +gtk_source_undo_manager_get_max_undo_levels(GtkSourceUndoManager *um) { + g_return_val_if_fail(um != NULL, 0); + g_return_val_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um), 0); + + return um->priv->max_undo_levels; +} + +void +gtk_source_undo_manager_set_max_undo_levels(GtkSourceUndoManager *um, + gint max_undo_levels) { + gint old_levels; + + g_return_if_fail(um != NULL); + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + + old_levels = um->priv->max_undo_levels; + um->priv->max_undo_levels = max_undo_levels; + + if(max_undo_levels < 1) + return; + + if(old_levels > max_undo_levels) + { + /* strip redo actions first */ + while(um->priv->next_redo >= 0 &&(um->priv->num_of_groups > max_undo_levels)) + { + gtk_source_undo_manager_free_first_n_actions(um, 1); + um->priv->next_redo--; + } + + /* now remove undo actions if necessary */ + gtk_source_undo_manager_check_list_size(um); + + /* emit "can_undo" and/or "can_redo" if appropiate */ + if(um->priv->next_redo < 0 && um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_REDO], 0, FALSE); + } + + if(um->priv->can_undo && + um->priv->next_redo >=(gint)(g_list_length(um->priv->actions) - 1)) + { + um->priv->can_undo = FALSE; + g_signal_emit(G_OBJECT(um), undo_manager_signals [CAN_UNDO], 0, FALSE); + } + } +} + +static void +gtk_source_undo_manager_modified_changed_handler(GtkTextBuffer *buffer, + GtkSourceUndoManager *um) { + GtkSourceUndoAction *action; + GList *list; + + g_return_if_fail(GTK_SOURCE_IS_UNDO_MANAGER(um)); + g_return_if_fail(um->priv != NULL); + + if(um->priv->actions == NULL) + return; + + list = g_list_nth(um->priv->actions, um->priv->next_redo + 1); + + if(list != NULL) + action =(GtkSourceUndoAction*) list->data; + else + action = NULL; + + if(gtk_text_buffer_get_modified(buffer) == FALSE) + { + if(action != NULL) + action->mergeable = FALSE; + + if(um->priv->modified_action != NULL) + { + if(um->priv->modified_action != INVALID) + um->priv->modified_action->modified = FALSE; + + um->priv->modified_action = NULL; + } + + return; + } + + if(action == NULL) + { + g_return_if_fail(um->priv->running_not_undoable_actions > 0); + + return; + } + + /* gtk_text_buffer_get_modified(buffer) == TRUE */ + + g_return_if_fail(um->priv->modified_action == NULL); + + if(action->order_in_group > 1) + um->priv->modified_undoing_group = TRUE; + + while(action->order_in_group > 1) + { + list = g_list_next(list); + g_return_if_fail(list != NULL); + + action =(GtkSourceUndoAction*) list->data; + g_return_if_fail(action != NULL); + } + + action->modified = TRUE; + um->priv->modified_action = action; +} + diff --git a/third_party/undoview/undo_manager.h b/third_party/undoview/undo_manager.h new file mode 100644 index 0000000..9be582c --- /dev/null +++ b/third_party/undoview/undo_manager.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence + * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi + * Copyright (C) 2002, 2003 Paolo Maggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_UNDO_MANAGER_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_UNDO_MANAGER_H_ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define GTK_SOURCE_TYPE_UNDO_MANAGER (gtk_source_undo_manager_get_type()) + +#define GTK_SOURCE_UNDO_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManager)) + +#define GTK_SOURCE_UNDO_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManagerClass)) + +#define GTK_SOURCE_IS_UNDO_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_SOURCE_TYPE_UNDO_MANAGER)) + +#define GTK_SOURCE_IS_UNDO_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_SOURCE_TYPE_UNDO_MANAGER)) + +#define GTK_SOURCE_UNDO_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManagerClass)) + +typedef struct _GtkSourceUndoManager GtkSourceUndoManager; +typedef struct _GtkSourceUndoManagerClass GtkSourceUndoManagerClass; + +typedef struct _GtkSourceUndoManagerPrivate GtkSourceUndoManagerPrivate; + +struct _GtkSourceUndoManager +{ + GObject base; + + GtkSourceUndoManagerPrivate *priv; +}; + +struct _GtkSourceUndoManagerClass +{ + GObjectClass parent_class; + + /* Signals */ + void (*can_undo)(GtkSourceUndoManager *um, gboolean can_undo); + void (*can_redo)(GtkSourceUndoManager *um, gboolean can_redo); +}; + +GType gtk_source_undo_manager_get_type(void) G_GNUC_CONST; + +GtkSourceUndoManager* gtk_source_undo_manager_new(GtkTextBuffer *buffer); + +gboolean gtk_source_undo_manager_can_undo(const GtkSourceUndoManager *um); +gboolean gtk_source_undo_manager_can_redo(const GtkSourceUndoManager *um); + +void gtk_source_undo_manager_undo(GtkSourceUndoManager *um); +void gtk_source_undo_manager_redo(GtkSourceUndoManager *um); + +void gtk_source_undo_manager_begin_not_undoable_action(GtkSourceUndoManager *um); +void gtk_source_undo_manager_end_not_undoable_action(GtkSourceUndoManager *um); + +gint gtk_source_undo_manager_get_max_undo_levels(GtkSourceUndoManager *um); +void gtk_source_undo_manager_set_max_undo_levels(GtkSourceUndoManager *um, + gint undo_levels); + +G_END_DECLS + +#endif // CHROME_BROWSER_AUTOCOMPLETE_UNDO_MANAGER_H_ + diff --git a/third_party/undoview/undo_view.c b/third_party/undoview/undo_view.c new file mode 100644 index 0000000..03ea16a --- /dev/null +++ b/third_party/undoview/undo_view.c @@ -0,0 +1,83 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Boilerplate code was generated by http://burtonini.com/cgi/gobject.py + +#include <gdk/gdkkeysyms.h> + +#include "undo_view.h" + +G_DEFINE_TYPE (GtkUndoView, gtk_undo_view, GTK_TYPE_TEXT_VIEW) + +static void +gtk_undo_view_dispose(GObject *object) { + GtkUndoView *uview = GTK_UNDO_VIEW(object); + + if(uview->undo_manager_) { + g_object_unref(G_OBJECT(uview->undo_manager_)); + uview->undo_manager_ = NULL; + } + G_OBJECT_CLASS(gtk_undo_view_parent_class)->dispose(object); +} + +static void +gtk_undo_view_undo(GtkUndoView *uview) { + if(gtk_source_undo_manager_can_undo(uview->undo_manager_)) + gtk_source_undo_manager_undo(uview->undo_manager_); +} + +static void +gtk_undo_view_redo(GtkUndoView *uview) { + if(gtk_source_undo_manager_can_redo(uview->undo_manager_)) + gtk_source_undo_manager_redo(uview->undo_manager_); +} + +static void +gtk_undo_view_class_init(GtkUndoViewClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GtkBindingSet *binding_set; + + g_signal_new("undo", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GtkUndoViewClass, undo), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + g_signal_new("redo", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GtkUndoViewClass, redo), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + klass->undo = gtk_undo_view_undo; + klass->redo = gtk_undo_view_redo; + + binding_set = gtk_binding_set_by_class(klass); + gtk_binding_entry_add_signal(binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_y, GDK_CONTROL_MASK, "redo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_F14, 0, "undo", 0); + + object_class->dispose = gtk_undo_view_dispose; +} + +static void +gtk_undo_view_init(GtkUndoView *self) { +} + +GtkWidget* +gtk_undo_view_new(GtkTextBuffer *buffer) { + GtkWidget *ret = g_object_new(GTK_TYPE_UNDO_VIEW, "buffer", buffer, NULL); + GTK_UNDO_VIEW(ret)->undo_manager_ = gtk_source_undo_manager_new(GTK_TEXT_BUFFER(buffer)); + + return ret; +} + diff --git a/third_party/undoview/undo_view.h b/third_party/undoview/undo_view.h new file mode 100644 index 0000000..57ab570 --- /dev/null +++ b/third_party/undoview/undo_view.h @@ -0,0 +1,51 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Boilerplate code was generated by http://burtonini.com/cgi/gobject.py + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_UNDO_VIEW_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_UNDO_VIEW_H_ + +#include <gtk/gtk.h> +#include "undo_manager.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_UNDO_VIEW gtk_undo_view_get_type() + +#define GTK_UNDO_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_UNDO_VIEW, GtkUndoView)) + +#define GTK_UNDO_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_UNDO_VIEW, GtkUndoViewClass)) + +#define GTK_IS_UNDO_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_UNDO_VIEW)) + +#define GTK_IS_UNDO_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_UNDO_VIEW)) + +#define GTK_UNDO_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_UNDO_VIEW, GtkUndoViewClass)) + +typedef struct { + GtkTextView parent; + GtkSourceUndoManager *undo_manager_; +} GtkUndoView; + +typedef struct { + GtkTextViewClass parent_class; + + void (*undo)(GtkUndoView *); + void (*redo)(GtkUndoView *); +} GtkUndoViewClass; + +GType gtk_undo_view_get_type(void); + +GtkWidget* gtk_undo_view_new(GtkTextBuffer *buffer); + +G_END_DECLS + +#endif // CHROME_BROWSER_AUTOCOMPLETE_UNDO_VIEW_H_ + diff --git a/third_party/undoview/undoview.gyp b/third_party/undoview/undoview.gyp new file mode 100644 index 0000000..430a321 --- /dev/null +++ b/third_party/undoview/undoview.gyp @@ -0,0 +1,22 @@ +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'undoview', + 'type': '<(library)', + 'sources': [ + 'undo_manager.h', + 'undo_manager.c', + 'undo_view.h', + 'undo_view.c', + ], + + 'dependencies' : [ + '../../build/linux/system.gyp:gtk', + ], + }, + ], +} |