Updated Spanish translation
[anjuta-git-plugin.git] / plugins / sourceview / anjuta-document-loader.c
blob14471136b4ce4ec06ca4dade07637eb51f2786a5
1 /*
2 * anjuta-document-loader.c
3 * This file is part of anjuta
5 * Copyright (C) 2005 - Paolo Maggi
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * Modified by the anjuta Team, 2005. See the AUTHORS file for a
25 * list of people on the anjuta Team.
26 * See the ChangeLog files for a list of changes.
28 * $Id$
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <sys/mman.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <string.h>
40 #include <errno.h>
42 #include <glib/gi18n.h>
43 #include <glib/gstdio.h>
44 #include <libgnomevfs/gnome-vfs.h>
46 #include "anjuta-encodings.h"
47 #include "anjuta-document-loader.h"
48 #include "anjuta-marshal.h"
49 #include "anjuta-convert.h"
51 #define READ_CHUNK_SIZE 8192
53 #define ANJUTA_DOCUMENT_LOADER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
54 ANJUTA_TYPE_DOCUMENT_LOADER, \
55 AnjutaDocumentLoaderPrivate))
57 static void async_close_cb (GnomeVFSAsyncHandle *handle,
58 GnomeVFSResult result,
59 gpointer data);
62 struct _AnjutaDocumentLoaderPrivate
64 AnjutaDocument *document;
66 gboolean used;
68 /* Info on the current file */
69 gchar *uri;
70 const AnjutaEncoding *encoding;
72 GnomeVFSURI *vfs_uri;
74 GnomeVFSFileInfo *info;
75 GnomeVFSFileSize bytes_read;
77 /* Handle for local files */
78 gint fd;
79 gchar *local_file_name;
81 /* Handle for remote files */
82 GnomeVFSAsyncHandle *handle;
83 GnomeVFSAsyncHandle *info_handle;
85 gchar *buffer;
87 const AnjutaEncoding *auto_detected_encoding;
89 GError *error;
92 G_DEFINE_TYPE(AnjutaDocumentLoader, anjuta_document_loader, G_TYPE_OBJECT)
94 /* Signals */
96 enum {
97 LOADING,
98 LAST_SIGNAL
101 static guint signals[LAST_SIGNAL] = { 0 };
103 /* Properties */
105 enum
107 PROP_0,
108 PROP_DOCUMENT,
111 static void
112 anjuta_document_loader_set_property (GObject *object,
113 guint prop_id,
114 const GValue *value,
115 GParamSpec *pspec)
117 AnjutaDocumentLoader *dl = ANJUTA_DOCUMENT_LOADER (object);
119 switch (prop_id)
121 case PROP_DOCUMENT:
122 g_return_if_fail (dl->priv->document == NULL);
123 dl->priv->document = g_value_get_object (value);
124 break;
125 default:
126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127 break;
131 static void
132 anjuta_document_loader_get_property (GObject *object,
133 guint prop_id,
134 GValue *value,
135 GParamSpec *pspec)
137 AnjutaDocumentLoader *dl = ANJUTA_DOCUMENT_LOADER (object);
139 switch (prop_id)
141 case PROP_DOCUMENT:
142 g_value_set_object (value,
143 dl->priv->document);
144 break;
145 default:
146 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147 break;
151 static void
152 anjuta_document_loader_finalize (GObject *object)
154 AnjutaDocumentLoaderPrivate *priv = ANJUTA_DOCUMENT_LOADER (object)->priv;
156 if (priv->handle != NULL)
158 if (priv->info_handle != NULL)
160 gnome_vfs_async_cancel (priv->info_handle);
161 gnome_vfs_async_close (priv->info_handle,
162 async_close_cb,
163 NULL);
166 gnome_vfs_async_cancel (priv->handle);
167 gnome_vfs_async_close (priv->handle,
168 async_close_cb,
169 NULL);
172 g_free (priv->uri);
174 if (priv->info)
175 gnome_vfs_file_info_unref (priv->info);
178 g_free (priv->local_file_name);
179 g_free (priv->buffer);
181 if (priv->vfs_uri)
182 gnome_vfs_uri_unref (priv->vfs_uri);
184 if (priv->error)
185 g_error_free (priv->error);
187 G_OBJECT_CLASS (anjuta_document_loader_parent_class)->finalize (object);
190 static void
191 anjuta_document_loader_class_init (AnjutaDocumentLoaderClass *klass)
193 GObjectClass *object_class = G_OBJECT_CLASS (klass);
195 object_class->finalize = anjuta_document_loader_finalize;
196 object_class->get_property = anjuta_document_loader_get_property;
197 object_class->set_property = anjuta_document_loader_set_property;
199 g_object_class_install_property (object_class,
200 PROP_DOCUMENT,
201 g_param_spec_object ("document",
202 "Document",
203 "The AnjutaDocument this AnjutaDocumentLoader is associated with",
204 ANJUTA_TYPE_DOCUMENT,
205 G_PARAM_READWRITE |
206 G_PARAM_CONSTRUCT_ONLY));
208 signals[LOADING] =
209 g_signal_new ("loading",
210 G_OBJECT_CLASS_TYPE (object_class),
211 G_SIGNAL_RUN_LAST,
212 G_STRUCT_OFFSET (AnjutaDocumentLoaderClass, loading),
213 NULL, NULL,
214 anjuta_marshal_VOID__BOOLEAN_POINTER,
215 G_TYPE_NONE,
217 G_TYPE_BOOLEAN,
218 G_TYPE_POINTER);
220 g_type_class_add_private (object_class, sizeof(AnjutaDocumentLoaderPrivate));
223 static void
224 anjuta_document_loader_init (AnjutaDocumentLoader *loader)
226 loader->priv = ANJUTA_DOCUMENT_LOADER_GET_PRIVATE (loader);
228 loader->priv->used = FALSE;
230 loader->priv->fd = -1;
232 loader->priv->error = NULL;
235 AnjutaDocumentLoader *
236 anjuta_document_loader_new (AnjutaDocument *doc)
238 AnjutaDocumentLoader *dl;
240 g_return_val_if_fail (ANJUTA_IS_DOCUMENT (doc), NULL);
242 dl = ANJUTA_DOCUMENT_LOADER (g_object_new (ANJUTA_TYPE_DOCUMENT_LOADER,
243 "document", doc,
244 NULL));
246 return dl;
249 static void
250 insert_text_in_document (AnjutaDocumentLoader *loader,
251 const gchar *text,
252 gint len)
254 gtk_source_buffer_begin_not_undoable_action (
255 GTK_SOURCE_BUFFER (loader->priv->document));
257 /* Insert text in the buffer */
258 gtk_text_buffer_set_text (GTK_TEXT_BUFFER (loader->priv->document),
259 text,
260 len);
262 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (loader->priv->document),
263 FALSE);
265 gtk_source_buffer_end_not_undoable_action (
266 GTK_SOURCE_BUFFER (loader->priv->document));
269 static gboolean
270 update_document_contents (AnjutaDocumentLoader *loader,
271 const gchar *file_contents,
272 gint file_size,
273 GError **error)
275 g_return_val_if_fail (file_size > 0, FALSE);
276 g_return_val_if_fail (file_contents != NULL, FALSE);
278 if (loader->priv->encoding == anjuta_encoding_get_utf8 ())
280 if (g_utf8_validate (file_contents, file_size, NULL))
282 insert_text_in_document (loader,
283 file_contents,
284 file_size);
286 return TRUE;
288 else
290 g_set_error (error,
291 G_CONVERT_ERROR,
292 G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
293 "The file you are trying to open contains an invalid byte sequence.");
295 return FALSE;
298 else
300 GError *conv_error = NULL;
301 gchar *converted_text = NULL;
302 gsize new_len = file_size;
304 if (converted_text == NULL)
306 loader->priv->auto_detected_encoding = loader->priv->encoding;
308 converted_text = anjuta_convert_to_utf8 (
309 file_contents,
310 file_size,
311 &loader->priv->auto_detected_encoding,
312 &new_len,
313 &conv_error);
315 if (converted_text == NULL)
317 /* Last change, let's try 8859-15 */
318 loader->priv->auto_detected_encoding =
319 anjuta_encoding_get_from_charset( "ISO-8859-15");
321 converted_text = anjuta_convert_to_utf8 (
322 file_contents,
323 file_size,
324 &loader->priv->auto_detected_encoding,
325 &new_len,
326 &conv_error);
329 if (converted_text == NULL)
331 g_return_val_if_fail (conv_error != NULL, FALSE);
333 g_propagate_error (error, conv_error);
335 return FALSE;
337 else
339 insert_text_in_document (loader,
340 converted_text,
341 new_len);
343 g_free (converted_text);
345 return TRUE;
349 g_return_val_if_reached (FALSE);
352 /* The following function has been copied from gnome-vfs
353 (modules/file-method.c) file */
354 static void
355 get_access_info (GnomeVFSFileInfo *file_info,
356 const gchar *full_name)
358 /* FIXME: should check errno after calling access because we don't
359 * want to set valid_fields if something bad happened during one
360 * of the access calls
362 if (g_access (full_name, W_OK) == 0)
363 file_info->permissions |= GNOME_VFS_PERM_ACCESS_WRITABLE;
366 * We don't need to know if a local file is readable or
367 * executable so I have commented the followig code to avoid
368 * multiple g_access calls - Paolo (Oct. 18, 2005)
372 * if (g_access (full_name, R_OK) == 0)
373 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_READABLE;
375 * #ifdef G_OS_WIN32
376 * if (g_file_test (full_name, G_FILE_TEST_IS_EXECUTABLE))
377 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
378 * #else
379 * if (g_access (full_name, X_OK) == 0)
380 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
381 * #endif
384 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACCESS;
387 /* The following function has been copied from gnome-vfs
388 (gnome-vfs-module-shared.c) file */
389 static void
390 stat_to_file_info (GnomeVFSFileInfo *file_info,
391 const struct stat *statptr)
393 if (S_ISDIR (statptr->st_mode))
394 file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
395 else if (S_ISCHR (statptr->st_mode))
396 file_info->type = GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE;
397 else if (S_ISBLK (statptr->st_mode))
398 file_info->type = GNOME_VFS_FILE_TYPE_BLOCK_DEVICE;
399 else if (S_ISFIFO (statptr->st_mode))
400 file_info->type = GNOME_VFS_FILE_TYPE_FIFO;
401 else if (S_ISSOCK (statptr->st_mode))
402 file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
403 else if (S_ISREG (statptr->st_mode))
404 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
405 else if (S_ISLNK (statptr->st_mode))
406 file_info->type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
407 else
408 file_info->type = GNOME_VFS_FILE_TYPE_UNKNOWN;
410 file_info->permissions
411 = statptr->st_mode & (GNOME_VFS_PERM_USER_ALL
412 | GNOME_VFS_PERM_GROUP_ALL
413 | GNOME_VFS_PERM_OTHER_ALL
414 | GNOME_VFS_PERM_SUID
415 | GNOME_VFS_PERM_SGID
416 | GNOME_VFS_PERM_STICKY);
418 file_info->device = statptr->st_dev;
419 file_info->inode = statptr->st_ino;
421 file_info->link_count = statptr->st_nlink;
423 file_info->uid = statptr->st_uid;
424 file_info->gid = statptr->st_gid;
426 file_info->size = statptr->st_size;
427 file_info->block_count = statptr->st_blocks;
428 file_info->io_block_size = statptr->st_blksize;
429 if (file_info->io_block_size > 0 &&
430 file_info->io_block_size < 4096) {
431 /* Never use smaller block than 4k,
432 should probably be pagesize.. */
433 file_info->io_block_size = 4096;
436 file_info->atime = statptr->st_atime;
437 file_info->ctime = statptr->st_ctime;
438 file_info->mtime = statptr->st_mtime;
440 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE |
441 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS | GNOME_VFS_FILE_INFO_FIELDS_FLAGS |
442 GNOME_VFS_FILE_INFO_FIELDS_DEVICE | GNOME_VFS_FILE_INFO_FIELDS_INODE |
443 GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_SIZE |
444 GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE |
445 GNOME_VFS_FILE_INFO_FIELDS_ATIME | GNOME_VFS_FILE_INFO_FIELDS_MTIME |
446 GNOME_VFS_FILE_INFO_FIELDS_CTIME;
449 static void
450 load_completed_or_failed (AnjutaDocumentLoader *loader)
453 /* the object will be unrefed in the callback of the loading
454 * signal, so we need to prevent finalization.
456 g_object_ref (loader);
458 g_signal_emit (loader,
459 signals[LOADING],
461 TRUE, /* completed */
462 loader->priv->error);
464 g_object_unref (loader);
467 /* ----------- local files ----------- */
469 #define MAX_MIME_SNIFF_SIZE 4096
471 static gboolean
472 load_local_file_real (AnjutaDocumentLoader *loader)
474 struct stat statbuf;
475 GnomeVFSResult result;
476 gint ret;
478 g_return_val_if_fail (loader->priv->fd != -1, FALSE);
480 if (fstat (loader->priv->fd, &statbuf) != 0)
482 result = gnome_vfs_result_from_errno ();
484 g_set_error (&loader->priv->error,
485 ANJUTA_DOCUMENT_ERROR,
486 result,
487 gnome_vfs_result_to_string (result));
489 goto done;
492 loader->priv->info = gnome_vfs_file_info_new ();
493 stat_to_file_info (loader->priv->info, &statbuf);
494 GNOME_VFS_FILE_INFO_SET_LOCAL (loader->priv->info, TRUE);
495 get_access_info (loader->priv->info, loader->priv->local_file_name);
497 if (loader->priv->info->size == 0)
499 if (loader->priv->encoding == NULL)
500 loader->priv->auto_detected_encoding = anjuta_encoding_get_current ();
502 /* guessing the mime from the filename is up to the caller */
504 else
506 gchar *mapped_file;
507 const gchar *mime_type;
509 /* CHECK: should we lock the file */
510 mapped_file = mmap (0, /* start */
511 loader->priv->info->size,
512 PROT_READ,
513 MAP_PRIVATE, /* flags */
514 loader->priv->fd,
515 0 /* offset */);
517 if (mapped_file == MAP_FAILED)
519 result = gnome_vfs_result_from_errno ();
521 g_set_error (&loader->priv->error,
522 ANJUTA_DOCUMENT_ERROR,
523 result,
524 gnome_vfs_result_to_string (result));
526 goto done;
529 loader->priv->bytes_read = loader->priv->info->size;
531 if (!update_document_contents (loader,
532 mapped_file,
533 loader->priv->info->size,
534 &loader->priv->error))
536 ret = munmap (mapped_file, loader->priv->info->size);
537 if (ret != 0)
538 g_warning ("File '%s' has not been correctly unmapped: %s",
539 loader->priv->uri,
540 strerror (errno));
542 goto done;
545 mime_type = gnome_vfs_get_mime_type_for_name(loader->priv->local_file_name);
546 if (mime_type == NULL)
547 mime_type = gnome_vfs_get_mime_type_for_data(mapped_file,
548 MIN (loader->priv->bytes_read, MAX_MIME_SNIFF_SIZE));
550 if ((mime_type != NULL) &&
551 strcmp (mime_type, GNOME_VFS_MIME_TYPE_UNKNOWN) != 0)
553 loader->priv->info->mime_type = g_strdup (mime_type);
554 loader->priv->info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
557 ret = munmap (mapped_file, loader->priv->info->size);
559 if (ret != 0)
560 g_warning ("File '%s' has not been correctly unmapped: %s",
561 loader->priv->uri,
562 strerror (errno));
565 ret = close (loader->priv->fd);
567 if (ret != 0)
568 g_warning ("File '%s' has not been correctly closed: %s",
569 loader->priv->uri,
570 strerror (errno));
572 loader->priv->fd = -1;
574 done:
575 load_completed_or_failed (loader);
577 return FALSE;
580 static gboolean
581 open_local_failed (AnjutaDocumentLoader *loader)
583 load_completed_or_failed (loader);
585 /* stop the timeout */
586 return FALSE;
589 static void
590 load_local_file (AnjutaDocumentLoader *loader,
591 const gchar *fname)
593 g_signal_emit (loader,
594 signals[LOADING],
596 FALSE,
597 NULL);
599 loader->priv->fd = open (fname, O_RDONLY);
600 if (loader->priv->fd == -1)
602 GnomeVFSResult result = gnome_vfs_result_from_errno ();
604 g_set_error (&loader->priv->error,
605 ANJUTA_DOCUMENT_ERROR,
606 result,
607 gnome_vfs_result_to_string (result));
609 g_timeout_add_full (G_PRIORITY_HIGH,
611 (GSourceFunc) open_local_failed,
612 loader,
613 NULL);
615 return;
618 g_free (loader->priv->local_file_name);
619 loader->priv->local_file_name = g_strdup (fname);
621 g_timeout_add_full (G_PRIORITY_HIGH,
623 (GSourceFunc) load_local_file_real,
624 loader,
625 NULL);
628 /* ----------- remote files ----------- */
630 static void
631 async_close_cb (GnomeVFSAsyncHandle *handle,
632 GnomeVFSResult result,
633 gpointer data)
635 /* nothing to do... no point in reporting an error */
638 static void
639 remote_load_completed_or_failed (AnjutaDocumentLoader *loader)
642 /* free the buffer and close the handle */
643 gnome_vfs_async_close (loader->priv->handle,
644 async_close_cb,
645 NULL);
647 loader->priv->handle = NULL;
649 g_free (loader->priv->buffer);
650 loader->priv->buffer = NULL;
652 load_completed_or_failed (loader);
655 /* prototype, because they call each other... isn't C lovely */
656 static void read_file_chunk (AnjutaDocumentLoader *loader);
658 static void
659 async_read_cb (GnomeVFSAsyncHandle *handle,
660 GnomeVFSResult result,
661 gpointer buffer,
662 GnomeVFSFileSize bytes_requested,
663 GnomeVFSFileSize bytes_read,
664 gpointer data)
666 AnjutaDocumentLoader *loader = ANJUTA_DOCUMENT_LOADER (data);
668 /* reality checks. */
669 g_return_if_fail (bytes_requested == READ_CHUNK_SIZE);
670 g_return_if_fail (loader->priv->handle == handle);
671 g_return_if_fail (loader->priv->buffer + loader->priv->bytes_read == buffer);
672 g_return_if_fail (bytes_read <= bytes_requested);
674 /* error occurred */
675 if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF)
677 g_set_error (&loader->priv->error,
678 ANJUTA_DOCUMENT_ERROR,
679 result,
680 gnome_vfs_result_to_string (result));
682 remote_load_completed_or_failed (loader);
684 return;
687 /* Check for the extremely unlikely case where the file size overflows. */
688 if (loader->priv->bytes_read + bytes_read < loader->priv->bytes_read)
690 g_set_error (&loader->priv->error,
691 ANJUTA_DOCUMENT_ERROR,
692 GNOME_VFS_ERROR_TOO_BIG,
693 gnome_vfs_result_to_string (GNOME_VFS_ERROR_TOO_BIG));
695 remote_load_completed_or_failed (loader);
697 return;
700 /* Bump the size. */
701 loader->priv->bytes_read += bytes_read;
703 /* end of the file, we are done! */
704 if (bytes_read == 0 || result != GNOME_VFS_OK)
706 update_document_contents (loader,
707 loader->priv->buffer,
708 loader->priv->bytes_read,
709 &loader->priv->error);
711 remote_load_completed_or_failed (loader);
713 return;
716 /* otherwise emit progress and read some more */
718 /* note that this signal blocks the read... check if it isn't
719 * a performance problem
721 g_signal_emit (loader,
722 signals[LOADING],
724 FALSE,
725 NULL);
727 read_file_chunk (loader);
730 static void
731 read_file_chunk (AnjutaDocumentLoader *loader)
733 loader->priv->buffer = g_realloc (loader->priv->buffer,
734 loader->priv->bytes_read + READ_CHUNK_SIZE);
736 gnome_vfs_async_read (loader->priv->handle,
737 loader->priv->buffer + loader->priv->bytes_read,
738 READ_CHUNK_SIZE,
739 async_read_cb,
740 loader);
743 static void
744 remote_get_info_cb (GnomeVFSAsyncHandle *handle,
745 GList *results,
746 gpointer data)
748 AnjutaDocumentLoader *loader = ANJUTA_DOCUMENT_LOADER (data);
749 GnomeVFSGetFileInfoResult *info_result;
751 /* assert that the list has one and only one item */
752 g_return_if_fail (results != NULL && results->next == NULL);
754 loader->priv->info_handle = NULL;
756 info_result = (GnomeVFSGetFileInfoResult *) results->data;
757 g_return_if_fail (info_result != NULL);
759 if (info_result->result != GNOME_VFS_OK)
761 g_set_error (&loader->priv->error,
762 ANJUTA_DOCUMENT_ERROR,
763 info_result->result,
764 gnome_vfs_result_to_string (info_result->result));
766 remote_load_completed_or_failed (loader);
768 return;
771 /* CHECK: ref is necessary, right? or the info will go away... */
772 loader->priv->info = info_result->file_info;
773 gnome_vfs_file_info_ref (loader->priv->info);
775 /* if it's not a regular file, error out... */
776 if (info_result->file_info->type != GNOME_VFS_FILE_TYPE_REGULAR)
778 g_set_error (&loader->priv->error,
779 ANJUTA_DOCUMENT_ERROR,
780 GNOME_VFS_ERROR_GENERIC, // FIXME
781 gnome_vfs_result_to_string (GNOME_VFS_ERROR_GENERIC));
783 remote_load_completed_or_failed (loader);
785 return;
788 /* start reading */
789 read_file_chunk (loader);
792 static void
793 async_open_callback (GnomeVFSAsyncHandle *handle,
794 GnomeVFSResult result,
795 AnjutaDocumentLoader *loader)
797 GList *uri_list = NULL;
799 g_return_if_fail (loader->priv->handle == handle);
801 if (result != GNOME_VFS_OK)
803 g_set_error (&loader->priv->error,
804 ANJUTA_DOCUMENT_ERROR,
805 result,
806 gnome_vfs_result_to_string (result));
808 /* in this case we don't need to close the handle */
809 load_completed_or_failed (loader);
811 return;
814 /* get the file info after open to avoid races... this really
815 * should be async_get_file_info_from_handle (fstat equivalent)
816 * but gnome-vfs lacks that.
819 uri_list = g_list_prepend (uri_list, loader->priv->vfs_uri);
821 gnome_vfs_async_get_file_info (&loader->priv->info_handle,
822 uri_list,
823 GNOME_VFS_FILE_INFO_DEFAULT |
824 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
825 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
826 GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
827 GNOME_VFS_PRIORITY_MAX,
828 remote_get_info_cb,
829 loader);
831 g_list_free (uri_list);
834 static void
835 load_remote_file (AnjutaDocumentLoader *loader)
837 g_return_if_fail (loader->priv->handle == NULL);
839 /* loading start */
840 g_signal_emit (loader,
841 signals[LOADING],
843 FALSE,
844 NULL);
846 gnome_vfs_async_open_uri (&loader->priv->handle,
847 loader->priv->vfs_uri,
848 GNOME_VFS_OPEN_READ,
849 GNOME_VFS_PRIORITY_MAX,
850 (GnomeVFSAsyncOpenCallback) async_open_callback,
851 loader);
854 /* ---------- public api ---------- */
856 static gboolean
857 vfs_uri_new_failed (AnjutaDocumentLoader *loader)
859 load_completed_or_failed (loader);
861 /* stop the timeout */
862 return FALSE;
865 /* If enconding == NULL, the encoding will be autodetected */
866 void
867 anjuta_document_loader_load (AnjutaDocumentLoader *loader,
868 const gchar *uri,
869 const AnjutaEncoding *encoding)
871 gchar *local_path;
873 g_return_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader));
874 g_return_if_fail (uri != NULL);
876 /* the loader can be used just once, then it must be thrown away */
877 g_return_if_fail (loader->priv->used == FALSE);
878 loader->priv->used = TRUE;
880 /* vfs_uri may be NULL for some valid but unsupported uris */
881 loader->priv->vfs_uri = gnome_vfs_uri_new (uri);
882 if (loader->priv->vfs_uri == NULL)
884 g_set_error (&loader->priv->error,
885 ANJUTA_DOCUMENT_ERROR,
886 GNOME_VFS_ERROR_NOT_SUPPORTED,
887 gnome_vfs_result_to_string (GNOME_VFS_ERROR_NOT_SUPPORTED));
889 g_timeout_add_full (G_PRIORITY_HIGH,
891 (GSourceFunc) vfs_uri_new_failed,
892 loader,
893 NULL);
895 return;
898 loader->priv->encoding = encoding;
900 loader->priv->uri = g_strdup (uri);
902 local_path = gnome_vfs_get_local_path_from_uri (uri);
903 if (local_path != NULL)
905 load_local_file (loader, local_path);
906 g_free (local_path);
908 else
910 load_remote_file (loader);
914 /* Returns STDIN_URI if loading from stdin */
915 const gchar *
916 anjuta_document_loader_get_uri (AnjutaDocumentLoader *loader)
918 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
920 return loader->priv->uri;
923 /* it may return NULL, it's up to anjuta-document handle it */
924 const gchar *
925 anjuta_document_loader_get_mime_type (AnjutaDocumentLoader *loader)
927 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
929 if (loader->priv->info &&
930 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE))
931 return loader->priv->info->mime_type;
932 else
933 return NULL;
936 time_t
937 anjuta_document_loader_get_mtime (AnjutaDocumentLoader *loader)
939 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
941 if (loader->priv->info &&
942 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME))
943 return loader->priv->info->mtime;
944 else
945 return 0;
948 /* Returns 0 if file size is unknown */
949 GnomeVFSFileSize
950 anjuta_document_loader_get_file_size (AnjutaDocumentLoader *loader)
952 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
954 if (loader->priv->info == NULL)
955 return 0;
957 return loader->priv->info->size;
960 GnomeVFSFileSize
961 anjuta_document_loader_get_bytes_read (AnjutaDocumentLoader *loader)
963 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
965 return loader->priv->bytes_read;
968 gboolean
969 anjuta_document_loader_cancel (AnjutaDocumentLoader *loader)
972 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), FALSE);
974 if (loader->priv->handle == NULL)
975 return FALSE;
977 if (loader->priv->info_handle != NULL)
979 gnome_vfs_async_cancel (loader->priv->info_handle);
980 gnome_vfs_async_close (loader->priv->info_handle,
981 async_close_cb,
982 NULL);
985 gnome_vfs_async_cancel (loader->priv->handle);
987 g_set_error (&loader->priv->error,
988 ANJUTA_DOCUMENT_ERROR,
989 GNOME_VFS_ERROR_CANCELLED,
990 gnome_vfs_result_to_string (GNOME_VFS_ERROR_CANCELLED));
992 remote_load_completed_or_failed (loader);
994 return TRUE;
997 /* In the case the loader does not know if the file is readonly, for example
998 for most remote files, the function returns FALSE, so that we can try writing
999 and if needed handle the error. */
1000 gboolean
1001 anjuta_document_loader_get_readonly (AnjutaDocumentLoader *loader)
1003 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), FALSE);
1005 if (loader->priv->info &&
1006 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS))
1007 return (loader->priv->info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) ? FALSE : TRUE;
1008 else
1009 return FALSE;
1012 const AnjutaEncoding *
1013 anjuta_document_loader_get_encoding (AnjutaDocumentLoader *loader)
1015 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
1017 if (loader->priv->encoding != NULL)
1018 return loader->priv->encoding;
1020 if (loader->priv->auto_detected_encoding == NULL)
1022 return anjuta_encoding_get_current ();
1025 return loader->priv->auto_detected_encoding;