1 /*
2 * xed-document.c
3 * This file is part of xed
4 *
5 * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
6 * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
7 * Copyright (C) 2002-2005 Paolo Maggi
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25 /*
26 * Modified by the xed Team, 1998-2005. See the AUTHORS file for a
27 * list of people on the xed Team.
28 * See the ChangeLog files for a list of changes.
29 *
30 * $Id$
31 */
32
33 #include <config.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <glib/gi18n.h>
37 #include <gtk/gtk.h>
38
39 #include "xed-document.h"
40 #include "xed-document-private.h"
41 #include "xed-settings.h"
42 #include "xed-debug.h"
43 #include "xed-utils.h"
44 #include "xed-metadata-manager.h"
45
46 #define METADATA_QUERY "metadata::*"
47
48 #define NO_LANGUAGE_NAME "_NORMAL_"
49
50 static void xed_document_loaded_real (XedDocument *doc);
51 static void xed_document_saved_real (XedDocument *doc);
52
53 typedef struct
54 {
55 GtkSourceFile *file;
56
57 GSettings *editor_settings;
58
59 gint untitled_number;
60 gchar *short_name;
61
62 GFileInfo *metadata_info;
63
64 gchar *content_type;
65
66 GTimeVal time_of_last_save_or_load;
67
68 GtkSourceSearchContext *search_context;
69
70 guint user_action;
71
72 guint last_save_was_manually : 1;
73 guint language_set_by_user : 1;
74 guint stop_cursor_moved_emission : 1;
75 guint use_gvfs_metadata : 1;
76
77 /* Create file if location points to a non existing file (for example
78 * when opened from the command line).
79 */
80 guint create : 1;
81 } XedDocumentPrivate;
82
83 enum
84 {
85 PROP_0,
86 PROP_SHORTNAME,
87 PROP_CONTENT_TYPE,
88 PROP_MIME_TYPE,
89 PROP_READ_ONLY,
90 PROP_USE_GVFS_METADATA,
91 LAST_PROP
92 };
93
94 static GParamSpec *properties[LAST_PROP];
95
96 enum
97 {
98 CURSOR_MOVED,
99 LOAD,
100 LOADED,
101 SAVE,
102 SAVED,
103 LAST_SIGNAL
104 };
105
106 static guint document_signals[LAST_SIGNAL];
107
108 static GHashTable *allocated_untitled_numbers = NULL;
109
G_DEFINE_TYPE_WITH_PRIVATE(XedDocument,xed_document,GTK_SOURCE_TYPE_BUFFER)110 G_DEFINE_TYPE_WITH_PRIVATE (XedDocument, xed_document, GTK_SOURCE_TYPE_BUFFER)
111
112 static gint
113 get_untitled_number (void)
114 {
115 gint i = 1;
116
117 if (allocated_untitled_numbers == NULL)
118 {
119 allocated_untitled_numbers = g_hash_table_new (NULL, NULL);
120 }
121
122 g_return_val_if_fail (allocated_untitled_numbers != NULL, -1);
123
124 while (TRUE)
125 {
126 if (g_hash_table_lookup (allocated_untitled_numbers, GINT_TO_POINTER (i)) == NULL)
127 {
128 g_hash_table_insert (allocated_untitled_numbers, GINT_TO_POINTER (i), GINT_TO_POINTER (i));
129
130 return i;
131 }
132
133 ++i;
134 }
135 }
136
137 static void
release_untitled_number(gint n)138 release_untitled_number (gint n)
139 {
140 g_return_if_fail (allocated_untitled_numbers != NULL);
141
142 g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n));
143 }
144
145 static const gchar *
get_language_string(XedDocument * doc)146 get_language_string (XedDocument *doc)
147 {
148 GtkSourceLanguage *lang = xed_document_get_language (doc);
149
150 return lang != NULL ? gtk_source_language_get_id (lang) : NO_LANGUAGE_NAME;
151 }
152
153 static void
save_metadata(XedDocument * doc)154 save_metadata (XedDocument *doc)
155 {
156 XedDocumentPrivate *priv;
157 const gchar *language = NULL;
158 GtkTextIter iter;
159 gchar *position;
160
161 priv = xed_document_get_instance_private (doc);
162 if (priv->language_set_by_user)
163 {
164 language = get_language_string (doc);
165 }
166
167 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
168 &iter,
169 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (doc)));
170
171 position = g_strdup_printf ("%d", gtk_text_iter_get_offset (&iter));
172
173 if (language == NULL)
174 {
175 xed_document_set_metadata (doc,
176 XED_METADATA_ATTRIBUTE_POSITION, position,
177 NULL);
178 }
179 else
180 {
181 xed_document_set_metadata (doc,
182 XED_METADATA_ATTRIBUTE_POSITION, position,
183 XED_METADATA_ATTRIBUTE_LANGUAGE, language,
184 NULL);
185 }
186
187 g_free (position);
188 }
189
190 static void
xed_document_dispose(GObject * object)191 xed_document_dispose (GObject *object)
192 {
193 XedDocumentPrivate *priv;
194
195 xed_debug (DEBUG_DOCUMENT);
196
197 priv = xed_document_get_instance_private (XED_DOCUMENT (object));
198
199 /* Metadata must be saved here and not in finalize because the language
200 * is gone by the time finalize runs.
201 */
202 if (priv->file != NULL)
203 {
204 save_metadata (XED_DOCUMENT (object));
205
206 g_object_unref (priv->file);
207 priv->file = NULL;
208 }
209
210 g_clear_object (&priv->editor_settings);
211 g_clear_object (&priv->metadata_info);
212 g_clear_object (&priv->search_context);
213
214 G_OBJECT_CLASS (xed_document_parent_class)->dispose (object);
215 }
216
217 static void
xed_document_finalize(GObject * object)218 xed_document_finalize (GObject *object)
219 {
220 XedDocumentPrivate *priv;
221
222 xed_debug (DEBUG_DOCUMENT);
223
224 priv = xed_document_get_instance_private (XED_DOCUMENT (object));
225
226 if (priv->untitled_number > 0)
227 {
228 release_untitled_number (priv->untitled_number);
229 }
230
231 g_free (priv->content_type);
232 g_free (priv->short_name);
233
234 G_OBJECT_CLASS (xed_document_parent_class)->finalize (object);
235 }
236
237 static void
xed_document_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)238 xed_document_get_property (GObject *object,
239 guint prop_id,
240 GValue *value,
241 GParamSpec *pspec)
242 {
243 XedDocument *doc = XED_DOCUMENT (object);
244 XedDocumentPrivate *priv;
245
246 priv = xed_document_get_instance_private (doc);
247
248 switch (prop_id)
249 {
250 case PROP_SHORTNAME:
251 g_value_take_string (value, xed_document_get_short_name_for_display (doc));
252 break;
253 case PROP_CONTENT_TYPE:
254 g_value_take_string (value, xed_document_get_content_type (doc));
255 break;
256 case PROP_MIME_TYPE:
257 g_value_take_string (value, xed_document_get_mime_type (doc));
258 break;
259 case PROP_READ_ONLY:
260 g_value_set_boolean (value, gtk_source_file_is_readonly (priv->file));
261 break;
262 case PROP_USE_GVFS_METADATA:
263 g_value_set_boolean (value, priv->use_gvfs_metadata);
264 break;
265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
267 break;
268 }
269 }
270
271 static void
xed_document_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)272 xed_document_set_property (GObject *object,
273 guint prop_id,
274 const GValue *value,
275 GParamSpec *pspec)
276 {
277 XedDocument *doc = XED_DOCUMENT (object);
278 XedDocumentPrivate *priv;
279
280 priv = xed_document_get_instance_private (doc);
281
282 switch (prop_id)
283 {
284 case PROP_SHORTNAME:
285 xed_document_set_short_name_for_display (doc, g_value_get_string (value));
286 break;
287 case PROP_CONTENT_TYPE:
288 xed_document_set_content_type (doc, g_value_get_string (value));
289 break;
290 case PROP_USE_GVFS_METADATA:
291 priv->use_gvfs_metadata = g_value_get_boolean (value);
292 break;
293 default:
294 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
295 break;
296 }
297 }
298
299 static void
xed_document_begin_user_action(GtkTextBuffer * buffer)300 xed_document_begin_user_action (GtkTextBuffer *buffer)
301 {
302 XedDocumentPrivate *priv;
303
304 priv = xed_document_get_instance_private (XED_DOCUMENT (buffer));
305
306 ++priv->user_action;
307
308 if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action != NULL)
309 {
310 GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action (buffer);
311 }
312 }
313
314 static void
xed_document_end_user_action(GtkTextBuffer * buffer)315 xed_document_end_user_action (GtkTextBuffer *buffer)
316 {
317 XedDocumentPrivate *priv;
318
319 priv = xed_document_get_instance_private (XED_DOCUMENT (buffer));
320
321 --priv->user_action;
322
323 if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action != NULL)
324 {
325 GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action (buffer);
326 }
327 }
328
329 static void
emit_cursor_moved(XedDocument * doc)330 emit_cursor_moved (XedDocument *doc)
331 {
332 XedDocumentPrivate *priv;
333
334 priv = xed_document_get_instance_private (doc);
335
336 if (!priv->stop_cursor_moved_emission)
337 {
338 g_signal_emit (doc, document_signals[CURSOR_MOVED], 0);
339 }
340 }
341
342 static void
xed_document_mark_set(GtkTextBuffer * buffer,const GtkTextIter * iter,GtkTextMark * mark)343 xed_document_mark_set (GtkTextBuffer *buffer,
344 const GtkTextIter *iter,
345 GtkTextMark *mark)
346 {
347 XedDocument *doc = XED_DOCUMENT (buffer);
348 XedDocumentPrivate *priv;
349
350 priv = xed_document_get_instance_private (doc);
351
352 if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set != NULL)
353 {
354 GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set (buffer, iter, mark);
355 }
356
357 if (mark == gtk_text_buffer_get_insert (buffer) && (priv->user_action == 0))
358 {
359 emit_cursor_moved (doc);
360 }
361 }
362
363 static void
xed_document_changed(GtkTextBuffer * buffer)364 xed_document_changed (GtkTextBuffer *buffer)
365 {
366 emit_cursor_moved (XED_DOCUMENT (buffer));
367
368 GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->changed (buffer);
369 }
370
371 static void
xed_document_constructed(GObject * object)372 xed_document_constructed (GObject *object)
373 {
374 XedDocument *doc = XED_DOCUMENT (object);
375 XedDocumentPrivate *priv;
376
377 priv = xed_document_get_instance_private (doc);
378
379 g_settings_bind (priv->editor_settings,
380 XED_SETTINGS_ENSURE_TRAILING_NEWLINE,
381 doc,
382 "implicit-trailing-newline",
383 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
384
385 G_OBJECT_CLASS (xed_document_parent_class)->constructed (object);
386 }
387
388 static void
xed_document_class_init(XedDocumentClass * klass)389 xed_document_class_init (XedDocumentClass *klass)
390 {
391 GObjectClass *object_class = G_OBJECT_CLASS (klass);
392 GtkTextBufferClass *buf_class = GTK_TEXT_BUFFER_CLASS (klass);
393
394 object_class->dispose = xed_document_dispose;
395 object_class->finalize = xed_document_finalize;
396 object_class->get_property = xed_document_get_property;
397 object_class->set_property = xed_document_set_property;
398 object_class->constructed = xed_document_constructed;
399
400 buf_class->begin_user_action = xed_document_begin_user_action;
401 buf_class->end_user_action = xed_document_end_user_action;
402 buf_class->mark_set = xed_document_mark_set;
403 buf_class->changed = xed_document_changed;
404
405 klass->loaded = xed_document_loaded_real;
406 klass->saved = xed_document_saved_real;
407
408 /**
409 * XedDocument:shortname:
410 *
411 * The documents short name.
412 */
413 properties[PROP_SHORTNAME] =
414 g_param_spec_string ("shortname",
415 "Short Name",
416 "The documents short name",
417 NULL,
418 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
419
420 /**
421 * XedDocument:content-type:
422 *
423 * The documents content type.
424 */
425 properties[PROP_CONTENT_TYPE] =
426 g_param_spec_string ("content-type",
427 "Content Type",
428 "The documents content type",
429 NULL,
430 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
431
432 /**
433 * XedDocument:mime-type:
434 *
435 * The documents MIME type.
436 */
437 properties[PROP_MIME_TYPE] =
438 g_param_spec_string ("mime-type",
439 "MIME Type",
440 "The documents MIME type",
441 "text/plain",
442 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
443
444 properties[PROP_READ_ONLY] =
445 g_param_spec_boolean ("read-only",
446 "Read Only",
447 "Whether the document is read-only or not",
448 FALSE,
449 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
450
451 /**
452 * XedDocument:use-gvfs-metadata:
453 *
454 * Whether to use GVFS metadata. If %FALSE, use the xed metadata
455 * manager that stores the metadata in an XML file in the user cache
456 * directory.
457 *
458 * <warning>
459 * The property is used internally by xed. It must not be used in a
460 * xed plugin. The property can be modified or removed at any time.
461 * </warning>
462 */
463 properties[PROP_USE_GVFS_METADATA] =
464 g_param_spec_boolean ("use-gvfs-metadata",
465 "Use GVFS metadata",
466 "",
467 TRUE,
468 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
469
470 g_object_class_install_properties (object_class, LAST_PROP, properties);
471
472 /* This signal is used to update the cursor position is the statusbar,
473 * it's emitted either when the insert mark is moved explicitely or
474 * when the buffer changes (insert/delete).
475 * We prevent the emission of the signal during replace_all to
476 * improve performance.
477 */
478 document_signals[CURSOR_MOVED] =
479 g_signal_new ("cursor-moved",
480 G_OBJECT_CLASS_TYPE (object_class),
481 G_SIGNAL_RUN_LAST,
482 G_STRUCT_OFFSET (XedDocumentClass, cursor_moved),
483 NULL, NULL, NULL,
484 G_TYPE_NONE,
485 0);
486
487 /**
488 * XedDocument::load:
489 * @document: the #XedDocument.
490 *
491 * The "load" signal is emitted at the beginning of file loading.
492 */
493 document_signals[LOAD] =
494 g_signal_new ("load",
495 G_OBJECT_CLASS_TYPE (object_class),
496 G_SIGNAL_RUN_LAST,
497 G_STRUCT_OFFSET (XedDocumentClass, load),
498 NULL, NULL, NULL,
499 G_TYPE_NONE, 0);
500
501 /**
502 * XedDocument::loaded:
503 * @document: the #XedDocument.
504 *
505 * The "loaded" signal is emitted at the end of a successful loading.
506 */
507 document_signals[LOADED] =
508 g_signal_new ("loaded",
509 G_OBJECT_CLASS_TYPE (object_class),
510 G_SIGNAL_RUN_FIRST,
511 G_STRUCT_OFFSET (XedDocumentClass, loaded),
512 NULL, NULL, NULL,
513 G_TYPE_NONE, 0);
514
515 /**
516 * XedDocument::save:
517 * @document: the #XedDocument.
518 *
519 * The "save" signal is emitted at the beginning of file saving.
520 */
521 document_signals[SAVE] =
522 g_signal_new ("save",
523 G_OBJECT_CLASS_TYPE (object_class),
524 G_SIGNAL_RUN_LAST,
525 G_STRUCT_OFFSET (XedDocumentClass, save),
526 NULL, NULL, NULL,
527 G_TYPE_NONE, 0);
528
529 /**
530 * XedDocument::saved:
531 * @document: the #XedDocument.
532 *
533 * The "saved" signal is emitted at the end of a successful file saving.
534 */
535 document_signals[SAVED] =
536 g_signal_new ("saved",
537 G_OBJECT_CLASS_TYPE (object_class),
538 G_SIGNAL_RUN_FIRST,
539 G_STRUCT_OFFSET (XedDocumentClass, saved),
540 NULL, NULL, NULL,
541 G_TYPE_NONE, 0);
542 }
543
544 static void
set_language(XedDocument * doc,GtkSourceLanguage * lang,gboolean set_by_user)545 set_language (XedDocument *doc,
546 GtkSourceLanguage *lang,
547 gboolean set_by_user)
548 {
549 XedDocumentPrivate *priv;
550 GtkSourceLanguage *old_lang;
551
552 xed_debug (DEBUG_DOCUMENT);
553
554 priv = xed_document_get_instance_private (doc);
555
556 old_lang = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc));
557
558 if (old_lang == lang)
559 {
560 return;
561 }
562
563 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), lang);
564
565 if (set_by_user)
566 {
567 const gchar *language = get_language_string (doc);
568
569 xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE, language, NULL);
570 }
571
572 priv->language_set_by_user = set_by_user;
573 }
574
575 static void
save_encoding_metadata(XedDocument * doc)576 save_encoding_metadata (XedDocument *doc)
577 {
578 XedDocumentPrivate *priv;
579 const GtkSourceEncoding *encoding;
580 const gchar *charset;
581
582 xed_debug (DEBUG_DOCUMENT);
583
584 priv = xed_document_get_instance_private (doc);
585
586 encoding = gtk_source_file_get_encoding (priv->file);
587
588 if (encoding == NULL)
589 {
590 encoding = gtk_source_encoding_get_utf8 ();
591 }
592
593 charset = gtk_source_encoding_get_charset (encoding);
594
595 xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_ENCODING, charset, NULL);
596 }
597
598 static GtkSourceStyleScheme *
get_default_style_scheme(GSettings * editor_settings)599 get_default_style_scheme (GSettings *editor_settings)
600 {
601 GtkSourceStyleSchemeManager *manager;
602 gchar *scheme_id;
603 GtkSourceStyleScheme *def_style;
604
605 manager = gtk_source_style_scheme_manager_get_default ();
606 scheme_id = g_settings_get_string (editor_settings, XED_SETTINGS_SCHEME);
607 def_style = gtk_source_style_scheme_manager_get_scheme (manager, scheme_id);
608
609 if (def_style == NULL)
610 {
611 g_warning ("Default style scheme '%s' cannot be found, falling back to 'classic' style scheme ", scheme_id);
612
613 def_style = gtk_source_style_scheme_manager_get_scheme (manager, "classic");
614 if (def_style == NULL)
615 {
616 g_warning ("Style scheme 'classic' cannot be found, check your GtkSourceView installation.");
617 }
618 }
619
620 g_free (scheme_id);
621
622 return def_style;
623 }
624
625 static GtkSourceLanguage *
guess_language(XedDocument * doc)626 guess_language (XedDocument *doc)
627 {
628 XedDocumentPrivate *priv;
629 gchar *data;
630 GtkSourceLanguageManager *manager = gtk_source_language_manager_get_default ();
631 GtkSourceLanguage *language = NULL;
632
633 priv = xed_document_get_instance_private (doc);
634
635 data = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE);
636
637 if (data != NULL)
638 {
639 xed_debug_message (DEBUG_DOCUMENT, "Language from metadata: %s", data);
640
641 if (!g_str_equal (data, NO_LANGUAGE_NAME))
642 {
643 language = gtk_source_language_manager_get_language (manager, data);
644 }
645
646 g_free (data);
647 }
648 else
649 {
650 GFile *location;
651 gchar *basename = NULL;
652
653 location = gtk_source_file_get_location (priv->file);
654 xed_debug_message (DEBUG_DOCUMENT, "Sniffing Language");
655
656 if (location != NULL)
657 {
658 basename = g_file_get_basename (location);
659 }
660 else if (priv->short_name != NULL)
661 {
662 basename = g_strdup (priv->short_name);
663 }
664
665 language = gtk_source_language_manager_guess_language (manager, basename, priv->content_type);
666
667 g_free (basename);
668 }
669
670 return language;
671 }
672
673 static void
on_content_type_changed(XedDocument * doc,GParamSpec * pspec,gpointer useless)674 on_content_type_changed (XedDocument *doc,
675 GParamSpec *pspec,
676 gpointer useless)
677 {
678 XedDocumentPrivate *priv;
679
680 priv = xed_document_get_instance_private (doc);
681
682 if (!priv->language_set_by_user)
683 {
684 GtkSourceLanguage *language = guess_language (doc);
685
686 xed_debug_message (DEBUG_DOCUMENT, "Language: %s",
687 language != NULL ? gtk_source_language_get_name (language) : "None");
688
689 set_language (doc, language, FALSE);
690 }
691 }
692
693 static gchar *
get_default_content_type(void)694 get_default_content_type (void)
695 {
696 return g_content_type_from_mime_type ("text/plain");
697 }
698
699 static void
on_location_changed(GtkSourceFile * file,GParamSpec * pspec,XedDocument * doc)700 on_location_changed (GtkSourceFile *file,
701 GParamSpec *pspec,
702 XedDocument *doc)
703 {
704 XedDocumentPrivate *priv;
705 GFile *location;
706
707 xed_debug (DEBUG_DOCUMENT);
708
709 priv = xed_document_get_instance_private (doc);
710
711 location = gtk_source_file_get_location (file);
712
713 if (location != NULL && priv->untitled_number > 0)
714 {
715 release_untitled_number (priv->untitled_number);
716 priv->untitled_number = 0;
717 }
718
719 if (priv->short_name == NULL)
720 {
721 g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]);
722 }
723
724 /* Load metadata for this location: we load sync since metadata is
725 * always local so it should be fast and we need the information
726 * right after the location was set.
727 */
728 if (priv->use_gvfs_metadata && location != NULL)
729 {
730 GError *error = NULL;
731
732 if (priv->metadata_info != NULL)
733 {
734 g_object_unref (priv->metadata_info);
735 }
736
737 priv->metadata_info = g_file_query_info (location,
738 METADATA_QUERY,
739 G_FILE_QUERY_INFO_NONE,
740 NULL,
741 &error);
742
743 if (error != NULL)
744 {
745 /* Do not complain about metadata if we are opening a
746 * non existing file.
747 */
748 if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) &&
749 !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) &&
750 !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
751 !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
752 {
753 g_warning ("%s", error->message);
754 }
755
756 g_error_free (error);
757 }
758
759 if (priv->metadata_info == NULL)
760 {
761 priv->metadata_info = g_file_info_new ();
762 }
763 }
764 }
765
766 static void
on_readonly_changed(GtkSourceFile * file,GParamSpec * pspec,XedDocument * doc)767 on_readonly_changed (GtkSourceFile *file,
768 GParamSpec *pspec,
769 XedDocument *doc)
770 {
771 g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_READ_ONLY]);
772 }
773
774 static void
xed_document_init(XedDocument * doc)775 xed_document_init (XedDocument *doc)
776 {
777 XedDocumentPrivate *priv;
778 GtkSourceStyleScheme *style_scheme;
779
780 xed_debug (DEBUG_DOCUMENT);
781
782 priv = xed_document_get_instance_private (doc);
783
784 priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor");
785 priv->untitled_number = get_untitled_number ();
786 priv->content_type = get_default_content_type ();
787 priv->stop_cursor_moved_emission = FALSE;
788 priv->last_save_was_manually = TRUE;
789 priv->language_set_by_user = FALSE;
790
791 g_get_current_time (&priv->time_of_last_save_or_load);
792
793 priv->file = gtk_source_file_new ();
794 priv->metadata_info = g_file_info_new ();
795
796 g_signal_connect_object (priv->file, "notify::location",
797 G_CALLBACK (on_location_changed), doc, 0);
798
799 g_signal_connect_object (priv->file, "notify::read-only",
800 G_CALLBACK (on_readonly_changed), doc, 0);
801
802 g_settings_bind (priv->editor_settings,
803 XED_SETTINGS_SYNTAX_HIGHLIGHTING,
804 doc,
805 "highlight-syntax",
806 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
807
808 g_settings_bind (priv->editor_settings,
809 XED_SETTINGS_MAX_UNDO_ACTIONS,
810 doc,
811 "max-undo-levels",
812 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
813
814 g_settings_bind (priv->editor_settings,
815 XED_SETTINGS_BRACKET_MATCHING,
816 doc,
817 "highlight-matching-brackets",
818 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
819
820 style_scheme = get_default_style_scheme (priv->editor_settings);
821 if (style_scheme != NULL)
822 {
823 gtk_source_buffer_set_style_scheme (GTK_SOURCE_BUFFER (doc), style_scheme);
824 }
825
826 g_signal_connect (doc, "notify::content-type", G_CALLBACK (on_content_type_changed), NULL);
827 }
828
829 XedDocument *
xed_document_new(void)830 xed_document_new (void)
831 {
832 gboolean use_gvfs_metadata;
833
834 #ifdef ENABLE_GVFS_METADATA
835 use_gvfs_metadata = TRUE;
836 #else
837 use_gvfs_metadata = FALSE;
838 #endif
839
840 return g_object_new (XED_TYPE_DOCUMENT,
841 "use-gvfs-metadata", use_gvfs_metadata,
842 NULL);
843 }
844
845 static void
set_content_type_no_guess(XedDocument * doc,const gchar * content_type)846 set_content_type_no_guess (XedDocument *doc,
847 const gchar *content_type)
848 {
849 XedDocumentPrivate *priv;
850 xed_debug (DEBUG_DOCUMENT);
851
852 priv = xed_document_get_instance_private (doc);
853
854 if (priv->content_type != NULL && content_type != NULL &&
855 g_str_equal (priv->content_type, content_type))
856 {
857 return;
858 }
859
860 g_free (priv->content_type);
861
862 if (content_type == NULL || g_content_type_is_unknown (content_type))
863 {
864 priv->content_type = get_default_content_type ();
865 }
866 else
867 {
868 priv->content_type = g_strdup (content_type);
869 }
870
871 g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_CONTENT_TYPE]);
872 }
873
874 /**
875 * xed_document_set_content_type:
876 * @doc:
877 * @content_type: (allow-none):
878 */
879 void
xed_document_set_content_type(XedDocument * doc,const gchar * content_type)880 xed_document_set_content_type (XedDocument *doc,
881 const gchar *content_type)
882 {
883 XedDocumentPrivate *priv;
884
885 g_return_if_fail (XED_IS_DOCUMENT (doc));
886
887 xed_debug (DEBUG_DOCUMENT);
888
889 priv = xed_document_get_instance_private (doc);
890
891 if (content_type == NULL)
892 {
893 GFile *location;
894 gchar *guessed_type = NULL;
895
896 /* If content type is null, we guess from the filename */
897 location = gtk_source_file_get_location (priv->file);
898 if (location != NULL)
899 {
900 gchar *basename;
901
902 basename = g_file_get_basename (location);
903 guessed_type = g_content_type_guess (basename, NULL, 0, NULL);
904
905 g_free (basename);
906 }
907
908 set_content_type_no_guess (doc, guessed_type);
909 g_free (guessed_type);
910 }
911 else
912 {
913 set_content_type_no_guess (doc, content_type);
914 }
915 }
916
917 /**
918 * xed_document_get_location:
919 * @doc: a #XedDocument
920 *
921 * Returns: (allow-none) (transfer full): a new #GFile
922 */
923 GFile *
xed_document_get_location(XedDocument * doc)924 xed_document_get_location (XedDocument *doc)
925 {
926 XedDocumentPrivate *priv;
927 GFile *location;
928
929 priv = xed_document_get_instance_private (doc);
930
931 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
932
933 location = gtk_source_file_get_location (priv->file);
934
935 return location != NULL ? g_object_ref (location) : NULL;
936 }
937
938 void
xed_document_set_location(XedDocument * doc,GFile * location)939 xed_document_set_location (XedDocument *doc,
940 GFile *location)
941 {
942 XedDocumentPrivate *priv;
943
944 g_return_if_fail (XED_IS_DOCUMENT (doc));
945 g_return_if_fail (G_IS_FILE (location));
946
947 priv = xed_document_get_instance_private (doc);
948
949 gtk_source_file_set_location (priv->file, location);
950 xed_document_set_content_type (doc, NULL);
951 }
952
953 /**
954 * xed_document_get_uri_for_display:
955 * @doc: a #XedDocument
956 *
957 * Note: this never returns %NULL.
958 **/
959 gchar *
xed_document_get_uri_for_display(XedDocument * doc)960 xed_document_get_uri_for_display (XedDocument *doc)
961 {
962 XedDocumentPrivate *priv;
963 GFile *location;
964
965 g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup (""));
966
967 priv = xed_document_get_instance_private (doc);
968
969 location = gtk_source_file_get_location (priv->file);
970
971 if (location == NULL)
972 {
973 return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number);
974 }
975 else
976 {
977 return g_file_get_parse_name (location);
978 }
979 }
980
981 /**
982 * xed_document_get_short_name_for_display:
983 * @doc: a #XedDocument
984 *
985 * Note: this never returns %NULL.
986 **/
987 gchar *
xed_document_get_short_name_for_display(XedDocument * doc)988 xed_document_get_short_name_for_display (XedDocument *doc)
989 {
990 XedDocumentPrivate *priv;
991 GFile *location;
992
993 g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup (""));
994
995 priv = xed_document_get_instance_private (doc);
996
997 location = gtk_source_file_get_location (priv->file);
998
999 if (priv->short_name != NULL)
1000 {
1001 return g_strdup (priv->short_name);
1002 }
1003 else if (location == NULL)
1004 {
1005 return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number);
1006 }
1007 else
1008 {
1009 return xed_utils_basename_for_display (location);
1010 }
1011 }
1012
1013 /**
1014 * xed_document_set_short_name_for_display:
1015 * @doc: a #XedDocument
1016 * @short_name: (allow-none): the short name to use
1017 */
1018 void
xed_document_set_short_name_for_display(XedDocument * doc,const gchar * short_name)1019 xed_document_set_short_name_for_display (XedDocument *doc,
1020 const gchar *short_name)
1021 {
1022 XedDocumentPrivate *priv;
1023
1024 g_return_if_fail (XED_IS_DOCUMENT (doc));
1025
1026 priv = xed_document_get_instance_private (doc);
1027
1028 g_free (priv->short_name);
1029 priv->short_name = g_strdup (short_name);
1030
1031 g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]);
1032 }
1033
1034 gchar *
xed_document_get_content_type(XedDocument * doc)1035 xed_document_get_content_type (XedDocument *doc)
1036 {
1037 XedDocumentPrivate *priv;
1038
1039 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1040
1041 priv = xed_document_get_instance_private (doc);
1042
1043 return g_strdup (priv->content_type);
1044 }
1045
1046 /**
1047 * xed_document_get_mime_type:
1048 * @doc: a #XedDocument
1049 *
1050 * Note: this never returns %NULL.
1051 **/
1052 gchar *
xed_document_get_mime_type(XedDocument * doc)1053 xed_document_get_mime_type (XedDocument *doc)
1054 {
1055 XedDocumentPrivate *priv;
1056
1057 g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("text/plain"));
1058
1059 priv = xed_document_get_instance_private (doc);
1060
1061 if (priv->content_type != NULL &&
1062 !g_content_type_is_unknown (priv->content_type))
1063 {
1064 return g_content_type_get_mime_type (priv->content_type);
1065 }
1066
1067 return g_strdup ("text/plain");
1068 }
1069
1070 gboolean
xed_document_get_readonly(XedDocument * doc)1071 xed_document_get_readonly (XedDocument *doc)
1072 {
1073 XedDocumentPrivate *priv;
1074
1075 g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
1076
1077 priv = xed_document_get_instance_private (doc);
1078
1079 return gtk_source_file_is_readonly (priv->file);
1080 }
1081
1082 static void
loaded_query_info_cb(GFile * location,GAsyncResult * result,XedDocument * doc)1083 loaded_query_info_cb (GFile *location,
1084 GAsyncResult *result,
1085 XedDocument *doc)
1086 {
1087 GFileInfo *info;
1088 GError *error = NULL;
1089
1090 info = g_file_query_info_finish (location, result, &error);
1091
1092 if (error != NULL)
1093 {
1094 /* Ignore not found error as it can happen when opening a
1095 * non-existent file from the command line.
1096 */
1097 if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_NOT_FOUND)
1098 {
1099 g_warning ("Document loading: query info error: %s", error->message);
1100 }
1101
1102 g_error_free (error);
1103 error = NULL;
1104 }
1105
1106 if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
1107 {
1108 const gchar *content_type;
1109
1110 content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1111
1112 xed_document_set_content_type (doc, content_type);
1113 }
1114
1115 g_clear_object (&info);
1116
1117 /* Async operation finished. */
1118 g_object_unref (doc);
1119 }
1120
1121 static void
xed_document_loaded_real(XedDocument * doc)1122 xed_document_loaded_real (XedDocument *doc)
1123 {
1124 XedDocumentPrivate *priv;
1125 GFile *location;
1126
1127 priv = xed_document_get_instance_private (doc);
1128
1129 if (!priv->language_set_by_user)
1130 {
1131 GtkSourceLanguage *language = guess_language (doc);
1132
1133 xed_debug_message (DEBUG_DOCUMENT, "Language: %s",
1134 language != NULL ? gtk_source_language_get_name (language) : "None");
1135
1136 set_language (doc, language, FALSE);
1137 }
1138
1139 g_get_current_time (&priv->time_of_last_save_or_load);
1140
1141 xed_document_set_content_type (doc, NULL);
1142
1143 location = gtk_source_file_get_location (priv->file);
1144
1145 if (location != NULL)
1146 {
1147 /* Keep the doc alive during the async operation. */
1148 g_object_ref (doc);
1149
1150 g_file_query_info_async (location,
1151 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
1152 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
1153 G_FILE_QUERY_INFO_NONE,
1154 G_PRIORITY_DEFAULT,
1155 NULL,
1156 (GAsyncReadyCallback) loaded_query_info_cb,
1157 doc);
1158 }
1159 }
1160
1161 static void
saved_query_info_cb(GFile * location,GAsyncResult * result,XedDocument * doc)1162 saved_query_info_cb (GFile *location,
1163 GAsyncResult *result,
1164 XedDocument *doc)
1165 {
1166 XedDocumentPrivate *priv;
1167 GFileInfo *info;
1168 const gchar *content_type = NULL;
1169 GError *error = NULL;
1170
1171 priv = xed_document_get_instance_private (doc);
1172
1173 info = g_file_query_info_finish (location, result, &error);
1174
1175 if (error != NULL)
1176 {
1177 g_warning ("Document saving: query info error: %s", error->message);
1178 g_error_free (error);
1179 error = NULL;
1180 }
1181
1182 if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
1183 {
1184 content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1185 }
1186
1187 xed_document_set_content_type (doc, content_type);
1188
1189 if (info != NULL)
1190 {
1191 g_object_unref (info);
1192 }
1193
1194 g_get_current_time (&priv->time_of_last_save_or_load);
1195
1196 priv->create = FALSE;
1197
1198 save_encoding_metadata (doc);
1199
1200 /* Async operation finished. */
1201 g_object_unref (doc);
1202 }
1203
1204 static void
xed_document_saved_real(XedDocument * doc)1205 xed_document_saved_real (XedDocument *doc)
1206 {
1207 XedDocumentPrivate *priv;
1208 GFile *location;
1209
1210 priv = xed_document_get_instance_private (doc);
1211
1212 location = gtk_source_file_get_location (priv->file);
1213
1214 /* Keep the doc alive during the async operation. */
1215 g_object_ref (doc);
1216
1217 g_file_query_info_async (location,
1218 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
1219 G_FILE_QUERY_INFO_NONE,
1220 G_PRIORITY_DEFAULT,
1221 NULL,
1222 (GAsyncReadyCallback) saved_query_info_cb,
1223 doc);
1224 }
1225
1226 gboolean
xed_document_is_untouched(XedDocument * doc)1227 xed_document_is_untouched (XedDocument *doc)
1228 {
1229 XedDocumentPrivate *priv;
1230 GFile *location;
1231
1232 priv = xed_document_get_instance_private (doc);
1233
1234 g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
1235
1236 location = gtk_source_file_get_location (priv->file);
1237
1238 return location == NULL && !gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
1239 }
1240
1241 gboolean
xed_document_is_untitled(XedDocument * doc)1242 xed_document_is_untitled (XedDocument *doc)
1243 {
1244 XedDocumentPrivate *priv;
1245
1246 g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
1247
1248 priv = xed_document_get_instance_private (doc);
1249
1250 return gtk_source_file_get_location (priv->file) == NULL;
1251 }
1252
1253 gboolean
xed_document_is_local(XedDocument * doc)1254 xed_document_is_local (XedDocument *doc)
1255 {
1256 XedDocumentPrivate *priv;
1257
1258 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1259
1260 priv = xed_document_get_instance_private (doc);
1261
1262 return gtk_source_file_is_local (priv->file);
1263 }
1264
1265 gboolean
xed_document_get_deleted(XedDocument * doc)1266 xed_document_get_deleted (XedDocument *doc)
1267 {
1268 XedDocumentPrivate *priv;
1269
1270 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1271
1272 priv = xed_document_get_instance_private (doc);
1273
1274 return gtk_source_file_is_deleted (priv->file);
1275 }
1276
1277 /*
1278 * Deletion and external modification is only checked for local files.
1279 */
1280 gboolean
_xed_document_needs_saving(XedDocument * doc)1281 _xed_document_needs_saving (XedDocument *doc)
1282 {
1283 XedDocumentPrivate *priv;
1284 gboolean externally_modified = FALSE;
1285 gboolean deleted = FALSE;
1286
1287 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1288
1289 priv = xed_document_get_instance_private (doc);
1290
1291 if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
1292 {
1293 return TRUE;
1294 }
1295
1296 if (gtk_source_file_is_local (priv->file))
1297 {
1298 gtk_source_file_check_file_on_disk (priv->file);
1299 externally_modified = gtk_source_file_is_externally_modified (priv->file);
1300 deleted = gtk_source_file_is_deleted (priv->file);
1301 }
1302
1303 return (externally_modified || deleted) && !priv->create;
1304 }
1305
1306 /*
1307 * If @line is bigger than the lines of the document, the cursor is moved
1308 * to the last line and FALSE is returned.
1309 */
1310 gboolean
xed_document_goto_line(XedDocument * doc,gint line)1311 xed_document_goto_line (XedDocument *doc,
1312 gint line)
1313 {
1314 GtkTextIter iter;
1315
1316 xed_debug (DEBUG_DOCUMENT);
1317
1318 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1319 g_return_val_if_fail (line >= -1, FALSE);
1320
1321 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line);
1322
1323 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
1324
1325 return gtk_text_iter_get_line (&iter) == line;
1326 }
1327
1328 gboolean
xed_document_goto_line_offset(XedDocument * doc,gint line,gint line_offset)1329 xed_document_goto_line_offset (XedDocument *doc,
1330 gint line,
1331 gint line_offset)
1332 {
1333 GtkTextIter iter;
1334
1335 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1336 g_return_val_if_fail (line >= -1, FALSE);
1337 g_return_val_if_fail (line_offset >= -1, FALSE);
1338
1339 gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc), &iter, line, line_offset);
1340
1341 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
1342
1343 return (gtk_text_iter_get_line (&iter) == line && gtk_text_iter_get_line_offset (&iter) == line_offset);
1344 }
1345
1346 /**
1347 * xed_document_set_language:
1348 * @doc:
1349 * @lang: (allow-none):
1350 **/
1351 void
xed_document_set_language(XedDocument * doc,GtkSourceLanguage * lang)1352 xed_document_set_language (XedDocument *doc,
1353 GtkSourceLanguage *lang)
1354 {
1355 g_return_if_fail (XED_IS_DOCUMENT (doc));
1356
1357 set_language (doc, lang, TRUE);
1358 }
1359
1360 /**
1361 * xed_document_get_language:
1362 * @doc:
1363 *
1364 * Return value: (transfer none):
1365 */
1366 GtkSourceLanguage *
xed_document_get_language(XedDocument * doc)1367 xed_document_get_language (XedDocument *doc)
1368 {
1369 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1370
1371 return gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc));
1372 }
1373
1374 const GtkSourceEncoding *
xed_document_get_encoding(XedDocument * doc)1375 xed_document_get_encoding (XedDocument *doc)
1376 {
1377 XedDocumentPrivate *priv;
1378
1379 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1380
1381 priv = xed_document_get_instance_private (doc);
1382
1383 return gtk_source_file_get_encoding (priv->file);
1384 }
1385
1386 glong
_xed_document_get_seconds_since_last_save_or_load(XedDocument * doc)1387 _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc)
1388 {
1389 XedDocumentPrivate *priv;
1390 GTimeVal current_time;
1391
1392 xed_debug (DEBUG_DOCUMENT);
1393
1394 g_return_val_if_fail (XED_IS_DOCUMENT (doc), -1);
1395
1396 priv = xed_document_get_instance_private (doc);
1397
1398 g_get_current_time (¤t_time);
1399
1400 return (current_time.tv_sec - priv->time_of_last_save_or_load.tv_sec);
1401 }
1402
1403 GtkSourceNewlineType
xed_document_get_newline_type(XedDocument * doc)1404 xed_document_get_newline_type (XedDocument *doc)
1405 {
1406 XedDocumentPrivate *priv;
1407
1408 g_return_val_if_fail (XED_IS_DOCUMENT (doc), 0);
1409
1410 priv = xed_document_get_instance_private (doc);
1411
1412 return gtk_source_file_get_newline_type (priv->file);
1413 }
1414
1415 static gchar *
get_metadata_from_metadata_manager(XedDocument * doc,const gchar * key)1416 get_metadata_from_metadata_manager (XedDocument *doc,
1417 const gchar *key)
1418 {
1419 XedDocumentPrivate *priv;
1420 GFile *location;
1421
1422 priv = xed_document_get_instance_private (doc);
1423
1424 location = gtk_source_file_get_location (priv->file);
1425
1426 if (location != NULL)
1427 {
1428 return xed_metadata_manager_get (location, key);
1429 }
1430
1431 return NULL;
1432 }
1433
1434 static gchar *
get_metadata_from_gvfs(XedDocument * doc,const gchar * key)1435 get_metadata_from_gvfs (XedDocument *doc,
1436 const gchar *key)
1437 {
1438 XedDocumentPrivate *priv;
1439
1440 priv = xed_document_get_instance_private (doc);
1441
1442 if (priv->metadata_info != NULL &&
1443 g_file_info_has_attribute (priv->metadata_info, key) &&
1444 g_file_info_get_attribute_type (priv->metadata_info, key) == G_FILE_ATTRIBUTE_TYPE_STRING)
1445 {
1446 return g_strdup (g_file_info_get_attribute_string (priv->metadata_info, key));
1447 }
1448
1449 return NULL;
1450 }
1451
1452 static void
set_gvfs_metadata(GFileInfo * info,const gchar * key,const gchar * value)1453 set_gvfs_metadata (GFileInfo *info,
1454 const gchar *key,
1455 const gchar *value)
1456 {
1457 g_return_if_fail (G_IS_FILE_INFO (info));
1458
1459 if (value != NULL)
1460 {
1461 g_file_info_set_attribute_string (info, key, value);
1462 }
1463 else
1464 {
1465 /* Unset the key */
1466 g_file_info_set_attribute (info, key, G_FILE_ATTRIBUTE_TYPE_INVALID, NULL);
1467 }
1468 }
1469
1470 /**
1471 * xed_document_get_metadata:
1472 * @doc: a #XedDocument
1473 * @key: name of the key
1474 *
1475 * Gets the metadata assigned to @key.
1476 *
1477 * Returns: the value assigned to @key. Free with g_free().
1478 */
1479 gchar *
xed_document_get_metadata(XedDocument * doc,const gchar * key)1480 xed_document_get_metadata (XedDocument *doc,
1481 const gchar *key)
1482 {
1483 XedDocumentPrivate *priv;
1484
1485 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1486 g_return_val_if_fail (key != NULL, NULL);
1487
1488 priv = xed_document_get_instance_private (doc);
1489
1490 if (priv->use_gvfs_metadata)
1491 {
1492 return get_metadata_from_gvfs (doc, key);
1493 }
1494
1495 return get_metadata_from_metadata_manager (doc, key);
1496 }
1497
1498 static void
set_attributes_cb(GFile * location,GAsyncResult * result)1499 set_attributes_cb (GFile *location,
1500 GAsyncResult *result)
1501 {
1502 GError *error = NULL;
1503
1504 g_file_set_attributes_finish (location, result, NULL, &error);
1505
1506 if (error != NULL)
1507 {
1508 g_warning ("Set document metadata failed: %s", error->message);
1509 g_error_free (error);
1510 }
1511 }
1512
1513 /**
1514 * xed_document_set_metadata:
1515 * @doc: a #XedDocument
1516 * @first_key: name of the first key to set
1517 * @...: value for the first key, followed optionally by more key/value pairs,
1518 * followed by %NULL.
1519 *
1520 * Sets metadata on a document.
1521 */
1522 void
xed_document_set_metadata(XedDocument * doc,const gchar * first_key,...)1523 xed_document_set_metadata (XedDocument *doc,
1524 const gchar *first_key,
1525 ...)
1526 {
1527 XedDocumentPrivate *priv;
1528 GFile *location;
1529 const gchar *key;
1530 va_list var_args;
1531 GFileInfo *info = NULL;
1532
1533 g_return_if_fail (XED_IS_DOCUMENT (doc));
1534 g_return_if_fail (first_key != NULL);
1535
1536 priv = xed_document_get_instance_private (doc);
1537
1538 location = gtk_source_file_get_location (priv->file);
1539
1540 /* With the metadata manager, can't set metadata for untitled documents.
1541 * With GVFS metadata, if the location is NULL the metadata is stored in
1542 * priv->metadata_info, so that it can be saved later if the document is
1543 * saved.
1544 */
1545
1546 if (!priv->use_gvfs_metadata && location == NULL)
1547 {
1548 return;
1549 }
1550
1551 if (priv->use_gvfs_metadata)
1552 {
1553 info = g_file_info_new ();
1554 }
1555
1556 va_start (var_args, first_key);
1557
1558 for (key = first_key; key; key = va_arg (var_args, const gchar *))
1559 {
1560 const gchar *value = va_arg (var_args, const gchar *);
1561
1562 if (priv->use_gvfs_metadata)
1563 {
1564 /* Collect the metadata into @info. */
1565 set_gvfs_metadata (info, key, value);
1566 set_gvfs_metadata (priv->metadata_info, key, value);
1567 }
1568 else
1569 {
1570 /* Unset the key */
1571 xed_metadata_manager_set (location, key, value);
1572 }
1573 }
1574
1575 va_end (var_args);
1576
1577 if (priv->use_gvfs_metadata && location != NULL)
1578 {
1579 g_file_set_attributes_async (location,
1580 info,
1581 G_FILE_QUERY_INFO_NONE,
1582 G_PRIORITY_DEFAULT,
1583 NULL,
1584 (GAsyncReadyCallback) set_attributes_cb,
1585 NULL);
1586 }
1587
1588 g_clear_object (&info);
1589 }
1590
1591 /**
1592 * xed_document_set_search_context:
1593 * @doc: a #XedDocument
1594 * @search_context: (allow-none): the new #GtkSourceSearchContext
1595 *
1596 * Sets the new search context for the document.
1597 */
1598 void
xed_document_set_search_context(XedDocument * doc,GtkSourceSearchContext * search_context)1599 xed_document_set_search_context (XedDocument *doc,
1600 GtkSourceSearchContext *search_context)
1601 {
1602 XedDocumentPrivate *priv;
1603
1604 g_return_if_fail (XED_IS_DOCUMENT (doc));
1605
1606 priv = xed_document_get_instance_private (doc);
1607
1608 g_clear_object (&priv->search_context);
1609 priv->search_context = search_context;
1610
1611 if (search_context != NULL)
1612 {
1613 gboolean highlight = g_settings_get_boolean (priv->editor_settings, XED_SETTINGS_SEARCH_HIGHLIGHTING);
1614
1615 gtk_source_search_context_set_highlight (search_context, highlight);
1616
1617 g_object_ref (search_context);
1618 }
1619 }
1620
1621 /**
1622 * xed_document_get_search_context:
1623 * @doc: a #XedDocument
1624 *
1625 * Returns: (transfer full): the current search context of the document,
1626 * or NULL if there is no search context
1627 */
1628 GtkSourceSearchContext *
xed_document_get_search_context(XedDocument * doc)1629 xed_document_get_search_context (XedDocument *doc)
1630 {
1631 XedDocumentPrivate *priv;
1632
1633 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1634
1635 priv = xed_document_get_instance_private (doc);
1636
1637 return priv->search_context;
1638 }
1639
1640 /**
1641 * xed_document_get_file:
1642 * @doc: a #XedDocument.
1643 *
1644 * Gets the associated #GtkSourceFile. You should use it only for reading
1645 * purposes, not for creating a #GtkSourceFileLoader or #GtkSourceFileSaver,
1646 * because xed does some extra work when loading or saving a file and
1647 * maintains an internal state. If you use in a plugin a file loader or saver on
1648 * the returned #GtkSourceFile, the internal state of xed won't be updated.
1649 *
1650 * If you want to save the #XedDocument to a secondary file, you can create a
1651 * new #GtkSourceFile and use a #GtkSourceFileSaver.
1652 *
1653 * Returns: (transfer none): the associated #GtkSourceFile.
1654 */
1655 GtkSourceFile *
xed_document_get_file(XedDocument * doc)1656 xed_document_get_file (XedDocument *doc)
1657 {
1658 XedDocumentPrivate *priv;
1659
1660 g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
1661
1662 priv = xed_document_get_instance_private (doc);
1663
1664 return priv->file;
1665 }
1666
1667 void
_xed_document_set_create(XedDocument * doc,gboolean create)1668 _xed_document_set_create (XedDocument *doc,
1669 gboolean create)
1670 {
1671 XedDocumentPrivate *priv;
1672
1673 g_return_if_fail (XED_IS_DOCUMENT (doc));
1674
1675 priv = xed_document_get_instance_private (doc);
1676
1677 priv->create = create != FALSE;
1678 }
1679
1680 gboolean
_xed_document_get_create(XedDocument * doc)1681 _xed_document_get_create (XedDocument *doc)
1682 {
1683 XedDocumentPrivate *priv;
1684
1685 g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
1686
1687 priv = xed_document_get_instance_private (doc);
1688
1689 return priv->create;
1690 }
1691