[Commits] [SCM] claws branch, master, updated. 3.9.3-217-g0dbb415
colin at claws-mail.org
colin at claws-mail.org
Thu May 22 21:10:06 CEST 2014
The branch master of project "claws" (Claws Mail) has been updated
via 0dbb415b36c512aa23ef1eb71d48cb7d78c72be5 (commit)
from eba3ff6f6f06cf91fe0016a706073696d3839531 (commit)
- Log -----------------------------------------------------------------
commit 0dbb415b36c512aa23ef1eb71d48cb7d78c72be5
Author: Colin Leroy <colin at colino.net>
Date: Thu May 22 20:57:01 2014 +0200
Fix Undo after wrapping a paragraph, which undid every line wrap one by one, and make it atomic.
diff --git a/src/compose.c b/src/compose.c
index 55c34ed..5da0cc0 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -4695,9 +4695,14 @@ static void compose_wrap_all_full(Compose *compose, gboolean force)
buffer = gtk_text_view_get_buffer(text);
gtk_text_buffer_get_start_iter(buffer, &iter);
+
+ undo_wrapping(compose->undostruct, TRUE);
+
while (!gtk_text_iter_is_end(&iter) && modified)
modified = compose_beautify_paragraph(compose, &iter, force);
+ undo_wrapping(compose->undostruct, FALSE);
+
}
static void compose_set_title(Compose *compose)
diff --git a/src/undo.c b/src/undo.c
index 0111733..ec24e6f 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -46,6 +46,15 @@ struct _UndoInfo
gint mergeable;
};
+struct _UndoWrap
+{
+ gint lock;
+ gchar *pre_wrap_content;
+ gint start_pos;
+ gint end_pos;
+ gint len_change;
+};
+
static void undo_free_list (GList **list_pointer);
static void undo_check_size (UndoMain *undostruct);
static gint undo_merge (GList *list,
@@ -526,10 +535,147 @@ void undo_unblock(UndoMain *undostruct)
undostruct);
}
+/* Init the WrapInfo structure */
+static void init_wrap_undo(UndoMain *undostruct)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ cm_return_if_fail(undostruct != NULL);
+ cm_return_if_fail(undostruct->wrap_info == NULL);
+
+ undostruct->wrap_info = g_new0(UndoWrap, 1);
+
+ /* Save the whole buffer as original contents. We'll retain the
+ * changed region when exiting wrap mode.
+ */
+ buffer = gtk_text_view_get_buffer(undostruct->textview);
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ undostruct->wrap_info->pre_wrap_content
+ = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+ undostruct->wrap_info->lock = 0;
+
+ /* start_pos == -1 means nothing changed yet. */
+ undostruct->wrap_info->start_pos = -1;
+ undostruct->wrap_info->end_pos = -1;
+ undostruct->wrap_info->len_change = 0;
+}
+
+static void end_wrap_undo(UndoMain *undostruct)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gchar *old_contents = NULL;
+ gchar *cur_contents = NULL;
+ gchar *new_contents = NULL;
+
+ cm_return_if_fail(undostruct != NULL);
+ cm_return_if_fail(undostruct->wrap_info != NULL);
+
+ /* If start_pos is still == -1, it means nothing changed. */
+ if (undostruct->wrap_info->start_pos == -1)
+ goto cleanup;
+
+ /* get the whole new (wrapped) contents */
+ buffer = gtk_text_view_get_buffer(undostruct->textview);
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ cur_contents = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+ debug_print("wrapping done from %d to %d, len change: %d\n",
+ undostruct->wrap_info->start_pos,
+ undostruct->wrap_info->end_pos,
+ undostruct->wrap_info->len_change);
+
+ /* keep the relevant old unwrapped part, which is what
+ * was between start_pos & end_pos - len_change
+ */
+ old_contents = g_utf8_substring(
+ undostruct->wrap_info->pre_wrap_content,
+ undostruct->wrap_info->start_pos,
+ undostruct->wrap_info->end_pos
+ - undostruct->wrap_info->len_change);
+
+ /* and get the changed contents, from start_pos to end_pos. */
+ new_contents = g_utf8_substring(
+ cur_contents,
+ undostruct->wrap_info->start_pos,
+ undostruct->wrap_info->end_pos);
+
+ /* add the deleted (unwrapped) text to the undo pile */
+ undo_add(old_contents,
+ undostruct->wrap_info->start_pos,
+ undostruct->wrap_info->end_pos
+ - undostruct->wrap_info->len_change,
+ UNDO_ACTION_REPLACE_DELETE,
+ undostruct);
+
+ /* add the inserted (wrapped) text to the undo pile */
+ undo_add(new_contents,
+ undostruct->wrap_info->start_pos,
+ undostruct->wrap_info->end_pos,
+ UNDO_ACTION_REPLACE_INSERT,
+ undostruct);
+
+ g_free(old_contents);
+ g_free(cur_contents);
+ g_free(new_contents);
+cleanup:
+ g_free(undostruct->wrap_info->pre_wrap_content);
+ g_free(undostruct->wrap_info);
+ undostruct->wrap_info = NULL;
+}
+
+static void update_wrap_undo(UndoMain *undostruct, const gchar *text, int start,
+ int end, UndoAction action)
+{
+ gint len = end - start;
+
+ /* If we don't yet have a start position, or farther than
+ * current, store it.
+ */
+ if (undostruct->wrap_info->start_pos == -1
+ || start < undostruct->wrap_info->start_pos) {
+ undostruct->wrap_info->start_pos = start;
+ }
+
+ if (action == UNDO_ACTION_INSERT) {
+ /* If inserting, the end of the region is at the end of the
+ * change, and the total length of the changed region
+ * increases.
+ */
+ undostruct->wrap_info->end_pos = end;
+ undostruct->wrap_info->len_change += len;
+ } else if (action == UNDO_ACTION_DELETE) {
+ /* If deleting, the end of the region is at the start of the
+ * change, and the total length of the changed region
+ * decreases.
+ */
+ undostruct->wrap_info->end_pos = start;
+ undostruct->wrap_info->len_change -= len;
+ }
+}
+
+/* Set wrapping mode, in which changes are agglomerated until
+ * the end of wrapping mode.
+ */
void undo_wrapping(UndoMain *undostruct, gboolean wrap)
{
-// debug_print("undo wrapping now %d\n", wrap);
- undostruct->wrap = wrap;
+ if (wrap) {
+ /* Start (or go deeper in) wrapping mode */
+ if (undostruct->wrap_info == NULL)
+ init_wrap_undo(undostruct);
+ undostruct->wrap_info->lock++;
+ } else if (undostruct->wrap_info != NULL) {
+ /* exit (& possible stop) one level of wrapping mode */
+ undostruct->wrap_info->lock--;
+ if (undostruct->wrap_info->lock == 0)
+ end_wrap_undo(undostruct);
+ } else {
+ g_warning("undo already out of wrap mode");
+ }
}
void undo_insert_text_cb(GtkTextBuffer *textbuf, GtkTextIter *iter,
@@ -538,29 +684,22 @@ void undo_insert_text_cb(GtkTextBuffer *textbuf, GtkTextIter *iter,
{
gchar *text_to_insert;
gint pos;
+ glong utf8_len;
+
if (prefs_common.undolevels <= 0) return;
pos = gtk_text_iter_get_offset(iter);
- if (undostruct->wrap && undostruct->undo) {
- UndoInfo *last_undo = undostruct->undo->data;
- if (last_undo && (last_undo->action == UNDO_ACTION_INSERT
- || last_undo->action == UNDO_ACTION_REPLACE_INSERT)
- && last_undo->start_pos < pos && last_undo->end_pos > pos) {
- GtkTextIter start,end;
- last_undo->end_pos += g_utf8_strlen(new_text, -1);
- gtk_text_buffer_get_iter_at_offset(textbuf, &start, last_undo->start_pos);
- gtk_text_buffer_get_iter_at_offset(textbuf, &end, last_undo->end_pos);
- g_free(last_undo->text);
- last_undo->text = gtk_text_buffer_get_text(textbuf, &start, &end, FALSE);
- debug_print("add:undo upd %d-%d\n", last_undo->start_pos, last_undo->end_pos);
- return;
- } else if (last_undo)
- debug_print("add:last: %d, %d-%d (%d)\n", last_undo->action,
- last_undo->start_pos, last_undo->end_pos, pos);
- }
Xstrndup_a(text_to_insert, new_text, new_text_length, return);
- debug_print("add:undo add %d-%ld\n", pos, pos + g_utf8_strlen(text_to_insert, -1));
- undo_add(text_to_insert, pos, pos + g_utf8_strlen(text_to_insert, -1),
+ utf8_len = g_utf8_strlen(text_to_insert, -1);
+
+ if (undostruct->wrap_info != NULL) {
+ update_wrap_undo(undostruct, text_to_insert,
+ pos, pos + utf8_len, UNDO_ACTION_INSERT);
+ return;
+ }
+
+ debug_print("add:undo add %d-%ld\n", pos, utf8_len);
+ undo_add(text_to_insert, pos, pos + utf8_len,
UNDO_ACTION_INSERT, undostruct);
}
@@ -578,23 +717,9 @@ void undo_delete_text_cb(GtkTextBuffer *textbuf, GtkTextIter *start,
start_pos = gtk_text_iter_get_offset(start);
end_pos = gtk_text_iter_get_offset(end);
- if (undostruct->wrap && undostruct->undo) {
- UndoInfo *last_undo = undostruct->undo->data;
- if (last_undo && (last_undo->action == UNDO_ACTION_INSERT
- || last_undo->action == UNDO_ACTION_REPLACE_INSERT)
- && last_undo->start_pos < start_pos && last_undo->end_pos > end_pos) {
- GtkTextIter start,end;
- last_undo->end_pos -= g_utf8_strlen(text_to_delete, -1);
- gtk_text_buffer_get_iter_at_offset(textbuf, &start, last_undo->start_pos);
- gtk_text_buffer_get_iter_at_offset(textbuf, &end, last_undo->end_pos);
- g_free(last_undo->text);
- last_undo->text = gtk_text_buffer_get_text(textbuf, &start, &end, FALSE);
- debug_print("del:undo upd %d-%d\n", last_undo->start_pos, last_undo->end_pos);
- return;
- } else if (last_undo)
- debug_print("del:last: %d, %d-%d (%d)\n", last_undo->action,
- last_undo->start_pos, last_undo->end_pos, start_pos);
-
+ if (undostruct->wrap_info != NULL) {
+ update_wrap_undo(undostruct, text_to_delete, start_pos, end_pos, UNDO_ACTION_DELETE);
+ return;
}
debug_print("del:undo add %d-%d\n", start_pos, end_pos);
undo_add(text_to_delete, start_pos, end_pos, UNDO_ACTION_DELETE,
diff --git a/src/undo.h b/src/undo.h
index 292eff3..3f7634b 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -42,6 +42,7 @@ typedef enum
} UndoState;
typedef struct _UndoMain UndoMain;
+typedef struct _UndoWrap UndoWrap;
typedef void (*UndoChangeStateFunc) (UndoMain *undostruct,
gint undo_state,
@@ -62,7 +63,8 @@ struct _UndoMain
gboolean redo_state : 1;
gint paste;
- gint wrap;
+
+ UndoWrap *wrap_info;
};
UndoMain *undo_init (GtkWidget *text);
-----------------------------------------------------------------------
Summary of changes:
src/compose.c | 5 ++
src/undo.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++-----------
src/undo.h | 4 +-
3 files changed, 171 insertions(+), 39 deletions(-)
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list