SF.net SVN: geany: [793] trunk

eht16 at users.sourceforge.net eht16 at xxxxx
Wed Sep 6 16:09:55 UTC 2006


Revision: 793
          http://svn.sourceforge.net/geany/?rev=793&view=rev
Author:   eht16
Date:     2006-09-06 09:09:08 -0700 (Wed, 06 Sep 2006)

Log Message:
-----------
Added own implementation of an Undo stack (not yet working).

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/src/callbacks.c
    trunk/src/document.c
    trunk/src/document.h
    trunk/src/sci_cb.c
    trunk/src/ui_utils.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/ChangeLog	2006-09-06 16:09:08 UTC (rev 793)
@@ -1,3 +1,9 @@
+2006-09-06  Enrico Tröger  <enrico.troeger at uvena.de>
+
+ * src/callbacks.c, src/document.c, src/ui_utils.c, src/sci_cb.c:
+   Added own implementation of an Undo stack (not yet working).
+
+
 2006-09-05  Enrico Tröger  <enrico.troeger at uvena.de>
 
  * src/templates.c, src/document.c, src/filetypes.c:

Modified: trunk/src/callbacks.c
===================================================================
--- trunk/src/callbacks.c	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/src/callbacks.c	2006-09-06 16:09:08 UTC (rev 793)
@@ -333,7 +333,7 @@
 {
 	gint idx = document_get_cur_idx();
 	if (idx == -1 || ! doc_list[idx].is_valid) return;
-	if (sci_can_undo(doc_list[idx].sci)) sci_undo(doc_list[idx].sci);
+	if (document_can_undo(idx)) document_undo(idx);
 }
 
 
@@ -343,7 +343,7 @@
 {
 	gint idx = document_get_cur_idx();
 	if (idx == -1 || ! doc_list[idx].is_valid) return;
-	if (sci_can_redo(doc_list[idx].sci)) sci_redo(doc_list[idx].sci);
+	if (document_can_redo(idx)) document_redo(idx);
 }
 
 
@@ -2393,10 +2393,9 @@
 	if (app->ignore_callback || idx < 0 || encodings[i].charset == NULL ||
 		utils_strcmp(encodings[i].charset, doc_list[idx].encoding)) return;
 
-	g_free(doc_list[idx].encoding);
+	// old charset string will be freed with the undo buffer
+	document_undo_add(idx, UNDO_ENCODING, doc_list[idx].encoding);
 	doc_list[idx].encoding = g_strdup(encodings[i].charset);
-	doc_list[idx].changed = TRUE;
-	document_set_text_changed(idx);
 	ui_update_statusbar(idx, -1);
 	gtk_widget_set_sensitive(lookup_widget(app->window, "menu_write_unicode_bom1"),
 			utils_is_unicode_charset(doc_list[idx].encoding));
@@ -2453,8 +2452,7 @@
 
 		doc_list[idx].has_bom = ! doc_list[idx].has_bom;
 
-		doc_list[idx].changed = TRUE;
-		document_set_text_changed(idx);
+		document_undo_add(idx, UNDO_BOM, GINT_TO_POINTER(! doc_list[idx].has_bom));
 		ui_update_statusbar(idx, -1);
 	}
 }

Modified: trunk/src/document.c
===================================================================
--- trunk/src/document.c	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/src/document.c	2006-09-06 16:09:08 UTC (rev 793)
@@ -157,34 +157,29 @@
 }
 
 
-/* changes the color of the tab text according to the status */
-void document_change_tab_color(gint index)
+void document_set_text_changed(gint idx)
 {
-	if (index >= 0 && doc_list[index].sci)
+	if (idx >= 0 && doc_list[idx].is_valid && ! app->quitting)
 	{
+		// changes the color of the tab text according to the status
 		GdkColor colorred = {0, 65535, 0, 0};
 		GdkColor colorblack = {0, 0, 0, 0};
 
-		gtk_widget_modify_fg(doc_list[index].tab_label, GTK_STATE_NORMAL,
-					(doc_list[index].changed) ? &colorred : &colorblack);
-		gtk_widget_modify_fg(doc_list[index].tab_label, GTK_STATE_ACTIVE,
-					(doc_list[index].changed) ? &colorred : &colorblack);
-		gtk_widget_modify_fg(doc_list[index].tabmenu_label, GTK_STATE_PRELIGHT,
-					(doc_list[index].changed) ? &colorred : &colorblack);
-		gtk_widget_modify_fg(doc_list[index].tabmenu_label, GTK_STATE_NORMAL,
-					(doc_list[index].changed) ? &colorred : &colorblack);
+		gtk_widget_modify_fg(doc_list[idx].tab_label, GTK_STATE_NORMAL,
+					(doc_list[idx].changed) ? &colorred : &colorblack);
+		gtk_widget_modify_fg(doc_list[idx].tab_label, GTK_STATE_ACTIVE,
+					(doc_list[idx].changed) ? &colorred : &colorblack);
+		gtk_widget_modify_fg(doc_list[idx].tabmenu_label, GTK_STATE_PRELIGHT,
+					(doc_list[idx].changed) ? &colorred : &colorblack);
+		gtk_widget_modify_fg(doc_list[idx].tabmenu_label, GTK_STATE_NORMAL,
+					(doc_list[idx].changed) ? &colorred : &colorblack);
+
+		ui_save_buttons_toggle(doc_list[idx].changed);
+		ui_set_window_title(idx);
 	}
 }
 
 
-void document_set_text_changed(gint index)
-{
-	document_change_tab_color(index);
-	ui_save_buttons_toggle(doc_list[index].changed);
-	ui_set_window_title(index);
-}
-
-
 /* sets in all document structs the flag is_valid to FALSE and initializes some members to NULL,
  * to mark it uninitialized. The flag is_valid is set to TRUE in document_create_new_sci(). */
 void document_init_doclist()
@@ -206,6 +201,8 @@
 		doc_list[i].encoding = NULL;
 		doc_list[i].has_bom = FALSE;
 		doc_list[i].sci = NULL;
+		doc_list[i].undo_actions = NULL;
+		doc_list[i].redo_actions = NULL;
 	}
 }
 
@@ -281,9 +278,6 @@
 	this->tag_store = NULL;
 	this->tag_tree = NULL;
 
-	// "the" SCI signal
-	g_signal_connect((GtkWidget*) sci, "sci-notify",
-					G_CALLBACK(on_editor_notification), GINT_TO_POINTER(new_idx));
 	// signal for insert-key(works without too, but to update the right status bar)
 /*	g_signal_connect((GtkWidget*) sci, "key-press-event",
 					G_CALLBACK(keybindings_got_event), GINT_TO_POINTER(new_idx));
@@ -336,6 +330,8 @@
 		g_free(doc_list[idx].encoding);
 		g_free(doc_list[idx].file_name);
 		tm_workspace_remove_object(doc_list[idx].tm_file, TRUE);
+		document_undo_clear(idx);
+		document_redo_clear(idx);
 		doc_list[idx].is_valid = FALSE;
 		doc_list[idx].sci = NULL;
 		doc_list[idx].file_name = NULL;
@@ -400,13 +396,17 @@
 		sci_empty_undo_buffer(doc_list[idx].sci);
 		sci_goto_pos(doc_list[idx].sci, 0, TRUE);
 
+		// "the" SCI signal (connect after initial setup(i.e. adding text))
+		g_signal_connect((GtkWidget*) doc_list[idx].sci, "sci-notify",
+					G_CALLBACK(on_editor_notification), GINT_TO_POINTER(idx));
+
 		msgwin_status_add(_("New file opened."));
 	}
 	else
 	{
 		dialogs_show_error(
 		_("You have opened too many files. There is a limit of %d concurrent open files."),
-		GEANY_MAX_OPEN_FILES);
+							GEANY_MAX_OPEN_FILES);
 	}
 }
 
@@ -636,6 +636,10 @@
 		document_update_tag_list(idx, TRUE);
 	}
 
+	// "the" SCI signal (connect after initial setup(i.e. adding text))
+	g_signal_connect((GtkWidget*) doc_list[idx].sci, "sci-notify",
+					G_CALLBACK(on_editor_notification), GINT_TO_POINTER(idx));
+
 	document_set_text_changed(idx);
 	ui_document_show_hide(idx); //update the document menu
 
@@ -1447,4 +1451,166 @@
 	}
 }
 
+/* own Undo / Redo implementation to be able to undo / redo changes
+ * to the encoding or the Unicode BOM (which are Scintilla independet).
+ * All Scintilla events are stored in the undo / redo buffer and are passed through. */
 
+/* Clears the Undo buffer (to be called after saving a file or when closing the document) */
+void document_undo_clear(gint idx)
+{
+	undo_action *a;
+
+	while (g_trash_stack_height(&doc_list[idx].undo_actions) > 0)
+	{
+		a = g_trash_stack_pop(&doc_list[idx].undo_actions);
+		if (a != NULL)
+		{
+			switch (a->type)
+			{
+				case UNDO_ENCODING: g_free(a->data); break;
+				default: break;
+			}
+
+			g_free(a);
+		}
+	}
+	doc_list[idx].undo_actions = NULL;
+
+	doc_list[idx].changed = FALSE;
+	if (! app->quitting) document_set_text_changed(idx);
+}
+
+
+/* Clears the Redo buffer (to be called after saving a file or when closing the document) */
+void document_redo_clear(gint idx)
+{
+/*
+	undo_action *a;
+
+	while (g_trash_stack_height(&doc_list[idx].redo_actions) > 0)
+	{
+		a = g_trash_stack_pop(&doc_list[idx].redo_actions);
+		if (a != NULL)
+		{
+			switch (a->type)
+			{
+				case UNDO_ENCODING: g_free(a->data); break;
+				default: break;
+			}
+
+			g_free(a);
+		}
+	}
+	doc_list[idx].redo_actions = NULL;
+
+	doc_list[idx].changed = FALSE;
+	if (! app->quitting) document_set_text_changed(idx);
+*/
+}
+
+
+void document_undo_add(gint idx, guint type, gpointer data)
+{
+	undo_action *action;
+
+	if (idx == -1 || ! doc_list[idx].is_valid) return;
+
+	action = g_new0(undo_action, 1);
+	action->type = type;
+	action->data = data;
+
+	g_trash_stack_push(&doc_list[idx].undo_actions, action);
+
+	doc_list[idx].changed = TRUE;
+	document_set_text_changed(idx);
+	ui_update_popup_reundo_items(idx);
+
+	{
+		geany_debug("%s: new stack height: %d, added type: %d", __func__,
+				g_trash_stack_height(&doc_list[idx].undo_actions), action->type);
+	}
+}
+
+
+gboolean document_can_undo(gint idx)
+{
+	return sci_can_undo(doc_list[idx].sci);
+
+	if (idx == -1 || ! doc_list[idx].is_valid) return FALSE;
+
+	if (g_trash_stack_height(&doc_list[idx].undo_actions) > 0 || sci_can_undo(doc_list[idx].sci))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+gboolean document_can_redo(gint idx)
+{
+	if (idx == -1 || ! doc_list[idx].is_valid) return FALSE;
+
+	return sci_can_redo(doc_list[idx].sci);
+}
+
+
+void document_undo(gint idx)
+{
+	sci_undo(doc_list[idx].sci);
+	return;
+
+	undo_action *action;
+
+	if (idx == -1 || ! doc_list[idx].is_valid) return;
+
+	action = g_trash_stack_pop(&doc_list[idx].undo_actions);
+
+	if (action == NULL)
+	{
+		// fallback, should not be necessary
+		sci_undo(doc_list[idx].sci);
+	}
+	else
+	{
+		switch (action->type)
+		{
+			case UNDO_SCINTILLA:
+			{
+				geany_debug("undo: Scintilla");
+				sci_undo(doc_list[idx].sci);
+				break;
+			}
+			case UNDO_BOM:
+			{
+				geany_debug("undo: BOM");
+				doc_list[idx].has_bom = GPOINTER_TO_INT(action->data);
+				ui_update_statusbar(idx, -1);
+				ui_document_show_hide(idx);
+				break;
+			}
+			case UNDO_ENCODING:
+			{
+				geany_debug("undo: Encoding");
+				doc_list[idx].encoding = (gchar*) action->data;
+				ui_update_statusbar(idx, -1);
+				encodings_select_radio_item(doc_list[idx].encoding);
+				gtk_widget_set_sensitive(lookup_widget(app->window, "menu_write_unicode_bom1"),
+								utils_is_unicode_charset(doc_list[idx].encoding));
+				break;
+			}
+			default: break;
+		}
+	}
+
+	if (g_trash_stack_height(&doc_list[idx].undo_actions) == 0) doc_list[idx].changed = FALSE;
+	ui_update_popup_reundo_items(idx);
+	geany_debug("%s: new stack height: %d", __func__, g_trash_stack_height(&doc_list[idx].undo_actions));
+}
+
+
+void document_redo(gint idx)
+{
+	if (idx == -1 || ! doc_list[idx].is_valid) return;
+
+	sci_redo(doc_list[idx].sci);
+}
+

Modified: trunk/src/document.h
===================================================================
--- trunk/src/document.h	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/src/document.h	2006-09-06 16:09:08 UTC (rev 793)
@@ -63,6 +63,8 @@
 	gboolean		 use_auto_indention;
 	time_t			 last_check;	// to remember the last disk check
 	time_t			 mtime;
+	GTrashStack		*undo_actions;
+	GTrashStack		*redo_actions;
 } document;
 
 
@@ -95,10 +97,6 @@
 gint document_get_new_idx();
 
 
-/* changes the color of the tab text according to the status */
-void document_change_tab_color(gint);
-
-
 void document_set_text_changed(gint);
 
 
@@ -182,4 +180,38 @@
 
 void document_ensure_final_newline(gint idx);
 
+
+
+/* own Undo / Redo implementation to be able to undo / redo changes
+ * to the encoding or the Unicode BOM (which are Scintilla independet).
+ * All Scintilla events are stored in the undo / redo buffer and are passed through. */
+enum
+{
+	UNDO_SCINTILLA = 0,
+	UNDO_ENCODING,
+	UNDO_BOM,
+	UNDO_ACTIONS_MAX
+};
+
+typedef struct
+{
+	GTrashStack *next;
+	guint type;	// to identify the action
+	gpointer *data; // the old value (before the change)
+} undo_action;
+
+gboolean document_can_undo(gint idx);
+
+gboolean document_can_redo(gint idx);
+
+void document_undo(gint idx);
+
+void document_redo(gint idx);
+
+void document_undo_add(gint idx, guint type, gpointer data);
+
+void document_undo_clear(gint idx);
+
+void document_redo_clear(gint idx);
+
 #endif

Modified: trunk/src/sci_cb.c
===================================================================
--- trunk/src/sci_cb.c	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/src/sci_cb.c	2006-09-06 16:09:08 UTC (rev 793)
@@ -155,6 +155,11 @@
 #endif
 			break;
 		}
+		case 2023:
+		{
+			geany_debug("Undo notification");
+			break;
+		}
 /*		case SCN_KEY:
 		{
 			//geany_debug("key notification triggered with %c", nt->ch);
@@ -162,9 +167,11 @@
 		}
 		case SCN_MODIFIED:
 		{
-			//if (nt->modificationType == SC_MOD_INSERTTEXT)
-			//	geany_debug("modi: %s", nt->text);
-
+			if (nt->modificationType  & SC_MOD_INSERTTEXT ||
+				nt->modificationType & SC_MOD_DELETETEXT)
+			{
+				document_undo_add(idx, UNDO_SCINTILLA, NULL);
+			}
 			break;
 		}
 */		case SCN_CHARADDED:

Modified: trunk/src/ui_utils.c
===================================================================
--- trunk/src/ui_utils.c	2006-09-05 18:33:48 UTC (rev 792)
+++ trunk/src/ui_utils.c	2006-09-06 16:09:08 UTC (rev 793)
@@ -335,11 +335,11 @@
 	}
 	else
 	{
-		enable_undo = sci_can_undo(doc_list[index].sci);
-		enable_redo = sci_can_redo(doc_list[index].sci);
+		enable_undo = document_can_undo(index);
+		enable_redo = document_can_redo(index);
 	}
 
-	// index 0 is the popup menu, 1 is the menubar
+	// index 0 is the popup menu, 1 is the menubar, 2 is the toolbar
 	gtk_widget_set_sensitive(app->undo_items[0], enable_undo);
 	gtk_widget_set_sensitive(app->undo_items[1], enable_undo);
 	gtk_widget_set_sensitive(app->undo_items[2], enable_undo);


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list