[gedit] Add GeditDocumentOutputStream and unit tests.
- From: Paolo Borelli <pborelli src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gedit] Add GeditDocumentOutputStream and unit tests.
- Date: Mon, 8 Feb 2010 15:50:53 +0000 (UTC)
commit 981647dc1f27e6688564e8fbfbb86b7267cec549
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Mon Feb 8 15:14:25 2010 +0100
Add GeditDocumentOutputStream and unit tests.
gedit/Makefile.am | 2 +
gedit/gedit-document-output-stream.c | 281 ++++++++++++++++++++++++++++++++++
gedit/gedit-document-output-stream.h | 64 ++++++++
gedit/gedit-gio-document-loader.c | 266 ++++++++++++++++----------------
tests/Makefile.am | 4 +
tests/document-output-stream.c | 106 +++++++++++++
6 files changed, 591 insertions(+), 132 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index e308c48..9c61383 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -67,6 +67,7 @@ NOINST_H_FILES = \
gedit-dirs.h \
gedit-document-input-stream.h \
gedit-document-loader.h \
+ gedit-document-output-stream.h \
gedit-document-saver.h \
gedit-documents-panel.h \
gedit-gio-document-loader.h \
@@ -144,6 +145,7 @@ libgedit_la_SOURCES = \
gedit-document.c \
gedit-document-input-stream.c \
gedit-document-loader.c \
+ gedit-document-output-stream.c \
gedit-gio-document-loader.c \
gedit-document-saver.c \
gedit-gio-document-saver.c \
diff --git a/gedit/gedit-document-output-stream.c b/gedit/gedit-document-output-stream.c
new file mode 100644
index 0000000..898df54
--- /dev/null
+++ b/gedit/gedit-document-output-stream.c
@@ -0,0 +1,281 @@
+/*
+ * gedit-document-output-stream.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+
+#include "gedit-document-output-stream.h"
+
+
+#define GEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStreamPrivate))
+
+struct _GeditDocumentOutputStreamPrivate
+{
+ GeditDocument *doc;
+ GtkTextIter pos;
+
+ guint is_initialized : 1;
+ guint is_closed : 1;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DOCUMENT
+};
+
+G_DEFINE_TYPE (GeditDocumentOutputStream, gedit_document_output_stream, G_TYPE_OUTPUT_STREAM)
+
+static gssize gedit_document_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+
+static gboolean gedit_document_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
+static void
+gedit_document_output_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOCUMENT:
+ stream->priv->doc = GEDIT_DOCUMENT (g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_document_output_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditDocumentOutputStream *stream = GEDIT_DOCUMENT_OUTPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOCUMENT:
+ g_value_set_object (value, stream->priv->doc);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_document_output_stream_class_init (GeditDocumentOutputStreamClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ object_class->get_property = gedit_document_output_stream_get_property;
+ object_class->set_property = gedit_document_output_stream_set_property;
+
+ stream_class->write_fn = gedit_document_output_stream_write;
+ stream_class->close_fn = gedit_document_output_stream_close;
+
+ g_object_class_install_property (object_class,
+ PROP_DOCUMENT,
+ g_param_spec_object ("document",
+ "Document",
+ "The document which is written",
+ GEDIT_TYPE_DOCUMENT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (GeditDocumentOutputStreamPrivate));
+}
+
+static void
+gedit_document_output_stream_init (GeditDocumentOutputStream *stream)
+{
+ stream->priv = GEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ stream->priv->is_initialized = FALSE;
+ stream->priv->is_closed = FALSE;
+}
+
+static GeditDocumentNewlineType
+get_newline_type (GtkTextIter *end)
+{
+ GeditDocumentNewlineType res;
+ GtkTextIter copy;
+ gunichar c;
+
+ copy = *end;
+ c = gtk_text_iter_get_char (©);
+
+ GtkTextIter tt = copy;
+ gtk_text_iter_forward_chars (&tt, 2);
+
+ if (g_unichar_break_type (c) == G_UNICODE_BREAK_CARRIAGE_RETURN)
+ {
+ if (gtk_text_iter_forward_char (©) &&
+ g_unichar_break_type (gtk_text_iter_get_char (©)) == G_UNICODE_BREAK_LINE_FEED)
+ {
+ res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF;
+ }
+ else
+ {
+ res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR;
+ }
+ }
+ else
+ {
+ res = GEDIT_DOCUMENT_NEWLINE_TYPE_LF;
+ }
+
+ return res;
+}
+
+GOutputStream *
+gedit_document_output_stream_new (GeditDocument *doc)
+{
+ return G_OUTPUT_STREAM (g_object_new (GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM,
+ "document", doc, NULL));
+}
+
+GeditDocumentNewlineType
+gedit_document_output_stream_detect_newline_type (GeditDocumentOutputStream *stream)
+{
+ GeditDocumentNewlineType type;
+ GtkTextIter iter;
+
+ g_return_val_if_fail (GEDIT_IS_DOCUMENT_OUTPUT_STREAM (stream),
+ GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
+
+ type = GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
+
+ gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc), &iter);
+
+ if (!gtk_text_iter_backward_line (&iter))
+ {
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->doc),
+ &iter);
+ }
+
+ if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
+ {
+ type = get_newline_type (&iter);
+ }
+
+ return type;
+}
+
+/* If the last char is a newline, remove it from the buffer (otherwise
+ GtkTextView shows it as an empty line). See bug #324942. */
+static void
+remove_ending_newline (GeditDocumentOutputStream *stream)
+{
+ GtkTextIter end;
+ GtkTextIter start;
+
+ gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc), &end);
+ start = end;
+
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ if (gtk_text_iter_ends_line (&start) &&
+ gtk_text_iter_backward_line (&start))
+ {
+ if (!gtk_text_iter_ends_line (&start))
+ {
+ gtk_text_iter_forward_to_line_end (&start);
+ }
+
+ /* Delete the empty line which is from 'start' to 'end' */
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->doc),
+ &start,
+ &end);
+ }
+}
+
+static void
+end_append_text_to_document (GeditDocumentOutputStream *stream)
+{
+ remove_ending_newline (stream);
+
+ gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
+ FALSE);
+
+ gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
+}
+
+static gssize
+gedit_document_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GeditDocumentOutputStream *ostream = GEDIT_DOCUMENT_OUTPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ if (!ostream->priv->is_initialized)
+ {
+ /* Init the undoable action */
+ gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (ostream->priv->doc));
+
+ /* clear the buffer */
+ gtk_text_buffer_set_text (GTK_TEXT_BUFFER (ostream->priv->doc),
+ "", 0);
+
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->doc),
+ &ostream->priv->pos);
+ ostream->priv->is_initialized = TRUE;
+ }
+
+ gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc),
+ &ostream->priv->pos, buffer, count);
+
+ return count;
+}
+
+static gboolean
+gedit_document_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GeditDocumentOutputStream *ostream = GEDIT_DOCUMENT_OUTPUT_STREAM (stream);
+
+ if (!ostream->priv->is_closed && ostream->priv->is_initialized)
+ {
+ end_append_text_to_document (ostream);
+ ostream->priv->is_closed = TRUE;
+ }
+
+ return TRUE;
+}
diff --git a/gedit/gedit-document-output-stream.h b/gedit/gedit-document-output-stream.h
new file mode 100644
index 0000000..a3f99fc
--- /dev/null
+++ b/gedit/gedit-document-output-stream.h
@@ -0,0 +1,64 @@
+/*
+ * gedit-document-output-stream.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef __GEDIT_DOCUMENT_OUTPUT_STREAM_H__
+#define __GEDIT_DOCUMENT_OUTPUT_STREAM_H__
+
+#include <gio/gio.h>
+#include "gedit-document.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM (gedit_document_output_stream_get_type ())
+#define GEDIT_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStream))
+#define GEDIT_DOCUMENT_OUTPUT_STREAM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStream const))
+#define GEDIT_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStreamClass))
+#define GEDIT_IS_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
+#define GEDIT_IS_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
+#define GEDIT_DOCUMENT_OUTPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, GeditDocumentOutputStreamClass))
+
+typedef struct _GeditDocumentOutputStream GeditDocumentOutputStream;
+typedef struct _GeditDocumentOutputStreamClass GeditDocumentOutputStreamClass;
+typedef struct _GeditDocumentOutputStreamPrivate GeditDocumentOutputStreamPrivate;
+
+struct _GeditDocumentOutputStream
+{
+ GOutputStream parent;
+
+ GeditDocumentOutputStreamPrivate *priv;
+};
+
+struct _GeditDocumentOutputStreamClass
+{
+ GOutputStreamClass parent_class;
+};
+
+GType gedit_document_output_stream_get_type (void) G_GNUC_CONST;
+
+GOutputStream *gedit_document_output_stream_new (GeditDocument *doc);
+
+GeditDocumentNewlineType gedit_document_output_stream_detect_newline_type (GeditDocumentOutputStream *stream);
+
+G_END_DECLS
+
+#endif /* __GEDIT_DOCUMENT_OUTPUT_STREAM_H__ */
diff --git a/gedit/gedit-gio-document-loader.c b/gedit/gedit-gio-document-loader.c
index ac5b8c4..9b26e53 100644
--- a/gedit/gedit-gio-document-loader.c
+++ b/gedit/gedit-gio-document-loader.c
@@ -39,6 +39,7 @@
#include <gio/gio.h>
#include "gedit-gio-document-loader.h"
+#include "gedit-document-output-stream.h"
#include "gedit-smart-charset-converter.h"
#include "gedit-prefs-manager.h"
#include "gedit-debug.h"
@@ -48,6 +49,9 @@ typedef struct
{
GeditGioDocumentLoader *loader;
GCancellable *cancellable;
+
+ gssize read;
+ gssize written;
gboolean tried_mount;
} AsyncData;
@@ -80,13 +84,12 @@ struct _GeditGioDocumentLoaderPrivate
/* Handle for remote files */
GCancellable *cancellable;
GInputStream *stream;
+ GOutputStream *output;
GeditSmartCharsetConverter *converter;
gchar buffer[READ_CHUNK_SIZE];
GError *error;
-
- guint started_insert : 1;
};
G_DEFINE_TYPE(GeditGioDocumentLoader, gedit_gio_document_loader, GEDIT_TYPE_DOCUMENT_LOADER)
@@ -111,6 +114,12 @@ gedit_gio_document_loader_dispose (GObject *object)
priv->stream = NULL;
}
+ if (priv->output != NULL)
+ {
+ g_object_unref (priv->output);
+ priv->output = NULL;
+ }
+
if (priv->converter != NULL)
{
g_object_unref (priv->converter);
@@ -161,7 +170,6 @@ gedit_gio_document_loader_init (GeditGioDocumentLoader *gvloader)
gvloader->priv->converter = NULL;
gvloader->priv->error = NULL;
- gvloader->priv->started_insert = FALSE;
}
static AsyncData *
@@ -229,25 +237,11 @@ get_metadata_encoding (GeditDocumentLoader *loader)
static void
remote_load_completed_or_failed (GeditGioDocumentLoader *gvloader, AsyncData *async)
{
- GeditDocumentLoader *loader;
-
- loader = GEDIT_DOCUMENT_LOADER (gvloader);
-
- if (async)
- async_data_free (async);
-
- if (gvloader->priv->stream)
- g_input_stream_close_async (G_INPUT_STREAM (gvloader->priv->stream),
- G_PRIORITY_HIGH, NULL, NULL, NULL);
-
- gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
+ gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (async->loader),
TRUE,
- gvloader->priv->error);
+ async->loader->priv->error);
}
-/* prototype, because they call each other... isn't C lovely */
-static void read_file_chunk (AsyncData *async);
-
static void
async_failed (AsyncData *async, GError *error)
{
@@ -256,110 +250,145 @@ async_failed (AsyncData *async, GError *error)
}
static void
-append_text_to_document (GeditDocumentLoader *loader,
- const gchar *text,
- gint len)
+close_output_stream_ready_cb (GOutputStream *stream,
+ GAsyncResult *res,
+ AsyncData *async)
{
- GeditDocument *doc = loader->document;
- GtkTextIter end;
-
- /* Insert text in the buffer */
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end);
+ GError *error = NULL;
- gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &end, text, len);
-}
-
-static GeditDocumentNewlineType
-get_newline_type (GtkTextIter *end)
-{
- GeditDocumentNewlineType res;
- GtkTextIter copy;
- gunichar c;
+ /* check cancelled state manually */
+ if (g_cancellable_is_cancelled (async->cancellable))
+ {
+ async_data_free (async);
+ return;
+ }
+
+ gedit_debug_message (DEBUG_SAVER, "Finished closing stream");
+
+ if (!g_output_stream_close_finish (stream, res, &error))
+ {
+ gedit_debug_message (DEBUG_SAVER, "Closing stream error: %s", error->message);
- copy = *end;
- c = gtk_text_iter_get_char (©);
+ async_failed (async, error);
+ return;
+ }
- GtkTextIter tt = copy;
- gtk_text_iter_forward_chars (&tt, 2);
+ remote_load_completed_or_failed (async->loader, async);
+}
- if (g_unichar_break_type (c) == G_UNICODE_BREAK_CARRIAGE_RETURN)
+static void
+close_input_stream_ready_cb (GInputStream *stream,
+ GAsyncResult *res,
+ AsyncData *async)
+{
+ GError *error = NULL;
+
+ /* check cancelled state manually */
+ if (g_cancellable_is_cancelled (async->cancellable))
{
- if (gtk_text_iter_forward_char (©) &&
- g_unichar_break_type (gtk_text_iter_get_char (©)) == G_UNICODE_BREAK_LINE_FEED)
- {
- res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF;
- }
- else
- {
- res = GEDIT_DOCUMENT_NEWLINE_TYPE_CR;
- }
+ async_data_free (async);
+ return;
}
- else
+
+ gedit_debug_message (DEBUG_SAVER, "Finished closing input stream");
+
+ if (!g_input_stream_close_finish (stream, res, &error))
{
- res = GEDIT_DOCUMENT_NEWLINE_TYPE_LF;
+ gedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
+
+ async_failed (async, error);
+ return;
}
- return res;
+ /* now we close the output stream */
+ gedit_debug_message (DEBUG_SAVER, "Close output stream");
+ g_output_stream_close_async (async->loader->priv->output,
+ G_PRIORITY_HIGH,
+ async->cancellable,
+ (GAsyncReadyCallback)close_output_stream_ready_cb,
+ async);
}
static void
-detect_newline_type (GeditDocumentLoader *loader)
+write_complete (AsyncData *async)
{
- GtkTextIter iter;
+ GeditDocumentLoader *loader;
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (loader->document), &iter);
+ loader = GEDIT_DOCUMENT_LOADER (async->loader);
- if (!gtk_text_iter_backward_line (&iter))
- {
- gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (loader->document), &iter);
- }
-
- if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
- {
- loader->auto_detected_newline_type = get_newline_type (&iter);
- }
+ if (async->loader->priv->stream)
+ g_input_stream_close_async (G_INPUT_STREAM (async->loader->priv->stream),
+ G_PRIORITY_HIGH,
+ async->cancellable,
+ (GAsyncReadyCallback)close_input_stream_ready_cb,
+ async);
}
+/* prototype, because they call each other... isn't C lovely */
+static void read_file_chunk (AsyncData *async);
+static void write_file_chunk (AsyncData *async);
+
static void
-remove_ending_newline (GeditDocumentLoader *loader)
+async_write_cb (GOutputStream *stream,
+ GAsyncResult *res,
+ AsyncData *async)
{
- GtkTextIter end;
- GtkTextIter start;
+ GeditGioDocumentLoader *gvloader;
+ gssize bytes_written;
+ GError *error = NULL;
+
+ /* Check cancelled state manually */
+ if (g_cancellable_is_cancelled (async->cancellable))
+ {
+ async_data_free (async);
+ return;
+ }
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (loader->document), &end);
- start = end;
+ bytes_written = g_output_stream_write_finish (stream, res, &error);
- gtk_text_iter_set_line_offset (&start, 0);
+ gedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
- if (gtk_text_iter_ends_line (&start) &&
- gtk_text_iter_backward_line (&start))
+ if (bytes_written == -1)
{
- if (!gtk_text_iter_ends_line (&start))
- {
- gtk_text_iter_forward_to_line_end (&start);
- }
+ gedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
+ async_failed (async, error);
+ return;
+ }
- /* Delete the empty line which is from 'start' to 'end' */
- gtk_text_buffer_delete (GTK_TEXT_BUFFER (loader->document),
- &start,
- &end);
+ gvloader = async->loader;
+ async->written += bytes_written;
+
+ /* write again */
+ if (async->written != async->read)
+ {
+ write_file_chunk (async);
+ return;
}
+
+ /* note that this signal blocks the read... check if it isn't
+ * a performance problem
+ */
+ gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
+ FALSE,
+ NULL);
+
+ read_file_chunk (async);
}
static void
-end_append_text_to_document (GeditDocumentLoader *loader)
+write_file_chunk (AsyncData *async)
{
- detect_newline_type (loader);
-
- /* If the last char is a newline, remove it from the buffer (otherwise
- GtkTextView shows it as an empty line). See bug #324942. */
- remove_ending_newline (loader);
-
- gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (loader->document), FALSE);
+ GeditGioDocumentLoader *gvloader;
- gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (loader->document));
+ gvloader = async->loader;
- GEDIT_GIO_DOCUMENT_LOADER (loader)->priv->started_insert = FALSE;
+ g_output_stream_write_async (G_OUTPUT_STREAM (gvloader->priv->output),
+ gvloader->priv->buffer + async->written,
+ async->read - async->written,
+ G_PRIORITY_HIGH,
+ async->cancellable,
+ (GAsyncReadyCallback) async_write_cb,
+ async);
}
static void
@@ -370,7 +399,6 @@ async_read_cb (GInputStream *stream,
gedit_debug (DEBUG_LOADER);
GeditGioDocumentLoader *gvloader;
GeditDocumentLoader *loader;
- gssize bytes_read;
GError *error = NULL;
gvloader = async->loader;
@@ -379,44 +407,44 @@ async_read_cb (GInputStream *stream,
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
- end_append_text_to_document (GEDIT_DOCUMENT_LOADER (gvloader));
remote_load_completed_or_failed (gvloader, async);
return;
}
- bytes_read = g_input_stream_read_finish (stream, res, &error);
+ async->read = g_input_stream_read_finish (stream, res, &error);
+ async->written = 0;
/* error occurred */
- if (bytes_read == -1)
+ if (async->read == -1)
{
async_failed (async, error);
return;
}
/* Check for the extremely unlikely case where the file size overflows. */
- if (gvloader->priv->bytes_read + bytes_read < gvloader->priv->bytes_read)
+ if (gvloader->priv->bytes_read + async->read < gvloader->priv->bytes_read)
{
g_set_error (&gvloader->priv->error,
GEDIT_DOCUMENT_ERROR,
GEDIT_DOCUMENT_ERROR_TOO_BIG,
"File too big");
- end_append_text_to_document (GEDIT_DOCUMENT_LOADER (gvloader));
- remote_load_completed_or_failed (gvloader, async);
-
+ async_failed (async, gvloader->priv->error);
return;
}
/* Bump the size. */
- gvloader->priv->bytes_read += bytes_read;
+ gvloader->priv->bytes_read += async->read;
/* end of the file, we are done! */
- if (bytes_read == 0)
+ if (async->read == 0)
{
GEDIT_DOCUMENT_LOADER (gvloader)->auto_detected_encoding =
gedit_smart_charset_converter_get_guessed (gvloader->priv->converter);
loader->auto_detected_encoding = gedit_smart_charset_converter_get_guessed (gvloader->priv->converter);
+ loader->auto_detected_newline_type =
+ gedit_document_output_stream_detect_newline_type (GEDIT_DOCUMENT_OUTPUT_STREAM (gvloader->priv->output));
/* Check if we needed some fallback char, if so, check if there was
a previous error and if not set a fallback used error */
@@ -431,27 +459,12 @@ async_read_cb (GInputStream *stream,
"needed to use a fallback char");
}*/
- end_append_text_to_document (GEDIT_DOCUMENT_LOADER (gvloader));
-
- remote_load_completed_or_failed (gvloader, async);
+ write_complete (async);
return;
}
- append_text_to_document (GEDIT_DOCUMENT_LOADER (gvloader),
- gvloader->priv->buffer,
- bytes_read);
-
- /* otherwise emit progress and read some more */
-
- /* note that this signal blocks the read... check if it isn't
- * a performance problem
- */
- gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
- FALSE,
- NULL);
-
- read_file_chunk (async);
+ write_file_chunk (async);
}
static void
@@ -461,20 +474,6 @@ read_file_chunk (AsyncData *async)
gvloader = async->loader;
- if (!gvloader->priv->started_insert)
- {
- GeditDocumentLoader *loader;
-
- loader = GEDIT_DOCUMENT_LOADER (gvloader);
-
- /* Init the undoable action */
- gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (loader->document));
- gvloader->priv->started_insert = TRUE;
-
- /* clear the buffer */
- gtk_text_buffer_set_text (GTK_TEXT_BUFFER (loader->document), "", 0);
- }
-
g_input_stream_read_async (G_INPUT_STREAM (gvloader->priv->stream),
gvloader->priv->buffer,
READ_CHUNK_SIZE,
@@ -551,6 +550,9 @@ finish_query_info (AsyncData *async)
gvloader->priv->stream = utf8_stream;
+ /* Output stream */
+ gvloader->priv->output = gedit_document_output_stream_new (loader->document);
+
/* start reading */
read_file_chunk (async);
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dd6ee4c..f54ce8c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -11,6 +11,10 @@ TEST_PROGS += document-input-stream
document_input_stream_SOURCES = document-input-stream.c
document_input_stream_LDADD = $(progs_ldadd)
+TEST_PROGS += document-output-stream
+document_output_stream_SOURCES = document-output-stream.c
+document_output_stream_LDADD = $(progs_ldadd)
+
TEST_PROGS += document-loader
document_loader_SOURCES = document-loader.c
document_loader_LDADD = $(progs_ldadd)
diff --git a/tests/document-output-stream.c b/tests/document-output-stream.c
new file mode 100644
index 0000000..57b6db5
--- /dev/null
+++ b/tests/document-output-stream.c
@@ -0,0 +1,106 @@
+/*
+ * document-output-stream.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2010 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+
+#include "gedit-document-output-stream.h"
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <string.h>
+
+static void
+test_consecutive_write (const gchar *inbuf,
+ const gchar *outbuf,
+ gsize write_chunk_len)
+{
+ GeditDocument *doc;
+ GOutputStream *out;
+ gsize len;
+ gssize n, w;
+ GError *err = NULL;
+ gchar *b;
+
+ doc = gedit_document_new ();
+ out = gedit_document_output_stream_new (doc);
+
+ n = 0;
+
+ do
+ {
+ len = MIN (write_chunk_len, strlen (inbuf + n));
+ w = g_output_stream_write (out, inbuf + n, len, NULL, &err);
+ g_assert_cmpint (w, >=, 0);
+ g_assert_no_error (err);
+
+ n += w;
+ } while (w != 0);
+
+ g_object_get (G_OBJECT (doc), "text", &b, NULL);
+
+ g_assert_cmpstr (inbuf, ==, b);
+ g_free (b);
+
+ g_output_stream_close (out, NULL, &err);
+ g_assert_no_error (err);
+
+ g_object_get (G_OBJECT (doc), "text", &b, NULL);
+
+ g_assert_cmpstr (outbuf, ==, b);
+ g_free (b);
+
+ g_assert (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)) == FALSE);
+}
+
+static void
+test_empty ()
+{
+ test_consecutive_write ("", "", 10);
+}
+
+static void
+test_consecutive ()
+{
+ test_consecutive_write ("hello\nhow\nare\nyou", "hello\nhow\nare\nyou", 2);
+}
+
+static void
+test_consecutive_tnewline ()
+{
+ test_consecutive_write ("hello\nhow\nare\nyou\n", "hello\nhow\nare\nyou", 2);
+ test_consecutive_write ("hello\r\nhow\r\nare\r\nyou\r\n", "hello\r\nhow\r\nare\r\nyou", 2);
+}
+
+int main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ gedit_prefs_manager_app_init ();
+
+ g_test_add_func ("/document-output-stream/empty", test_empty);
+
+ g_test_add_func ("/document-output-stream/consecutive", test_consecutive);
+ g_test_add_func ("/document-output-stream/consecutive_tnewline", test_consecutive_tnewline);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]