[gtksourceview] UndoManager: reorganize the order of the functions
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview] UndoManager: reorganize the order of the functions
- Date: Thu, 21 Aug 2014 21:09:03 +0000 (UTC)
commit e3a7c1fc4d36a6d538a40e3f97ff5f4b7d40ec70
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Aug 21 22:50:34 2014 +0200
UndoManager: reorganize the order of the functions
So prototypes are not needed.
gtksourceview/gtksourceundomanagerdefault.c | 952 +++++++++++++--------------
1 files changed, 461 insertions(+), 491 deletions(-)
---
diff --git a/gtksourceview/gtksourceundomanagerdefault.c b/gtksourceview/gtksourceundomanagerdefault.c
index 358563a..aed9c98 100644
--- a/gtksourceview/gtksourceundomanagerdefault.c
+++ b/gtksourceview/gtksourceundomanagerdefault.c
@@ -135,36 +135,6 @@ struct _GtkSourceUndoManagerDefaultPrivate
GtkSourceUndoAction *modified_action;
};
-static void insert_text_cb (GtkTextBuffer *buffer,
- GtkTextIter *pos,
- const gchar *text,
- gint length,
- GtkSourceUndoManagerDefault *manager);
-
-static void delete_range_cb (GtkTextBuffer *buffer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceUndoManagerDefault *manager);
-
-static void begin_user_action_cb (GtkTextBuffer *buffer,
- GtkSourceUndoManagerDefault *manager);
-
-static void modified_changed_cb (GtkTextBuffer *buffer,
- GtkSourceUndoManagerDefault *manager);
-
-static void free_action_list (GtkSourceUndoManagerDefault *um);
-
-static void add_action (GtkSourceUndoManagerDefault *um,
- const GtkSourceUndoAction *undo_action);
-
-static void free_first_n_actions (GtkSourceUndoManagerDefault *um,
- gint n);
-
-static void check_list_size (GtkSourceUndoManagerDefault *um);
-
-static gboolean merge_action (GtkSourceUndoManagerDefault *um,
- const GtkSourceUndoAction *undo_action);
-
static void gtk_source_undo_manager_iface_init (GtkSourceUndoManagerIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkSourceUndoManagerDefault, gtk_source_undo_manager_default, G_TYPE_OBJECT,
@@ -173,229 +143,397 @@ G_DEFINE_TYPE_WITH_CODE (GtkSourceUndoManagerDefault, gtk_source_undo_manager_de
gtk_source_undo_manager_iface_init))
static void
-gtk_source_undo_manager_default_finalize (GObject *object)
+gtk_source_undo_action_free (GtkSourceUndoAction *action)
{
- GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
+ if (action == NULL)
+ {
+ return;
+ }
- free_action_list (manager);
- g_ptr_array_free (manager->priv->actions, TRUE);
+ 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_free (action);
+ g_return_if_reached ();
+ }
- G_OBJECT_CLASS (gtk_source_undo_manager_default_parent_class)->finalize (object);
+ g_free (action);
}
static void
-clear_undo (GtkSourceUndoManagerDefault *manager)
+free_action_list (GtkSourceUndoManagerDefault *um)
{
- free_action_list (manager);
-
- manager->priv->next_redo = -1;
+ gint i;
- if (manager->priv->can_undo)
+ for (i = (gint)um->priv->actions->len - 1; i >= 0; i--)
{
- manager->priv->can_undo = FALSE;
- gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ GtkSourceUndoAction *action = um->priv->actions->pdata[i];
+
+ if (action->order_in_group == 1)
+ --um->priv->num_of_groups;
+
+ if (action->modified)
+ um->priv->modified_action = NULL;
+
+ gtk_source_undo_action_free (action);
}
- if (manager->priv->can_redo)
+ /* Some arbitrary limit, to avoid wasting space */
+ if (um->priv->actions->len > 2048)
{
- manager->priv->can_redo = FALSE;
- gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ g_ptr_array_free (um->priv->actions, TRUE);
+ um->priv->actions = g_ptr_array_new ();
+ }
+ else
+ {
+ g_ptr_array_set_size (um->priv->actions, 0);
}
}
-static void
-buffer_notify (GtkSourceUndoManagerDefault *manager,
- gpointer where_the_object_was)
+static GtkSourceUndoAction *
+action_list_nth_data (GPtrArray *array,
+ gint n)
{
- manager->priv->buffer = NULL;
+ if (n < 0 || n >= (gint)array->len)
+ return NULL;
+ else
+ return array->pdata[array->len - 1 - n];
}
static void
-set_buffer (GtkSourceUndoManagerDefault *manager,
- GtkTextBuffer *buffer)
+action_list_prepend (GPtrArray *array,
+ GtkSourceUndoAction *action)
{
- g_assert (manager->priv->buffer == NULL);
+ g_ptr_array_add (array, action);
+}
- if (buffer == NULL)
+static GtkSourceUndoAction *
+action_list_last_data (GPtrArray *array)
+{
+ if (array->len != 0)
+ return array->pdata[0];
+ else
+ return NULL;
+}
+
+static void
+action_list_delete_last (GPtrArray *array)
+{
+ if (array->len != 0)
{
- return;
+ memmove (&array->pdata[0], &array->pdata[1], (array->len - 1)*sizeof (gpointer));
+ g_ptr_array_set_size (array, array->len - 1);
}
+}
- manager->priv->buffer = buffer;
+static void
+free_first_n_actions (GtkSourceUndoManagerDefault *um,
+ gint n)
+{
+ gint i;
- g_object_weak_ref (G_OBJECT (buffer),
- (GWeakNotify)buffer_notify,
- manager);
+ if (um->priv->actions->len == 0)
+ return;
- g_signal_connect_object (buffer,
- "insert-text",
- G_CALLBACK (insert_text_cb),
- manager,
- 0);
+ for (i = 0; i < n; i++)
+ {
+ GtkSourceUndoAction *action = um->priv->actions->pdata[um->priv->actions->len - 1];
- g_signal_connect_object (buffer,
- "delete-range",
- G_CALLBACK (delete_range_cb),
- manager,
- 0);
+ if (action->order_in_group == 1)
+ --um->priv->num_of_groups;
- g_signal_connect_object (buffer,
- "begin-user-action",
- G_CALLBACK (begin_user_action_cb),
- manager,
- 0);
+ if (action->modified)
+ um->priv->modified_action = NULL;
- g_signal_connect_object (buffer,
- "modified-changed",
- G_CALLBACK (modified_changed_cb),
- manager,
- 0);
+ gtk_source_undo_action_free (action);
+
+ g_ptr_array_set_size (um->priv->actions, um->priv->actions->len - 1);
+
+ if (um->priv->actions->len == 0)
+ return;
+ }
}
static void
-set_max_undo_levels (GtkSourceUndoManagerDefault *manager,
- gint max_undo_levels)
+check_list_size (GtkSourceUndoManagerDefault *um)
{
- gint old_levels;
+ gint undo_levels;
- old_levels = manager->priv->max_undo_levels;
- manager->priv->max_undo_levels = max_undo_levels;
+ undo_levels = um->priv->max_undo_levels;
- if (max_undo_levels < 1)
+ if (undo_levels < 1)
return;
- if (old_levels > max_undo_levels)
+ if (um->priv->num_of_groups > undo_levels)
{
- /* strip redo actions first */
- while (manager->priv->next_redo >= 0 &&
- (manager->priv->num_of_groups > max_undo_levels))
+ GtkSourceUndoAction *undo_action;
+
+ undo_action = action_list_last_data (um->priv->actions);
+
+ do
{
- free_first_n_actions (manager, 1);
- manager->priv->next_redo--;
- }
+ if (undo_action->order_in_group == 1)
+ --um->priv->num_of_groups;
- /* now remove undo actions if necessary */
- check_list_size (manager);
+ if (undo_action->modified)
+ um->priv->modified_action = NULL;
- /* emit "can_undo" and/or "can_redo" if appropiate */
- if (manager->priv->next_redo < 0 && manager->priv->can_redo)
+ gtk_source_undo_action_free (undo_action);
+
+ action_list_delete_last (um->priv->actions);
+
+ undo_action = action_list_last_data (um->priv->actions);
+ g_return_if_fail (undo_action != NULL);
+
+ } while ((undo_action->order_in_group > 1) ||
+ (um->priv->num_of_groups > undo_levels));
+ }
+}
+
+/*
+ * merge_action:
+ * @um: a #GtkSourceUndoManagerDefault.
+ * @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 sucessful, %FALSE otherwise.
+ */
+static gboolean
+merge_action (GtkSourceUndoManagerDefault *um,
+ const GtkSourceUndoAction *undo_action)
+{
+ GtkSourceUndoAction *last_action;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER_DEFAULT (um), FALSE);
+ g_return_val_if_fail (um->priv != NULL, FALSE);
+
+ if (um->priv->actions->len == 0)
+ return FALSE;
+
+ last_action = action_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)))
{
- manager->priv->can_redo = FALSE;
- gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ last_action->mergeable = FALSE;
+ return FALSE;
}
- if (manager->priv->can_undo &&
- manager->priv->next_redo >= (gint)manager->priv->actions->len - 1)
+ if (last_action->action.delete.start == undo_action->action.delete.start)
{
- manager->priv->can_undo = FALSE;
- gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ 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;
-static void
-gtk_source_undo_manager_default_dispose (GObject *object)
-{
- GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
+ /* 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;
+ }
- if (manager->priv->buffer != NULL)
+ 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)
{
- clear_undo (manager);
+ gchar* str;
- g_object_weak_unref (G_OBJECT (manager->priv->buffer),
- (GWeakNotify)buffer_notify,
- manager);
+#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;
- manager->priv->buffer = NULL;
}
+ else
+ /* Unknown action inside undo merge encountered */
+ g_return_val_if_reached (TRUE);
- G_OBJECT_CLASS (gtk_source_undo_manager_default_parent_class)->dispose (object);
+ return TRUE;
}
static void
-gtk_source_undo_manager_default_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+add_action (GtkSourceUndoManagerDefault *um,
+ const GtkSourceUndoAction *undo_action)
{
- GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
+ GtkSourceUndoAction* action;
- switch (prop_id)
+ if (um->priv->next_redo >= 0)
{
- case PROP_BUFFER:
- set_buffer (manager, g_value_get_object (value));
- break;
+ free_first_n_actions (um, um->priv->next_redo + 1);
+ }
- case PROP_MAX_UNDO_LEVELS:
- gtk_source_undo_manager_default_set_max_undo_levels (manager, g_value_get_int
(value));
- break;
+ um->priv->next_redo = -1;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ if (!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;
+
+ action_list_prepend (um->priv->actions, action);
+ }
+
+ check_list_size (um);
+
+ if (!um->priv->can_undo)
+ {
+ um->priv->can_undo = TRUE;
+ gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (um));
+ }
+
+ if (um->priv->can_redo)
+ {
+ um->priv->can_redo = FALSE;
+ gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (um));
}
}
static void
-gtk_source_undo_manager_default_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+clear_undo (GtkSourceUndoManagerDefault *manager)
{
- GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
+ free_action_list (manager);
- switch (prop_id)
- {
- case PROP_BUFFER:
- g_value_set_object (value, manager->priv->buffer);
- break;
+ manager->priv->next_redo = -1;
- case PROP_MAX_UNDO_LEVELS:
- g_value_set_int (value, manager->priv->max_undo_levels);
- break;
+ if (manager->priv->can_undo)
+ {
+ manager->priv->can_undo = FALSE;
+ gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ if (manager->priv->can_redo)
+ {
+ manager->priv->can_redo = FALSE;
+ gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
}
}
static void
-gtk_source_undo_manager_default_class_init (GtkSourceUndoManagerDefaultClass *klass)
+set_max_undo_levels (GtkSourceUndoManagerDefault *manager,
+ gint max_undo_levels)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ gint old_levels;
- object_class->finalize = gtk_source_undo_manager_default_finalize;
- object_class->dispose = gtk_source_undo_manager_default_dispose;
+ old_levels = manager->priv->max_undo_levels;
+ manager->priv->max_undo_levels = max_undo_levels;
- object_class->set_property = gtk_source_undo_manager_default_set_property;
- object_class->get_property = gtk_source_undo_manager_default_get_property;
+ if (max_undo_levels < 1)
+ return;
- g_object_class_install_property (object_class,
- PROP_BUFFER,
- g_param_spec_object ("buffer",
- "Buffer",
- "The text buffer to add undo support on",
- GTK_TYPE_TEXT_BUFFER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ if (old_levels > max_undo_levels)
+ {
+ /* strip redo actions first */
+ while (manager->priv->next_redo >= 0 &&
+ (manager->priv->num_of_groups > max_undo_levels))
+ {
+ free_first_n_actions (manager, 1);
+ manager->priv->next_redo--;
+ }
- g_object_class_install_property (object_class,
- PROP_MAX_UNDO_LEVELS,
- g_param_spec_int ("max-undo-levels",
- "Maximum Undo Levels",
- "Number of undo levels for the buffer",
- -1,
- G_MAXINT,
- DEFAULT_MAX_UNDO_LEVELS,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-}
+ /* now remove undo actions if necessary */
+ check_list_size (manager);
-static void
-gtk_source_undo_manager_default_init (GtkSourceUndoManagerDefault *manager)
-{
- manager->priv = gtk_source_undo_manager_default_get_instance_private (manager);
- manager->priv->actions = g_ptr_array_new ();
- manager->priv->next_redo = -1;
+ /* emit "can_undo" and/or "can_redo" if appropiate */
+ if (manager->priv->next_redo < 0 && manager->priv->can_redo)
+ {
+ manager->priv->can_redo = FALSE;
+ gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ }
+
+ if (manager->priv->can_undo &&
+ manager->priv->next_redo >= (gint)manager->priv->actions->len - 1)
+ {
+ manager->priv->can_undo = FALSE;
+ gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (manager));
+ }
+ }
}
static void
@@ -517,42 +655,6 @@ get_chars (GtkTextBuffer *buffer,
return gtk_text_buffer_get_slice (buffer, &start_iter, &end_iter, TRUE);
}
-static GtkSourceUndoAction *
-action_list_nth_data (GPtrArray *array,
- gint n)
-{
- if (n < 0 || n >= (gint)array->len)
- return NULL;
- else
- return array->pdata[array->len - 1 - n];
-}
-
-static void
-action_list_prepend (GPtrArray *array,
- GtkSourceUndoAction *action)
-{
- g_ptr_array_add (array, action);
-}
-
-static GtkSourceUndoAction *
-action_list_last_data (GPtrArray *array)
-{
- if (array->len != 0)
- return array->pdata[0];
- else
- return NULL;
-}
-
-static void
-action_list_delete_last (GPtrArray *array)
-{
- if (array->len != 0)
- {
- memmove (&array->pdata[0], &array->pdata[1], (array->len - 1)*sizeof (gpointer));
- g_ptr_array_set_size (array, array->len - 1);
- }
-}
-
static void
selection_bounds_offsets (GtkTextBuffer *buffer,
gint *insert_offset,
@@ -805,61 +907,6 @@ gtk_source_undo_manager_redo_impl (GtkSourceUndoManager *manager)
}
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_free (action);
- g_return_if_reached ();
- }
-
- g_free (action);
-}
-
-static void
-free_action_list (GtkSourceUndoManagerDefault *um)
-{
- gint i;
-
- for (i = (gint)um->priv->actions->len - 1; i >= 0; i--)
- {
- GtkSourceUndoAction *action = um->priv->actions->pdata[i];
-
- if (action->order_in_group == 1)
- --um->priv->num_of_groups;
-
- if (action->modified)
- um->priv->modified_action = NULL;
-
- gtk_source_undo_action_free (action);
- }
-
- /* Some arbitrary limit, to avoid wasting space */
- if (um->priv->actions->len > 2048)
- {
- g_ptr_array_free (um->priv->actions, TRUE);
- um->priv->actions = g_ptr_array_new ();
- }
- else
- {
- g_ptr_array_set_size (um->priv->actions, 0);
- }
-}
-
-static void
insert_text_cb (GtkTextBuffer *buffer,
GtkTextIter *pos,
const gchar *text,
@@ -950,298 +997,221 @@ begin_user_action_cb (GtkTextBuffer *buffer,
}
static void
-add_action (GtkSourceUndoManagerDefault *um,
- const GtkSourceUndoAction *undo_action)
+modified_changed_cb (GtkTextBuffer *buffer,
+ GtkSourceUndoManagerDefault *manager)
{
- GtkSourceUndoAction* action;
+ GtkSourceUndoAction *action;
+ gint idx;
- if (um->priv->next_redo >= 0)
- {
- free_first_n_actions (um, um->priv->next_redo + 1);
- }
+ if (manager->priv->actions->len == 0)
+ return;
- um->priv->next_redo = -1;
+ idx = manager->priv->next_redo + 1;
+ action = action_list_nth_data (manager->priv->actions, idx);
- if (!merge_action (um, undo_action))
+ if (gtk_text_buffer_get_modified (buffer) == FALSE)
{
- action = g_new (GtkSourceUndoAction, 1);
- *action = *undo_action;
+ if (action != NULL)
+ action->mergeable = FALSE;
- 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
+ if (manager->priv->modified_action != NULL)
{
- g_free (action);
- g_return_if_reached ();
+ manager->priv->modified_action->modified = FALSE;
+ manager->priv->modified_action = NULL;
}
- ++um->priv->actions_in_current_group;
- action->order_in_group = um->priv->actions_in_current_group;
+ return;
+ }
- if (action->order_in_group == 1)
- ++um->priv->num_of_groups;
+ if (action == NULL)
+ {
+ g_return_if_fail (manager->priv->running_not_undoable_actions > 0);
- action_list_prepend (um->priv->actions, action);
+ return;
}
- check_list_size (um);
-
- if (!um->priv->can_undo)
+ if (manager->priv->modified_action != NULL)
{
- um->priv->can_undo = TRUE;
- gtk_source_undo_manager_can_undo_changed (GTK_SOURCE_UNDO_MANAGER (um));
+ g_message ("%s: oops", G_STRLOC);
+ return;
}
- if (um->priv->can_redo)
+ if (action->order_in_group > 1)
+ manager->priv->modified_undoing_group = TRUE;
+
+ while (action->order_in_group > 1)
{
- um->priv->can_redo = FALSE;
- gtk_source_undo_manager_can_redo_changed (GTK_SOURCE_UNDO_MANAGER (um));
+ action = action_list_nth_data (manager->priv->actions, ++idx);
+ g_return_if_fail (action != NULL);
}
+
+ action->modified = TRUE;
+ manager->priv->modified_action = action;
}
static void
-free_first_n_actions (GtkSourceUndoManagerDefault *um,
- gint n)
+buffer_notify (GtkSourceUndoManagerDefault *manager,
+ gpointer where_the_object_was)
{
- gint i;
-
- if (um->priv->actions->len == 0)
- return;
-
- for (i = 0; i < n; i++)
- {
- GtkSourceUndoAction *action = um->priv->actions->pdata[um->priv->actions->len - 1];
-
- if (action->order_in_group == 1)
- --um->priv->num_of_groups;
-
- if (action->modified)
- um->priv->modified_action = NULL;
-
- gtk_source_undo_action_free (action);
-
- g_ptr_array_set_size (um->priv->actions, um->priv->actions->len - 1);
-
- if (um->priv->actions->len == 0)
- return;
- }
+ manager->priv->buffer = NULL;
}
static void
-check_list_size (GtkSourceUndoManagerDefault *um)
+set_buffer (GtkSourceUndoManagerDefault *manager,
+ GtkTextBuffer *buffer)
{
- gint undo_levels;
-
- undo_levels = um->priv->max_undo_levels;
-
- if (undo_levels < 1)
- return;
+ g_assert (manager->priv->buffer == NULL);
- if (um->priv->num_of_groups > undo_levels)
+ if (buffer == NULL)
{
- GtkSourceUndoAction *undo_action;
-
- undo_action = action_list_last_data (um->priv->actions);
+ return;
+ }
- do
- {
- if (undo_action->order_in_group == 1)
- --um->priv->num_of_groups;
+ manager->priv->buffer = buffer;
- if (undo_action->modified)
- um->priv->modified_action = NULL;
+ g_object_weak_ref (G_OBJECT (buffer),
+ (GWeakNotify)buffer_notify,
+ manager);
- gtk_source_undo_action_free (undo_action);
+ g_signal_connect_object (buffer,
+ "insert-text",
+ G_CALLBACK (insert_text_cb),
+ manager,
+ 0);
- action_list_delete_last (um->priv->actions);
+ g_signal_connect_object (buffer,
+ "delete-range",
+ G_CALLBACK (delete_range_cb),
+ manager,
+ 0);
- undo_action = action_list_last_data (um->priv->actions);
- g_return_if_fail (undo_action != NULL);
+ g_signal_connect_object (buffer,
+ "begin-user-action",
+ G_CALLBACK (begin_user_action_cb),
+ manager,
+ 0);
- } while ((undo_action->order_in_group > 1) ||
- (um->priv->num_of_groups > undo_levels));
- }
+ g_signal_connect_object (buffer,
+ "modified-changed",
+ G_CALLBACK (modified_changed_cb),
+ manager,
+ 0);
}
-/**
- * gtk_source_undo_manager_default_merge_action:
- * @um: a #GtkSourceUndoManagerDefault.
- * @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 sucessful, %FALSE otherwise.
- **/
-static gboolean
-merge_action (GtkSourceUndoManagerDefault *um,
- const GtkSourceUndoAction *undo_action)
+static void
+gtk_source_undo_manager_default_dispose (GObject *object)
{
- GtkSourceUndoAction *last_action;
-
- g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER_DEFAULT (um), FALSE);
- g_return_val_if_fail (um->priv != NULL, FALSE);
-
- if (um->priv->actions->len == 0)
- return FALSE;
-
- last_action = action_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;
- }
+ GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
- if (undo_action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE)
+ if (manager->priv->buffer != NULL)
{
- 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;
- }
+ clear_undo (manager);
- if (last_action->action.delete.start == undo_action->action.delete.start)
- {
- gchar *str;
+ g_object_weak_unref (G_OBJECT (manager->priv->buffer),
+ (GWeakNotify)buffer_notify,
+ manager);
-#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)))
+ manager->priv->buffer = NULL;
+ }
- /* 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;
- }
+ G_OBJECT_CLASS (gtk_source_undo_manager_default_parent_class)->dispose (object);
+}
- str = g_strdup_printf ("%s%s", last_action->action.delete.text,
- undo_action->action.delete.text);
+static void
+gtk_source_undo_manager_default_finalize (GObject *object)
+{
+ GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
- 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;
+ free_action_list (manager);
+ g_ptr_array_free (manager->priv->actions, TRUE);
- /* 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;
- }
+ G_OBJECT_CLASS (gtk_source_undo_manager_default_parent_class)->finalize (object);
+}
- str = g_strdup_printf ("%s%s", undo_action->action.delete.text,
- last_action->action.delete.text);
+static void
+gtk_source_undo_manager_default_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
- 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)
+ switch (prop_id)
{
- 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);
+ case PROP_BUFFER:
+ set_buffer (manager, g_value_get_object (value));
+ break;
- 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;
+ case PROP_MAX_UNDO_LEVELS:
+ gtk_source_undo_manager_default_set_max_undo_levels (manager, g_value_get_int
(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
- else
- /* Unknown action inside undo merge encountered */
- g_return_val_if_reached (TRUE);
-
- return TRUE;
}
static void
-modified_changed_cb (GtkTextBuffer *buffer,
- GtkSourceUndoManagerDefault *manager)
+gtk_source_undo_manager_default_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GtkSourceUndoAction *action;
- gint idx;
-
- if (manager->priv->actions->len == 0)
- return;
-
- idx = manager->priv->next_redo + 1;
- action = action_list_nth_data (manager->priv->actions, idx);
+ GtkSourceUndoManagerDefault *manager = GTK_SOURCE_UNDO_MANAGER_DEFAULT (object);
- if (gtk_text_buffer_get_modified (buffer) == FALSE)
+ switch (prop_id)
{
- if (action != NULL)
- action->mergeable = FALSE;
+ case PROP_BUFFER:
+ g_value_set_object (value, manager->priv->buffer);
+ break;
- if (manager->priv->modified_action != NULL)
- {
- manager->priv->modified_action->modified = FALSE;
- manager->priv->modified_action = NULL;
- }
+ case PROP_MAX_UNDO_LEVELS:
+ g_value_set_int (value, manager->priv->max_undo_levels);
+ break;
- return;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
+}
- if (action == NULL)
- {
- g_return_if_fail (manager->priv->running_not_undoable_actions > 0);
+static void
+gtk_source_undo_manager_default_class_init (GtkSourceUndoManagerDefaultClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- return;
- }
+ object_class->dispose = gtk_source_undo_manager_default_dispose;
+ object_class->finalize = gtk_source_undo_manager_default_finalize;
- if (manager->priv->modified_action != NULL)
- {
- g_message ("%s: oops", G_STRLOC);
- return;
- }
+ object_class->set_property = gtk_source_undo_manager_default_set_property;
+ object_class->get_property = gtk_source_undo_manager_default_get_property;
- if (action->order_in_group > 1)
- manager->priv->modified_undoing_group = TRUE;
+ g_object_class_install_property (object_class,
+ PROP_BUFFER,
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "The text buffer to add undo support on",
+ GTK_TYPE_TEXT_BUFFER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- while (action->order_in_group > 1)
- {
- action = action_list_nth_data (manager->priv->actions, ++idx);
- g_return_if_fail (action != NULL);
- }
+ g_object_class_install_property (object_class,
+ PROP_MAX_UNDO_LEVELS,
+ g_param_spec_int ("max-undo-levels",
+ "Maximum Undo Levels",
+ "Number of undo levels for the buffer",
+ -1,
+ G_MAXINT,
+ DEFAULT_MAX_UNDO_LEVELS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
- action->modified = TRUE;
- manager->priv->modified_action = action;
+static void
+gtk_source_undo_manager_default_init (GtkSourceUndoManagerDefault *manager)
+{
+ manager->priv = gtk_source_undo_manager_default_get_instance_private (manager);
+ manager->priv->actions = g_ptr_array_new ();
+ manager->priv->next_redo = -1;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]