Author: erikharrison
Date: 2007-01-15 21:47:38 +0000 (Mon, 15 Jan 2007)
New Revision: 24498

Modified:
   mousepad/trunk/src/callback.c
   mousepad/trunk/src/undo.c
   mousepad/trunk/src/undo.h
Log:
Moving undo system changes from local tree to Xfce svn, and resuming work there


Modified: mousepad/trunk/src/callback.c
===================================================================
--- mousepad/trunk/src/callback.c       2007-01-15 21:38:34 UTC (rev 24497)
+++ mousepad/trunk/src/callback.c       2007-01-15 21:47:38 UTC (rev 24498)
@@ -264,14 +264,12 @@
 
 void cb_edit_undo(StructData *sd)
 {
-       while (undo_undo(sd->mainwin->textbuffer)) {}
+       undo_undo(sd->mainwin->textbuffer);
 }
 
 void cb_edit_redo(StructData *sd)
 {
-       while (undo_redo(sd->mainwin->textbuffer)) {
-               undo_set_sequency(TRUE);
-       }
+       undo_redo(sd->mainwin->textbuffer);
 }
 
 void cb_edit_cut(StructData *sd)

Modified: mousepad/trunk/src/undo.c
===================================================================
--- mousepad/trunk/src/undo.c   2007-01-15 21:38:34 UTC (rev 24497)
+++ mousepad/trunk/src/undo.c   2007-01-15 21:47:38 UTC (rev 24498)
@@ -26,14 +26,32 @@
 
 #define DV(x)
 
+/* This struct is used to carry info about a undo/redo steps.
+ * ->next holds a pointer to the next element in the stack. 
+          See the GTrashStack docs for more (vague) info.
+ * ->command holds the type of action, backspace, delete, or inset.
+ * ->start is the _character_ offset of the beginning of the step
+ * ->end is offset for the end of the step, mostly for deletions
+ * ->seq is a flag for cases (like overwriting text with a paste)
+ *       where one user level undo involves multiple steps. For 
+ *       example, overwriting text via a paste involves an deletion
+ *       and an insertion. The insertion will be at the top of the 
+ *       stack with the seq flag set, the deletion below it, with
+ *       the flag unset. If a step with the flag set is undone or
+ *       redone, we perform the next step as well, until we undo
+ *       or redo a step without the flag set
+ * ->sty, the text of the change
+ */
 typedef struct {
+       GTrashStack *next;
        gint command;
        gint start;
        gint end;
-       gboolean seq; /* sequency flag */
+       gboolean seq; 
        gchar *str;
 } UndoInfo;
 
+/* For the command field in UndoInfo*/
 enum {
        BS = 0,
        DEL,
@@ -43,14 +61,26 @@
 static GtkWidget *undo_menu_item = NULL;
 static GtkWidget *redo_menu_item = NULL;
 
-static GList *undo_list = NULL;
-static GList *redo_list = NULL;
+static GTrashStack *undo_stack = NULL;
+static GTrashStack *redo_stack = NULL;
+/*undo_gstr acts like a temp for UndoInfo->str, growing or shrinking
+  with insertions until a word boundry is set, and it's copied to
+  ui->str */
 static GString *undo_gstr;
+/*we keep one of these around to "build up" before copying it
+into the undo list when a word boundry is met*/
 static UndoInfo *ui_tmp;
+/*doesn't seem to do anything but store 0 so that we can know when we're
+out of data in the undo_list EXPME*/
 static gint step_modif;
 static GtkWidget *view;
+/*I dunno why we track whether or not overwrite is on. I mean, it
+seems like a good idea, I guess EXPME*/
 static gboolean overwrite_mode = FALSE;
+/*instead of passing stuff in through arguments, we use locals. Fun*/
 static guint keyval;
+/*on occasion we need the previous keyval to determine whether or not we've
+hit a word boundry*/
 static guint prev_keyval;/*, keyevent_setval(0); */
 
 static void cb_toggle_overwrite(void)
@@ -61,22 +91,31 @@
 
 static void undo_clear_undo_info(void)
 {
-       while (g_list_length(undo_list)) {
-               g_free(((UndoInfo *)undo_list->data)->str);
-               g_free(undo_list->data);
-               undo_list = g_list_delete_link(undo_list, undo_list);
+       UndoInfo *ui;
+       
+       /*Peeking is O(1) while checking the height is O(N)*/
+       while (g_trash_stack_peek(&undo_stack)) {
+               ui = (UndoInfo *)g_trash_stack_pop(&undo_stack);
+               g_free(ui->str);
+               g_free(ui);
        }
 }
 
 static void undo_clear_redo_info(void)
 {
-       while (g_list_length(redo_list)) {
-               g_free(((UndoInfo *)redo_list->data)->str);
-               g_free(redo_list->data);
-               redo_list = g_list_delete_link(redo_list, redo_list);
+       UndoInfo *ri;
+       
+       while (g_trash_stack_peek(&redo_stack)) {
+               ri = (UndoInfo *)g_trash_stack_pop(&redo_stack);
+               g_free(ri->str);
+               g_free(ri);
        }
+       
 }
 
+/*takes command, offsets and a string, and builds a UndoInfo object, which
+we stuff into the undo_list. Note that you can't set ->seq this way.
+Also (FIXME) we have no use for the buffer passed to us*/
 static void undo_append_undo_info(GtkTextBuffer *buffer, gint command, gint 
start, gint end, gchar *str)
 {
        UndoInfo *ui = g_malloc(sizeof(UndoInfo));
@@ -86,10 +125,25 @@
        ui->end = end;
        ui->seq = FALSE;
        ui->str = str;
-       undo_list = g_list_append(undo_list, ui);
-DV(g_print("undo_cb: %d %s (%d-%d)\n", command, str, start, end));
+       g_trash_stack_push(&undo_stack, ui);
+DV(g_print("undo_append_undo_info: command: %d string: %s range: (%d-%d)\n", 
command, str, start, end));
 }
 
+/* Here it is. The monster that drives everything around here and does
+ * most of the work. The various callbacks hooked into the buffer pass
+ * the buck here. Since this function will be called for every little
+ * change to the buffer it attempts to determine if the current change
+ * is part of an ongoing action the user will want to undo/redo in one 
+ * go (confusingly, also called a sequence) or the start of a new 
+ * sequence. If it's part of an ongoing sequence, it builds up data in 
+ * the undo_gstr or ui_tmp variables. If it's the start of a new 
+ * sequence, it copies the ui_tmp and undo_gstr data into the 
+ * undo_info list (via undo_append_undo_info), and then clears ui_tmp
+ * and undo_gstr for the next run. 
+ *
+ * Note that a sequence is not just a series of insertions and a word
+ * boundry, but also a linefeed, a deletion or a backspace
+ */ 
 static void undo_create_undo_info(GtkTextBuffer *buffer, gint command, gint 
start, gint end)
 {
        GtkTextIter start_iter, end_iter;
@@ -98,6 +152,9 @@
        
        gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, start);
        gtk_text_buffer_get_iter_at_offset(buffer, &end_iter, end);
+       
+       /*The callbacks have the text - why do we get it from the buffer? 
+         For redo, maybe? EXPME*/
        str = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
        
        if (undo_gstr->len) {
@@ -168,7 +225,7 @@
                g_string_append(undo_gstr, str);
        } else 
                undo_append_undo_info(buffer, command, start, end, 
g_strdup(str));
-       
+DV(g_print("undo_create_undo_info: ui_tmp->command: %d", ui_tmp->command));
        undo_clear_redo_info();
        prev_keyval = keyval;
        keyevent_setval(0);
@@ -186,9 +243,13 @@
        end = gtk_text_iter_get_offset(end_iter);
        
 DV(g_print("delete-range: keyval = 0x%x\n", keyval));
+
+       /*Overwriting text from the menubar or context menu. I have
+       no idea why ovewriting from the context menu generates a keyevent
+       but inserting does not (see comments in the inset-text callback*/       
+       if (!keyval && prev_keyval) 
+               undo_set_sequency(TRUE);
        
-       if (!keyval && prev_keyval)
-               undo_set_sequency(TRUE);
        if (keyval == 0x10000 && prev_keyval > 0x10000) /* for Ctrl+V overwrite 
*/
                undo_set_sequency(TRUE);
        if (keyval == GDK_BackSpace)
@@ -206,14 +267,6 @@
        end = gtk_text_iter_get_offset(iter);
        start = end - g_utf8_strlen(str, -1);
        
-DV(g_print("insert-text: keyval = 0x%x\n", keyevent_getval()));
-       
-       if (!keyval && prev_keyval)
-               undo_set_sequency(TRUE);
-#if 0
-       if (keyval == 0x10000 && prev_keyval > 0x10000) /* don't need probably 
*/
-               undo_set_sequency(TRUE);
-#endif
        undo_create_undo_info(buffer, INS, start, end);
 }
 
@@ -239,15 +292,19 @@
        set_main_window_title_with_asterisk(TRUE);
 }
 
+/*I'm this is only called by init, and when we save. We call it from 
+the save call back, so that we can properly handle the asterisk in the
+titlebar and warn that the document is altered after a save, but 
+retain the undo history. The leads to (FIXME) bug 2730*/
 void undo_reset_step_modif(void)
 {
-       step_modif = g_list_length(undo_list);
+       step_modif = g_trash_stack_height(&undo_stack);
 DV(g_print("undo_reset_step_modif: Reseted step_modif by %d\n", step_modif));
 }
 
 static void undo_check_step_modif(GtkTextBuffer *buffer)
 {
-       if (g_list_length(undo_list) == step_modif) {
+       if (g_trash_stack_height(&undo_stack) == step_modif) {
                g_signal_handlers_block_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_modified_changed), NULL);
                gtk_text_buffer_set_modified(buffer, FALSE);
                g_signal_handlers_unblock_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_modified_changed), NULL);
@@ -255,6 +312,11 @@
        }
 }
 
+/*used by undo_init to attach the various callbacks we need
+  to generate the undo history. Of course, it is a bit of 
+  a misnomer, as it only connects tp signals from the buffer, 
+  undo_init connects to signals emitted by the textview
+ */
 static gint undo_connect_signal(GtkTextBuffer *buffer)
 {
        g_signal_connect(G_OBJECT(buffer), "delete-range",
@@ -266,18 +328,22 @@
                G_CALLBACK(cb_modified_changed), NULL);
 }
 
+/*Sets up this party. It also tracks if it's been called multiple times, 
+  and cleans up after itself (sorta) if it has. Which is odd, as only 
+  we only call it during startup.*/
 void undo_init(GtkWidget *textview, GtkTextBuffer *buffer, GtkWidget *menubar)
 {
        GtkItemFactory *ifactory;
        static guint init_flag = 0; /* TODO: divide to undo_clear() */
        
-       if (undo_list)
+       if (undo_stack != NULL)
                undo_clear_undo_info();
-       if (redo_list)
+       if (redo_stack != NULL)
                undo_clear_redo_info();
        undo_reset_step_modif();
 DV(g_print("undo_init: list reseted\n"));
        
+       /*This is retarded*/
        if (!undo_menu_item) {
                ifactory = gtk_item_factory_from_widget(menubar);
                undo_menu_item = gtk_item_factory_get_widget(ifactory, 
"/Edit/Undo");
@@ -288,7 +354,7 @@
        
        if (!init_flag) {
                g_signal_connect(G_OBJECT(textview), "toggle-overwrite",
-                       G_CALLBACK(cb_toggle_overwrite), NULL);
+                       G_CALLBACK(cb_toggle_overwrite), NULL); /*I dunno why 
we care*/
                view = textview;
                init_flag = undo_connect_signal(buffer);
                keyevent_setval(0);
@@ -296,10 +362,15 @@
                /* ui_tmp->str = g_strdup(""); */
                undo_gstr = g_string_new("");
        }
+       /*Not sure why we do this here, and not in the insert callback*/
        ui_tmp->command = INS;
        undo_gstr = g_string_erase(undo_gstr, 0, -1);
 }
 
+/*Straight forward. When performing the undo/redo, we don't want our
+  deletion and insertion callbacks getting called and going all wonky
+  so we provide a couple of functions to block and unblock. This 
+  constitutes all the code in this file which doesn't suck*/
 gint undo_block_signal(GtkTextBuffer *buffer)
 {
        return 
@@ -316,37 +387,58 @@
        g_signal_handlers_unblock_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_insert_text), buffer);
 }
 
-gint undo_disconnect_signal(GtkTextBuffer *buffer) /*must be not needed */
-{
-       return 
-       g_signal_handlers_disconnect_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_delete_range), buffer) +
-/*     g_signal_handlers_disconnect_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_modified_changed), buffer) + */
-       g_signal_handlers_disconnect_by_func(G_OBJECT(buffer), 
G_CALLBACK(cb_insert_text), buffer);
-}
 
+/* More in the world of the bizarre sequency flag. If we ever need to set the
+   flag, by definition the UndoInfo struct for the undo step is already on 
+   the stack, and a new temp object already being filled up - probably
+   getting ready to be saved itself. So we need a way to set the flag
+   on the UndoInfo struct at the top of the stack.
+   TaaDaa!
+  */
 void undo_set_sequency(gboolean seq)
 {
        UndoInfo *ui;
-       
-       if (g_list_length(undo_list)) {
-               ui = g_list_last(undo_list)->data;
+
+       ui = g_trash_stack_peek(&undo_stack);
+       if (ui != NULL) {
                ui->seq = seq;
        }
 DV(g_print("<undo_set_sequency: %d>\n", seq)); 
 }
 
-gboolean undo_undo(GtkTextBuffer *buffer)
+/* Pretty straightforward, believe it or not. First thing it does is
+ * put any data from undo_gstr in a UndoInfo struct on the stack.
+ * Once that's done, it sees if there is anything on the stack,
+ * pops it, blocks the undo callbacks on the buffer, and inspects
+ * the command on the UndoInfo struct. If were undoing an insertion
+ * then we need to delete text. Grab iterators from the offsets
+ * in the UndoInfo object, and delete that sucker. If it is a 
+ * deletion were undoing, then insert the text back in. REMEMBER:
+ * overwritten text winds up being handled via a two part process
+ * with the sequency flag. If the sequency flag is set for the
+ * NEXT step in the stack, then (Lord Help Us and also FIXME)
+ * we return true, so we tell the caller to call us again so
+ * we can do it all over again. If, on the other hand, the
+ * sequency flag is not set, then we tidy up after ourselves, 
+ * putting the curser in the right place, and scrolling the textview,
+ * setting the redo menu item sensitive, fixing the title bar if 
+ * necessary and finally set the undo item insensitive if we've 
+ * emptied the stack. Whew!
+ */
+void undo_undo(GtkTextBuffer *buffer)
 {
        GtkTextIter start_iter, end_iter;
        UndoInfo *ui;
        
        if (undo_gstr->len) {
+DV(g_print("undo_undo_real: ui_tmp->command %d", ui_tmp->command));
                undo_append_undo_info(buffer, ui_tmp->command, ui_tmp->start, 
ui_tmp->end, g_strdup(undo_gstr->str));
                undo_gstr = g_string_erase(undo_gstr, 0, -1);
        }
-       if (g_list_length(undo_list)) {
+       if ((g_trash_stack_peek(&undo_stack)) != NULL) {
                undo_block_signal(buffer);
-               ui = g_list_last(undo_list)->data;
+               ui = (UndoInfo *)(g_trash_stack_pop(&undo_stack));
+DV(g_print("undo_undo_real: ui->command %d", ui->command));
                gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, 
ui->start);
                switch (ui->command) {
                case INS:
@@ -356,14 +448,15 @@
                default:
                        gtk_text_buffer_insert(buffer, &start_iter, ui->str, 
-1);
                }
-               redo_list = g_list_append(redo_list, ui);
-               undo_list = g_list_delete_link(undo_list, 
g_list_last(undo_list));
-DV(g_print("cb_edit_undo: undo list left %d\n", g_list_length(undo_list)));
+               g_trash_stack_push(&redo_stack, ui);
+DV(g_print("cb_edit_undo: undo list left %d\n", 
g_trash_stack_height(&undo_stack)));
                undo_unblock_signal(buffer);
                undo_check_step_modif(buffer);
-               if (g_list_length(undo_list)) {
-                       if (((UndoInfo *)g_list_last(undo_list)->data)->seq)
-                               return TRUE;
+               if (undo_stack != NULL) {
+                       if (((UndoInfo *)g_trash_stack_peek(&undo_stack))->seq) 
{
+                               undo_undo(buffer);
+                               return;
+                       }
                } else
                        gtk_widget_set_sensitive(undo_menu_item, FALSE);
                gtk_widget_set_sensitive(redo_menu_item, TRUE);
@@ -373,17 +466,18 @@
                gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view), &start_iter,
                        0.1, FALSE, 0.5, 0.5);
        }
-       return FALSE;
+       return;
 }
 
-gboolean undo_redo(GtkTextBuffer *buffer)
+/*yeah, so, basically this is exactly like undo_undo, except simpler*/
+void undo_redo(GtkTextBuffer *buffer)
 {
        GtkTextIter start_iter, end_iter;
        UndoInfo *ri;
        
-       if (g_list_length(redo_list)) {
+       if (redo_stack != NULL) {
                undo_block_signal(buffer);
-               ri = g_list_last(redo_list)->data;
+               ri = (UndoInfo *)(g_trash_stack_pop(&redo_stack));
                gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, 
ri->start);
                switch (ri->command) {
                case INS:
@@ -393,19 +487,20 @@
                        gtk_text_buffer_get_iter_at_offset(buffer, &end_iter, 
ri->end);
                        gtk_text_buffer_delete(buffer, &start_iter, &end_iter);
                }
-               undo_list = g_list_append(undo_list, ri);
-               redo_list = g_list_delete_link(redo_list, 
g_list_last(redo_list));
-DV(g_print("cb_edit_redo: redo list left %d\n", g_list_length(redo_list)));
+               g_trash_stack_push(&undo_stack, ri);
+DV(g_print("cb_edit_redo: redo list left %d\n", 
g_trash_stack_height(&redo_stack)));
                undo_unblock_signal(buffer);
                undo_check_step_modif(buffer);
-               if (ri->seq)
-                       return TRUE;
-               if (!g_list_length(redo_list))
+               if (ri->seq) {
+                       undo_redo(buffer);
+                       return;
+               }
+               if (redo_stack == NULL)
                        gtk_widget_set_sensitive(redo_menu_item, FALSE);
                gtk_widget_set_sensitive(undo_menu_item, TRUE);
                gtk_text_buffer_place_cursor(buffer, &start_iter);
                gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view), &start_iter,
                        0.1, FALSE, 0.5, 0.5);
        }
-       return FALSE;
+       return;
 }

Modified: mousepad/trunk/src/undo.h
===================================================================
--- mousepad/trunk/src/undo.h   2007-01-15 21:38:34 UTC (rev 24497)
+++ mousepad/trunk/src/undo.h   2007-01-15 21:47:38 UTC (rev 24498)
@@ -28,7 +28,7 @@
 gint undo_unblock_signal(GtkTextBuffer *buffer);
 gint undo_disconnect_signal(GtkTextBuffer *buffer);
 void undo_set_sequency(gboolean seq);
-gboolean undo_undo(GtkTextBuffer *buffer);
-gboolean undo_redo(GtkTextBuffer *buffer);
+void undo_undo(GtkTextBuffer *buffer);
+void undo_redo(GtkTextBuffer *buffer);
 
 #endif /* _UNDO_H */

_______________________________________________
Xfce4-commits mailing list
[email protected]
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to