[gedit] Rework the document input stream to use a mark



commit 3875227aa368f4b4de8d3e66a7ceb433acbbbd3f
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Mar 13 16:19:31 2010 +0100

    Rework the document input stream to use a mark
    
    This is necessary even if the text is not modified during the read since
    gtksourceview or plugins can interact with the buffer applying tags and
    changing marks. The patch hopefully fixes bug #611757, which I cannot
    reproduce anymore, though we've not been able to create a simple unit
    test isolating the bug.

 gedit/gedit-document-input-stream.c |   99 ++++++++++++++++++++---------------
 tests/document-input-stream.c       |    5 ++
 2 files changed, 62 insertions(+), 42 deletions(-)
---
diff --git a/gedit/gedit-document-input-stream.c b/gedit/gedit-document-input-stream.c
index 4b01d9a..45cba7e 100644
--- a/gedit/gedit-document-input-stream.c
+++ b/gedit/gedit-document-input-stream.c
@@ -40,8 +40,8 @@ G_DEFINE_TYPE (GeditDocumentInputStream, gedit_document_input_stream, G_TYPE_INP
 struct _GeditDocumentInputStreamPrivate
 {
 	GtkTextBuffer *buffer;
-	GtkTextIter    pos;
-	guint          bytes_partial;
+	GtkTextMark   *pos;
+	gint           bytes_partial;
 
 	GeditDocumentNewlineType newline_type;
 
@@ -229,7 +229,12 @@ gedit_document_input_stream_tell (GeditDocumentInputStream *stream)
 	}
 	else
 	{
-		return gtk_text_iter_get_offset (&stream->priv->pos);
+		GtkTextIter iter;
+
+		gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
+						  &iter,
+						  stream->priv->pos);
+		return gtk_text_iter_get_offset (&iter);
 	}
 }
 
@@ -261,32 +266,34 @@ read_line (GeditDocumentInputStream *stream,
 	   gchar                    *outbuf,
 	   gsize                     space_left)
 {
-	GtkTextIter *start, next, end;
+	GtkTextIter start, next, end;
 	gchar *buf;
-	gsize read, bytes, newline_size, bytes_to_write;
+	gint bytes; /* int since it's what iter_get_offset returns */
+	gsize bytes_to_write, newline_size, read;
 	const gchar *newline;
 	gboolean is_last;
 
-	start = &stream->priv->pos;
-
-	end = next = *start;
-	newline = get_new_line (stream);
-	newline_size = get_new_line_size (stream);
+	gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
+					  &start,
+					  stream->priv->pos);
 
-	if (gtk_text_iter_is_end (start))
+	if (gtk_text_iter_is_end (&start))
 		return 0;
 
+	end = next = start;
+	newline = get_new_line (stream);
+
 	/* Check needed for empty lines */
 	if (!gtk_text_iter_ends_line (&end))
 		gtk_text_iter_forward_to_line_end (&end);
 
 	gtk_text_iter_forward_line (&next);
 
-	buf = gtk_text_iter_get_slice (start, &end);
+	buf = gtk_text_iter_get_slice (&start, &end);
 
 	/* the bytes of a line includes also the newline, so with the
 	   offsets we remove the newline and we add the new newline size */
-	bytes = gtk_text_iter_get_bytes_in_line (start) - stream->priv->bytes_partial;
+	bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;
 
 	/* bytes_in_line includes the newlines, so we remove that assuming that
 	   they are single byte characters */
@@ -300,15 +307,16 @@ read_line (GeditDocumentInputStream *stream,
 	bytes_to_write = bytes;
 
 	/* do not add the new newline_size for the last line */
+	newline_size = get_new_line_size (stream);
 	if (!is_last)
 		bytes_to_write += newline_size;
 
 	if (bytes_to_write > space_left)
 	{
 		gchar *ptr;
-		gint offset;
+		gint char_offset;
+		gint written;
 		gsize to_write;
-		gsize next_size;
 
 		/* Here the line does not fit in the buffer, we thus write
 		   the amount of bytes we can still fit, storing the position
@@ -317,33 +325,22 @@ read_line (GeditDocumentInputStream *stream,
 		   iteration */
 		to_write = MIN (space_left, bytes);
 		ptr = buf;
-		next_size = 0;
-		offset = 0;
+		written = 0;
+		char_offset = 0;
 
-		do
+		while (written < to_write)
 		{
-			read = next_size;
-
-			if (read == to_write)
-			{
-				/* Make sure offset is still one past what we
-				   wrote... */
-				++offset;
-				break;
-			}
-
 			ptr = g_utf8_next_char (ptr);
-			next_size = ptr - buf;
-
-			++offset;
-		} while (next_size <= to_write);
+			written = (ptr - buf);
+			++char_offset;
+		}
 
-		memcpy (outbuf, buf, read);
+		memcpy (outbuf, buf, written);
 
 		/* Note: offset is one past what we wrote */
-		gtk_text_iter_forward_chars (start, offset - 1);
-
-		stream->priv->bytes_partial += read;
+		gtk_text_iter_forward_chars (&start, char_offset);
+		stream->priv->bytes_partial += written;
+		read = written;
 	}
 	else
 	{
@@ -356,12 +353,15 @@ read_line (GeditDocumentInputStream *stream,
 			memcpy (outbuf + bytes, newline, newline_size);
 		}
 
-		read = bytes_to_write;
-		*start = next;
-
+		start = next;
 		stream->priv->bytes_partial = 0;
+		read = bytes_to_write;
 	}
 
+	gtk_text_buffer_move_mark (stream->priv->buffer,
+				   stream->priv->pos,
+				   &start);
+
 	g_free (buf);
 	return read;
 }
@@ -374,6 +374,7 @@ gedit_document_input_stream_read (GInputStream  *stream,
 				  GError       **error)
 {
 	GeditDocumentInputStream *dstream;
+	GtkTextIter iter;
 	gssize space_left, read, n;
 
 	dstream = GEDIT_DOCUMENT_INPUT_STREAM (stream);
@@ -391,7 +392,12 @@ gedit_document_input_stream_read (GInputStream  *stream,
 	/* Initialize the mark to the first char in the text buffer */
 	if (!dstream->priv->is_initialized)
 	{
-		gtk_text_buffer_get_start_iter (dstream->priv->buffer, &dstream->priv->pos);
+		gtk_text_buffer_get_start_iter (dstream->priv->buffer, &iter);
+		dstream->priv->pos = gtk_text_buffer_create_mark (dstream->priv->buffer,
+								 NULL,
+								 &iter,
+								 FALSE);
+
 		dstream->priv->is_initialized = TRUE;
 	}
 
@@ -407,8 +413,12 @@ gedit_document_input_stream_read (GInputStream  *stream,
 
 	/* Make sure that non-empty files are always terminated with \n (see bug #95676).
 	 * Note that we strip the trailing \n when loading the file */
-	if (gtk_text_iter_is_end (&dstream->priv->pos) &&
-	    !gtk_text_iter_is_start (&dstream->priv->pos))
+	gtk_text_buffer_get_iter_at_mark (dstream->priv->buffer,
+					  &iter,
+					  dstream->priv->pos);
+
+	if (gtk_text_iter_is_end (&iter) &&
+	    !gtk_text_iter_is_start (&iter))
 	{
 		gssize newline_size;
 
@@ -440,5 +450,10 @@ gedit_document_input_stream_close (GInputStream  *stream,
 
 	dstream->priv->newline_added = FALSE;
 
+	if (dstream->priv->is_initialized)
+	{
+		gtk_text_buffer_delete_mark (dstream->priv->buffer, dstream->priv->pos);
+	}
+
 	return TRUE;
 }
diff --git a/tests/document-input-stream.c b/tests/document-input-stream.c
index bd792d6..152a39f 100644
--- a/tests/document-input-stream.c
+++ b/tests/document-input-stream.c
@@ -39,6 +39,7 @@ test_consecutive_read (const gchar *inbuf,
 	gssize n, r;
 	GError *err = NULL;
 	gchar *b;
+	gboolean close;
 
 	buf = gtk_text_buffer_new (NULL);
 	gtk_text_buffer_set_text (buf, inbuf, -1);
@@ -64,6 +65,10 @@ test_consecutive_read (const gchar *inbuf,
 
 	g_assert_cmpstr (b, ==, outbuf);
 
+	close = g_input_stream_close (in, NULL, &err);
+	g_assert (close);
+	g_assert_no_error (err);
+
 	g_object_unref (buf);
 	g_object_unref (in);
 	g_free (b);



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