[gitg] Fixed enabling/disabling diff view, showing normal file contents



commit 2a05cbe6df78f50dc80b98d850aad2340c2af8df
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun May 30 20:19:02 2010 +0200

    Fixed enabling/disabling diff view, showing normal file contents

 gitg/gitg-commit-view.c |  150 ++++++++++++--------
 gitg/gitg-diff-view.c   |  371 +++++++++++++++++++++++++++++++++++------------
 gitg/gitg-runner.c      |    8 +-
 gitg/gitg-utils.c       |   88 ++++++++---
 4 files changed, 438 insertions(+), 179 deletions(-)
---
diff --git a/gitg/gitg-commit-view.c b/gitg/gitg-commit-view.c
index f39d553..b2c1c0f 100644
--- a/gitg/gitg-commit-view.c
+++ b/gitg/gitg-commit-view.c
@@ -188,91 +188,118 @@ set_icon_data_func(GitgCommitView *view, GtkTreeView *treeview, GtkCellRenderer
 static void
 set_language(GitgCommitView *view, GtkSourceLanguage *language)
 {
-	GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(view->priv->changes_view)));
+	GtkTextView *text_view;
+	GtkSourceBuffer *buffer;
 
-	gtk_source_buffer_set_language(buffer, language);
-	gitg_diff_view_set_diff_enabled(GITG_DIFF_VIEW(view->priv->changes_view), FALSE);
+	text_view = GTK_TEXT_VIEW (view->priv->changes_view);
+	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (text_view));
+
+	gtk_source_buffer_set_language (buffer, language);
+	gitg_diff_view_set_diff_enabled (GITG_DIFF_VIEW (view->priv->changes_view),
+	                                 FALSE);
 }
 
 static void
-set_diff_language(GitgCommitView *view)
+set_diff_language (GitgCommitView *view)
 {
-	GtkSourceLanguageManager *manager = gtk_source_language_manager_get_default();
-	GtkSourceLanguage *language = gtk_source_language_manager_get_language(manager, "gitgdiff");
+	GtkSourceLanguageManager *manager = gtk_source_language_manager_get_default ();
+	GtkSourceLanguage *language = gtk_source_language_manager_get_language (manager, "gitgdiff");
 
-	set_language(view, language);
-	gitg_diff_view_set_diff_enabled(GITG_DIFF_VIEW(view->priv->changes_view), TRUE);
-	gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hscale_context), TRUE);
+	set_language (view, language);
+	gitg_diff_view_set_diff_enabled (GITG_DIFF_VIEW(view->priv->changes_view), TRUE);
+	gtk_widget_set_sensitive (GTK_WIDGET(view->priv->hscale_context), TRUE);
 }
 
 static void
-show_binary_information(GitgCommitView *view)
+show_binary_information (GitgCommitView *view)
 {
-	set_language(view, NULL);
-	gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hscale_context), FALSE);
+	set_language (view, NULL);
+
+	gtk_widget_set_sensitive (GTK_WIDGET (view->priv->hscale_context), FALSE);
 
-	gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(view->priv->changes_view)), _("Cannot display file content as text"), -1);
+	gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->changes_view)),
+	                          _("Cannot display file content as text"),
+	                          -1);
 }
 
 static void
-on_changes_update(GitgRunner *runner, gchar **buffer, GitgCommitView *view)
+on_changes_update (GitgRunner *runner, gchar **buffer, GitgCommitView *view)
 {
 	gchar *line;
-	GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view->priv->changes_view));
+	GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(view->priv->changes_view));
 	GtkTextIter iter;
 
-	gtk_text_buffer_get_end_iter(buf, &iter);
+	gtk_text_buffer_get_end_iter (buf, &iter);
 
 	while ((line = *(buffer++)))
 	{
-		if (view->priv->is_diff && g_str_has_prefix(line, "@@"))
+		if (view->priv->is_diff && g_str_has_prefix (line, "@@"))
 		{
 			if (view->priv->current_changes & GITG_CHANGED_FILE_CHANGES_UNSTAGED)
-				gtk_source_buffer_create_source_mark(GTK_SOURCE_BUFFER(buf), NULL, CATEGORY_STAGE_HUNK, &iter);
+			{
+				gtk_source_buffer_create_source_mark (GTK_SOURCE_BUFFER(buf),
+				                                      NULL,
+				                                      CATEGORY_STAGE_HUNK,
+				                                      &iter);
+			}
 			else
-				gtk_source_buffer_create_source_mark(GTK_SOURCE_BUFFER(buf), NULL, CATEGORY_UNSTAGE_HUNK, &iter);
+			{
+				gtk_source_buffer_create_source_mark (GTK_SOURCE_BUFFER(buf),
+				                                      NULL,
+				                                      CATEGORY_UNSTAGE_HUNK,
+				                                      &iter);
+			}
 		}
 
-		gtk_text_buffer_insert(buf, &iter, line, -1);
-		gtk_text_buffer_insert(buf, &iter, "\n", -1);
+		gtk_text_buffer_insert (buf, &iter, line, -1);
+		gtk_text_buffer_insert (buf, &iter, "\n", -1);
 	}
 
-	if (gtk_source_buffer_get_language(GTK_SOURCE_BUFFER(buf)) == NULL)
+	if (gtk_source_buffer_get_language (GTK_SOURCE_BUFFER(buf)) == NULL)
 	{
-		gchar *content_type = gitg_utils_guess_content_type(GTK_TEXT_BUFFER(buf));
+		gchar *content_type = gitg_utils_guess_content_type (GTK_TEXT_BUFFER(buf));
 
-		if (content_type && !gitg_utils_can_display_content_type(content_type))
+		if (content_type && !gitg_utils_can_display_content_type (content_type))
 		{
-			gitg_runner_cancel(runner);
-			show_binary_information(view);
+			gitg_runner_cancel (runner);
+			show_binary_information (view);
 		}
 		else if (content_type)
 		{
-			GtkSourceLanguage *language = gitg_utils_get_language(NULL, content_type);
-			set_language(view, language);
-			gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hscale_context), FALSE);
+			GtkSourceLanguage *language = gitg_utils_get_language (NULL, content_type);
+			set_language (view, language);
+			gtk_widget_set_sensitive (GTK_WIDGET (view->priv->hscale_context), FALSE);
 		}
 
-		g_free(content_type);
+		g_free (content_type);
 	}
 
-	while (gtk_events_pending())
-		gtk_main_iteration();
+	while (gtk_events_pending ())
+	{
+		gtk_main_iteration ();
+	}
 }
 
 static void
-connect_update(GitgCommitView *view)
+connect_update (GitgCommitView *view)
 {
-	view->priv->update_id = g_signal_connect(view->priv->runner, "update", G_CALLBACK(on_changes_update), view);
+	view->priv->update_id = g_signal_connect (view->priv->runner,
+	                                          "update",
+	                                          G_CALLBACK (on_changes_update),
+	                                          view);
 }
 
 static void
-set_current_file(GitgCommitView *view, GitgChangedFile *file, GitgChangedFileChanges changes)
+set_current_file (GitgCommitView *view,
+                  GitgChangedFile *file,
+                  GitgChangedFileChanges changes)
 {
 	if (view->priv->current_file != NULL)
-		g_object_unref(view->priv->current_file);
+	{
+		g_object_unref (view->priv->current_file);
+	}
 
-	view->priv->current_file = file ? g_object_ref(file) : NULL;
+	view->priv->current_file = file ? g_object_ref (file) : NULL;
 	view->priv->current_changes = changes;
 }
 
@@ -403,63 +430,66 @@ unselect_tree_view(GtkTreeView *view)
 }
 
 static void
-unstaged_selection_changed(GtkTreeSelection *selection, GitgCommitView *view)
+unstaged_selection_changed (GtkTreeSelection *selection,
+                            GitgCommitView   *view)
 {
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 
-	if (!check_selection(view->priv->tree_view_unstaged, &iter, view))
+	if (!check_selection (view->priv->tree_view_unstaged, &iter, view))
+	{
 		return;
+	}
 
-	model = gtk_tree_view_get_model(view->priv->tree_view_unstaged);
-	unselect_tree_view(view->priv->tree_view_staged);
+	model = gtk_tree_view_get_model (view->priv->tree_view_unstaged);
+	unselect_tree_view (view->priv->tree_view_staged);
 
 	GitgChangedFile *file;
 
-	gtk_tree_model_get(model, &iter, COLUMN_FILE, &file, -1);
-	GitgChangedFileStatus status = gitg_changed_file_get_status(file);
-	GFile *f = gitg_changed_file_get_file(file);
+	gtk_tree_model_get (model, &iter, COLUMN_FILE, &file, -1);
+	GitgChangedFileStatus status = gitg_changed_file_get_status (file);
+	GFile *f = gitg_changed_file_get_file (file);
 
 	if (status == GITG_CHANGED_FILE_STATUS_NEW)
 	{
-		gchar *content_type = gitg_utils_get_content_type(f);
+		gchar *content_type = gitg_utils_get_content_type (f);
 
-		if (!gitg_utils_can_display_content_type(content_type))
+		if (!gitg_utils_can_display_content_type (content_type))
 		{
-			show_binary_information(view);
+			show_binary_information (view);
 		}
 		else
 		{
-			GInputStream *stream = G_INPUT_STREAM(g_file_read(f, NULL, NULL));
+			GInputStream *stream = G_INPUT_STREAM (g_file_read (f, NULL, NULL));
 
 			if (!stream)
 			{
-				show_binary_information(view);
+				show_binary_information (view);
 			}
 			else
 			{
-				gchar *basename = g_file_get_basename(f);
-				GtkSourceLanguage *language = gitg_utils_get_language(basename, content_type);
-				g_free(basename);
+				gchar *basename = g_file_get_basename (f);
+				GtkSourceLanguage *language = gitg_utils_get_language (basename, content_type);
+				g_free (basename);
 
-				set_language(view, language);
-				gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hscale_context), FALSE);
+				set_language (view, language);
+				gtk_widget_set_sensitive (GTK_WIDGET (view->priv->hscale_context), FALSE);
 
 				view->priv->is_diff = FALSE;
-				connect_update(view);
+				connect_update (view);
 
-				gitg_runner_run_stream(view->priv->runner, stream, NULL);
-				g_object_unref(stream);
+				gitg_runner_run_stream (view->priv->runner, stream, NULL);
+				g_object_unref (stream);
 			}
 		}
 
-		g_free(content_type);
+		g_free (content_type);
 	}
 	else
 	{
-		set_diff_language(view);
+		set_diff_language (view);
 		view->priv->is_diff = TRUE;
-		connect_update(view);
+		connect_update (view);
 
 		gchar *path = gitg_repository_relative (view->priv->repository, f);
 
diff --git a/gitg/gitg-diff-view.c b/gitg/gitg-diff-view.c
index db97dc3..ffa9e8f 100644
--- a/gitg/gitg-diff-view.c
+++ b/gitg/gitg-diff-view.c
@@ -46,8 +46,16 @@
 #define GITG_DIFF_ITER_SET_REGION(iter, region) ((iter)->userdata2 = region)
 #define GITG_DIFF_ITER_SET_VIEW(iter, view) ((iter)->userdata = view)
 
-static void on_buffer_insert_text(GtkTextBuffer *buffer, GtkTextIter *iter, gchar const *text, gint len, GitgDiffView *view);
-static void on_buffer_delete_range(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GitgDiffView *view);
+static void on_buffer_insert_text (GtkTextBuffer *buffer,
+                                   GtkTextIter *iter,
+                                   gchar const *text,
+                                   gint len,
+                                   GitgDiffView *view);
+
+static void on_buffer_delete_range (GtkTextBuffer *buffer,
+                                    GtkTextIter *start,
+                                    GtkTextIter *end,
+                                    GitgDiffView *view);
 
 static void
 line_renderer_size_func (GtkSourceGutter *gutter,
@@ -60,7 +68,10 @@ line_renderer_data_func (GtkSourceGutter *gutter,
                          gboolean         current_line,
                          GitgDiffView    *view);
 
-static gboolean on_idle_scan(GitgDiffView *view);
+static void disable_diff_view (GitgDiffView *view);
+static void enable_diff_view (GitgDiffView *view);
+
+static gboolean on_idle_scan (GitgDiffView *view);
 
 /* Signals */
 enum
@@ -139,50 +150,53 @@ static gboolean gitg_diff_view_expose(GtkWidget *widget, GdkEventExpose *event);
 static guint diff_view_signals[NUM_SIGNALS] = {0,};
 
 static void
-region_free(Region *region)
+region_free (Region   *region,
+             gboolean  all)
 {
 	if (!region)
+	{
 		return;
+	}
 
-	region_free(region->next);
+	if (all)
+	{
+		region_free (region->next, all);
+	}
+	else
+	{
+		if (region->next)
+		{
+			region->next->prev = region->prev;
+		}
+
+		if (region->prev)
+		{
+			region->prev->next = region->next;
+		}
+	}
 
 	if (region->type == GITG_DIFF_ITER_TYPE_HEADER)
-		g_slice_free(Header, (Header *)region);
+	{
+		g_slice_free (Header, (Header *)region);
+	}
 	else
-		g_slice_free(Hunk, (Hunk *)region);
+	{
+		g_slice_free (Hunk, (Hunk *)region);
+	}
 }
 
 static void
-regions_free(GitgDiffView *view, gboolean remove_signals)
+regions_free (GitgDiffView *view)
 {
-	region_free(view->priv->regions);
-	g_sequence_remove_range(g_sequence_get_begin_iter(view->priv->regions_index), g_sequence_get_end_iter(view->priv->regions_index));
+	region_free (view->priv->regions, TRUE);
+
+	g_sequence_remove_range (g_sequence_get_begin_iter (view->priv->regions_index),
+	                         g_sequence_get_end_iter (view->priv->regions_index));
 
 	view->priv->regions = NULL;
 	view->priv->last_region = NULL;
 	view->priv->last_scan_line = 0;
 	view->priv->max_line_count = 99;
-
-	if (view->priv->scan_id)
-	{
-		g_source_remove(view->priv->scan_id);
-		view->priv->scan_id = 0;
-	}
-
-	if (view->priv->current_buffer && remove_signals)
-	{
-		g_signal_handlers_disconnect_by_func(view->priv->current_buffer, G_CALLBACK(on_buffer_insert_text), view);
-		g_signal_handlers_disconnect_by_func(view->priv->current_buffer, G_CALLBACK(on_buffer_delete_range), view);
-
-		gtk_text_tag_table_remove (gtk_text_buffer_get_tag_table(view->priv->current_buffer), view->priv->invisible_tag);
-		gtk_text_tag_table_remove (gtk_text_buffer_get_tag_table(view->priv->current_buffer), view->priv->subheader_tag);
-
-		g_object_unref (view->priv->current_buffer);
-
-		view->priv->current_buffer = NULL;
-		view->priv->invisible_tag = NULL;
-		view->priv->subheader_tag = NULL;
-	}
 }
 
 static void
@@ -190,9 +204,13 @@ gitg_diff_view_finalize (GObject *object)
 {
 	GitgDiffView *view = GITG_DIFF_VIEW (object);
 
-	regions_free (view, TRUE);
+	regions_free (view);
 	g_sequence_free (view->priv->regions_index);
 
+	disable_diff_view (view);
+
+	g_object_unref (view->priv->line_renderer);
+
 	if (view->priv->label_func &&
 	    view->priv->label_func_destroy_notify)
 	{
@@ -203,40 +221,60 @@ gitg_diff_view_finalize (GObject *object)
 }
 
 static void
-set_diff_enabled(GitgDiffView *view, gboolean enabled)
+set_diff_enabled (GitgDiffView *view,
+                  gboolean      enabled)
 {
-	view->priv->diff_enabled = enabled;
-	gtk_widget_queue_draw(GTK_WIDGET(view));
+	if (enabled == view->priv->diff_enabled)
+	{
+		return;
+	}
+
+	if (enabled)
+	{
+		enable_diff_view (view);
+	}
+	else
+	{
+		disable_diff_view (view);
+	}
+
+	gtk_widget_queue_draw (GTK_WIDGET(view));
 }
 
 static void
-gitg_diff_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+gitg_diff_view_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
 {
 	GitgDiffView *self = GITG_DIFF_VIEW(object);
 
 	switch (prop_id)
 	{
 		case PROP_DIFF_ENABLED:
-			set_diff_enabled(self, g_value_get_boolean(value));
+			set_diff_enabled(self, g_value_get_boolean (value));
 		break;
 		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
 	}
 }
 
 static void
-gitg_diff_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+gitg_diff_view_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
 {
-	GitgDiffView *self = GITG_DIFF_VIEW(object);
+	GitgDiffView *self = GITG_DIFF_VIEW (object);
 
 	switch (prop_id)
 	{
 		case PROP_DIFF_ENABLED:
-			g_value_set_boolean(value, self->priv->diff_enabled);
+			g_value_set_boolean (value, self->priv->diff_enabled);
 		break;
 		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
 	}
 }
@@ -262,7 +300,7 @@ gitg_diff_view_class_init(GitgDiffViewClass *klass)
 	widget_class->expose_event = gitg_diff_view_expose;
 
 	diff_view_signals[HEADER_ADDED] =
-   		g_signal_new ("header-added",
+		g_signal_new ("header-added",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (GitgDiffViewClass, header_added),
@@ -273,7 +311,7 @@ gitg_diff_view_class_init(GitgDiffViewClass *klass)
 			      G_TYPE_POINTER);
 
 	diff_view_signals[HUNK_ADDED] =
-   		g_signal_new ("hunk-added",
+		g_signal_new ("hunk-added",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (GitgDiffViewClass, hunk_added),
@@ -290,57 +328,145 @@ gitg_diff_view_class_init(GitgDiffViewClass *klass)
 							      FALSE,
 							      G_PARAM_READWRITE));
 
-	g_type_class_add_private(object_class, sizeof(GitgDiffViewPrivate));
+	g_type_class_add_private (object_class, sizeof(GitgDiffViewPrivate));
 }
 
 static void
-on_buffer_set(GitgDiffView *self, GParamSpec *spec, gpointer userdata)
+disable_diff_view (GitgDiffView *view)
 {
-	/* remove all regions for a new buffer */
-	regions_free(self, TRUE);
+	if (!view->priv->diff_enabled)
+	{
+		return;
+	}
+
+	regions_free (view);
+
+	if (view->priv->scan_id)
+	{
+		g_source_remove (view->priv->scan_id);
+		view->priv->scan_id = 0;
+	}
+
+	if (view->priv->current_buffer)
+	{
+		GtkTextTagTable *table;
+		GtkSourceGutter *gutter;
+
+		table = gtk_text_buffer_get_tag_table (view->priv->current_buffer);
+
+		g_signal_handlers_disconnect_by_func (view->priv->current_buffer,
+		                                      G_CALLBACK (on_buffer_insert_text),
+		                                      view);
+
+		g_signal_handlers_disconnect_by_func (view->priv->current_buffer,
+		                                      G_CALLBACK (on_buffer_delete_range),
+		                                      view);
+
+		gtk_text_tag_table_remove (table, view->priv->invisible_tag);
+		gtk_text_tag_table_remove (table, view->priv->subheader_tag);
+
+		g_object_unref (view->priv->current_buffer);
 
-	self->priv->current_buffer = g_object_ref(gtk_text_view_get_buffer(GTK_TEXT_VIEW(self)));
-	g_signal_connect_after(self->priv->current_buffer, "insert-text", G_CALLBACK(on_buffer_insert_text), self);
-	g_signal_connect_after(self->priv->current_buffer, "delete-range", G_CALLBACK(on_buffer_delete_range), self);
+		view->priv->current_buffer = NULL;
+		view->priv->invisible_tag = NULL;
+		view->priv->subheader_tag = NULL;
 
-	self->priv->scan_id = g_idle_add((GSourceFunc)on_idle_scan, self);
-	self->priv->invisible_tag = gtk_text_buffer_create_tag(self->priv->current_buffer, "GitgHunkInvisible", "invisible", TRUE, NULL);
-	self->priv->subheader_tag = gtk_text_buffer_create_tag(self->priv->current_buffer, "GitgHunkSubHeader", "invisible", TRUE, NULL);
+		gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (view),
+		                                     GTK_TEXT_WINDOW_LEFT);
+
+		gtk_source_gutter_remove (gutter,
+		                          GTK_CELL_RENDERER (view->priv->line_renderer));
+	}
 
-	gtk_text_tag_set_priority (self->priv->subheader_tag,
-	                           gtk_text_tag_table_get_size (gtk_text_buffer_get_tag_table (self->priv->current_buffer)) - 1);
+	view->priv->diff_enabled = FALSE;
 }
 
 static void
-gitg_diff_view_init (GitgDiffView *self)
+enable_diff_view (GitgDiffView *view)
 {
+	GtkTextBuffer *buffer;
+	GtkTextTagTable *table;
 	GtkSourceGutter *gutter;
 
-	self->priv = GITG_DIFF_VIEW_GET_PRIVATE (self);
+	if (view->priv->diff_enabled)
+	{
+		disable_diff_view (view);
+	}
 
-	self->priv->regions_index = g_sequence_new (NULL);
-	self->priv->line_renderer = gitg_diff_line_renderer_new ();
+	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+	view->priv->current_buffer = g_object_ref (buffer);
 
-	g_object_set (self->priv->line_renderer, "xpad", 2, NULL);
+	g_signal_connect_after (buffer,
+	                        "insert-text",
+	                        G_CALLBACK (on_buffer_insert_text),
+	                        view);
+
+	g_signal_connect_after (buffer,
+	                        "delete-range",
+	                        G_CALLBACK (on_buffer_delete_range),
+	                        view);
+
+	view->priv->scan_id = g_idle_add ((GSourceFunc)on_idle_scan, view);
+
+	view->priv->invisible_tag = gtk_text_buffer_create_tag (view->priv->current_buffer,
+	                                                        "GitgHunkInvisible",
+	                                                        "invisible",
+	                                                        TRUE,
+	                                                        NULL);
+
+	view->priv->subheader_tag = gtk_text_buffer_create_tag (view->priv->current_buffer,
+	                                                        "GitgHunkSubHeader",
+	                                                        "invisible",
+	                                                        TRUE,
+	                                                        NULL);
 
-	gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
+	table = gtk_text_buffer_get_tag_table (view->priv->current_buffer);
+
+	gtk_text_tag_set_priority (view->priv->subheader_tag,
+	                           gtk_text_tag_table_get_size (table) - 1);
+
+	gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (view),
+	                                     GTK_TEXT_WINDOW_LEFT);
 
 	gtk_source_gutter_insert (gutter,
-	                          GTK_CELL_RENDERER (self->priv->line_renderer),
+	                          GTK_CELL_RENDERER (view->priv->line_renderer),
 	                          0);
 
 	gtk_source_gutter_set_cell_data_func (gutter,
-	                                      GTK_CELL_RENDERER (self->priv->line_renderer),
+	                                      GTK_CELL_RENDERER (view->priv->line_renderer),
 	                                      (GtkSourceGutterDataFunc)line_renderer_data_func,
-	                                      self,
+	                                      view,
 	                                      NULL);
 
 	gtk_source_gutter_set_cell_size_func (gutter,
-	                                      GTK_CELL_RENDERER (self->priv->line_renderer),
+	                                      GTK_CELL_RENDERER (view->priv->line_renderer),
 	                                      (GtkSourceGutterSizeFunc)line_renderer_size_func,
-	                                      self,
+	                                      view,
 	                                      NULL);
 
+	view->priv->diff_enabled = TRUE;
+}
+
+static void
+on_buffer_set (GitgDiffView *self, GParamSpec *spec, gpointer userdata)
+{
+	if (self->priv->diff_enabled)
+	{
+		enable_diff_view (self);
+	}
+}
+
+static void
+gitg_diff_view_init (GitgDiffView *self)
+{
+	self->priv = GITG_DIFF_VIEW_GET_PRIVATE (self);
+
+	self->priv->regions_index = g_sequence_new (NULL);
+	self->priv->line_renderer = gitg_diff_line_renderer_new ();
+
+	g_object_ref (self->priv->line_renderer);
+	g_object_set (self->priv->line_renderer, "xpad", 2, NULL);
+
 	g_signal_connect (self, "notify::buffer", G_CALLBACK (on_buffer_set), NULL);
 }
 
@@ -921,6 +1047,11 @@ gitg_diff_view_get_start_iter(GitgDiffView *view, GitgDiffIter *iter)
 	g_return_val_if_fail(GITG_IS_DIFF_VIEW(view), FALSE);
 	g_return_val_if_fail(iter != NULL, FALSE);
 
+	if (!view->priv->diff_enabled)
+	{
+		return FALSE;
+	}
+
 	region_to_iter (view, view->priv->regions, iter);
 	return GITG_DIFF_ITER_GET_REGION (iter) != NULL;
 }
@@ -1109,24 +1240,34 @@ header_parse_index(GitgDiffView *view, Header *header)
 }
 
 gboolean
-gitg_diff_iter_get_index(GitgDiffIter *iter, gchar **from, gchar **to)
+gitg_diff_iter_get_index (GitgDiffIter  *iter,
+                          gchar        **from,
+                          gchar        **to)
 {
 	Region *region = GITG_DIFF_ITER_GET_REGION (iter);
 
 	while (region && region->type != GITG_DIFF_ITER_TYPE_HEADER)
+	{
 		region = region->prev;
+	}
 
 	if (!region)
+	{
 		return FALSE;
+	}
 
 	Header *header = (Header *)region;
 	gboolean ret = TRUE;
 
 	if (!*(header->index_to))
+	{
 		ret = header_parse_index (GITG_DIFF_ITER_GET_VIEW (iter), header);
+	}
 
 	if (!ret)
+	{
 		return FALSE;
+	}
 
 	*from = header->index_from;
 	*to = header->index_to;
@@ -1134,67 +1275,86 @@ gitg_diff_iter_get_index(GitgDiffIter *iter, gchar **from, gchar **to)
 	return TRUE;
 }
 
-static gboolean 
-iter_in_view(GitgDiffView *view, GtkTextIter *iter)
+static gboolean
+iter_in_view (GitgDiffView *view,
+              GtkTextIter  *iter)
 {
 	GtkTextIter start;
 	GtkTextIter end;
 	GdkRectangle rect;
-	GtkTextView *textview = GTK_TEXT_VIEW(view);
+	GtkTextView *textview = GTK_TEXT_VIEW (view);
 
-	gtk_text_view_get_visible_rect(textview, &rect);
-	gtk_text_view_get_iter_at_location(textview, &start, rect.x, rect.y);
-	gtk_text_view_get_iter_at_location(textview, &end, rect.x + rect.width, rect.y + rect.height);
+	gtk_text_view_get_visible_rect (textview, &rect);
+	gtk_text_view_get_iter_at_location (textview, &start, rect.x, rect.y);
+	gtk_text_view_get_iter_at_location (textview, &end, rect.x + rect.width, rect.y + rect.height);
 
 	return gtk_text_iter_in_range(iter, &start, &end) || gtk_text_iter_equal(iter, &end);
 }
 
 static gboolean
-try_scan(GitgDiffView *view)
+try_scan (GitgDiffView *view)
 {
-	gint lines = gtk_text_buffer_get_line_count(view->priv->current_buffer);
+	gint lines = gtk_text_buffer_get_line_count (view->priv->current_buffer);
 
 	if (view->priv->last_scan_line > lines)
+	{
 		return FALSE;
+	}
 
-	guint num = MIN(lines - view->priv->last_scan_line, IDLE_SCAN_COUNT);
+	guint num = MIN (lines - view->priv->last_scan_line, IDLE_SCAN_COUNT);
 
 	if (num == 0)
+	{
 		return FALSE;
+	}
 
 	gchar str[8];
-	g_snprintf(str, sizeof(str), "%u", view->priv->max_line_count);
-	guint max_line = strlen(str);
+	g_snprintf (str, sizeof (str), "%u", view->priv->max_line_count);
+	guint max_line = strlen (str);
 
 	guint last = view->priv->last_scan_line;
-	ensure_scan(view, view->priv->last_scan_line + num);
-	g_snprintf(str, sizeof(str), "%u", view->priv->max_line_count);
+	ensure_scan (view, view->priv->last_scan_line + num);
+	g_snprintf (str, sizeof (str), "%u", view->priv->max_line_count);
 
-	if (strlen(str) > max_line)
-		gtk_widget_queue_draw(GTK_WIDGET(view));
+	if (strlen (str) > max_line)
+	{
+		gtk_widget_queue_draw (GTK_WIDGET (view));
+	}
 
 	return last != view->priv->last_scan_line;
 }
 
 static void
-on_buffer_delete_range(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GitgDiffView *view)
+on_buffer_delete_range (GtkTextBuffer *buffer,
+                        GtkTextIter   *start,
+                        GtkTextIter   *end,
+                        GitgDiffView  *view)
 {
 	if (view->priv->ignore_changes)
 	{
 		return;
 	}
 
-	regions_free(view, FALSE);
+	regions_free (view);
 
-	if (iter_in_view(view, start) || iter_in_view(view, end))
-		try_scan(view);
+	if (iter_in_view (view, start) || iter_in_view (view, end))
+	{
+		try_scan (view);
+	}
 
 	if (!view->priv->scan_id)
-		view->priv->scan_id = g_idle_add((GSourceFunc)on_idle_scan, view);
+	{
+		view->priv->scan_id = g_idle_add ((GSourceFunc)on_idle_scan,
+		                                  view);
+	}
 }
 
-static void 
-on_buffer_insert_text(GtkTextBuffer *buffer, GtkTextIter *iter, gchar const *text, gint len, GitgDiffView *view)
+static void
+on_buffer_insert_text (GtkTextBuffer *buffer,
+                       GtkTextIter   *iter,
+                       gchar const   *text,
+                       gint           len,
+                       GitgDiffView  *view)
 {
 	if (view->priv->ignore_changes)
 	{
@@ -1202,18 +1362,24 @@ on_buffer_insert_text(GtkTextBuffer *buffer, GtkTextIter *iter, gchar const *tex
 	}
 
 	/* if region is in current view and not scanned, issue scan now */
-	if (iter_in_view(view, iter))
-		try_scan(view);
+	if (iter_in_view (view, iter))
+	{
+		try_scan (view);
+	}
 
 	if (!view->priv->scan_id)
-		view->priv->scan_id = g_idle_add((GSourceFunc)on_idle_scan, view);
+	{
+		view->priv->scan_id = g_idle_add ((GSourceFunc)on_idle_scan, view);
+	}
 }
 
-static gboolean 
-on_idle_scan(GitgDiffView *view)
+static gboolean
+on_idle_scan (GitgDiffView *view)
 {
 	if (try_scan(view))
+	{
 		return TRUE;
+	}
 
 	view->priv->scan_id = 0;
 	return FALSE;
@@ -1228,6 +1394,11 @@ gitg_diff_view_get_header_at_iter (GitgDiffView *view,
 	g_return_val_if_fail (iter != NULL, FALSE);
 	g_return_val_if_fail (diff_iter != NULL, FALSE);
 
+	if (!view->priv->diff_enabled)
+	{
+		return FALSE;
+	}
+
 	ensure_scan (view, gtk_text_iter_get_line (iter));
 
 	Region *region = find_current_region (view, gtk_text_iter_get_line (iter));
@@ -1250,6 +1421,11 @@ gitg_diff_view_get_hunk_at_iter (GitgDiffView *view,
 	g_return_val_if_fail (iter != NULL, FALSE);
 	g_return_val_if_fail (diff_iter != NULL, FALSE);
 
+	if (!view->priv->diff_enabled)
+	{
+		return FALSE;
+	}
+
 	ensure_scan (view, gtk_text_iter_get_line (iter));
 
 	Region *region = find_current_region (view, gtk_text_iter_get_line (iter));
@@ -1309,6 +1485,11 @@ gitg_diff_view_get_line_type (GitgDiffView *view, GtkTextIter const *iter)
 	g_return_val_if_fail (GITG_IS_DIFF_VIEW (view), GITG_DIFF_LINE_TYPE_NONE);
 	g_return_val_if_fail (iter != NULL, GITG_DIFF_LINE_TYPE_NONE);
 
+	if (!view->priv->diff_enabled)
+	{
+		return GITG_DIFF_LINE_TYPE_NONE;
+	}
+
 	GitgDiffIter diff_iter;
 
 	if (!gitg_diff_view_get_hunk_at_iter (view, iter, &diff_iter))
diff --git a/gitg/gitg-runner.c b/gitg/gitg-runner.c
index 6c9991e..c151ea0 100644
--- a/gitg/gitg-runner.c
+++ b/gitg/gitg-runner.c
@@ -470,9 +470,15 @@ read_output_ready(GInputStream *stream, GAsyncResult *result, AsyncData *data)
 	if (read == 0)
 	{
 		/* End */
-		gchar *b[] = {data->runner->priv->buffer, NULL};
+		gchar *converted = gitg_utils_convert_utf8 (data->runner->priv->buffer,
+		                                            -1);
+
+		gchar *b[] = {converted, NULL};
+
 		g_signal_emit(data->runner, runner_signals[UPDATE], 0, b);
 
+		g_free (converted);
+
 		gint status = 0;
 		waitpid(data->runner->priv->pid, &status, 0);
 
diff --git a/gitg/gitg-utils.c b/gitg/gitg-utils.c
index 361c7e3..cb49a7f 100644
--- a/gitg/gitg-utils.c
+++ b/gitg/gitg-utils.c
@@ -205,55 +205,97 @@ gitg_utils_export_files (GitgRepository *repository,
 	return ret;
 }
 
+static void
+utf8_validate_fallback (gchar  *text,
+                        gssize  size)
+{
+	gchar const *end;
+
+	while (!g_utf8_validate (text, size, &end))
+	{
+		*((gchar *)end) = '?';
+	}
+}
+
 static gchar *
-convert_fallback (gchar const *text, gssize size, gchar const *fallback)
+convert_fallback (gchar const *text,
+                  gssize       size,
+                  gchar const *fallback)
 {
 	gchar *res;
 	gsize read, written;
-	GString *str = g_string_new("");
-
-	while ((res = g_convert(text, size, "UTF-8", "ASCII", &read, &written, NULL))
-			== NULL) {
-		res = g_convert(text, read, "UTF-8", "ASCII", NULL, NULL, NULL);
-		str = g_string_append(str, res);
+	GString *str = g_string_new ("");
+
+	while ((res = g_convert(text,
+	                        size,
+	                        "UTF-8",
+	                        "ASCII",
+	                        &read,
+	                        &written,
+	                        NULL)) == NULL)
+	{
+		res = g_convert (text, read, "UTF-8", "ASCII", NULL, NULL, NULL);
+		str = g_string_append (str, res);
 
-		str = g_string_append(str, fallback);
+		str = g_string_append (str, fallback);
 		text = text + read + 1;
 		size = size - read;
 	}
 
-	str = g_string_append(str, res);
-	g_free(res);
+	str = g_string_append (str, res);
+	g_free (res);
 
-	res = str->str;
-	g_string_free(str, FALSE);
-	return res;
+	utf8_validate_fallback (str->str, str->len);
+	return g_string_free (str, FALSE);
 }
 
 gchar *
-gitg_utils_convert_utf8(gchar const *str, gssize size)
+gitg_utils_convert_utf8 (gchar const *str, gssize size)
 {
 	static gchar *encodings[] = {
 		"ISO-8859-15",
 		"ASCII"
 	};
 
-	if (g_utf8_validate(str, size, NULL))
-		return g_strndup(str, size == -1 ? strlen(str) : size);
+	if (str == NULL)
+	{
+		return NULL;
+	}
+
+	if (size == -1)
+	{
+		size = strlen (str);
+	}
+
+	if (g_utf8_validate (str, size, NULL))
+	{
+		return g_strndup (str, size);
+	}
 
 	int i;
-	for (i = 0; i < sizeof(encodings) / sizeof(gchar *); ++i)
+	for (i = 0; i < sizeof (encodings) / sizeof (gchar *); ++i)
 	{
 		gsize read;
 		gsize written;
 
-		gchar *ret = g_convert(str, size, "UTF-8", encodings[i], &read, &written, NULL);
+		gchar *ret = g_convert (str,
+		                        size,
+		                        "UTF-8",
+		                        encodings[i],
+		                        &read,
+		                        &written,
+		                        NULL);
 
-		if (ret)
+		if (ret && read == size)
+		{
+			utf8_validate_fallback (ret, written);
 			return ret;
+		}
+
+		g_free (ret);
 	}
 
-	return convert_fallback(str, size, "?");
+	return convert_fallback (str, size, "?");
 }
 
 guint
@@ -302,10 +344,10 @@ gitg_utils_get_content_type(GFile *file)
 }
 
 gboolean
-gitg_utils_can_display_content_type(gchar const *content_type)
+gitg_utils_can_display_content_type (gchar const *content_type)
 {
-	return g_content_type_is_a(content_type, "text/plain") || 
-		   g_content_type_equals(content_type, "application/octet-stream");
+	return g_content_type_is_a (content_type, "text/plain") ||
+	       g_content_type_equals (content_type, "application/octet-stream");
 }
 
 GtkSourceLanguage *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]