* scripts/anjuta_import.sh.in,
[anjuta-git-plugin.git] / plugins / sourceview / anjuta-document-loader.c
blob39eba07587e718af151fb907ab6c6c0ec1d54da0
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/types.h>
36 #include <sys/mman.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 <libanjuta/anjuta-encodings.h>
47 #include <libanjuta/anjuta-convert.h>
49 #include "anjuta-document-loader.h"
50 #include "anjuta-marshal.h"
53 #define READ_CHUNK_SIZE 8192
55 #define ANJUTA_DOCUMENT_LOADER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
56 ANJUTA_TYPE_DOCUMENT_LOADER, \
57 AnjutaDocumentLoaderPrivate))
59 static void async_close_cb (GnomeVFSAsyncHandle *handle,
60 GnomeVFSResult result,
61 gpointer data);
64 struct _AnjutaDocumentLoaderPrivate
66 AnjutaDocument *document;
68 gboolean used;
70 /* Info on the current file */
71 gchar *uri;
72 const AnjutaEncoding *encoding;
74 GnomeVFSURI *vfs_uri;
76 GnomeVFSFileInfo *info;
77 GnomeVFSFileSize bytes_read;
79 /* Handle for local files */
80 gint fd;
81 gchar *local_file_name;
83 /* Handle for remote files */
84 GnomeVFSAsyncHandle *handle;
85 GnomeVFSAsyncHandle *info_handle;
87 gchar *buffer;
89 const AnjutaEncoding *auto_detected_encoding;
91 GError *error;
94 G_DEFINE_TYPE(AnjutaDocumentLoader, anjuta_document_loader, G_TYPE_OBJECT)
96 /* Signals */
98 enum {
99 LOADING,
100 LAST_SIGNAL
103 static guint signals[LAST_SIGNAL] = { 0 };
105 /* Properties */
107 enum
109 PROP_0,
110 PROP_DOCUMENT,
113 static void
114 anjuta_document_loader_set_property (GObject *object,
115 guint prop_id,
116 const GValue *value,
117 GParamSpec *pspec)
119 AnjutaDocumentLoader *dl = ANJUTA_DOCUMENT_LOADER (object);
121 switch (prop_id)
123 case PROP_DOCUMENT:
124 g_return_if_fail (dl->priv->document == NULL);
125 dl->priv->document = g_value_get_object (value);
126 break;
127 default:
128 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129 break;
133 static void
134 anjuta_document_loader_get_property (GObject *object,
135 guint prop_id,
136 GValue *value,
137 GParamSpec *pspec)
139 AnjutaDocumentLoader *dl = ANJUTA_DOCUMENT_LOADER (object);
141 switch (prop_id)
143 case PROP_DOCUMENT:
144 g_value_set_object (value,
145 dl->priv->document);
146 break;
147 default:
148 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
149 break;
153 static void
154 anjuta_document_loader_finalize (GObject *object)
156 AnjutaDocumentLoaderPrivate *priv = ANJUTA_DOCUMENT_LOADER (object)->priv;
158 if (priv->handle != NULL)
160 if (priv->info_handle != NULL)
162 gnome_vfs_async_cancel (priv->info_handle);
163 gnome_vfs_async_close (priv->info_handle,
164 async_close_cb,
165 NULL);
168 gnome_vfs_async_cancel (priv->handle);
169 gnome_vfs_async_close (priv->handle,
170 async_close_cb,
171 NULL);
174 g_free (priv->uri);
176 if (priv->info)
177 gnome_vfs_file_info_unref (priv->info);
180 g_free (priv->local_file_name);
181 g_free (priv->buffer);
183 if (priv->vfs_uri)
184 gnome_vfs_uri_unref (priv->vfs_uri);
186 if (priv->error)
187 g_error_free (priv->error);
189 G_OBJECT_CLASS (anjuta_document_loader_parent_class)->finalize (object);
192 static void
193 anjuta_document_loader_class_init (AnjutaDocumentLoaderClass *klass)
195 GObjectClass *object_class = G_OBJECT_CLASS (klass);
197 object_class->finalize = anjuta_document_loader_finalize;
198 object_class->get_property = anjuta_document_loader_get_property;
199 object_class->set_property = anjuta_document_loader_set_property;
201 g_object_class_install_property (object_class,
202 PROP_DOCUMENT,
203 g_param_spec_object ("document",
204 "Document",
205 "The AnjutaDocument this AnjutaDocumentLoader is associated with",
206 ANJUTA_TYPE_DOCUMENT,
207 G_PARAM_READWRITE |
208 G_PARAM_CONSTRUCT_ONLY));
210 signals[LOADING] =
211 g_signal_new ("loading",
212 G_OBJECT_CLASS_TYPE (object_class),
213 G_SIGNAL_RUN_LAST,
214 G_STRUCT_OFFSET (AnjutaDocumentLoaderClass, loading),
215 NULL, NULL,
216 anjuta_marshal_VOID__BOOLEAN_POINTER,
217 G_TYPE_NONE,
219 G_TYPE_BOOLEAN,
220 G_TYPE_POINTER);
222 g_type_class_add_private (object_class, sizeof(AnjutaDocumentLoaderPrivate));
225 static void
226 anjuta_document_loader_init (AnjutaDocumentLoader *loader)
228 loader->priv = ANJUTA_DOCUMENT_LOADER_GET_PRIVATE (loader);
230 loader->priv->used = FALSE;
232 loader->priv->fd = -1;
234 loader->priv->error = NULL;
237 AnjutaDocumentLoader *
238 anjuta_document_loader_new (AnjutaDocument *doc)
240 AnjutaDocumentLoader *dl;
242 g_return_val_if_fail (ANJUTA_IS_DOCUMENT (doc), NULL);
244 dl = ANJUTA_DOCUMENT_LOADER (g_object_new (ANJUTA_TYPE_DOCUMENT_LOADER,
245 "document", doc,
246 NULL));
248 return dl;
251 static void
252 insert_text_in_document (AnjutaDocumentLoader *loader,
253 const gchar *text,
254 gint len)
256 gtk_source_buffer_begin_not_undoable_action (
257 GTK_SOURCE_BUFFER (loader->priv->document));
259 /* Insert text in the buffer */
260 gtk_text_buffer_set_text (GTK_TEXT_BUFFER (loader->priv->document),
261 text,
262 len);
264 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (loader->priv->document),
265 FALSE);
267 gtk_source_buffer_end_not_undoable_action (
268 GTK_SOURCE_BUFFER (loader->priv->document));
271 static gboolean
272 update_document_contents (AnjutaDocumentLoader *loader,
273 const gchar *file_contents,
274 gint file_size,
275 GError **error)
277 g_return_val_if_fail (file_size > 0, FALSE);
278 g_return_val_if_fail (file_contents != NULL, FALSE);
280 if (loader->priv->encoding == anjuta_encoding_get_utf8 ())
282 if (g_utf8_validate (file_contents, file_size, NULL))
284 insert_text_in_document (loader,
285 file_contents,
286 file_size);
288 return TRUE;
290 else
292 g_set_error (error,
293 G_CONVERT_ERROR,
294 G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
295 "The file you are trying to open contains an invalid byte sequence.");
297 return FALSE;
300 else
302 GError *conv_error = NULL;
303 gchar *converted_text = NULL;
304 gsize new_len = file_size;
306 if (converted_text == NULL)
308 loader->priv->auto_detected_encoding = loader->priv->encoding;
310 converted_text = anjuta_convert_to_utf8 (
311 file_contents,
312 file_size,
313 &loader->priv->auto_detected_encoding,
314 &new_len,
315 &conv_error);
317 if (converted_text == NULL)
319 /* Last change, let's try 8859-15 */
320 loader->priv->auto_detected_encoding =
321 anjuta_encoding_get_from_charset( "ISO-8859-15");
323 converted_text = anjuta_convert_to_utf8 (
324 file_contents,
325 file_size,
326 &loader->priv->auto_detected_encoding,
327 &new_len,
328 &conv_error);
331 if (converted_text == NULL)
333 g_return_val_if_fail (conv_error != NULL, FALSE);
335 g_propagate_error (error, conv_error);
337 return FALSE;
339 else
341 insert_text_in_document (loader,
342 converted_text,
343 new_len);
345 g_free (converted_text);
347 return TRUE;
351 g_return_val_if_reached (FALSE);
354 /* The following function has been copied from gnome-vfs
355 (modules/file-method.c) file */
356 static void
357 get_access_info (GnomeVFSFileInfo *file_info,
358 const gchar *full_name)
360 /* FIXME: should check errno after calling access because we don't
361 * want to set valid_fields if something bad happened during one
362 * of the access calls
364 if (g_access (full_name, W_OK) == 0)
365 file_info->permissions |= GNOME_VFS_PERM_ACCESS_WRITABLE;
368 * We don't need to know if a local file is readable or
369 * executable so I have commented the followig code to avoid
370 * multiple g_access calls - Paolo (Oct. 18, 2005)
374 * if (g_access (full_name, R_OK) == 0)
375 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_READABLE;
377 * #ifdef G_OS_WIN32
378 * if (g_file_test (full_name, G_FILE_TEST_IS_EXECUTABLE))
379 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
380 * #else
381 * if (g_access (full_name, X_OK) == 0)
382 * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
383 * #endif
386 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACCESS;
389 /* The following function has been copied from gnome-vfs
390 (gnome-vfs-module-shared.c) file */
391 static void
392 stat_to_file_info (GnomeVFSFileInfo *file_info,
393 const struct stat *statptr)
395 if (S_ISDIR (statptr->st_mode))
396 file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
397 else if (S_ISCHR (statptr->st_mode))
398 file_info->type = GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE;
399 else if (S_ISBLK (statptr->st_mode))
400 file_info->type = GNOME_VFS_FILE_TYPE_BLOCK_DEVICE;
401 else if (S_ISFIFO (statptr->st_mode))
402 file_info->type = GNOME_VFS_FILE_TYPE_FIFO;
403 else if (S_ISSOCK (statptr->st_mode))
404 file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
405 else if (S_ISREG (statptr->st_mode))
406 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
407 else if (S_ISLNK (statptr->st_mode))
408 file_info->type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
409 else
410 file_info->type = GNOME_VFS_FILE_TYPE_UNKNOWN;
412 file_info->permissions
413 = statptr->st_mode & (GNOME_VFS_PERM_USER_ALL
414 | GNOME_VFS_PERM_GROUP_ALL
415 | GNOME_VFS_PERM_OTHER_ALL
416 | GNOME_VFS_PERM_SUID
417 | GNOME_VFS_PERM_SGID
418 | GNOME_VFS_PERM_STICKY);
420 file_info->device = statptr->st_dev;
421 file_info->inode = statptr->st_ino;
423 file_info->link_count = statptr->st_nlink;
425 file_info->uid = statptr->st_uid;
426 file_info->gid = statptr->st_gid;
428 file_info->size = statptr->st_size;
429 file_info->block_count = statptr->st_blocks;
430 file_info->io_block_size = statptr->st_blksize;
431 if (file_info->io_block_size > 0 &&
432 file_info->io_block_size < 4096) {
433 /* Never use smaller block than 4k,
434 should probably be pagesize.. */
435 file_info->io_block_size = 4096;
438 file_info->atime = statptr->st_atime;
439 file_info->ctime = statptr->st_ctime;
440 file_info->mtime = statptr->st_mtime;
442 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE |
443 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS | GNOME_VFS_FILE_INFO_FIELDS_FLAGS |
444 GNOME_VFS_FILE_INFO_FIELDS_DEVICE | GNOME_VFS_FILE_INFO_FIELDS_INODE |
445 GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_SIZE |
446 GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE |
447 GNOME_VFS_FILE_INFO_FIELDS_ATIME | GNOME_VFS_FILE_INFO_FIELDS_MTIME |
448 GNOME_VFS_FILE_INFO_FIELDS_CTIME;
451 static void
452 load_completed_or_failed (AnjutaDocumentLoader *loader)
455 /* the object will be unrefed in the callback of the loading
456 * signal, so we need to prevent finalization.
458 g_object_ref (loader);
460 g_signal_emit (loader,
461 signals[LOADING],
463 TRUE, /* completed */
464 loader->priv->error);
466 g_object_unref (loader);
469 /* ----------- local files ----------- */
471 #define MAX_MIME_SNIFF_SIZE 4096
473 static gboolean
474 load_local_file_real (AnjutaDocumentLoader *loader)
476 struct stat statbuf;
477 GnomeVFSResult result;
478 gint ret;
480 g_return_val_if_fail (loader->priv->fd != -1, FALSE);
482 if (fstat (loader->priv->fd, &statbuf) != 0)
484 result = gnome_vfs_result_from_errno ();
486 g_set_error (&loader->priv->error,
487 ANJUTA_DOCUMENT_ERROR,
488 result,
489 gnome_vfs_result_to_string (result));
491 goto done;
494 loader->priv->info = gnome_vfs_file_info_new ();
495 stat_to_file_info (loader->priv->info, &statbuf);
496 GNOME_VFS_FILE_INFO_SET_LOCAL (loader->priv->info, TRUE);
497 get_access_info (loader->priv->info, loader->priv->local_file_name);
499 if (loader->priv->info->size == 0)
501 if (loader->priv->encoding == NULL)
502 loader->priv->auto_detected_encoding = anjuta_encoding_get_current ();
504 /* guessing the mime from the filename is up to the caller */
506 else
508 gchar *mapped_file;
509 const gchar *mime_type;
511 /* CHECK: should we lock the file */
512 mapped_file = mmap (0, /* start */
513 loader->priv->info->size,
514 PROT_READ,
515 MAP_PRIVATE, /* flags */
516 loader->priv->fd,
517 0 /* offset */);
519 if (mapped_file == MAP_FAILED)
521 result = gnome_vfs_result_from_errno ();
523 g_set_error (&loader->priv->error,
524 ANJUTA_DOCUMENT_ERROR,
525 result,
526 gnome_vfs_result_to_string (result));
528 goto done;
531 loader->priv->bytes_read = loader->priv->info->size;
533 if (!update_document_contents (loader,
534 mapped_file,
535 loader->priv->info->size,
536 &loader->priv->error))
538 ret = munmap (mapped_file, loader->priv->info->size);
539 if (ret != 0)
540 g_warning ("File '%s' has not been correctly unmapped: %s",
541 loader->priv->uri,
542 strerror (errno));
544 goto done;
547 mime_type = gnome_vfs_get_mime_type_for_name(loader->priv->local_file_name);
548 if (mime_type == NULL)
549 mime_type = gnome_vfs_get_mime_type_for_data(mapped_file,
550 MIN (loader->priv->bytes_read, MAX_MIME_SNIFF_SIZE));
552 if ((mime_type != NULL) &&
553 strcmp (mime_type, GNOME_VFS_MIME_TYPE_UNKNOWN) != 0)
555 loader->priv->info->mime_type = g_strdup (mime_type);
556 loader->priv->info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
559 ret = munmap (mapped_file, loader->priv->info->size);
561 if (ret != 0)
562 g_warning ("File '%s' has not been correctly unmapped: %s",
563 loader->priv->uri,
564 strerror (errno));
567 ret = close (loader->priv->fd);
569 if (ret != 0)
570 g_warning ("File '%s' has not been correctly closed: %s",
571 loader->priv->uri,
572 strerror (errno));
574 loader->priv->fd = -1;
576 done:
577 load_completed_or_failed (loader);
579 return FALSE;
582 static gboolean
583 open_local_failed (AnjutaDocumentLoader *loader)
585 load_completed_or_failed (loader);
587 /* stop the timeout */
588 return FALSE;
591 static void
592 load_local_file (AnjutaDocumentLoader *loader,
593 const gchar *fname)
595 g_signal_emit (loader,
596 signals[LOADING],
598 FALSE,
599 NULL);
601 loader->priv->fd = open (fname, O_RDONLY);
602 if (loader->priv->fd == -1)
604 GnomeVFSResult result = gnome_vfs_result_from_errno ();
606 g_set_error (&loader->priv->error,
607 ANJUTA_DOCUMENT_ERROR,
608 result,
609 gnome_vfs_result_to_string (result));
611 g_timeout_add_full (G_PRIORITY_HIGH,
613 (GSourceFunc) open_local_failed,
614 loader,
615 NULL);
617 return;
620 g_free (loader->priv->local_file_name);
621 loader->priv->local_file_name = g_strdup (fname);
623 g_timeout_add_full (G_PRIORITY_HIGH,
625 (GSourceFunc) load_local_file_real,
626 loader,
627 NULL);
630 /* ----------- remote files ----------- */
632 static void
633 async_close_cb (GnomeVFSAsyncHandle *handle,
634 GnomeVFSResult result,
635 gpointer data)
637 /* nothing to do... no point in reporting an error */
640 static void
641 remote_load_completed_or_failed (AnjutaDocumentLoader *loader)
644 /* free the buffer and close the handle */
645 gnome_vfs_async_close (loader->priv->handle,
646 async_close_cb,
647 NULL);
649 loader->priv->handle = NULL;
651 g_free (loader->priv->buffer);
652 loader->priv->buffer = NULL;
654 load_completed_or_failed (loader);
657 /* prototype, because they call each other... isn't C lovely */
658 static void read_file_chunk (AnjutaDocumentLoader *loader);
660 static void
661 async_read_cb (GnomeVFSAsyncHandle *handle,
662 GnomeVFSResult result,
663 gpointer buffer,
664 GnomeVFSFileSize bytes_requested,
665 GnomeVFSFileSize bytes_read,
666 gpointer data)
668 AnjutaDocumentLoader *loader = ANJUTA_DOCUMENT_LOADER (data);
670 /* reality checks. */
671 g_return_if_fail (bytes_requested == READ_CHUNK_SIZE);
672 g_return_if_fail (loader->priv->handle == handle);
673 g_return_if_fail (loader->priv->buffer + loader->priv->bytes_read == buffer);
674 g_return_if_fail (bytes_read <= bytes_requested);
676 /* error occurred */
677 if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF)
679 g_set_error (&loader->priv->error,
680 ANJUTA_DOCUMENT_ERROR,
681 result,
682 gnome_vfs_result_to_string (result));
684 remote_load_completed_or_failed (loader);
686 return;
689 /* Check for the extremely unlikely case where the file size overflows. */
690 if (loader->priv->bytes_read + bytes_read < loader->priv->bytes_read)
692 g_set_error (&loader->priv->error,
693 ANJUTA_DOCUMENT_ERROR,
694 GNOME_VFS_ERROR_TOO_BIG,
695 gnome_vfs_result_to_string (GNOME_VFS_ERROR_TOO_BIG));
697 remote_load_completed_or_failed (loader);
699 return;
702 /* Bump the size. */
703 loader->priv->bytes_read += bytes_read;
705 /* end of the file, we are done! */
706 if (bytes_read == 0 || result != GNOME_VFS_OK)
708 update_document_contents (loader,
709 loader->priv->buffer,
710 loader->priv->bytes_read,
711 &loader->priv->error);
713 remote_load_completed_or_failed (loader);
715 return;
718 /* otherwise emit progress and read some more */
720 /* note that this signal blocks the read... check if it isn't
721 * a performance problem
723 g_signal_emit (loader,
724 signals[LOADING],
726 FALSE,
727 NULL);
729 read_file_chunk (loader);
732 static void
733 read_file_chunk (AnjutaDocumentLoader *loader)
735 loader->priv->buffer = g_realloc (loader->priv->buffer,
736 loader->priv->bytes_read + READ_CHUNK_SIZE);
738 gnome_vfs_async_read (loader->priv->handle,
739 loader->priv->buffer + loader->priv->bytes_read,
740 READ_CHUNK_SIZE,
741 async_read_cb,
742 loader);
745 static void
746 remote_get_info_cb (GnomeVFSAsyncHandle *handle,
747 GList *results,
748 gpointer data)
750 AnjutaDocumentLoader *loader = ANJUTA_DOCUMENT_LOADER (data);
751 GnomeVFSGetFileInfoResult *info_result;
753 /* assert that the list has one and only one item */
754 g_return_if_fail (results != NULL && results->next == NULL);
756 loader->priv->info_handle = NULL;
758 info_result = (GnomeVFSGetFileInfoResult *) results->data;
759 g_return_if_fail (info_result != NULL);
761 if (info_result->result != GNOME_VFS_OK)
763 g_set_error (&loader->priv->error,
764 ANJUTA_DOCUMENT_ERROR,
765 info_result->result,
766 gnome_vfs_result_to_string (info_result->result));
768 remote_load_completed_or_failed (loader);
770 return;
773 /* CHECK: ref is necessary, right? or the info will go away... */
774 loader->priv->info = info_result->file_info;
775 gnome_vfs_file_info_ref (loader->priv->info);
777 /* if it's not a regular file, error out... */
778 if (info_result->file_info->type != GNOME_VFS_FILE_TYPE_REGULAR)
780 g_set_error (&loader->priv->error,
781 ANJUTA_DOCUMENT_ERROR,
782 GNOME_VFS_ERROR_GENERIC, // FIXME
783 gnome_vfs_result_to_string (GNOME_VFS_ERROR_GENERIC));
785 remote_load_completed_or_failed (loader);
787 return;
790 /* start reading */
791 read_file_chunk (loader);
794 static void
795 async_open_callback (GnomeVFSAsyncHandle *handle,
796 GnomeVFSResult result,
797 AnjutaDocumentLoader *loader)
799 GList *uri_list = NULL;
801 g_return_if_fail (loader->priv->handle == handle);
803 if (result != GNOME_VFS_OK)
805 g_set_error (&loader->priv->error,
806 ANJUTA_DOCUMENT_ERROR,
807 result,
808 gnome_vfs_result_to_string (result));
810 /* in this case we don't need to close the handle */
811 load_completed_or_failed (loader);
813 return;
816 /* get the file info after open to avoid races... this really
817 * should be async_get_file_info_from_handle (fstat equivalent)
818 * but gnome-vfs lacks that.
821 uri_list = g_list_prepend (uri_list, loader->priv->vfs_uri);
823 gnome_vfs_async_get_file_info (&loader->priv->info_handle,
824 uri_list,
825 GNOME_VFS_FILE_INFO_DEFAULT |
826 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
827 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
828 GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
829 GNOME_VFS_PRIORITY_MAX,
830 remote_get_info_cb,
831 loader);
833 g_list_free (uri_list);
836 static void
837 load_remote_file (AnjutaDocumentLoader *loader)
839 g_return_if_fail (loader->priv->handle == NULL);
841 /* loading start */
842 g_signal_emit (loader,
843 signals[LOADING],
845 FALSE,
846 NULL);
848 gnome_vfs_async_open_uri (&loader->priv->handle,
849 loader->priv->vfs_uri,
850 GNOME_VFS_OPEN_READ,
851 GNOME_VFS_PRIORITY_MAX,
852 (GnomeVFSAsyncOpenCallback) async_open_callback,
853 loader);
856 /* ---------- public api ---------- */
858 static gboolean
859 vfs_uri_new_failed (AnjutaDocumentLoader *loader)
861 load_completed_or_failed (loader);
863 /* stop the timeout */
864 return FALSE;
867 /* If enconding == NULL, the encoding will be autodetected */
868 void
869 anjuta_document_loader_load (AnjutaDocumentLoader *loader,
870 const gchar *uri,
871 const AnjutaEncoding *encoding)
873 gchar *local_path;
875 g_return_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader));
876 g_return_if_fail (uri != NULL);
878 /* the loader can be used just once, then it must be thrown away */
879 g_return_if_fail (loader->priv->used == FALSE);
880 loader->priv->used = TRUE;
882 /* vfs_uri may be NULL for some valid but unsupported uris */
883 loader->priv->vfs_uri = gnome_vfs_uri_new (uri);
884 if (loader->priv->vfs_uri == NULL)
886 g_set_error (&loader->priv->error,
887 ANJUTA_DOCUMENT_ERROR,
888 GNOME_VFS_ERROR_NOT_SUPPORTED,
889 gnome_vfs_result_to_string (GNOME_VFS_ERROR_NOT_SUPPORTED));
891 g_timeout_add_full (G_PRIORITY_HIGH,
893 (GSourceFunc) vfs_uri_new_failed,
894 loader,
895 NULL);
897 return;
900 loader->priv->encoding = encoding;
902 loader->priv->uri = g_strdup (uri);
904 local_path = gnome_vfs_get_local_path_from_uri (uri);
905 if (local_path != NULL)
907 load_local_file (loader, local_path);
908 g_free (local_path);
910 else
912 load_remote_file (loader);
916 /* Returns STDIN_URI if loading from stdin */
917 const gchar *
918 anjuta_document_loader_get_uri (AnjutaDocumentLoader *loader)
920 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
922 return loader->priv->uri;
925 /* it may return NULL, it's up to anjuta-document handle it */
926 const gchar *
927 anjuta_document_loader_get_mime_type (AnjutaDocumentLoader *loader)
929 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
931 if (loader->priv->info &&
932 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE))
933 return loader->priv->info->mime_type;
934 else
935 return NULL;
938 time_t
939 anjuta_document_loader_get_mtime (AnjutaDocumentLoader *loader)
941 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
943 if (loader->priv->info &&
944 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME))
945 return loader->priv->info->mtime;
946 else
947 return 0;
950 /* Returns 0 if file size is unknown */
951 GnomeVFSFileSize
952 anjuta_document_loader_get_file_size (AnjutaDocumentLoader *loader)
954 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
956 if (loader->priv->info == NULL)
957 return 0;
959 return loader->priv->info->size;
962 GnomeVFSFileSize
963 anjuta_document_loader_get_bytes_read (AnjutaDocumentLoader *loader)
965 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), 0);
967 return loader->priv->bytes_read;
970 gboolean
971 anjuta_document_loader_cancel (AnjutaDocumentLoader *loader)
974 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), FALSE);
976 if (loader->priv->handle == NULL)
977 return FALSE;
979 if (loader->priv->info_handle != NULL)
981 gnome_vfs_async_cancel (loader->priv->info_handle);
982 gnome_vfs_async_close (loader->priv->info_handle,
983 async_close_cb,
984 NULL);
987 gnome_vfs_async_cancel (loader->priv->handle);
989 g_set_error (&loader->priv->error,
990 ANJUTA_DOCUMENT_ERROR,
991 GNOME_VFS_ERROR_CANCELLED,
992 gnome_vfs_result_to_string (GNOME_VFS_ERROR_CANCELLED));
994 remote_load_completed_or_failed (loader);
996 return TRUE;
999 /* In the case the loader does not know if the file is readonly, for example
1000 for most remote files, the function returns FALSE, so that we can try writing
1001 and if needed handle the error. */
1002 gboolean
1003 anjuta_document_loader_get_readonly (AnjutaDocumentLoader *loader)
1005 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), FALSE);
1007 if (loader->priv->info &&
1008 (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS))
1009 return (loader->priv->info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) ? FALSE : TRUE;
1010 else
1011 return FALSE;
1014 const AnjutaEncoding *
1015 anjuta_document_loader_get_encoding (AnjutaDocumentLoader *loader)
1017 g_return_val_if_fail (ANJUTA_IS_DOCUMENT_LOADER (loader), NULL);
1019 if (loader->priv->encoding != NULL)
1020 return loader->priv->encoding;
1022 if (loader->priv->auto_detected_encoding == NULL)
1024 return anjuta_encoding_get_current ();
1027 return loader->priv->auto_detected_encoding;