[gedit/docstream2: 3/16] Add newline changing support
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gedit/docstream2: 3/16] Add newline changing support
- Date: Sat, 23 Jan 2010 13:30:25 +0000 (UTC)
commit 55bec7a7d19d38a6ec90fdb02fa19726bf3867e6
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Wed Jan 20 14:59:06 2010 +0100
Add newline changing support
gedit/gedit-document-input-stream.c | 176 ++++++++++++++++++++++++++++-------
gedit/gedit-document-input-stream.h | 5 +-
gedit/gedit-document.h | 7 ++
gedit/gedit-gio-document-saver.c | 3 +-
tests/document-input-stream.c | 79 ++++++----------
5 files changed, 185 insertions(+), 85 deletions(-)
---
diff --git a/gedit/gedit-document-input-stream.c b/gedit/gedit-document-input-stream.c
index bd05748..7c65f5a 100644
--- a/gedit/gedit-document-input-stream.c
+++ b/gedit/gedit-document-input-stream.c
@@ -28,6 +28,7 @@
#include <string.h>
#include "gedit-document-input-stream.h"
+#include "gedit-enum-types.h"
G_DEFINE_TYPE (GeditDocumentInputStream, gedit_document_input_stream, G_TYPE_INPUT_STREAM);
@@ -36,9 +37,7 @@ struct _GeditDocumentInputStreamPrivate
GtkTextBuffer *buffer;
GtkTextMark *pos;
- /* store the trailing line */
- gchar *line;
- gsize line_len;
+ GeditDocumentNewlineType newline_type;
guint newline_added : 1;
};
@@ -46,7 +45,8 @@ struct _GeditDocumentInputStreamPrivate
enum
{
PROP_0,
- PROP_BUFFER
+ PROP_BUFFER,
+ PROP_NEWLINE_TYPE
};
static gssize gedit_document_input_stream_read (GInputStream *stream,
@@ -61,10 +61,6 @@ static gboolean gedit_document_input_stream_close (GInputStream *strea
static void
gedit_document_input_stream_finalize (GObject *object)
{
- GeditDocumentInputStream *stream = GEDIT_DOCUMENT_INPUT_STREAM (object);
-
- g_free (stream->priv->line);
-
G_OBJECT_CLASS (gedit_document_input_stream_parent_class)->finalize (object);
}
@@ -98,6 +94,10 @@ gedit_document_input_stream_set_property (GObject *object,
stream->priv->buffer = GTK_TEXT_BUFFER (g_value_get_object (value));
break;
+ case PROP_NEWLINE_TYPE:
+ stream->priv->newline_type = g_value_get_enum (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -118,6 +118,10 @@ gedit_document_input_stream_get_property (GObject *object,
g_value_set_object (value, stream->priv->buffer);
break;
+ case PROP_NEWLINE_TYPE:
+ g_value_set_enum (value, stream->priv->newline_type);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -148,6 +152,24 @@ gedit_document_input_stream_class_init (GeditDocumentInputStreamClass *klass)
GTK_TYPE_TEXT_BUFFER,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GeditDocumentInputStream:newline-type:
+ *
+ * The :newline-type property determines what is considered
+ * as a line ending when reading complete lines from the stream.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_NEWLINE_TYPE,
+ g_param_spec_enum ("newline-type",
+ "Newline type",
+ "The accepted types of line ending",
+ GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
+ GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_CONSTRUCT_ONLY));
}
static void
@@ -157,12 +179,29 @@ gedit_document_input_stream_init (GeditDocumentInputStream *stream)
GEDIT_TYPE_DOCUMENT_INPUT_STREAM,
GeditDocumentInputStreamPrivate);
- stream->priv->line = NULL;
- stream->priv->line_len = 0;
- stream->priv->pos = NULL;
stream->priv->newline_added = FALSE;
}
+static gsize
+get_new_line_size (GeditDocumentInputStream *stream)
+{
+ gsize ret;
+
+ switch (stream->priv->newline_type)
+ {
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_CR:
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_LF:
+ ret = 1;
+ break;
+
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
+ ret = 2;
+ break;
+ }
+
+ return ret;
+}
+
/**
* gedit_document_input_stream_new:
* @buffer: a #GtkTextBuffer
@@ -172,7 +211,8 @@ gedit_document_input_stream_init (GeditDocumentInputStream *stream)
* Returns: a new #GInputStream to read @buffer
*/
GInputStream *
-gedit_document_input_stream_new (GtkTextBuffer *buffer)
+gedit_document_input_stream_new (GtkTextBuffer *buffer,
+ GeditDocumentNewlineType type)
{
GeditDocumentInputStream *stream;
@@ -180,6 +220,7 @@ gedit_document_input_stream_new (GtkTextBuffer *buffer)
stream = g_object_new (GEDIT_TYPE_DOCUMENT_INPUT_STREAM,
"buffer", buffer,
+ "newline-type", type,
NULL);
return G_INPUT_STREAM (stream);
@@ -207,6 +248,29 @@ gedit_document_input_stream_tell (GeditDocumentInputStream *stream)
return gtk_text_iter_get_offset (&iter);
}
+static const gchar *
+get_new_line (GeditDocumentInputStream *stream)
+{
+ const gchar *ret;
+
+ switch (stream->priv->newline_type)
+ {
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_CR:
+ ret = "\r";
+ break;
+
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_LF:
+ ret = "\n";
+ break;
+
+ case GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
+ ret = "\r\n";
+ break;
+ }
+
+ return ret;
+}
+
static gsize
read_line (GeditDocumentInputStream *stream,
gchar *outbuf,
@@ -214,37 +278,56 @@ read_line (GeditDocumentInputStream *stream,
{
GtkTextIter start, next, end;
gchar *buf;
- gsize read, bytes;
+ gsize read, bytes, newline_size;
+ const gchar *newline;
+ gboolean is_last;
gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
&start,
stream->priv->pos);
end = next = start;
+ newline = get_new_line (stream);
+ newline_size = get_new_line_size (stream);
if (gtk_text_iter_is_end (&start))
return 0;
if (!gtk_text_iter_ends_line (&end))
- gtk_text_iter_forward_line (&end);
+ gtk_text_iter_forward_to_line_end (&end);
+
+ gtk_text_iter_forward_line (&next);
buf = gtk_text_iter_get_slice (&start, &end);
- bytes = gtk_text_iter_get_bytes_in_line (&start);
+
+ /* 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_offset (&end) - gtk_text_iter_get_offset (&start);
+ is_last = gtk_text_iter_is_end (&end);
+
+ /* do not add the new newline_size if there wasn't a previous one */
+ if (!is_last)
+ bytes += newline_size;
if (bytes > space_left)
{
gchar *ptr;
gint offset;
+ gsize to_write;
+ /* we don't want to write here the newline so we write what
+ it is missing in the line and we leave the newline for the
+ new iteration */
+ to_write = MIN (space_left, (bytes - newline_size));
ptr = buf;
- while ((ptr - buf) < space_left)
+ while ((ptr - buf) < to_write)
ptr = g_utf8_next_char (ptr);
- if ((ptr - buf) > space_left)
+ if ((ptr - buf) > to_write)
ptr = g_utf8_prev_char (ptr);
- memcpy (outbuf + read, buf, (ptr - buf));
+ memcpy (outbuf, buf, (ptr - buf));
read = (ptr - buf);
offset = gtk_text_iter_get_line_offset (&start);
@@ -252,10 +335,19 @@ read_line (GeditDocumentInputStream *stream,
}
else
{
- memcpy (outbuf + read, buf, bytes);
- read = bytes;
-
- start = end;
+
+ memcpy (outbuf, buf, bytes - newline_size);
+ read = bytes - newline_size;
+
+ /* do not add the newline if there wasn't a previous, this can
+ happen in the last line */
+ if (!is_last)
+ {
+ memcpy (outbuf + read, newline, newline_size);
+ read += newline_size;
+ }
+
+ start = next;
}
g_free (buf);
@@ -275,24 +367,32 @@ gedit_document_input_stream_read (GInputStream *stream,
GError **error)
{
GeditDocumentInputStream *dstream;
- gssize space_left, read, n;
+ gssize space_left, read, n, newline_size;
+ GtkTextIter pos;
dstream = GEDIT_DOCUMENT_INPUT_STREAM (stream);
+ if (count < 6)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ "Not enougth space on destiny");
+ return -1;
+ }
+
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
+ /* Initialize the mark to the first char in the text buffer */
if (dstream->priv->pos == NULL)
{
GtkTextIter start;
gtk_text_buffer_get_start_iter (dstream->priv->buffer, &start);
- dstream->priv->pos = gtk_text_mark_new (NULL, TRUE);
-
- gtk_text_buffer_add_mark (dstream->priv->buffer,
- dstream->priv->pos,
- &start);
+ dstream->priv->pos = gtk_text_buffer_create_mark (dstream->priv->buffer,
+ NULL,
+ &start,
+ TRUE);
}
space_left = count;
@@ -307,10 +407,21 @@ gedit_document_input_stream_read (GInputStream *stream,
/* make sure files are always terminated with \n (see bug #95676). Note
that we strip the trailing \n when loading the file */
- if (space_left > 0 && !dstream->priv->newline_added)
+ gtk_text_buffer_get_iter_at_mark (dstream->priv->buffer,
+ &pos,
+ dstream->priv->pos);
+
+ newline_size = get_new_line_size (dstream);
+
+ if (gtk_text_iter_is_end (&pos) && space_left >= newline_size &&
+ !dstream->priv->newline_added)
{
- memcpy (buffer, "\n", 1);
- read++;
+ const gchar *newline;
+
+ newline = get_new_line (dstream);
+
+ memcpy (buffer + read, newline, newline_size);
+ read += newline_size;
dstream->priv->newline_added = TRUE;
}
@@ -324,9 +435,6 @@ gedit_document_input_stream_close (GInputStream *stream,
{
GeditDocumentInputStream *dstream = GEDIT_DOCUMENT_INPUT_STREAM (stream);
- g_free (dstream->priv->line);
- dstream->priv->line = NULL;
- dstream->priv->line_len = 0;
dstream->priv->newline_added = FALSE;
return TRUE;
diff --git a/gedit/gedit-document-input-stream.h b/gedit/gedit-document-input-stream.h
index ec686fa..01f6a49 100644
--- a/gedit/gedit-document-input-stream.h
+++ b/gedit/gedit-document-input-stream.h
@@ -26,6 +26,8 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
+#include "gedit-document.h"
+
G_BEGIN_DECLS
#define GEDIT_TYPE_DOCUMENT_INPUT_STREAM (gedit_document_input_stream_get_type ())
@@ -54,7 +56,8 @@ struct _GeditDocumentInputStreamClass
GType gedit_document_input_stream_get_type (void) G_GNUC_CONST;
-GInputStream *gedit_document_input_stream_new (GtkTextBuffer *buffer);
+GInputStream *gedit_document_input_stream_new (GtkTextBuffer *buffer,
+ GeditDocumentNewlineType type);
gsize gedit_document_input_stream_get_total_size (GeditDocumentInputStream *stream);
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index 0b8fde9..6d29fea 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -63,6 +63,13 @@ G_BEGIN_DECLS
typedef enum
{
+ GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
+ GEDIT_DOCUMENT_NEWLINE_TYPE_CR,
+ GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF
+} GeditDocumentNewlineType;
+
+typedef enum
+{
GEDIT_SEARCH_DONT_SET_FLAGS = 1 << 0,
GEDIT_SEARCH_ENTIRE_WORD = 1 << 1,
GEDIT_SEARCH_CASE_SENSITIVE = 1 << 2
diff --git a/gedit/gedit-gio-document-saver.c b/gedit/gedit-gio-document-saver.c
index a2d099c..57a194c 100644
--- a/gedit/gedit-gio-document-saver.c
+++ b/gedit/gedit-gio-document-saver.c
@@ -537,7 +537,8 @@ async_replace_ready_callback (GFile *source,
gvsaver->priv->stream = G_OUTPUT_STREAM (file_stream);
}
- gvsaver->priv->input = gedit_document_input_stream_new (GTK_TEXT_BUFFER (saver->document));
+ gvsaver->priv->input = gedit_document_input_stream_new (GTK_TEXT_BUFFER (saver->document),
+ G_DATA_STREAM_NEWLINE_TYPE_LF);
gvsaver->priv->size = gedit_document_input_stream_get_total_size (GEDIT_DOCUMENT_INPUT_STREAM (gvsaver->priv->input));
diff --git a/tests/document-input-stream.c b/tests/document-input-stream.c
index ea2d6aa..06c7f06 100644
--- a/tests/document-input-stream.c
+++ b/tests/document-input-stream.c
@@ -27,37 +27,11 @@
#include <glib.h>
#include <string.h>
-#define TEXT_TO_TEST "hello this is some text\nsencond line of the text"
-
static void
-test_single_read ()
-{
- GtkTextBuffer *buf;
- GInputStream *in;
- gsize r;
- GError *err = NULL;
- gchar *b;
-
- buf = gtk_text_buffer_new (NULL);
-
- gtk_text_buffer_set_text (buf, TEXT_TO_TEST, -1);
-
- b = g_malloc (200);
- in = gedit_document_input_stream_new (buf);
-
- r = g_input_stream_read (in, b, strlen (TEXT_TO_TEST), NULL, &err);
-
- g_assert_no_error (err);
-
- g_assert_cmpint (r, >, 0);
-
- b[strlen (TEXT_TO_TEST)] = '\0';
-
- g_assert_cmpstr (b, ==, TEXT_TO_TEST);
-}
-
-static void
-test_consecutive_read ()
+test_consecutive_read (const gchar *inbuf,
+ const gchar *outbuf,
+ GeditDocumentNewlineType type,
+ gsize mem)
{
GtkTextBuffer *buf;
GInputStream *in;
@@ -67,41 +41,48 @@ test_consecutive_read ()
buf = gtk_text_buffer_new (NULL);
- gtk_text_buffer_set_text (buf, TEXT_TO_TEST, -1);
+ gtk_text_buffer_set_text (buf, inbuf, -1);
b = g_malloc (200);
- in = gedit_document_input_stream_new (buf);
+ in = gedit_document_input_stream_new (buf, type);
n = 0;
do
{
- r = g_input_stream_read (in, b + n, 6, NULL, &err);
+ r = g_input_stream_read (in, b + n, mem, NULL, &err);
n += r;
g_assert_no_error (err);
} while (r != 0);
g_assert_cmpint (n, >, 0);
- g_assert_cmpstr (b, ==, TEXT_TO_TEST"\n");
+ g_assert_cmpstr (b, ==, outbuf);
}
static void
-test_size ()
+test_consecutive_cut_char ()
{
- GtkTextBuffer *buf;
- GInputStream *in;
- gsize size;
-
- buf = gtk_text_buffer_new (NULL);
-
- gtk_text_buffer_set_text (buf, TEXT_TO_TEST, -1);
-
- in = gedit_document_input_stream_new (buf);
+ /* first \n is read then fo and then is added \r but not \n */
+ test_consecutive_read ("\nfo\nbar\n\nblah\n", "\r\nfo\r\nbar\r\n\r\nblah\r\n\r\n", GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF, 8);
+}
- size = gedit_document_input_stream_get_total_size (GEDIT_DOCUMENT_INPUT_STREAM (in));
+static void
+test_consecutive_big_read ()
+{
+ test_consecutive_read ("\nfo\nbar\n\nblah\n", "\rfo\rbar\r\rblah\r\r", GEDIT_DOCUMENT_NEWLINE_TYPE_CR, 200);
+ test_consecutive_read ("\rfo\rbar\r\rblah\r", "\nfo\nbar\n\nblah\n\n", GEDIT_DOCUMENT_NEWLINE_TYPE_LF, 200);
+ test_consecutive_read ("\r\nfo\r\nbar\r\n\r\nblah\r\n", "\nfo\nbar\n\nblah\n\n", GEDIT_DOCUMENT_NEWLINE_TYPE_LF, 200);
+ test_consecutive_read ("\nfo\nbar\n\nblah\n", "\r\nfo\r\nbar\r\n\r\nblah\r\n\r\n", GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF, 200);
+}
- g_assert_cmpint (size, ==, strlen (TEXT_TO_TEST));
+static void
+test_consecutive_middle_read ()
+{
+ test_consecutive_read ("\nfo\nbar\n\nblah\n", "\rfo\rbar\r\rblah\r\r", GEDIT_DOCUMENT_NEWLINE_TYPE_CR, 6);
+ test_consecutive_read ("\rfo\rbar\r\rblah\r", "\nfo\nbar\n\nblah\n\n", GEDIT_DOCUMENT_NEWLINE_TYPE_LF, 6);
+ test_consecutive_read ("\r\nfo\r\nbar\r\n\r\nblah\r\n", "\nfo\nbar\n\nblah\n\n", GEDIT_DOCUMENT_NEWLINE_TYPE_LF, 6);
+ test_consecutive_read ("\nfo\nbar\n\nblah\n", "\r\nfo\r\nbar\r\n\r\nblah\r\n\r\n", GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF, 6);
}
int main (int argc,
@@ -110,9 +91,9 @@ int main (int argc,
g_type_init ();
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/document-input-stream/single_read", test_single_read);
- g_test_add_func ("/document-input-stream/consecutive_read", test_consecutive_read);
- g_test_add_func ("/document-input-stream/size", test_size);
+ g_test_add_func ("/document-input-stream/consecutive_cut_char", test_consecutive_cut_char);
+ g_test_add_func ("/document-input-stream/consecutive_big_read", test_consecutive_big_read);
+ g_test_add_func ("/document-input-stream/consecutive_middle_read", test_consecutive_middle_read);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]