summaryrefslogtreecommitdiff
path: root/gedit/gedit-gio-document-loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'gedit/gedit-gio-document-loader.c')
-rwxr-xr-xgedit/gedit-gio-document-loader.c708
1 files changed, 0 insertions, 708 deletions
diff --git a/gedit/gedit-gio-document-loader.c b/gedit/gedit-gio-document-loader.c
deleted file mode 100755
index 73cfe113..00000000
--- a/gedit/gedit-gio-document-loader.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * gedit-gio-document-loader.c
- * This file is part of gedit
- *
- * Copyright (C) 2005 - Paolo Maggi
- * Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
- * Copyright (C) 2008 - Jesse van den Kieboom
- *
- * This program 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.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the gedit Team, 2005-2008. See the AUTHORS file for a
- * list of people on the gedit Team.
- * See the ChangeLog files for a list of changes.
- *
- * $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-#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"
-#include "gedit-utils.h"
-
-#ifndef ENABLE_GVFS_METADATA
-#include "gedit-metadata-manager.h"
-#endif
-
-typedef struct
-{
- GeditGioDocumentLoader *loader;
- GCancellable *cancellable;
-
- gssize read;
- gboolean tried_mount;
-} AsyncData;
-
-#define READ_CHUNK_SIZE 8192
-#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
- G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
- G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
- G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
- G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," \
- GEDIT_METADATA_ATTRIBUTE_ENCODING
-
-#define GEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE(object) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
- GEDIT_TYPE_GIO_DOCUMENT_LOADER, \
- GeditGioDocumentLoaderPrivate))
-
-static void gedit_gio_document_loader_load (GeditDocumentLoader *loader);
-static gboolean gedit_gio_document_loader_cancel (GeditDocumentLoader *loader);
-static goffset gedit_gio_document_loader_get_bytes_read (GeditDocumentLoader *loader);
-
-static void open_async_read (AsyncData *async);
-
-struct _GeditGioDocumentLoaderPrivate
-{
- /* Info on the current file */
- GFile *gfile;
-
- goffset bytes_read;
-
- /* Handle for remote files */
- GCancellable *cancellable;
- GInputStream *stream;
- GOutputStream *output;
- GeditSmartCharsetConverter *converter;
-
- gchar buffer[READ_CHUNK_SIZE];
-
- GError *error;
-};
-
-G_DEFINE_TYPE(GeditGioDocumentLoader, gedit_gio_document_loader, GEDIT_TYPE_DOCUMENT_LOADER)
-
-static void
-gedit_gio_document_loader_dispose (GObject *object)
-{
- GeditGioDocumentLoaderPrivate *priv;
-
- priv = GEDIT_GIO_DOCUMENT_LOADER (object)->priv;
-
- if (priv->cancellable != NULL)
- {
- g_cancellable_cancel (priv->cancellable);
- g_object_unref (priv->cancellable);
- priv->cancellable = NULL;
- }
-
- if (priv->stream != NULL)
- {
- g_object_unref (priv->stream);
- priv->stream = NULL;
- }
-
- if (priv->output != NULL)
- {
- g_object_unref (priv->output);
- priv->output = NULL;
- }
-
- if (priv->converter != NULL)
- {
- g_object_unref (priv->converter);
- priv->converter = NULL;
- }
-
- if (priv->gfile != NULL)
- {
- g_object_unref (priv->gfile);
- priv->gfile = NULL;
- }
-
- if (priv->error != NULL)
- {
- g_error_free (priv->error);
- priv->error = NULL;
- }
-
- G_OBJECT_CLASS (gedit_gio_document_loader_parent_class)->dispose (object);
-}
-
-static void
-gedit_gio_document_loader_class_init (GeditGioDocumentLoaderClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GeditDocumentLoaderClass *loader_class = GEDIT_DOCUMENT_LOADER_CLASS (klass);
-
- object_class->dispose = gedit_gio_document_loader_dispose;
-
- loader_class->load = gedit_gio_document_loader_load;
- loader_class->cancel = gedit_gio_document_loader_cancel;
- loader_class->get_bytes_read = gedit_gio_document_loader_get_bytes_read;
-
- g_type_class_add_private (object_class, sizeof(GeditGioDocumentLoaderPrivate));
-}
-
-static void
-gedit_gio_document_loader_init (GeditGioDocumentLoader *gvloader)
-{
- gvloader->priv = GEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE (gvloader);
-
- gvloader->priv->converter = NULL;
- gvloader->priv->error = NULL;
-}
-
-static AsyncData *
-async_data_new (GeditGioDocumentLoader *gvloader)
-{
- AsyncData *async;
-
- async = g_slice_new (AsyncData);
- async->loader = gvloader;
- async->cancellable = g_object_ref (gvloader->priv->cancellable);
- async->tried_mount = FALSE;
-
- return async;
-}
-
-static void
-async_data_free (AsyncData *async)
-{
- g_object_unref (async->cancellable);
- g_slice_free (AsyncData, async);
-}
-
-static const GeditEncoding *
-get_metadata_encoding (GeditDocumentLoader *loader)
-{
- const GeditEncoding *enc = NULL;
-
-#ifndef ENABLE_GVFS_METADATA
- gchar *charset;
- const gchar *uri;
-
- uri = gedit_document_loader_get_uri (loader);
-
- charset = gedit_metadata_manager_get (uri, "encoding");
-
- if (charset == NULL)
- return NULL;
-
- enc = gedit_encoding_get_from_charset (charset);
-
- g_free (charset);
-#else
- GFileInfo *info;
-
- info = gedit_document_loader_get_info (loader);
-
- /* check if the encoding was set in the metadata */
- if (g_file_info_has_attribute (info, GEDIT_METADATA_ATTRIBUTE_ENCODING))
- {
- const gchar *charset;
-
- charset = g_file_info_get_attribute_string (info,
- GEDIT_METADATA_ATTRIBUTE_ENCODING);
-
- if (charset == NULL)
- return NULL;
-
- enc = gedit_encoding_get_from_charset (charset);
- }
-#endif
-
- return enc;
-}
-
-static void
-remote_load_completed_or_failed (GeditGioDocumentLoader *loader, AsyncData *async)
-{
- gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (loader),
- TRUE,
- loader->priv->error);
-
- if (async)
- async_data_free (async);
-}
-
-static void
-async_failed (AsyncData *async, GError *error)
-{
- g_propagate_error (&async->loader->priv->error, error);
- remote_load_completed_or_failed (async->loader, async);
-}
-
-static void
-close_input_stream_ready_cb (GInputStream *stream,
- GAsyncResult *res,
- AsyncData *async)
-{
- GError *error = NULL;
-
- gedit_debug (DEBUG_LOADER);
-
- /* check cancelled state manually */
- if (g_cancellable_is_cancelled (async->cancellable))
- {
- async_data_free (async);
- return;
- }
-
- gedit_debug_message (DEBUG_SAVER, "Finished closing input stream");
-
- if (!g_input_stream_close_finish (stream, res, &error))
- {
- gedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
-
- async_failed (async, error);
- return;
- }
-
- gedit_debug_message (DEBUG_SAVER, "Close output stream");
- if (!g_output_stream_close (async->loader->priv->output,
- async->cancellable, &error))
- {
- async_failed (async, error);
- return;
- }
-
- remote_load_completed_or_failed (async->loader, async);
-}
-
-static void
-write_complete (AsyncData *async)
-{
- GeditDocumentLoader *loader;
-
- loader = GEDIT_DOCUMENT_LOADER (async->loader);
-
- 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)
-{
- GeditGioDocumentLoader *gvloader;
- gssize bytes_written;
- GError *error = NULL;
-
- gvloader = async->loader;
-
- /* we use sync methods on doc stream since it is in memory. Using async
- would be racy and we can endup with invalidated iters */
- bytes_written = g_output_stream_write (G_OUTPUT_STREAM (gvloader->priv->output),
- gvloader->priv->buffer,
- async->read,
- async->cancellable,
- &error);
-
- gedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
- if (bytes_written == -1)
- {
- gedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
- async_failed (async, error);
- 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
-async_read_cb (GInputStream *stream,
- GAsyncResult *res,
- AsyncData *async)
-{
- gedit_debug (DEBUG_LOADER);
- GeditGioDocumentLoader *gvloader;
- GError *error = NULL;
-
- gedit_debug (DEBUG_LOADER);
-
- /* manually check cancelled state */
- if (g_cancellable_is_cancelled (async->cancellable))
- {
- async_data_free (async);
- return;
- }
-
- gvloader = async->loader;
-
- async->read = g_input_stream_read_finish (stream, res, &error);
-
- /* error occurred */
- 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 + async->read < gvloader->priv->bytes_read)
- {
- g_set_error (&gvloader->priv->error,
- GEDIT_DOCUMENT_ERROR,
- GEDIT_DOCUMENT_ERROR_TOO_BIG,
- "File too big");
-
- async_failed (async, gvloader->priv->error);
- return;
- }
-
- /* Bump the size. */
- gvloader->priv->bytes_read += async->read;
-
- /* end of the file, we are done! */
- if (async->read == 0)
- {
- GeditDocumentLoader *loader;
-
- loader = GEDIT_DOCUMENT_LOADER (gvloader);
-
- 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 */
- /* FIXME Uncomment this when we want to manage conversion fallback */
- /*if ((gedit_smart_charset_converter_get_num_fallbacks (gvloader->priv->converter) != 0) &&
- gvloader->priv->error == NULL)
- {
- g_set_error_literal (&gvloader->priv->error,
- GEDIT_DOCUMENT_ERROR,
- GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
- "There was a conversion error and it was "
- "needed to use a fallback char");
- }*/
-
- write_complete (async);
-
- return;
- }
-
- write_file_chunk (async);
-}
-
-static void
-read_file_chunk (AsyncData *async)
-{
- GeditGioDocumentLoader *gvloader;
-
- gvloader = async->loader;
-
- g_input_stream_read_async (G_INPUT_STREAM (gvloader->priv->stream),
- gvloader->priv->buffer,
- READ_CHUNK_SIZE,
- G_PRIORITY_HIGH,
- async->cancellable,
- (GAsyncReadyCallback) async_read_cb,
- async);
-}
-
-static GSList *
-get_candidate_encodings (GeditGioDocumentLoader *gvloader)
-{
- const GeditEncoding *metadata;
- GSList *encodings = NULL;
-
- encodings = gedit_prefs_manager_get_auto_detected_encodings ();
-
- metadata = get_metadata_encoding (GEDIT_DOCUMENT_LOADER (gvloader));
- if (metadata != NULL)
- {
- encodings = g_slist_prepend (encodings, (gpointer)metadata);
- }
-
- return encodings;
-}
-
-static void
-finish_query_info (AsyncData *async)
-{
- GeditGioDocumentLoader *gvloader;
- GeditDocumentLoader *loader;
- GInputStream *conv_stream;
- GFileInfo *info;
- GSList *candidate_encodings;
-
- gvloader = async->loader;
- loader = GEDIT_DOCUMENT_LOADER (gvloader);
- info = loader->info;
-
- /* if it's not a regular file, error out... */
- if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
- g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
- {
- g_set_error (&gvloader->priv->error,
- G_IO_ERROR,
- G_IO_ERROR_NOT_REGULAR_FILE,
- "Not a regular file");
-
- remote_load_completed_or_failed (gvloader, async);
-
- return;
- }
-
- /* Get the candidate encodings */
- if (loader->encoding == NULL)
- {
- candidate_encodings = get_candidate_encodings (gvloader);
- }
- else
- {
- candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->encoding);
- }
-
- gvloader->priv->converter = gedit_smart_charset_converter_new (candidate_encodings);
- g_slist_free (candidate_encodings);
-
- conv_stream = g_converter_input_stream_new (gvloader->priv->stream,
- G_CONVERTER (gvloader->priv->converter));
- g_object_unref (gvloader->priv->stream);
-
- gvloader->priv->stream = conv_stream;
-
- /* Output stream */
- gvloader->priv->output = gedit_document_output_stream_new (loader->document);
-
- /* start reading */
- read_file_chunk (async);
-}
-
-static void
-query_info_cb (GFile *source,
- GAsyncResult *res,
- AsyncData *async)
-{
- GeditGioDocumentLoader *gvloader;
- GFileInfo *info;
- GError *error = NULL;
-
- gedit_debug (DEBUG_LOADER);
-
- /* manually check the cancelled state */
- if (g_cancellable_is_cancelled (async->cancellable))
- {
- async_data_free (async);
- return;
- }
-
- gvloader = async->loader;
-
- /* finish the info query */
- info = g_file_query_info_finish (gvloader->priv->gfile,
- res,
- &error);
-
- if (info == NULL)
- {
- /* propagate the error and clean up */
- async_failed (async, error);
- return;
- }
-
- GEDIT_DOCUMENT_LOADER (gvloader)->info = info;
-
- finish_query_info (async);
-}
-
-static void
-mount_ready_callback (GFile *file,
- GAsyncResult *res,
- AsyncData *async)
-{
- GError *error = NULL;
- gboolean mounted;
-
- gedit_debug (DEBUG_LOADER);
-
- /* manual check for cancelled state */
- if (g_cancellable_is_cancelled (async->cancellable))
- {
- async_data_free (async);
- return;
- }
-
- mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
-
- if (!mounted)
- {
- async_failed (async, error);
- }
- else
- {
- /* try again to open the file for reading */
- open_async_read (async);
- }
-}
-
-static void
-recover_not_mounted (AsyncData *async)
-{
- GeditDocument *doc;
- GMountOperation *mount_operation;
-
- gedit_debug (DEBUG_LOADER);
-
- doc = gedit_document_loader_get_document (GEDIT_DOCUMENT_LOADER (async->loader));
- mount_operation = _gedit_document_create_mount_operation (doc);
-
- async->tried_mount = TRUE;
- g_file_mount_enclosing_volume (async->loader->priv->gfile,
- G_MOUNT_MOUNT_NONE,
- mount_operation,
- async->cancellable,
- (GAsyncReadyCallback) mount_ready_callback,
- async);
-
- g_object_unref (mount_operation);
-}
-
-static void
-async_read_ready_callback (GObject *source,
- GAsyncResult *res,
- AsyncData *async)
-{
- GError *error = NULL;
- GeditGioDocumentLoader *gvloader;
-
- gedit_debug (DEBUG_LOADER);
-
- /* manual check for cancelled state */
- if (g_cancellable_is_cancelled (async->cancellable))
- {
- async_data_free (async);
- return;
- }
-
- gvloader = async->loader;
-
- gvloader->priv->stream = G_INPUT_STREAM (g_file_read_finish (gvloader->priv->gfile,
- res, &error));
-
- if (!gvloader->priv->stream)
- {
- if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
- {
- recover_not_mounted (async);
- g_error_free (error);
- return;
- }
-
- /* Propagate error */
- g_propagate_error (&gvloader->priv->error, error);
- gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
- TRUE,
- gvloader->priv->error);
-
- async_data_free (async);
- return;
- }
-
- /* get the file info: note we cannot use
- * g_file_input_stream_query_info_async since it is not able to get the
- * content type etc, beside it is not supported by gvfs.
- * Using the file instead of the stream is slightly racy, but for
- * loading this is not too bad...
- */
- g_file_query_info_async (gvloader->priv->gfile,
- REMOTE_QUERY_ATTRIBUTES,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_HIGH,
- async->cancellable,
- (GAsyncReadyCallback) query_info_cb,
- async);
-}
-
-static void
-open_async_read (AsyncData *async)
-{
- g_file_read_async (async->loader->priv->gfile,
- G_PRIORITY_HIGH,
- async->cancellable,
- (GAsyncReadyCallback) async_read_ready_callback,
- async);
-}
-
-static void
-gedit_gio_document_loader_load (GeditDocumentLoader *loader)
-{
- GeditGioDocumentLoader *gvloader = GEDIT_GIO_DOCUMENT_LOADER (loader);
- AsyncData *async;
-
- gedit_debug (DEBUG_LOADER);
-
- /* make sure no load operation is currently running */
- g_return_if_fail (gvloader->priv->cancellable == NULL);
-
- gvloader->priv->gfile = g_file_new_for_uri (loader->uri);
-
- /* loading start */
- gedit_document_loader_loading (GEDIT_DOCUMENT_LOADER (gvloader),
- FALSE,
- NULL);
-
- gvloader->priv->cancellable = g_cancellable_new ();
- async = async_data_new (gvloader);
-
- open_async_read (async);
-}
-
-static goffset
-gedit_gio_document_loader_get_bytes_read (GeditDocumentLoader *loader)
-{
- return GEDIT_GIO_DOCUMENT_LOADER (loader)->priv->bytes_read;
-}
-
-static gboolean
-gedit_gio_document_loader_cancel (GeditDocumentLoader *loader)
-{
- GeditGioDocumentLoader *gvloader = GEDIT_GIO_DOCUMENT_LOADER (loader);
-
- if (gvloader->priv->cancellable == NULL)
- return FALSE;
-
- g_cancellable_cancel (gvloader->priv->cancellable);
-
- g_set_error (&gvloader->priv->error,
- G_IO_ERROR,
- G_IO_ERROR_CANCELLED,
- "Operation cancelled");
-
- remote_load_completed_or_failed (gvloader, NULL);
-
- return TRUE;
-}