1 /*
2  * gedit-tab.c
3  * This file is part of gedit
4  *
5  * Copyright (C) 2005 - Paolo Maggi
6  * Copyright (C) 2014, 2015 - Sébastien Wilmet
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "gedit-tab.h"
23 #include "gedit-tab-private.h"
24 
25 #include <stdlib.h>
26 #include <glib/gi18n.h>
27 #include <tepl/tepl.h>
28 
29 #include "gedit-app.h"
30 #include "gedit-app-private.h"
31 #include "gedit-recent.h"
32 #include "gedit-utils.h"
33 #include "gedit-io-error-info-bar.h"
34 #include "gedit-print-job.h"
35 #include "gedit-print-preview.h"
36 #include "gedit-debug.h"
37 #include "gedit-document.h"
38 #include "gedit-document-private.h"
39 #include "gedit-enum-types.h"
40 #include "gedit-settings.h"
41 #include "gedit-view-frame.h"
42 
43 #define GEDIT_TAB_KEY "GEDIT_TAB_KEY"
44 
45 struct _GeditTab
46 {
47 	GtkBox parent_instance;
48 
49 	GeditTabState state;
50 
51 	GSettings *editor_settings;
52 
53 	GeditViewFrame *frame;
54 
55 	GtkWidget *info_bar;
56 	GtkWidget *info_bar_hidden;
57 
58 	GeditPrintJob *print_job;
59 	GtkWidget *print_preview;
60 
61 	GtkSourceFileSaverFlags save_flags;
62 
63 	guint idle_scroll;
64 
65 	gint auto_save_interval;
66 	guint auto_save_timeout;
67 
68 	GCancellable *cancellable;
69 
70 	guint editable : 1;
71 	guint auto_save : 1;
72 
73 	guint ask_if_externally_modified : 1;
74 };
75 
76 typedef struct _SaverData SaverData;
77 typedef struct _LoaderData LoaderData;
78 
79 struct _SaverData
80 {
81 	GtkSourceFileSaver *saver;
82 
83 	GTimer *timer;
84 
85 	/* Notes about the create_backup saver flag:
86 	 * - At the beginning of a new file saving, force_no_backup is FALSE.
87 	 *   The create_backup flag is set to the saver if it is enabled in
88 	 *   GSettings and if it isn't an auto-save.
89 	 * - If creating the backup gives an error, and if the user wants to
90 	 *   save the file without the backup, force_no_backup is set to TRUE
91 	 *   and the create_backup flag is removed from the saver.
92 	 *   force_no_backup as TRUE means that the create_backup flag should
93 	 *   never be added again to the saver (for the current file saving).
94 	 * - When another error occurs and if the user explicitly retry again
95 	 *   the file saving, the create_backup flag is added to the saver if
96 	 *   (1) it is enabled in GSettings, (2) if force_no_backup is FALSE.
97 	 * - The create_backup flag is added when the user expressed his or her
98 	 *   willing to save the file, by pressing a button for example. For an
99 	 *   auto-save, the create_backup flag is thus not added initially, but
100 	 *   can be added later when an error occurs and the user clicks on a
101 	 *   button in the info bar to retry the file saving.
102 	 */
103 	guint force_no_backup : 1;
104 };
105 
106 struct _LoaderData
107 {
108 	GeditTab *tab;
109 	GtkSourceFileLoader *loader;
110 	GTimer *timer;
111 	gint line_pos;
112 	gint column_pos;
113 	guint user_requested_encoding : 1;
114 };
115 
116 G_DEFINE_TYPE (GeditTab, gedit_tab, GTK_TYPE_BOX)
117 
118 enum
119 {
120 	PROP_0,
121 	PROP_NAME,
122 	PROP_STATE,
123 	PROP_AUTO_SAVE,
124 	PROP_AUTO_SAVE_INTERVAL,
125 	PROP_CAN_CLOSE,
126 	LAST_PROP
127 };
128 
129 static GParamSpec *properties[LAST_PROP];
130 
131 enum
132 {
133 	DROP_URIS,
134 	LAST_SIGNAL
135 };
136 
137 static guint signals[LAST_SIGNAL];
138 
139 static gboolean gedit_tab_auto_save (GeditTab *tab);
140 
141 static void launch_loader (GTask                   *loading_task,
142 			   const GtkSourceEncoding *encoding);
143 
144 static void launch_saver (GTask *saving_task);
145 
146 static SaverData *
saver_data_new(void)147 saver_data_new (void)
148 {
149 	return g_slice_new0 (SaverData);
150 }
151 
152 static void
saver_data_free(SaverData * data)153 saver_data_free (SaverData *data)
154 {
155 	if (data != NULL)
156 	{
157 		if (data->saver != NULL)
158 		{
159 			g_object_unref (data->saver);
160 		}
161 
162 		if (data->timer != NULL)
163 		{
164 			g_timer_destroy (data->timer);
165 		}
166 
167 		g_slice_free (SaverData, data);
168 	}
169 }
170 
171 static LoaderData *
loader_data_new(void)172 loader_data_new (void)
173 {
174 	return g_slice_new0 (LoaderData);
175 }
176 
177 static void
loader_data_free(LoaderData * data)178 loader_data_free (LoaderData *data)
179 {
180 	if (data != NULL)
181 	{
182 		if (data->loader != NULL)
183 		{
184 			g_object_unref (data->loader);
185 		}
186 
187 		if (data->timer != NULL)
188 		{
189 			g_timer_destroy (data->timer);
190 		}
191 
192 		g_slice_free (LoaderData, data);
193 	}
194 }
195 
196 static void
set_editable(GeditTab * tab,gboolean editable)197 set_editable (GeditTab *tab,
198 	      gboolean  editable)
199 {
200 	GeditView *view;
201 	gboolean val;
202 
203 	tab->editable = editable != FALSE;
204 
205 	view = gedit_tab_get_view (tab);
206 
207 	val = (tab->state == GEDIT_TAB_STATE_NORMAL &&
208 	       tab->editable);
209 
210 	gtk_text_view_set_editable (GTK_TEXT_VIEW (view), val);
211 }
212 
213 static void
install_auto_save_timeout(GeditTab * tab)214 install_auto_save_timeout (GeditTab *tab)
215 {
216 	if (tab->auto_save_timeout == 0)
217 	{
218 		g_return_if_fail (tab->auto_save_interval > 0);
219 
220 		tab->auto_save_timeout = g_timeout_add_seconds (tab->auto_save_interval * 60,
221 		                                                (GSourceFunc) gedit_tab_auto_save,
222 		                                                tab);
223 	}
224 }
225 
226 static void
remove_auto_save_timeout(GeditTab * tab)227 remove_auto_save_timeout (GeditTab *tab)
228 {
229 	gedit_debug (DEBUG_TAB);
230 
231 	if (tab->auto_save_timeout > 0)
232 	{
233 		g_source_remove (tab->auto_save_timeout);
234 		tab->auto_save_timeout = 0;
235 	}
236 }
237 
238 static void
update_auto_save_timeout(GeditTab * tab)239 update_auto_save_timeout (GeditTab *tab)
240 {
241 	GeditDocument *doc;
242 	GtkSourceFile *file;
243 
244 	gedit_debug (DEBUG_TAB);
245 
246 	doc = gedit_tab_get_document (tab);
247 	file = gedit_document_get_file (doc);
248 
249 	if (tab->state == GEDIT_TAB_STATE_NORMAL &&
250 	    tab->auto_save &&
251 	    !gedit_document_is_untitled (doc) &&
252 	    !gtk_source_file_is_readonly (file))
253 	{
254 		install_auto_save_timeout (tab);
255 	}
256 	else
257 	{
258 		remove_auto_save_timeout (tab);
259 	}
260 }
261 
262 static void
gedit_tab_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)263 gedit_tab_get_property (GObject    *object,
264 		        guint       prop_id,
265 		        GValue     *value,
266 		        GParamSpec *pspec)
267 {
268 	GeditTab *tab = GEDIT_TAB (object);
269 
270 	switch (prop_id)
271 	{
272 		case PROP_NAME:
273 			g_value_take_string (value, _gedit_tab_get_name (tab));
274 			break;
275 
276 		case PROP_STATE:
277 			g_value_set_enum (value, gedit_tab_get_state (tab));
278 			break;
279 
280 		case PROP_AUTO_SAVE:
281 			g_value_set_boolean (value, gedit_tab_get_auto_save_enabled (tab));
282 			break;
283 
284 		case PROP_AUTO_SAVE_INTERVAL:
285 			g_value_set_int (value, gedit_tab_get_auto_save_interval (tab));
286 			break;
287 
288 		case PROP_CAN_CLOSE:
289 			g_value_set_boolean (value, _gedit_tab_get_can_close (tab));
290 			break;
291 
292 		default:
293 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294 			break;
295 	}
296 }
297 
298 static void
gedit_tab_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)299 gedit_tab_set_property (GObject      *object,
300 		        guint         prop_id,
301 		        const GValue *value,
302 		        GParamSpec   *pspec)
303 {
304 	GeditTab *tab = GEDIT_TAB (object);
305 
306 	switch (prop_id)
307 	{
308 		case PROP_AUTO_SAVE:
309 			gedit_tab_set_auto_save_enabled (tab, g_value_get_boolean (value));
310 			break;
311 
312 		case PROP_AUTO_SAVE_INTERVAL:
313 			gedit_tab_set_auto_save_interval (tab, g_value_get_int (value));
314 			break;
315 
316 		default:
317 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
318 			break;
319 	}
320 }
321 
322 static void
gedit_tab_dispose(GObject * object)323 gedit_tab_dispose (GObject *object)
324 {
325 	GeditTab *tab = GEDIT_TAB (object);
326 
327 	g_clear_object (&tab->editor_settings);
328 	g_clear_object (&tab->print_job);
329 	g_clear_object (&tab->print_preview);
330 
331 	remove_auto_save_timeout (tab);
332 
333 	if (tab->idle_scroll != 0)
334 	{
335 		g_source_remove (tab->idle_scroll);
336 		tab->idle_scroll = 0;
337 	}
338 
339 	if (tab->cancellable != NULL)
340 	{
341 		g_cancellable_cancel (tab->cancellable);
342 		g_clear_object (&tab->cancellable);
343 	}
344 
345 	G_OBJECT_CLASS (gedit_tab_parent_class)->dispose (object);
346 }
347 
348 static void
gedit_tab_grab_focus(GtkWidget * widget)349 gedit_tab_grab_focus (GtkWidget *widget)
350 {
351 	GeditTab *tab = GEDIT_TAB (widget);
352 
353 	GTK_WIDGET_CLASS (gedit_tab_parent_class)->grab_focus (widget);
354 
355 	if (tab->info_bar != NULL)
356 	{
357 		gtk_widget_grab_focus (tab->info_bar);
358 	}
359 	else
360 	{
361 		GeditView *view = gedit_tab_get_view (tab);
362 		gtk_widget_grab_focus (GTK_WIDGET (view));
363 	}
364 }
365 
366 static void
gedit_tab_drop_uris(GeditTab * tab,gchar ** uri_list)367 gedit_tab_drop_uris (GeditTab  *tab,
368                      gchar    **uri_list)
369 {
370 	gedit_debug (DEBUG_TAB);
371 }
372 
373 static void
gedit_tab_class_init(GeditTabClass * klass)374 gedit_tab_class_init (GeditTabClass *klass)
375 {
376 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
377 	GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
378 
379 	object_class->dispose = gedit_tab_dispose;
380 	object_class->get_property = gedit_tab_get_property;
381 	object_class->set_property = gedit_tab_set_property;
382 
383 	gtkwidget_class->grab_focus = gedit_tab_grab_focus;
384 
385 	properties[PROP_NAME] =
386 		g_param_spec_string ("name",
387 		                     "Name",
388 		                     "The tab's name",
389 		                     NULL,
390 		                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
391 
392 	properties[PROP_STATE] =
393 		g_param_spec_enum ("state",
394 		                   "State",
395 		                   "The tab's state",
396 		                   GEDIT_TYPE_TAB_STATE,
397 		                   GEDIT_TAB_STATE_NORMAL,
398 		                   G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
399 
400 	properties[PROP_AUTO_SAVE] =
401 		g_param_spec_boolean ("autosave",
402 		                      "Autosave",
403 		                      "Autosave feature",
404 		                      TRUE,
405 		                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
406 
407 	properties[PROP_AUTO_SAVE_INTERVAL] =
408 		g_param_spec_int ("autosave-interval",
409 		                  "AutosaveInterval",
410 		                  "Time between two autosaves",
411 		                  0,
412 		                  G_MAXINT,
413 		                  0,
414 		                  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
415 
416 	properties[PROP_CAN_CLOSE] =
417 		g_param_spec_boolean ("can-close",
418 		                      "Can close",
419 		                      "Whether the tab can be closed",
420 		                      TRUE,
421 		                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
422 
423 	g_object_class_install_properties (object_class, LAST_PROP, properties);
424 
425 	signals[DROP_URIS] =
426 		g_signal_new_class_handler ("drop-uris",
427 		                            G_TYPE_FROM_CLASS (klass),
428 		                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
429 		                            G_CALLBACK (gedit_tab_drop_uris),
430 		                            NULL, NULL, NULL,
431 		                            G_TYPE_NONE,
432 		                            1,
433 		                            G_TYPE_STRV);
434 }
435 
436 /**
437  * gedit_tab_get_state:
438  * @tab: a #GeditTab
439  *
440  * Gets the #GeditTabState of @tab.
441  *
442  * Returns: the #GeditTabState of @tab
443  */
444 GeditTabState
gedit_tab_get_state(GeditTab * tab)445 gedit_tab_get_state (GeditTab *tab)
446 {
447 	g_return_val_if_fail (GEDIT_IS_TAB (tab), GEDIT_TAB_STATE_NORMAL);
448 
449 	return tab->state;
450 }
451 
452 static void
set_cursor_according_to_state(GtkTextView * view,GeditTabState state)453 set_cursor_according_to_state (GtkTextView   *view,
454 			       GeditTabState  state)
455 {
456 	GdkDisplay *display;
457 	GdkCursor *cursor;
458 	GdkWindow *text_window;
459 	GdkWindow *left_window;
460 
461 	display = gtk_widget_get_display (GTK_WIDGET (view));
462 
463 	text_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_TEXT);
464 	left_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT);
465 
466 	if ((state == GEDIT_TAB_STATE_LOADING)          ||
467 	    (state == GEDIT_TAB_STATE_REVERTING)        ||
468 	    (state == GEDIT_TAB_STATE_SAVING)           ||
469 	    (state == GEDIT_TAB_STATE_PRINTING)         ||
470 	    (state == GEDIT_TAB_STATE_CLOSING))
471 	{
472 		cursor = gdk_cursor_new_from_name (display, "progress");
473 
474 		if (text_window != NULL)
475 			gdk_window_set_cursor (text_window, cursor);
476 		if (left_window != NULL)
477 			gdk_window_set_cursor (left_window, cursor);
478 
479 		g_clear_object (&cursor);
480 	}
481 	else
482 	{
483 		cursor = gdk_cursor_new_from_name (display, "text");
484 
485 		if (text_window != NULL)
486 			gdk_window_set_cursor (text_window, cursor);
487 		if (left_window != NULL)
488 			gdk_window_set_cursor (left_window, NULL);
489 
490 		g_clear_object (&cursor);
491 	}
492 }
493 
494 static void
view_realized(GtkTextView * view,GeditTab * tab)495 view_realized (GtkTextView *view,
496 	       GeditTab    *tab)
497 {
498 	set_cursor_according_to_state (view, tab->state);
499 }
500 
501 static void
set_view_properties_according_to_state(GeditTab * tab,GeditTabState state)502 set_view_properties_according_to_state (GeditTab      *tab,
503 					GeditTabState  state)
504 {
505 	GeditView *view;
506 	gboolean val;
507 	gboolean hl_current_line;
508 
509 	hl_current_line = g_settings_get_boolean (tab->editor_settings,
510 						  GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE);
511 
512 	view = gedit_tab_get_view (tab);
513 
514 	val = ((state == GEDIT_TAB_STATE_NORMAL) &&
515 	       tab->editable);
516 	gtk_text_view_set_editable (GTK_TEXT_VIEW (view), val);
517 
518 	val = ((state != GEDIT_TAB_STATE_LOADING) &&
519 	       (state != GEDIT_TAB_STATE_CLOSING));
520 	gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), val);
521 
522 	val = ((state != GEDIT_TAB_STATE_LOADING) &&
523 	       (state != GEDIT_TAB_STATE_CLOSING) &&
524 	       (hl_current_line));
525 	gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (view), val);
526 }
527 
528 static void
gedit_tab_set_state(GeditTab * tab,GeditTabState state)529 gedit_tab_set_state (GeditTab      *tab,
530 		     GeditTabState  state)
531 {
532 	g_return_if_fail ((state >= 0) && (state < GEDIT_TAB_NUM_OF_STATES));
533 
534 	if (tab->state == state)
535 	{
536 		return;
537 	}
538 
539 	tab->state = state;
540 
541 	set_view_properties_according_to_state (tab, state);
542 
543 	/* Hide or show the document.
544 	 * For GEDIT_TAB_STATE_LOADING_ERROR, tab->frame is either shown or
545 	 * hidden, depending on the error.
546 	 */
547 	if (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
548 	{
549 		gtk_widget_hide (GTK_WIDGET (tab->frame));
550 	}
551 	else if (state != GEDIT_TAB_STATE_LOADING_ERROR)
552 	{
553 		gtk_widget_show (GTK_WIDGET (tab->frame));
554 	}
555 
556 	set_cursor_according_to_state (GTK_TEXT_VIEW (gedit_tab_get_view (tab)),
557 				       state);
558 
559 	update_auto_save_timeout (tab);
560 
561 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_STATE]);
562 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
563 }
564 
565 static void
document_location_notify_handler(GtkSourceFile * file,GParamSpec * pspec,GeditTab * tab)566 document_location_notify_handler (GtkSourceFile *file,
567 				  GParamSpec    *pspec,
568 				  GeditTab      *tab)
569 {
570 	gedit_debug (DEBUG_TAB);
571 
572 	/* Notify the change in the location */
573 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
574 }
575 
576 static void
document_shortname_notify_handler(TeplFile * file,GParamSpec * pspec,GeditTab * tab)577 document_shortname_notify_handler (TeplFile   *file,
578 				   GParamSpec *pspec,
579 				   GeditTab   *tab)
580 {
581 	gedit_debug (DEBUG_TAB);
582 
583 	/* Notify the change in the shortname */
584 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
585 }
586 
587 static void
document_modified_changed(GtkTextBuffer * document,GeditTab * tab)588 document_modified_changed (GtkTextBuffer *document,
589 			   GeditTab      *tab)
590 {
591 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
592 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
593 }
594 
595 static void
set_info_bar(GeditTab * tab,GtkWidget * info_bar,GtkResponseType default_response)596 set_info_bar (GeditTab        *tab,
597               GtkWidget       *info_bar,
598               GtkResponseType  default_response)
599 {
600 	gedit_debug (DEBUG_TAB);
601 
602 	if (tab->info_bar == info_bar)
603 	{
604 		return;
605 	}
606 
607 	if (info_bar == NULL)
608 	{
609 		/* Don't destroy the old info_bar right away,
610 		   we want the hide animation. */
611 		if (tab->info_bar_hidden != NULL)
612 		{
613 			gtk_widget_destroy (tab->info_bar_hidden);
614 		}
615 
616 		tab->info_bar_hidden = tab->info_bar;
617 		gtk_widget_hide (tab->info_bar_hidden);
618 
619 		tab->info_bar = NULL;
620 	}
621 	else
622 	{
623 		if (tab->info_bar != NULL)
624 		{
625 			gedit_debug_message (DEBUG_TAB, "Replacing existing notification");
626 			gtk_widget_destroy (tab->info_bar);
627 		}
628 
629 		/* Make sure to stop a possibly still ongoing hiding animation. */
630 		if (tab->info_bar_hidden != NULL)
631 		{
632 			gtk_widget_destroy (tab->info_bar_hidden);
633 			tab->info_bar_hidden = NULL;
634 		}
635 
636 		tab->info_bar = info_bar;
637 		gtk_box_pack_start (GTK_BOX (tab), info_bar, FALSE, FALSE, 0);
638 
639 		/* Note this must be done after the info bar is added to the window */
640 		if (default_response != GTK_RESPONSE_NONE)
641 		{
642 			gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar),
643 			                                   default_response);
644 		}
645 
646 		gtk_widget_show (info_bar);
647 	}
648 }
649 
650 static void
remove_tab(GeditTab * tab)651 remove_tab (GeditTab *tab)
652 {
653 	GtkWidget *notebook;
654 
655 	notebook = gtk_widget_get_parent (GTK_WIDGET (tab));
656 	gtk_container_remove (GTK_CONTAINER (notebook), GTK_WIDGET (tab));
657 }
658 
659 static void
io_loading_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * loading_task)660 io_loading_error_info_bar_response (GtkWidget *info_bar,
661 				    gint       response_id,
662 				    GTask     *loading_task)
663 {
664 	LoaderData *data = g_task_get_task_data (loading_task);
665 	GFile *location;
666 	const GtkSourceEncoding *encoding;
667 
668 	location = gtk_source_file_loader_get_location (data->loader);
669 
670 	switch (response_id)
671 	{
672 		case GTK_RESPONSE_OK:
673 			encoding = gedit_conversion_error_info_bar_get_encoding (GTK_WIDGET (info_bar));
674 
675 			set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
676 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING);
677 
678 			launch_loader (loading_task, encoding);
679 			break;
680 
681 		case GTK_RESPONSE_YES:
682 			/* This means that we want to edit the document anyway */
683 			set_editable (data->tab, TRUE);
684 			set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
685 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
686 
687 			g_task_return_boolean (loading_task, TRUE);
688 			g_object_unref (loading_task);
689 			break;
690 
691 		default:
692 			if (location != NULL)
693 			{
694 				gedit_recent_remove_if_local (location);
695 			}
696 
697 			remove_tab (data->tab);
698 
699 			g_task_return_boolean (loading_task, FALSE);
700 			g_object_unref (loading_task);
701 			break;
702 	}
703 }
704 
705 static void
file_already_open_warning_info_bar_response(GtkWidget * info_bar,gint response_id,GeditTab * tab)706 file_already_open_warning_info_bar_response (GtkWidget *info_bar,
707 					     gint       response_id,
708 					     GeditTab  *tab)
709 {
710 	GeditView *view = gedit_tab_get_view (tab);
711 
712 	if (response_id == GTK_RESPONSE_YES)
713 	{
714 		set_editable (tab, TRUE);
715 	}
716 
717 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
718 
719 	gtk_widget_grab_focus (GTK_WIDGET (view));
720 }
721 
722 static void
load_cancelled(GtkWidget * bar,gint response_id,GTask * loading_task)723 load_cancelled (GtkWidget *bar,
724 		gint       response_id,
725 		GTask     *loading_task)
726 {
727 	LoaderData *data = g_task_get_task_data (loading_task);
728 
729 	g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
730 
731 	g_cancellable_cancel (g_task_get_cancellable (loading_task));
732 	remove_tab (data->tab);
733 }
734 
735 static void
unrecoverable_reverting_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * loading_task)736 unrecoverable_reverting_error_info_bar_response (GtkWidget *info_bar,
737 						 gint       response_id,
738 						 GTask     *loading_task)
739 {
740 	LoaderData *data = g_task_get_task_data (loading_task);
741 	GeditView *view;
742 
743 	gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
744 
745 	set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
746 
747 	view = gedit_tab_get_view (data->tab);
748 	gtk_widget_grab_focus (GTK_WIDGET (view));
749 
750 	g_task_return_boolean (loading_task, FALSE);
751 	g_object_unref (loading_task);
752 }
753 
754 #define MAX_MSG_LENGTH 100
755 
756 static void
show_loading_info_bar(GTask * loading_task)757 show_loading_info_bar (GTask *loading_task)
758 {
759 	LoaderData *data = g_task_get_task_data (loading_task);
760 	TeplProgressInfoBar *bar;
761 	GeditDocument *doc;
762 	gchar *name;
763 	gchar *dirname = NULL;
764 	gchar *msg = NULL;
765 	gchar *name_markup;
766 	gchar *dirname_markup;
767 	gint len;
768 
769 	if (data->tab->info_bar != NULL)
770 	{
771 		return;
772 	}
773 
774 	gedit_debug (DEBUG_TAB);
775 
776 	doc = gedit_tab_get_document (data->tab);
777 
778 	name = gedit_document_get_short_name_for_display (doc);
779 	len = g_utf8_strlen (name, -1);
780 
781 	/* if the name is awfully long, truncate it and be done with it,
782 	 * otherwise also show the directory (ellipsized if needed)
783 	 */
784 	if (len > MAX_MSG_LENGTH)
785 	{
786 		gchar *str;
787 
788 		str = tepl_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
789 		g_free (name);
790 		name = str;
791 	}
792 	else
793 	{
794 		GtkSourceFile *file = gedit_document_get_file (doc);
795 		GFile *location = gtk_source_file_get_location (file);
796 
797 		if (location != NULL)
798 		{
799 			gchar *str = gedit_utils_location_get_dirname_for_display (location);
800 
801 			/* use the remaining space for the dir, but use a min of 20 chars
802 			 * so that we do not end up with a dirname like "(a...b)".
803 			 * This means that in the worst case when the filename is long 99
804 			 * we have a title long 99 + 20, but I think it's a rare enough
805 			 * case to be acceptable. It's justa darn title afterall :)
806 			 */
807 			dirname = tepl_utils_str_middle_truncate (str,
808 								  MAX (20, MAX_MSG_LENGTH - len));
809 			g_free (str);
810 		}
811 	}
812 
813 	name_markup = g_markup_printf_escaped ("<b>%s</b>", name);
814 
815 	if (data->tab->state == GEDIT_TAB_STATE_REVERTING)
816 	{
817 		if (dirname != NULL)
818 		{
819 			dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
820 
821 			/* Translators: the first %s is a file name (e.g. test.txt) the second one
822 			   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
823 			msg = g_strdup_printf (_("Reverting %s from %s"),
824 					       name_markup,
825 					       dirname_markup);
826 			g_free (dirname_markup);
827 		}
828 		else
829 		{
830 			msg = g_strdup_printf (_("Reverting %s"), name_markup);
831 		}
832 
833 		bar = tepl_progress_info_bar_new ("document-revert", msg, TRUE);
834 	}
835 	else
836 	{
837 		if (dirname != NULL)
838 		{
839 			dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
840 
841 			/* Translators: the first %s is a file name (e.g. test.txt) the second one
842 			   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
843 			msg = g_strdup_printf (_("Loading %s from %s"),
844 					       name_markup,
845 					       dirname_markup);
846 			g_free (dirname_markup);
847 		}
848 		else
849 		{
850 			msg = g_strdup_printf (_("Loading %s"), name_markup);
851 		}
852 
853 		bar = tepl_progress_info_bar_new ("document-open", msg, TRUE);
854 	}
855 
856 	g_signal_connect_object (bar,
857 				 "response",
858 				 G_CALLBACK (load_cancelled),
859 				 loading_task,
860 				 0);
861 
862 	set_info_bar (data->tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
863 
864 	g_free (msg);
865 	g_free (name);
866 	g_free (name_markup);
867 	g_free (dirname);
868 }
869 
870 static void
show_saving_info_bar(GTask * saving_task)871 show_saving_info_bar (GTask *saving_task)
872 {
873 	GeditTab *tab = g_task_get_source_object (saving_task);
874 	TeplProgressInfoBar *bar;
875 	GeditDocument *doc;
876 	gchar *short_name;
877 	gchar *from;
878 	gchar *to = NULL;
879 	gchar *from_markup;
880 	gchar *to_markup;
881 	gchar *msg = NULL;
882 	gint len;
883 
884 	if (tab->info_bar != NULL)
885 	{
886 		return;
887 	}
888 
889 	gedit_debug (DEBUG_TAB);
890 
891 	doc = gedit_tab_get_document (tab);
892 
893 	short_name = gedit_document_get_short_name_for_display (doc);
894 
895 	len = g_utf8_strlen (short_name, -1);
896 
897 	/* if the name is awfully long, truncate it and be done with it,
898 	 * otherwise also show the directory (ellipsized if needed)
899 	 */
900 	if (len > MAX_MSG_LENGTH)
901 	{
902 		from = tepl_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
903 		g_free (short_name);
904 	}
905 	else
906 	{
907 		gchar *str;
908 		SaverData *data;
909 		GFile *location;
910 
911 		data = g_task_get_task_data (saving_task);
912 		location = gtk_source_file_saver_get_location (data->saver);
913 
914 		from = short_name;
915 		to = g_file_get_parse_name (location);
916 		str = tepl_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
917 		g_free (to);
918 
919 		to = str;
920 	}
921 
922 	from_markup = g_markup_printf_escaped ("<b>%s</b>", from);
923 
924 	if (to != NULL)
925 	{
926 		to_markup = g_markup_printf_escaped ("<b>%s</b>", to);
927 
928 		/* Translators: the first %s is a file name (e.g. test.txt) the second one
929 		   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
930 		msg = g_strdup_printf (_("Saving %s to %s"), from_markup, to_markup);
931 		g_free (to_markup);
932 	}
933 	else
934 	{
935 		msg = g_strdup_printf (_("Saving %s"), from_markup);
936 	}
937 
938 	bar = tepl_progress_info_bar_new ("document-save", msg, FALSE);
939 
940 	set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
941 
942 	g_free (msg);
943 	g_free (to);
944 	g_free (from);
945 	g_free (from_markup);
946 }
947 
948 static void
info_bar_set_progress(GeditTab * tab,goffset size,goffset total_size)949 info_bar_set_progress (GeditTab *tab,
950 		       goffset   size,
951 		       goffset   total_size)
952 {
953 	TeplProgressInfoBar *progress_info_bar;
954 
955 	if (tab->info_bar == NULL)
956 	{
957 		return;
958 	}
959 
960 	gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT, size, total_size);
961 
962 	g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
963 
964 	progress_info_bar = TEPL_PROGRESS_INFO_BAR (tab->info_bar);
965 
966 	if (total_size != 0)
967 	{
968 		gdouble frac = (gdouble)size / (gdouble)total_size;
969 
970 		tepl_progress_info_bar_set_fraction (progress_info_bar, frac);
971 	}
972 	else if (size != 0)
973 	{
974 		tepl_progress_info_bar_pulse (progress_info_bar);
975 	}
976 	else
977 	{
978 		tepl_progress_info_bar_set_fraction (progress_info_bar, 0);
979 	}
980 }
981 
982 /* Returns whether progress info should be shown. */
983 static gboolean
should_show_progress_info(GTimer ** timer,goffset size,goffset total_size)984 should_show_progress_info (GTimer  **timer,
985 			   goffset   size,
986 			   goffset   total_size)
987 {
988 	gdouble elapsed_time;
989 	gdouble total_time;
990 	gdouble remaining_time;
991 
992 	g_assert (timer != NULL);
993 
994 	if (*timer == NULL)
995 	{
996 		return TRUE;
997 	}
998 
999 	elapsed_time = g_timer_elapsed (*timer, NULL);
1000 
1001 	/* Wait a little, because at the very beginning it's maybe not very
1002 	 * accurate (it takes initially more time for the first bytes, the
1003 	 * following chunks should arrive more quickly, as a rough guess).
1004 	 */
1005 	if (elapsed_time < 0.5)
1006 	{
1007 		return FALSE;
1008 	}
1009 
1010 	/* elapsed_time / total_time = size / total_size */
1011 	total_time = (elapsed_time * total_size) / size;
1012 
1013 	remaining_time = total_time - elapsed_time;
1014 
1015 	/* Approximately more than 3 seconds remaining. */
1016 	if (remaining_time > 3.0)
1017 	{
1018 		/* Once the progress info bar is shown, it must remain
1019 		 * shown until the end, so we don't need the timer
1020 		 * anymore.
1021 		 */
1022 		g_timer_destroy (*timer);
1023 		*timer = NULL;
1024 
1025 		return TRUE;
1026 	}
1027 
1028 	return FALSE;
1029 }
1030 
1031 static gboolean
scroll_to_cursor(GeditTab * tab)1032 scroll_to_cursor (GeditTab *tab)
1033 {
1034 	GeditView *view;
1035 
1036 	view = gedit_tab_get_view (tab);
1037 	tepl_view_scroll_to_cursor (TEPL_VIEW (view));
1038 
1039 	tab->idle_scroll = 0;
1040 	return G_SOURCE_REMOVE;
1041 }
1042 
1043 static void
unrecoverable_saving_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1044 unrecoverable_saving_error_info_bar_response (GtkWidget *info_bar,
1045 					      gint       response_id,
1046 					      GTask     *saving_task)
1047 {
1048 	GeditTab *tab = g_task_get_source_object (saving_task);
1049 	GeditView *view;
1050 
1051 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
1052 
1053 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1054 
1055 	view = gedit_tab_get_view (tab);
1056 	gtk_widget_grab_focus (GTK_WIDGET (view));
1057 
1058 	g_task_return_boolean (saving_task, FALSE);
1059 	g_object_unref (saving_task);
1060 }
1061 
1062 /* Sets the save flags after an info bar response. */
1063 static void
response_set_save_flags(GTask * saving_task,GtkSourceFileSaverFlags save_flags)1064 response_set_save_flags (GTask                   *saving_task,
1065 			 GtkSourceFileSaverFlags  save_flags)
1066 {
1067 	GeditTab *tab = g_task_get_source_object (saving_task);
1068 	SaverData *data = g_task_get_task_data (saving_task);
1069 	gboolean create_backup;
1070 
1071 	create_backup = g_settings_get_boolean (tab->editor_settings,
1072 						GEDIT_SETTINGS_CREATE_BACKUP_COPY);
1073 
1074 	/* If we are here, it means that the user expressed his or her willing
1075 	 * to save the file, by pressing a button in the info bar. So even if
1076 	 * the file saving was initially an auto-save, we set the create_backup
1077 	 * flag (if the conditions are met).
1078 	 */
1079 	if (create_backup && !data->force_no_backup)
1080 	{
1081 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
1082 	}
1083 	else
1084 	{
1085 		save_flags &= ~GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
1086 	}
1087 
1088 	gtk_source_file_saver_set_flags (data->saver, save_flags);
1089 }
1090 
1091 static void
invalid_character_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1092 invalid_character_info_bar_response (GtkWidget *info_bar,
1093 				     gint       response_id,
1094 				     GTask     *saving_task)
1095 {
1096 	if (response_id == GTK_RESPONSE_YES)
1097 	{
1098 		GeditTab *tab = g_task_get_source_object (saving_task);
1099 		SaverData *data = g_task_get_task_data (saving_task);
1100 		GtkSourceFileSaverFlags save_flags;
1101 
1102 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1103 
1104 		/* Don't bug the user again with this... */
1105 		tab->save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
1106 
1107 		save_flags = gtk_source_file_saver_get_flags (data->saver);
1108 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
1109 		response_set_save_flags (saving_task, save_flags);
1110 
1111 		/* Force saving */
1112 		launch_saver (saving_task);
1113 	}
1114 	else
1115 	{
1116 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1117 	}
1118 }
1119 
1120 static void
cant_create_backup_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1121 cant_create_backup_error_info_bar_response (GtkWidget *info_bar,
1122 					    gint       response_id,
1123 					    GTask     *saving_task)
1124 {
1125 	if (response_id == GTK_RESPONSE_YES)
1126 	{
1127 		GeditTab *tab = g_task_get_source_object (saving_task);
1128 		SaverData *data = g_task_get_task_data (saving_task);
1129 		GtkSourceFileSaverFlags save_flags;
1130 
1131 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1132 
1133 		data->force_no_backup = TRUE;
1134 		save_flags = gtk_source_file_saver_get_flags (data->saver);
1135 		response_set_save_flags (saving_task, save_flags);
1136 
1137 		/* Force saving */
1138 		launch_saver (saving_task);
1139 	}
1140 	else
1141 	{
1142 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1143 	}
1144 }
1145 
1146 static void
externally_modified_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1147 externally_modified_error_info_bar_response (GtkWidget *info_bar,
1148 					     gint       response_id,
1149 					     GTask     *saving_task)
1150 {
1151 	if (response_id == GTK_RESPONSE_YES)
1152 	{
1153 		GeditTab *tab = g_task_get_source_object (saving_task);
1154 		SaverData *data = g_task_get_task_data (saving_task);
1155 		GtkSourceFileSaverFlags save_flags;
1156 
1157 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1158 
1159 		/* ignore_modification_time should not be persisted in save
1160 		 * flags across saves (i.e. tab->save_flags is not modified).
1161 		 */
1162 		save_flags = gtk_source_file_saver_get_flags (data->saver);
1163 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
1164 		response_set_save_flags (saving_task, save_flags);
1165 
1166 		/* Force saving */
1167 		launch_saver (saving_task);
1168 	}
1169 	else
1170 	{
1171 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1172 	}
1173 }
1174 
1175 static void
recoverable_saving_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1176 recoverable_saving_error_info_bar_response (GtkWidget *info_bar,
1177 					    gint       response_id,
1178 					    GTask     *saving_task)
1179 {
1180 	if (response_id == GTK_RESPONSE_OK)
1181 	{
1182 		GeditTab *tab = g_task_get_source_object (saving_task);
1183 		SaverData *data = g_task_get_task_data (saving_task);
1184 		const GtkSourceEncoding *encoding;
1185 
1186 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1187 
1188 		encoding = gedit_conversion_error_info_bar_get_encoding (GTK_WIDGET (info_bar));
1189 		g_return_if_fail (encoding != NULL);
1190 
1191 		gtk_source_file_saver_set_encoding (data->saver, encoding);
1192 		launch_saver (saving_task);
1193 	}
1194 	else
1195 	{
1196 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1197 	}
1198 }
1199 
1200 static void
externally_modified_notification_info_bar_response(GtkWidget * info_bar,gint response_id,GeditTab * tab)1201 externally_modified_notification_info_bar_response (GtkWidget *info_bar,
1202 						    gint       response_id,
1203 						    GeditTab  *tab)
1204 {
1205 	GeditView *view;
1206 
1207 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1208 
1209 	view = gedit_tab_get_view (tab);
1210 
1211 	if (response_id == GTK_RESPONSE_OK)
1212 	{
1213 		_gedit_tab_revert (tab);
1214 	}
1215 	else
1216 	{
1217 		tab->ask_if_externally_modified = FALSE;
1218 
1219 		/* go back to normal state */
1220 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
1221 	}
1222 
1223 	gtk_widget_grab_focus (GTK_WIDGET (view));
1224 }
1225 
1226 static void
display_externally_modified_notification(GeditTab * tab)1227 display_externally_modified_notification (GeditTab *tab)
1228 {
1229 	TeplInfoBar *info_bar;
1230 	GeditDocument *doc;
1231 	GtkSourceFile *file;
1232 	GFile *location;
1233 	gboolean document_modified;
1234 
1235 	doc = gedit_tab_get_document (tab);
1236 	file = gedit_document_get_file (doc);
1237 
1238 	/* we're here because the file we're editing changed on disk */
1239 	location = gtk_source_file_get_location (file);
1240 	g_return_if_fail (location != NULL);
1241 
1242 	document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
1243 	info_bar = tepl_io_error_info_bar_externally_modified (location, document_modified);
1244 
1245 	set_info_bar (tab, GTK_WIDGET (info_bar), GTK_RESPONSE_OK);
1246 
1247 	g_signal_connect (info_bar,
1248 			  "response",
1249 			  G_CALLBACK (externally_modified_notification_info_bar_response),
1250 			  tab);
1251 }
1252 
1253 static gboolean
view_focused_in(GtkWidget * widget,GdkEventFocus * event,GeditTab * tab)1254 view_focused_in (GtkWidget     *widget,
1255                  GdkEventFocus *event,
1256                  GeditTab      *tab)
1257 {
1258 	GeditDocument *doc;
1259 	GtkSourceFile *file;
1260 
1261 	g_return_val_if_fail (GEDIT_IS_TAB (tab), GDK_EVENT_PROPAGATE);
1262 
1263 	/* we try to detect file changes only in the normal state */
1264 	if (tab->state != GEDIT_TAB_STATE_NORMAL)
1265 	{
1266 		return GDK_EVENT_PROPAGATE;
1267 	}
1268 
1269 	/* we already asked, don't bug the user again */
1270 	if (!tab->ask_if_externally_modified)
1271 	{
1272 		return GDK_EVENT_PROPAGATE;
1273 	}
1274 
1275 	doc = gedit_tab_get_document (tab);
1276 	file = gedit_document_get_file (doc);
1277 
1278 	/* If file was never saved or is remote we do not check */
1279 	if (gtk_source_file_is_local (file))
1280 	{
1281 		gtk_source_file_check_file_on_disk (file);
1282 
1283 		if (gtk_source_file_is_externally_modified (file))
1284 		{
1285 			gedit_tab_set_state (tab, GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
1286 
1287 			display_externally_modified_notification (tab);
1288 		}
1289 	}
1290 
1291 	return GDK_EVENT_PROPAGATE;
1292 }
1293 
1294 static void
on_drop_uris(GeditView * view,gchar ** uri_list,GeditTab * tab)1295 on_drop_uris (GeditView  *view,
1296 	      gchar     **uri_list,
1297 	      GeditTab   *tab)
1298 {
1299 	g_signal_emit (G_OBJECT (tab), signals[DROP_URIS], 0, uri_list);
1300 }
1301 
1302 static void
gedit_tab_init(GeditTab * tab)1303 gedit_tab_init (GeditTab *tab)
1304 {
1305 	gboolean auto_save;
1306 	gint auto_save_interval;
1307 	GeditDocument *doc;
1308 	GeditView *view;
1309 	GtkSourceFile *file;
1310 	TeplFile *tepl_file;
1311 
1312 	tab->state = GEDIT_TAB_STATE_NORMAL;
1313 
1314 	tab->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
1315 
1316 	tab->editable = TRUE;
1317 
1318 	tab->ask_if_externally_modified = TRUE;
1319 
1320 	gtk_orientable_set_orientation (GTK_ORIENTABLE (tab),
1321 	                                GTK_ORIENTATION_VERTICAL);
1322 
1323 	/* Manage auto save data */
1324 	auto_save = g_settings_get_boolean (tab->editor_settings,
1325 					    GEDIT_SETTINGS_AUTO_SAVE);
1326 	g_settings_get (tab->editor_settings, GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
1327 			"u", &auto_save_interval);
1328 	tab->auto_save = auto_save != FALSE;
1329 	tab->auto_save_interval = auto_save_interval;
1330 
1331 	/* Create the frame */
1332 	tab->frame = gedit_view_frame_new ();
1333 	gtk_widget_show (GTK_WIDGET (tab->frame));
1334 
1335 	gtk_box_pack_end (GTK_BOX (tab), GTK_WIDGET (tab->frame), TRUE, TRUE, 0);
1336 
1337 	doc = gedit_tab_get_document (tab);
1338 	g_object_set_data (G_OBJECT (doc), GEDIT_TAB_KEY, tab);
1339 
1340 	file = gedit_document_get_file (doc);
1341 	tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
1342 
1343 	g_signal_connect_object (file,
1344 				 "notify::location",
1345 				 G_CALLBACK (document_location_notify_handler),
1346 				 tab,
1347 				 0);
1348 
1349 	g_signal_connect_object (tepl_file,
1350 				 "notify::short-name",
1351 				 G_CALLBACK (document_shortname_notify_handler),
1352 				 tab,
1353 				 0);
1354 
1355 	g_signal_connect (doc,
1356 			  "modified_changed",
1357 			  G_CALLBACK (document_modified_changed),
1358 			  tab);
1359 
1360 	view = gedit_tab_get_view (tab);
1361 
1362 	g_signal_connect_after (view,
1363 				"focus-in-event",
1364 				G_CALLBACK (view_focused_in),
1365 				tab);
1366 
1367 	g_signal_connect_after (view,
1368 				"realize",
1369 				G_CALLBACK (view_realized),
1370 				tab);
1371 
1372 	g_signal_connect (view,
1373 			  "drop-uris",
1374 			  G_CALLBACK (on_drop_uris),
1375 			  tab);
1376 }
1377 
1378 GeditTab *
_gedit_tab_new(void)1379 _gedit_tab_new (void)
1380 {
1381 	return g_object_new (GEDIT_TYPE_TAB, NULL);
1382 }
1383 
1384 /**
1385  * gedit_tab_get_view:
1386  * @tab: a #GeditTab
1387  *
1388  * Gets the #GeditView inside @tab.
1389  *
1390  * Returns: (transfer none): the #GeditView inside @tab
1391  */
1392 GeditView *
gedit_tab_get_view(GeditTab * tab)1393 gedit_tab_get_view (GeditTab *tab)
1394 {
1395 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1396 
1397 	return gedit_view_frame_get_view (tab->frame);
1398 }
1399 
1400 /**
1401  * gedit_tab_get_document:
1402  * @tab: a #GeditTab
1403  *
1404  * Gets the #GeditDocument associated to @tab.
1405  *
1406  * Returns: (transfer none): the #GeditDocument associated to @tab
1407  */
1408 GeditDocument *
gedit_tab_get_document(GeditTab * tab)1409 gedit_tab_get_document (GeditTab *tab)
1410 {
1411 	GeditView *view;
1412 
1413 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1414 
1415 	view = gedit_view_frame_get_view (tab->frame);
1416 
1417 	return GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
1418 }
1419 
1420 #define MAX_DOC_NAME_LENGTH 40
1421 
1422 gchar *
_gedit_tab_get_name(GeditTab * tab)1423 _gedit_tab_get_name (GeditTab *tab)
1424 {
1425 	GeditDocument *doc;
1426 	gchar *name;
1427 	gchar *docname;
1428 	gchar *tab_name;
1429 
1430 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1431 
1432 	doc = gedit_tab_get_document (tab);
1433 
1434 	name = gedit_document_get_short_name_for_display (doc);
1435 
1436 	/* Truncate the name so it doesn't get insanely wide. */
1437 	docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
1438 
1439 	if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
1440 	{
1441 		tab_name = g_strdup_printf ("*%s", docname);
1442 	}
1443 	else
1444 	{
1445 		tab_name = g_strdup (docname);
1446 	}
1447 
1448 	g_free (docname);
1449 	g_free (name);
1450 
1451 	return tab_name;
1452 }
1453 
1454 gchar *
_gedit_tab_get_tooltip(GeditTab * tab)1455 _gedit_tab_get_tooltip (GeditTab *tab)
1456 {
1457 	GeditDocument *doc;
1458 	gchar *tip;
1459 	gchar *uri;
1460 	gchar *ruri;
1461 	gchar *ruri_markup;
1462 
1463 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1464 
1465 	doc = gedit_tab_get_document (tab);
1466 
1467 	uri = _gedit_document_get_uri_for_display (doc);
1468 	g_return_val_if_fail (uri != NULL, NULL);
1469 
1470 	ruri = 	tepl_utils_replace_home_dir_with_tilde (uri);
1471 	g_free (uri);
1472 
1473 	ruri_markup = g_markup_printf_escaped ("<i>%s</i>", ruri);
1474 
1475 	switch (tab->state)
1476 	{
1477 		gchar *content_type;
1478 		gchar *mime_type;
1479 		gchar *content_description;
1480 		gchar *content_full_description;
1481 		gchar *encoding;
1482 		GtkSourceFile *file;
1483 		const GtkSourceEncoding *enc;
1484 
1485 		case GEDIT_TAB_STATE_LOADING_ERROR:
1486 			tip = g_strdup_printf (_("Error opening file %s"),
1487 					       ruri_markup);
1488 			break;
1489 
1490 		case GEDIT_TAB_STATE_REVERTING_ERROR:
1491 			tip = g_strdup_printf (_("Error reverting file %s"),
1492 					       ruri_markup);
1493 			break;
1494 
1495 		case GEDIT_TAB_STATE_SAVING_ERROR:
1496 			tip =  g_strdup_printf (_("Error saving file %s"),
1497 						ruri_markup);
1498 			break;
1499 		default:
1500 			content_type = gedit_document_get_content_type (doc);
1501 			mime_type = gedit_document_get_mime_type (doc);
1502 			content_description = g_content_type_get_description (content_type);
1503 
1504 			if (content_description == NULL)
1505 				content_full_description = g_strdup (mime_type);
1506 			else
1507 				content_full_description = g_strdup_printf ("%s (%s)",
1508 						content_description, mime_type);
1509 
1510 			g_free (content_type);
1511 			g_free (mime_type);
1512 			g_free (content_description);
1513 
1514 			file = gedit_document_get_file (doc);
1515 			enc = gtk_source_file_get_encoding (file);
1516 
1517 			if (enc == NULL)
1518 			{
1519 				enc = gtk_source_encoding_get_utf8 ();
1520 			}
1521 
1522 			encoding = gtk_source_encoding_to_string (enc);
1523 
1524 			tip =  g_markup_printf_escaped ("<b>%s</b> %s\n\n"
1525 						        "<b>%s</b> %s\n"
1526 						        "<b>%s</b> %s",
1527 						        _("Name:"), ruri,
1528 						        _("MIME Type:"), content_full_description,
1529 						        _("Encoding:"), encoding);
1530 
1531 			g_free (encoding);
1532 			g_free (content_full_description);
1533 			break;
1534 	}
1535 
1536 	g_free (ruri);
1537 	g_free (ruri_markup);
1538 
1539 	return tip;
1540 }
1541 
1542 GdkPixbuf *
_gedit_tab_get_icon(GeditTab * tab)1543 _gedit_tab_get_icon (GeditTab *tab)
1544 {
1545 	const gchar *icon_name;
1546 	GdkPixbuf *pixbuf = NULL;
1547 
1548 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1549 
1550 	switch (tab->state)
1551 	{
1552 		case GEDIT_TAB_STATE_PRINTING:
1553 			icon_name = "printer-printing-symbolic";
1554 			break;
1555 
1556 		case GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW:
1557 			icon_name = "printer-symbolic";
1558 			break;
1559 
1560 		case GEDIT_TAB_STATE_LOADING_ERROR:
1561 		case GEDIT_TAB_STATE_REVERTING_ERROR:
1562 		case GEDIT_TAB_STATE_SAVING_ERROR:
1563 		case GEDIT_TAB_STATE_GENERIC_ERROR:
1564 			icon_name = "dialog-error-symbolic";
1565 			break;
1566 
1567 		case GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION:
1568 			icon_name = "dialog-warning-symbolic";
1569 			break;
1570 
1571 		default:
1572 			icon_name = NULL;
1573 	}
1574 
1575 	if (icon_name != NULL)
1576 	{
1577 		GdkScreen *screen;
1578 		GtkIconTheme *theme;
1579 		gint icon_size;
1580 
1581 		screen = gtk_widget_get_screen (GTK_WIDGET (tab));
1582 		theme = gtk_icon_theme_get_for_screen (screen);
1583 		g_return_val_if_fail (theme != NULL, NULL);
1584 
1585 		gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size);
1586 
1587 		pixbuf = gtk_icon_theme_load_icon (theme, icon_name, icon_size, 0, NULL);
1588 	}
1589 
1590 	return pixbuf;
1591 }
1592 
1593 /**
1594  * gedit_tab_get_from_document:
1595  * @doc: a #GeditDocument
1596  *
1597  * Gets the #GeditTab associated with @doc.
1598  *
1599  * Returns: (transfer none): the #GeditTab associated with @doc
1600  */
1601 GeditTab *
gedit_tab_get_from_document(GeditDocument * doc)1602 gedit_tab_get_from_document (GeditDocument *doc)
1603 {
1604 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
1605 
1606 	return g_object_get_data (G_OBJECT (doc), GEDIT_TAB_KEY);
1607 }
1608 
1609 static void
loader_progress_cb(goffset size,goffset total_size,GTask * loading_task)1610 loader_progress_cb (goffset  size,
1611 		    goffset  total_size,
1612 		    GTask   *loading_task)
1613 {
1614 	LoaderData *data = g_task_get_task_data (loading_task);
1615 
1616 	g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_LOADING ||
1617 			  data->tab->state == GEDIT_TAB_STATE_REVERTING);
1618 
1619 	if (should_show_progress_info (&data->timer, size, total_size))
1620 	{
1621 		show_loading_info_bar (loading_task);
1622 		info_bar_set_progress (data->tab, size, total_size);
1623 	}
1624 }
1625 
1626 static void
goto_line(GTask * loading_task)1627 goto_line (GTask *loading_task)
1628 {
1629 	LoaderData *data = g_task_get_task_data (loading_task);
1630 	GeditDocument *doc = gedit_tab_get_document (data->tab);
1631 	GtkTextIter iter;
1632 
1633 	/* Move the cursor at the requested line if any. */
1634 	if (data->line_pos > 0)
1635 	{
1636 		TeplView *view = TEPL_VIEW (gedit_tab_get_view (data->tab));
1637 
1638 		tepl_view_goto_line_offset (view,
1639 					    data->line_pos - 1,
1640 					    MAX (0, data->column_pos - 1));
1641 		return;
1642 	}
1643 
1644 	/* If enabled, move to the position stored in the metadata. */
1645 	if (g_settings_get_boolean (data->tab->editor_settings, GEDIT_SETTINGS_RESTORE_CURSOR_POSITION))
1646 	{
1647 		gchar *pos;
1648 		gint offset;
1649 
1650 		pos = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_POSITION);
1651 
1652 		offset = pos != NULL ? atoi (pos) : 0;
1653 		g_free (pos);
1654 
1655 		gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
1656 						    &iter,
1657 						    MAX (0, offset));
1658 
1659 		/* make sure it's a valid position, if the file
1660 		 * changed we may have ended up in the middle of
1661 		 * a utf8 character cluster */
1662 		if (!gtk_text_iter_is_cursor_position (&iter))
1663 		{
1664 			gtk_text_iter_set_line_offset (&iter, 0);
1665 		}
1666 	}
1667 
1668 	/* Otherwise to the top. */
1669 	else
1670 	{
1671 		gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), &iter);
1672 	}
1673 
1674 	gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
1675 }
1676 
1677 static gboolean
file_already_opened(GeditDocument * doc,GFile * location)1678 file_already_opened (GeditDocument *doc,
1679 		     GFile         *location)
1680 {
1681 	GList *all_documents;
1682 	GList *l;
1683 	gboolean already_opened = FALSE;
1684 
1685 	if (location == NULL)
1686 	{
1687 		return FALSE;
1688 	}
1689 
1690 	all_documents = gedit_app_get_documents (GEDIT_APP (g_application_get_default ()));
1691 
1692 	for (l = all_documents; l != NULL; l = l->next)
1693 	{
1694 		GeditDocument *cur_doc = l->data;
1695 		GtkSourceFile *cur_file;
1696 		GFile *cur_location;
1697 
1698 		if (cur_doc == doc)
1699 		{
1700 			continue;
1701 		}
1702 
1703 		cur_file = gedit_document_get_file (cur_doc);
1704 		cur_location = gtk_source_file_get_location (cur_file);
1705 
1706 		if (cur_location != NULL &&
1707 		    g_file_equal (location, cur_location))
1708 		{
1709 			already_opened = TRUE;
1710 			break;
1711 		}
1712 	}
1713 
1714 	g_list_free (all_documents);
1715 
1716 	return already_opened;
1717 }
1718 
1719 static void
successful_load(GTask * loading_task)1720 successful_load (GTask *loading_task)
1721 {
1722 	LoaderData *data = g_task_get_task_data (loading_task);
1723 	GeditDocument *doc = gedit_tab_get_document (data->tab);
1724 	GtkSourceFile *file = gedit_document_get_file (doc);
1725 	GFile *location;
1726 
1727 	if (data->user_requested_encoding)
1728 	{
1729 		const GtkSourceEncoding *encoding = gtk_source_file_loader_get_encoding (data->loader);
1730 		const gchar *charset = gtk_source_encoding_get_charset (encoding);
1731 
1732 		gedit_document_set_metadata (doc,
1733 					     GEDIT_METADATA_ATTRIBUTE_ENCODING, charset,
1734 					     NULL);
1735 	}
1736 
1737 	goto_line (loading_task);
1738 
1739 	/* Scroll to the cursor when the document is loaded, we need to do it in
1740 	 * an idle as after the document is loaded the textview is still
1741 	 * redrawing and relocating its internals.
1742 	 */
1743 	if (data->tab->idle_scroll == 0)
1744 	{
1745 		data->tab->idle_scroll = g_idle_add ((GSourceFunc)scroll_to_cursor, data->tab);
1746 	}
1747 
1748 	location = gtk_source_file_loader_get_location (data->loader);
1749 
1750 	/* If the document is readonly we don't care how many times the file
1751 	 * is opened.
1752 	 */
1753 	if (!gtk_source_file_is_readonly (file) &&
1754 	    file_already_opened (doc, location))
1755 	{
1756 		TeplInfoBar *info_bar;
1757 
1758 		set_editable (data->tab, FALSE);
1759 
1760 		info_bar = tepl_io_error_info_bar_file_already_open (location);
1761 
1762 		g_signal_connect (info_bar,
1763 				  "response",
1764 				  G_CALLBACK (file_already_open_warning_info_bar_response),
1765 				  data->tab);
1766 
1767 		set_info_bar (data->tab, GTK_WIDGET (info_bar), GTK_RESPONSE_CANCEL);
1768 	}
1769 
1770 	/* When loading from stdin, the contents may not be saved, so set the
1771 	 * buffer as modified.
1772 	 */
1773 	if (location == NULL)
1774 	{
1775 		gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), TRUE);
1776 	}
1777 
1778 	data->tab->ask_if_externally_modified = TRUE;
1779 
1780 	g_signal_emit_by_name (doc, "loaded");
1781 }
1782 
1783 static void
load_cb(GtkSourceFileLoader * loader,GAsyncResult * result,GTask * loading_task)1784 load_cb (GtkSourceFileLoader *loader,
1785 	 GAsyncResult        *result,
1786 	 GTask               *loading_task)
1787 {
1788 	LoaderData *data = g_task_get_task_data (loading_task);
1789 	GeditDocument *doc;
1790 	GFile *location = gtk_source_file_loader_get_location (loader);
1791 	gboolean create_named_new_doc;
1792 	GError *error = NULL;
1793 
1794 	g_clear_pointer (&data->timer, g_timer_destroy);
1795 
1796 	gtk_source_file_loader_load_finish (loader, result, &error);
1797 
1798 	if (error != NULL)
1799 	{
1800 		gedit_debug_message (DEBUG_TAB, "File loading error: %s", error->message);
1801 
1802 		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1803 		{
1804 			g_task_return_boolean (loading_task, FALSE);
1805 			g_object_unref (loading_task);
1806 
1807 			g_error_free (error);
1808 			return;
1809 		}
1810 	}
1811 
1812 	doc = gedit_tab_get_document (data->tab);
1813 
1814 	g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_LOADING ||
1815 			  data->tab->state == GEDIT_TAB_STATE_REVERTING);
1816 
1817 	set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
1818 
1819 	/* Special case creating a named new doc. */
1820 	create_named_new_doc = (_gedit_document_get_create (doc) &&
1821 				g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
1822 				g_file_has_uri_scheme (location, "file"));
1823 
1824 	if (create_named_new_doc)
1825 	{
1826 		g_error_free (error);
1827 		error = NULL;
1828 	}
1829 
1830 	if (g_error_matches (error,
1831 			     GTK_SOURCE_FILE_LOADER_ERROR,
1832 			     GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK))
1833 	{
1834 		GtkWidget *info_bar;
1835 		const GtkSourceEncoding *encoding;
1836 
1837 		/* Set the tab as not editable as we have an error, the user can
1838 		 * decide to make it editable again.
1839 		 */
1840 		set_editable (data->tab, FALSE);
1841 
1842 		encoding = gtk_source_file_loader_get_encoding (loader);
1843 
1844 		info_bar = gedit_io_loading_error_info_bar_new (location, encoding, error);
1845 
1846 		g_signal_connect (info_bar,
1847 				  "response",
1848 				  G_CALLBACK (io_loading_error_info_bar_response),
1849 				  loading_task);
1850 
1851 		set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
1852 
1853 		if (data->tab->state == GEDIT_TAB_STATE_LOADING)
1854 		{
1855 			gtk_widget_show (GTK_WIDGET (data->tab->frame));
1856 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING_ERROR);
1857 		}
1858 		else
1859 		{
1860 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_REVERTING_ERROR);
1861 		}
1862 
1863 		/* The loading was successful, despite some invalid characters. */
1864 		successful_load (loading_task);
1865 		gedit_recent_add_document (doc);
1866 
1867 		g_error_free (error);
1868 		return;
1869 	}
1870 
1871 	if (error != NULL)
1872 	{
1873 		GtkWidget *info_bar;
1874 
1875 		if (data->tab->state == GEDIT_TAB_STATE_LOADING)
1876 		{
1877 			gtk_widget_hide (GTK_WIDGET (data->tab->frame));
1878 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING_ERROR);
1879 		}
1880 		else
1881 		{
1882 			gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_REVERTING_ERROR);
1883 		}
1884 
1885 		if (location != NULL)
1886 		{
1887 			gedit_recent_remove_if_local (location);
1888 		}
1889 
1890 		if (data->tab->state == GEDIT_TAB_STATE_LOADING_ERROR)
1891 		{
1892 			const GtkSourceEncoding *encoding;
1893 
1894 			encoding = gtk_source_file_loader_get_encoding (loader);
1895 
1896 			info_bar = gedit_io_loading_error_info_bar_new (location, encoding, error);
1897 
1898 			g_signal_connect (info_bar,
1899 					  "response",
1900 					  G_CALLBACK (io_loading_error_info_bar_response),
1901 					  loading_task);
1902 		}
1903 		else
1904 		{
1905 			g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_REVERTING_ERROR);
1906 
1907 			info_bar = gedit_unrecoverable_reverting_error_info_bar_new (location, error);
1908 
1909 			g_signal_connect (info_bar,
1910 					  "response",
1911 					  G_CALLBACK (unrecoverable_reverting_error_info_bar_response),
1912 					  loading_task);
1913 		}
1914 
1915 		set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
1916 
1917 		g_error_free (error);
1918 		return;
1919 	}
1920 
1921 	g_assert (error == NULL);
1922 
1923 	gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
1924 	successful_load (loading_task);
1925 
1926 	if (!create_named_new_doc)
1927 	{
1928 		gedit_recent_add_document (doc);
1929 	}
1930 
1931 	g_task_return_boolean (loading_task, TRUE);
1932 	g_object_unref (loading_task);
1933 }
1934 
1935 /* The returned list may contain duplicated encodings. Only the first occurrence
1936  * of a duplicated encoding should be kept, like it is done by
1937  * gtk_source_file_loader_set_candidate_encodings().
1938  */
1939 static GSList *
get_candidate_encodings(GeditTab * tab)1940 get_candidate_encodings (GeditTab *tab)
1941 {
1942 	GSList *candidates = NULL;
1943 	GeditDocument *doc;
1944 	GtkSourceFile *file;
1945 	gchar *metadata_charset;
1946 	const GtkSourceEncoding *file_encoding;
1947 
1948 	candidates = gedit_settings_get_candidate_encodings (NULL);
1949 
1950 	/* Prepend the encoding stored in the metadata. */
1951 	doc = gedit_tab_get_document (tab);
1952 	metadata_charset = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_ENCODING);
1953 
1954 	if (metadata_charset != NULL)
1955 	{
1956 		const GtkSourceEncoding *metadata_enc;
1957 
1958 		metadata_enc = gtk_source_encoding_get_from_charset (metadata_charset);
1959 
1960 		if (metadata_enc != NULL)
1961 		{
1962 			candidates = g_slist_prepend (candidates, (gpointer)metadata_enc);
1963 		}
1964 	}
1965 
1966 	/* Finally prepend the GtkSourceFile's encoding, if previously set by a
1967 	 * file loader or file saver.
1968 	 */
1969 	file = gedit_document_get_file (doc);
1970 	file_encoding = gtk_source_file_get_encoding (file);
1971 
1972 	if (file_encoding != NULL)
1973 	{
1974 		candidates = g_slist_prepend (candidates, (gpointer)file_encoding);
1975 	}
1976 
1977 	g_free (metadata_charset);
1978 	return candidates;
1979 }
1980 
1981 static void
launch_loader(GTask * loading_task,const GtkSourceEncoding * encoding)1982 launch_loader (GTask                   *loading_task,
1983 	       const GtkSourceEncoding *encoding)
1984 {
1985 	LoaderData *data = g_task_get_task_data (loading_task);
1986 	GSList *candidate_encodings = NULL;
1987 	GeditDocument *doc;
1988 
1989 	if (encoding != NULL)
1990 	{
1991 		data->user_requested_encoding = TRUE;
1992 		candidate_encodings = g_slist_append (NULL, (gpointer) encoding);
1993 	}
1994 	else
1995 	{
1996 		data->user_requested_encoding = FALSE;
1997 		candidate_encodings = get_candidate_encodings (data->tab);
1998 	}
1999 
2000 	gtk_source_file_loader_set_candidate_encodings (data->loader, candidate_encodings);
2001 	g_slist_free (candidate_encodings);
2002 
2003 	doc = gedit_tab_get_document (data->tab);
2004 	g_signal_emit_by_name (doc, "load");
2005 
2006 	if (data->timer != NULL)
2007 	{
2008 		g_timer_destroy (data->timer);
2009 	}
2010 
2011 	data->timer = g_timer_new ();
2012 
2013 	gtk_source_file_loader_load_async (data->loader,
2014 					   G_PRIORITY_DEFAULT,
2015 					   g_task_get_cancellable (loading_task),
2016 					   (GFileProgressCallback) loader_progress_cb,
2017 					   loading_task,
2018 					   NULL,
2019 					   (GAsyncReadyCallback) load_cb,
2020 					   loading_task);
2021 }
2022 
2023 static void
load_async(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2024 load_async (GeditTab                *tab,
2025 	    GFile                   *location,
2026 	    const GtkSourceEncoding *encoding,
2027 	    gint                     line_pos,
2028 	    gint                     column_pos,
2029 	    gboolean                 create,
2030 	    GCancellable            *cancellable,
2031 	    GAsyncReadyCallback      callback,
2032 	    gpointer                 user_data)
2033 {
2034 	GeditDocument *doc;
2035 	GtkSourceFile *file;
2036 	GTask *loading_task;
2037 	LoaderData *data;
2038 
2039 	g_return_if_fail (GEDIT_IS_TAB (tab));
2040 	g_return_if_fail (G_IS_FILE (location));
2041 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2042 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2043 
2044 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
2045 
2046 	doc = gedit_tab_get_document (tab);
2047 	file = gedit_document_get_file (doc);
2048 	gtk_source_file_set_location (file, location);
2049 
2050 	loading_task = g_task_new (NULL, cancellable, callback, user_data);
2051 
2052 	data = loader_data_new ();
2053 	g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2054 
2055 	data->tab = tab;
2056 	data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
2057 	data->line_pos = line_pos;
2058 	data->column_pos = column_pos;
2059 
2060 	_gedit_document_set_create (doc, create);
2061 
2062 	launch_loader (loading_task, encoding);
2063 }
2064 
2065 static gboolean
load_finish(GeditTab * tab,GAsyncResult * result)2066 load_finish (GeditTab     *tab,
2067 	     GAsyncResult *result)
2068 {
2069 	g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
2070 
2071 	return g_task_propagate_boolean (G_TASK (result), NULL);
2072 }
2073 
2074 void
_gedit_tab_load(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create)2075 _gedit_tab_load (GeditTab                *tab,
2076 		 GFile                   *location,
2077 		 const GtkSourceEncoding *encoding,
2078 		 gint                     line_pos,
2079 		 gint                     column_pos,
2080 		 gboolean                 create)
2081 {
2082 	if (tab->cancellable != NULL)
2083 	{
2084 		g_cancellable_cancel (tab->cancellable);
2085 		g_object_unref (tab->cancellable);
2086 	}
2087 
2088 	tab->cancellable = g_cancellable_new ();
2089 
2090 	load_async (tab,
2091 		    location,
2092 		    encoding,
2093 		    line_pos,
2094 		    column_pos,
2095 		    create,
2096 		    tab->cancellable,
2097 		    (GAsyncReadyCallback) load_finish,
2098 		    NULL);
2099 }
2100 
2101 static void
load_stream_async(GeditTab * tab,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2102 load_stream_async (GeditTab                *tab,
2103 		   GInputStream            *stream,
2104 		   const GtkSourceEncoding *encoding,
2105 		   gint                     line_pos,
2106 		   gint                     column_pos,
2107 		   GCancellable            *cancellable,
2108 		   GAsyncReadyCallback      callback,
2109 		   gpointer                 user_data)
2110 {
2111 	GeditDocument *doc;
2112 	GtkSourceFile *file;
2113 	GTask *loading_task;
2114 	LoaderData *data;
2115 
2116 	g_return_if_fail (GEDIT_IS_TAB (tab));
2117 	g_return_if_fail (G_IS_INPUT_STREAM (stream));
2118 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2119 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2120 
2121 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
2122 
2123 	doc = gedit_tab_get_document (tab);
2124 	file = gedit_document_get_file (doc);
2125 
2126 	gtk_source_file_set_location (file, NULL);
2127 
2128 	loading_task = g_task_new (NULL, cancellable, callback, user_data);
2129 
2130 	data = loader_data_new ();
2131 	g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2132 
2133 	data->tab = tab;
2134 	data->loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (doc),
2135 							       file,
2136 							       stream);
2137 	data->line_pos = line_pos;
2138 	data->column_pos = column_pos;
2139 
2140 	_gedit_document_set_create (doc, FALSE);
2141 
2142 	launch_loader (loading_task, encoding);
2143 }
2144 
2145 void
_gedit_tab_load_stream(GeditTab * tab,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)2146 _gedit_tab_load_stream (GeditTab                *tab,
2147 			GInputStream            *stream,
2148 			const GtkSourceEncoding *encoding,
2149 			gint                     line_pos,
2150 			gint                     column_pos)
2151 {
2152 	if (tab->cancellable != NULL)
2153 	{
2154 		g_cancellable_cancel (tab->cancellable);
2155 		g_object_unref (tab->cancellable);
2156 	}
2157 
2158 	tab->cancellable = g_cancellable_new ();
2159 
2160 	load_stream_async (tab,
2161 			   stream,
2162 			   encoding,
2163 			   line_pos,
2164 			   column_pos,
2165 			   tab->cancellable,
2166 			   (GAsyncReadyCallback) load_finish,
2167 			   NULL);
2168 }
2169 
2170 static void
revert_async(GeditTab * tab,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2171 revert_async (GeditTab            *tab,
2172 	      GCancellable        *cancellable,
2173 	      GAsyncReadyCallback  callback,
2174 	      gpointer             user_data)
2175 {
2176 	GeditDocument *doc;
2177 	GtkSourceFile *file;
2178 	GFile *location;
2179 	GTask *loading_task;
2180 	LoaderData *data;
2181 
2182 	g_return_if_fail (GEDIT_IS_TAB (tab));
2183 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2184 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2185 	                  tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
2186 
2187 	if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2188 	{
2189 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2190 	}
2191 
2192 	doc = gedit_tab_get_document (tab);
2193 	file = gedit_document_get_file (doc);
2194 	location = gtk_source_file_get_location (file);
2195 	g_return_if_fail (location != NULL);
2196 
2197 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING);
2198 
2199 	loading_task = g_task_new (NULL, cancellable, callback, user_data);
2200 
2201 	data = loader_data_new ();
2202 	g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2203 
2204 	data->tab = tab;
2205 	data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
2206 	data->line_pos = 0;
2207 	data->column_pos = 0;
2208 
2209 	launch_loader (loading_task, NULL);
2210 }
2211 
2212 void
_gedit_tab_revert(GeditTab * tab)2213 _gedit_tab_revert (GeditTab *tab)
2214 {
2215 	if (tab->cancellable != NULL)
2216 	{
2217 		g_cancellable_cancel (tab->cancellable);
2218 		g_object_unref (tab->cancellable);
2219 	}
2220 
2221 	tab->cancellable = g_cancellable_new ();
2222 
2223 	revert_async (tab,
2224 		      tab->cancellable,
2225 		      (GAsyncReadyCallback) load_finish,
2226 		      NULL);
2227 }
2228 
2229 static void
close_printing(GeditTab * tab)2230 close_printing (GeditTab *tab)
2231 {
2232 	if (tab->print_preview != NULL)
2233 	{
2234 		gtk_widget_destroy (tab->print_preview);
2235 	}
2236 
2237 	g_clear_object (&tab->print_job);
2238 	g_clear_object (&tab->print_preview);
2239 
2240 	/* destroy the info bar */
2241 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2242 
2243 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
2244 }
2245 
2246 static void
saver_progress_cb(goffset size,goffset total_size,GTask * saving_task)2247 saver_progress_cb (goffset  size,
2248 		   goffset  total_size,
2249 		   GTask   *saving_task)
2250 {
2251 	GeditTab *tab = g_task_get_source_object (saving_task);
2252 	SaverData *data = g_task_get_task_data (saving_task);
2253 
2254 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_SAVING);
2255 
2256 	if (should_show_progress_info (&data->timer, size, total_size))
2257 	{
2258 		show_saving_info_bar (saving_task);
2259 		info_bar_set_progress (tab, size, total_size);
2260 	}
2261 }
2262 
2263 static void
save_cb(GtkSourceFileSaver * saver,GAsyncResult * result,GTask * saving_task)2264 save_cb (GtkSourceFileSaver *saver,
2265 	 GAsyncResult       *result,
2266 	 GTask              *saving_task)
2267 {
2268 	GeditTab *tab = g_task_get_source_object (saving_task);
2269 	SaverData *data = g_task_get_task_data (saving_task);
2270 	GeditDocument *doc = gedit_tab_get_document (tab);
2271 	GFile *location = gtk_source_file_saver_get_location (saver);
2272 	GError *error = NULL;
2273 
2274 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_SAVING);
2275 
2276 	gtk_source_file_saver_save_finish (saver, result, &error);
2277 
2278 	if (error != NULL)
2279 	{
2280 		gedit_debug_message (DEBUG_TAB, "File saving error: %s", error->message);
2281 	}
2282 
2283 	if (data->timer != NULL)
2284 	{
2285 		g_timer_destroy (data->timer);
2286 		data->timer = NULL;
2287 	}
2288 
2289 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2290 
2291 	if (error != NULL)
2292 	{
2293 		GtkWidget *info_bar;
2294 
2295 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR);
2296 
2297 		if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
2298 		    error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED)
2299 		{
2300 			/* This error is recoverable */
2301 			info_bar = gedit_externally_modified_saving_error_info_bar_new (location, error);
2302 			g_return_if_fail (info_bar != NULL);
2303 
2304 			g_signal_connect (info_bar,
2305 					  "response",
2306 					  G_CALLBACK (externally_modified_error_info_bar_response),
2307 					  saving_task);
2308 		}
2309 		else if (error->domain == G_IO_ERROR &&
2310 			 error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
2311 		{
2312 			/* This error is recoverable */
2313 			info_bar = GTK_WIDGET (tepl_io_error_info_bar_cant_create_backup (location, error));
2314 			g_return_if_fail (info_bar != NULL);
2315 
2316 			g_signal_connect (info_bar,
2317 					  "response",
2318 					  G_CALLBACK (cant_create_backup_error_info_bar_response),
2319 					  saving_task);
2320 		}
2321 		else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
2322 			 error->code == GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS)
2323 		{
2324 			/* If we have any invalid char in the document we must warn the user
2325 			 * as it can make the document useless if it is saved.
2326 			 */
2327 			info_bar = GTK_WIDGET (tepl_io_error_info_bar_invalid_characters (location));
2328 			g_return_if_fail (info_bar != NULL);
2329 
2330 			g_signal_connect (info_bar,
2331 			                  "response",
2332 			                  G_CALLBACK (invalid_character_info_bar_response),
2333 			                  saving_task);
2334 		}
2335 		else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR ||
2336 			 (error->domain == G_IO_ERROR &&
2337 			  error->code != G_IO_ERROR_INVALID_DATA &&
2338 			  error->code != G_IO_ERROR_PARTIAL_INPUT))
2339 		{
2340 			/* These errors are _NOT_ recoverable */
2341 			gedit_recent_remove_if_local (location);
2342 
2343 			info_bar = gedit_unrecoverable_saving_error_info_bar_new (location, error);
2344 			g_return_if_fail (info_bar != NULL);
2345 
2346 			g_signal_connect (info_bar,
2347 					  "response",
2348 					  G_CALLBACK (unrecoverable_saving_error_info_bar_response),
2349 					  saving_task);
2350 		}
2351 		else
2352 		{
2353 			const GtkSourceEncoding *encoding;
2354 
2355 			/* This error is recoverable */
2356 			g_return_if_fail (error->domain == G_CONVERT_ERROR ||
2357 			                  error->domain == G_IO_ERROR);
2358 
2359 			encoding = gtk_source_file_saver_get_encoding (saver);
2360 
2361 			info_bar = gedit_conversion_error_while_saving_info_bar_new (location, encoding, error);
2362 			g_return_if_fail (info_bar != NULL);
2363 
2364 			g_signal_connect (info_bar,
2365 					  "response",
2366 					  G_CALLBACK (recoverable_saving_error_info_bar_response),
2367 					  saving_task);
2368 		}
2369 
2370 		set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
2371 	}
2372 	else
2373 	{
2374 		gedit_recent_add_document (doc);
2375 
2376 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
2377 
2378 		tab->ask_if_externally_modified = TRUE;
2379 
2380 		g_signal_emit_by_name (doc, "saved");
2381 		g_task_return_boolean (saving_task, TRUE);
2382 		g_object_unref (saving_task);
2383 	}
2384 
2385 	if (error != NULL)
2386 	{
2387 		g_error_free (error);
2388 	}
2389 }
2390 
2391 static void
launch_saver(GTask * saving_task)2392 launch_saver (GTask *saving_task)
2393 {
2394 	GeditTab *tab = g_task_get_source_object (saving_task);
2395 	GeditDocument *doc = gedit_tab_get_document (tab);
2396 	SaverData *data = g_task_get_task_data (saving_task);
2397 
2398 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
2399 
2400 	g_signal_emit_by_name (doc, "save");
2401 
2402 	if (data->timer != NULL)
2403 	{
2404 		g_timer_destroy (data->timer);
2405 	}
2406 
2407 	data->timer = g_timer_new ();
2408 
2409 	gtk_source_file_saver_save_async (data->saver,
2410 					  G_PRIORITY_DEFAULT,
2411 					  g_task_get_cancellable (saving_task),
2412 					  (GFileProgressCallback) saver_progress_cb,
2413 					  saving_task,
2414 					  NULL,
2415 					  (GAsyncReadyCallback) save_cb,
2416 					  saving_task);
2417 }
2418 
2419 /* Gets the initial save flags, when launching a new FileSaver. */
2420 static GtkSourceFileSaverFlags
get_initial_save_flags(GeditTab * tab,gboolean auto_save)2421 get_initial_save_flags (GeditTab *tab,
2422 			gboolean  auto_save)
2423 {
2424 	GtkSourceFileSaverFlags save_flags;
2425 	gboolean create_backup;
2426 
2427 	save_flags = tab->save_flags;
2428 
2429 	create_backup = g_settings_get_boolean (tab->editor_settings,
2430 						GEDIT_SETTINGS_CREATE_BACKUP_COPY);
2431 
2432 	/* In case of autosaving, we need to preserve the backup that was produced
2433 	 * the last time the user "manually" saved the file. So we don't set the
2434 	 * CREATE_BACKUP flag for an automatic file saving.
2435 	 */
2436 	if (create_backup && !auto_save)
2437 	{
2438 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
2439 	}
2440 
2441 	return save_flags;
2442 }
2443 
2444 void
_gedit_tab_save_async(GeditTab * tab,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2445 _gedit_tab_save_async (GeditTab            *tab,
2446 		       GCancellable        *cancellable,
2447 		       GAsyncReadyCallback  callback,
2448 		       gpointer             user_data)
2449 {
2450 	GTask *saving_task;
2451 	SaverData *data;
2452 	GeditDocument *doc;
2453 	GtkSourceFile *file;
2454 	GtkSourceFileSaverFlags save_flags;
2455 
2456 	g_return_if_fail (GEDIT_IS_TAB (tab));
2457 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2458 	                  tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
2459 	                  tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2460 
2461 	/* The Save and Save As window actions are insensitive when the print
2462 	 * preview is shown, but it's still possible to save several documents
2463 	 * at once (with the Save All action or when quitting gedit). In that
2464 	 * case, the print preview is simply closed. Handling correctly the
2465 	 * document saving when the print preview is shown is more complicated
2466 	 * and error-prone, it doesn't worth the effort. (the print preview
2467 	 * would need to be updated when the filename changes, dealing with file
2468 	 * saving errors is also more complicated, etc).
2469 	 */
2470 	if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2471 	{
2472 		close_printing (tab);
2473 	}
2474 
2475 	doc = gedit_tab_get_document (tab);
2476 	g_return_if_fail (!gedit_document_is_untitled (doc));
2477 
2478 	saving_task = g_task_new (tab, cancellable, callback, user_data);
2479 
2480 	data = saver_data_new ();
2481 	g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2482 
2483 	save_flags = get_initial_save_flags (tab, FALSE);
2484 
2485 	if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2486 	{
2487 		/* We already told the user about the external modification:
2488 		 * hide the message bar and set the save flag.
2489 		 */
2490 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2491 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
2492 	}
2493 
2494 	file = gedit_document_get_file (doc);
2495 
2496 	data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
2497 
2498 	gtk_source_file_saver_set_flags (data->saver, save_flags);
2499 
2500 	launch_saver (saving_task);
2501 }
2502 
2503 gboolean
_gedit_tab_save_finish(GeditTab * tab,GAsyncResult * result)2504 _gedit_tab_save_finish (GeditTab     *tab,
2505 			GAsyncResult *result)
2506 {
2507 	g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
2508 
2509 	return g_task_propagate_boolean (G_TASK (result), NULL);
2510 }
2511 
2512 static void
auto_save_finished_cb(GeditTab * tab,GAsyncResult * result,gpointer user_data)2513 auto_save_finished_cb (GeditTab     *tab,
2514 		       GAsyncResult *result,
2515 		       gpointer      user_data)
2516 {
2517 	_gedit_tab_save_finish (tab, result);
2518 }
2519 
2520 static gboolean
gedit_tab_auto_save(GeditTab * tab)2521 gedit_tab_auto_save (GeditTab *tab)
2522 {
2523 	GTask *saving_task;
2524 	SaverData *data;
2525 	GeditDocument *doc;
2526 	GtkSourceFile *file;
2527 	GtkSourceFileSaverFlags save_flags;
2528 
2529 	gedit_debug (DEBUG_TAB);
2530 
2531 	doc = gedit_tab_get_document (tab);
2532 	file = gedit_document_get_file (doc);
2533 
2534 	g_return_val_if_fail (!gedit_document_is_untitled (doc), G_SOURCE_REMOVE);
2535 	g_return_val_if_fail (!gtk_source_file_is_readonly (file), G_SOURCE_REMOVE);
2536 
2537 	if (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
2538 	{
2539 		gedit_debug_message (DEBUG_TAB, "Document not modified");
2540 
2541 		return G_SOURCE_CONTINUE;
2542 	}
2543 
2544 	if (tab->state != GEDIT_TAB_STATE_NORMAL)
2545 	{
2546 		gedit_debug_message (DEBUG_TAB, "Retry after 30 seconds");
2547 
2548 		tab->auto_save_timeout = g_timeout_add_seconds (30,
2549 		                                                (GSourceFunc) gedit_tab_auto_save,
2550 		                                                tab);
2551 
2552 		/* Destroy the old timeout. */
2553 		return G_SOURCE_REMOVE;
2554 	}
2555 
2556 	/* Set auto_save_timeout to 0 since the timeout is going to be destroyed */
2557 	tab->auto_save_timeout = 0;
2558 
2559 	saving_task = g_task_new (tab,
2560 				  NULL,
2561 				  (GAsyncReadyCallback) auto_save_finished_cb,
2562 				  NULL);
2563 
2564 	data = saver_data_new ();
2565 	g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2566 
2567 	data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
2568 
2569 	save_flags = get_initial_save_flags (tab, TRUE);
2570 	gtk_source_file_saver_set_flags (data->saver, save_flags);
2571 
2572 	launch_saver (saving_task);
2573 
2574 	return G_SOURCE_REMOVE;
2575 }
2576 
2577 /* Call _gedit_tab_save_finish() in @callback, there is no
2578  * _gedit_tab_save_as_finish().
2579  */
2580 void
_gedit_tab_save_as_async(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,GtkSourceNewlineType newline_type,GtkSourceCompressionType compression_type,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2581 _gedit_tab_save_as_async (GeditTab                 *tab,
2582 			  GFile                    *location,
2583 			  const GtkSourceEncoding  *encoding,
2584 			  GtkSourceNewlineType      newline_type,
2585 			  GtkSourceCompressionType  compression_type,
2586 			  GCancellable             *cancellable,
2587 			  GAsyncReadyCallback       callback,
2588 			  gpointer                  user_data)
2589 {
2590 	GTask *saving_task;
2591 	SaverData *data;
2592 	GeditDocument *doc;
2593 	GtkSourceFile *file;
2594 	GtkSourceFileSaverFlags save_flags;
2595 
2596 	g_return_if_fail (GEDIT_IS_TAB (tab));
2597 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2598 	                  tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
2599 	                  tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2600 	g_return_if_fail (G_IS_FILE (location));
2601 	g_return_if_fail (encoding != NULL);
2602 
2603 	/* See note at _gedit_tab_save_async(). */
2604 	if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2605 	{
2606 		close_printing (tab);
2607 	}
2608 
2609 	saving_task = g_task_new (tab, cancellable, callback, user_data);
2610 
2611 	data = saver_data_new ();
2612 	g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2613 
2614 	doc = gedit_tab_get_document (tab);
2615 
2616 	/* reset the save flags, when saving as */
2617 	tab->save_flags = GTK_SOURCE_FILE_SAVER_FLAGS_NONE;
2618 
2619 	save_flags = get_initial_save_flags (tab, FALSE);
2620 
2621 	if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2622 	{
2623 		/* We already told the user about the external modification:
2624 		 * hide the message bar and set the save flag.
2625 		 */
2626 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2627 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
2628 	}
2629 
2630 	file = gedit_document_get_file (doc);
2631 
2632 	data->saver = gtk_source_file_saver_new_with_target (GTK_SOURCE_BUFFER (doc),
2633 							     file,
2634 							     location);
2635 
2636 	gtk_source_file_saver_set_encoding (data->saver, encoding);
2637 	gtk_source_file_saver_set_newline_type (data->saver, newline_type);
2638 	gtk_source_file_saver_set_compression_type (data->saver, compression_type);
2639 	gtk_source_file_saver_set_flags (data->saver, save_flags);
2640 
2641 	launch_saver (saving_task);
2642 }
2643 
2644 #define GEDIT_PAGE_SETUP_KEY "gedit-page-setup-key"
2645 #define GEDIT_PRINT_SETTINGS_KEY "gedit-print-settings-key"
2646 
2647 static GtkPageSetup *
get_page_setup(GeditTab * tab)2648 get_page_setup (GeditTab *tab)
2649 {
2650 	gpointer data;
2651 	GeditDocument *doc;
2652 
2653 	doc = gedit_tab_get_document (tab);
2654 
2655 	data = g_object_get_data (G_OBJECT (doc),
2656 				  GEDIT_PAGE_SETUP_KEY);
2657 
2658 	if (data == NULL)
2659 	{
2660 		return _gedit_app_get_default_page_setup (GEDIT_APP (g_application_get_default ()));
2661 	}
2662 	else
2663 	{
2664 		return gtk_page_setup_copy (GTK_PAGE_SETUP (data));
2665 	}
2666 }
2667 
2668 static GtkPrintSettings *
get_print_settings(GeditTab * tab)2669 get_print_settings (GeditTab *tab)
2670 {
2671 	gpointer data;
2672 	GeditDocument *doc;
2673 	GtkPrintSettings *settings;
2674 	gchar *name;
2675 
2676 	doc = gedit_tab_get_document (tab);
2677 
2678 	data = g_object_get_data (G_OBJECT (doc),
2679 				  GEDIT_PRINT_SETTINGS_KEY);
2680 
2681 	if (data == NULL)
2682 	{
2683 		settings = _gedit_app_get_default_print_settings (GEDIT_APP (g_application_get_default ()));
2684 	}
2685 	else
2686 	{
2687 		settings = gtk_print_settings_copy (GTK_PRINT_SETTINGS (data));
2688 	}
2689 
2690 	/* Be sure the OUTPUT_URI is unset, because otherwise the
2691 	 * OUTPUT_BASENAME is not taken into account.
2692 	 */
2693 	gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, NULL);
2694 
2695 	name = gedit_document_get_short_name_for_display (doc);
2696 	gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, name);
2697 
2698 	g_free (name);
2699 
2700 	return settings;
2701 }
2702 
2703 /* FIXME: show the info bar only if the operation will be "long" */
2704 static void
printing_cb(GeditPrintJob * job,GeditPrintJobStatus status,GeditTab * tab)2705 printing_cb (GeditPrintJob       *job,
2706 	     GeditPrintJobStatus  status,
2707 	     GeditTab            *tab)
2708 {
2709 	g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
2710 
2711 	gtk_widget_show (tab->info_bar);
2712 
2713 	tepl_progress_info_bar_set_text (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
2714 					 gedit_print_job_get_status_string (job));
2715 
2716 	tepl_progress_info_bar_set_fraction (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
2717 					     gedit_print_job_get_progress (job));
2718 }
2719 
2720 static void
store_print_settings(GeditTab * tab,GeditPrintJob * job)2721 store_print_settings (GeditTab      *tab,
2722 		      GeditPrintJob *job)
2723 {
2724 	GeditDocument *doc;
2725 	GtkPrintSettings *settings;
2726 	GtkPageSetup *page_setup;
2727 
2728 	doc = gedit_tab_get_document (tab);
2729 
2730 	settings = gedit_print_job_get_print_settings (job);
2731 
2732 	/* clear n-copies settings since we do not want to
2733 	 * persist that one */
2734 	gtk_print_settings_unset (settings,
2735 				  GTK_PRINT_SETTINGS_N_COPIES);
2736 
2737 	/* remember settings for this document */
2738 	g_object_set_data_full (G_OBJECT (doc),
2739 				GEDIT_PRINT_SETTINGS_KEY,
2740 				g_object_ref (settings),
2741 				(GDestroyNotify)g_object_unref);
2742 
2743 	/* make them the default */
2744 	_gedit_app_set_default_print_settings (GEDIT_APP (g_application_get_default ()),
2745 					       settings);
2746 
2747 	page_setup = gedit_print_job_get_page_setup (job);
2748 
2749 	/* remember page setup for this document */
2750 	g_object_set_data_full (G_OBJECT (doc),
2751 				GEDIT_PAGE_SETUP_KEY,
2752 				g_object_ref (page_setup),
2753 				(GDestroyNotify)g_object_unref);
2754 
2755 	/* make it the default */
2756 	_gedit_app_set_default_page_setup (GEDIT_APP (g_application_get_default ()),
2757 					   page_setup);
2758 }
2759 
2760 static void
done_printing_cb(GeditPrintJob * job,GeditPrintJobResult result,GError * error,GeditTab * tab)2761 done_printing_cb (GeditPrintJob       *job,
2762 		  GeditPrintJobResult  result,
2763 		  GError              *error,
2764 		  GeditTab            *tab)
2765 {
2766 	GeditView *view;
2767 
2768 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW ||
2769 	                  tab->state == GEDIT_TAB_STATE_PRINTING);
2770 
2771 	if (result == GEDIT_PRINT_JOB_RESULT_OK)
2772 	{
2773 		store_print_settings (tab, job);
2774 	}
2775 
2776 	/* TODO Show the error in an info bar. */
2777 	if (error != NULL)
2778 	{
2779 		g_warning ("Printing error: %s", error->message);
2780 		g_error_free (error);
2781 		error = NULL;
2782 	}
2783 
2784 	close_printing (tab);
2785 
2786 	view = gedit_tab_get_view (tab);
2787 	gtk_widget_grab_focus (GTK_WIDGET (view));
2788 }
2789 
2790 static void
show_preview_cb(GeditPrintJob * job,GeditPrintPreview * preview,GeditTab * tab)2791 show_preview_cb (GeditPrintJob     *job,
2792 		 GeditPrintPreview *preview,
2793 		 GeditTab          *tab)
2794 {
2795 	g_return_if_fail (tab->print_preview == NULL);
2796 
2797 	/* destroy the info bar */
2798 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2799 
2800 	tab->print_preview = GTK_WIDGET (preview);
2801 	g_object_ref_sink (tab->print_preview);
2802 
2803 	gtk_box_pack_end (GTK_BOX (tab), tab->print_preview, TRUE, TRUE, 0);
2804 
2805 	gtk_widget_show (tab->print_preview);
2806 	gtk_widget_grab_focus (tab->print_preview);
2807 
2808 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2809 }
2810 
2811 static void
print_cancelled(GtkWidget * bar,gint response_id,GeditTab * tab)2812 print_cancelled (GtkWidget *bar,
2813 		 gint       response_id,
2814 		 GeditTab  *tab)
2815 {
2816 	gedit_debug (DEBUG_TAB);
2817 
2818 	if (tab->print_job != NULL)
2819 	{
2820 		gedit_print_job_cancel (tab->print_job);
2821 	}
2822 }
2823 
2824 static void
add_printing_info_bar(GeditTab * tab)2825 add_printing_info_bar (GeditTab *tab)
2826 {
2827 	TeplProgressInfoBar *bar;
2828 
2829 	bar = tepl_progress_info_bar_new ("document-print", NULL, TRUE);
2830 
2831 	g_signal_connect (bar,
2832 			  "response",
2833 			  G_CALLBACK (print_cancelled),
2834 			  tab);
2835 
2836 	set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
2837 
2838 	/* hide until we start printing */
2839 	gtk_widget_hide (GTK_WIDGET (bar));
2840 }
2841 
2842 void
_gedit_tab_print(GeditTab * tab)2843 _gedit_tab_print (GeditTab *tab)
2844 {
2845 	GeditView *view;
2846 	GtkPageSetup *setup;
2847 	GtkPrintSettings *settings;
2848 	GtkPrintOperationResult res;
2849 	GError *error = NULL;
2850 
2851 	g_return_if_fail (GEDIT_IS_TAB (tab));
2852 
2853 	/* FIXME: currently we can have just one printoperation going on at a
2854 	 * given time, so before starting the print we close the preview.
2855 	 * Would be nice to handle it properly though.
2856 	 */
2857 	if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2858 	{
2859 		close_printing (tab);
2860 	}
2861 
2862 	g_return_if_fail (tab->print_job == NULL);
2863 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2864 
2865 	view = gedit_tab_get_view (tab);
2866 
2867 	tab->print_job = gedit_print_job_new (view);
2868 
2869 	add_printing_info_bar (tab);
2870 
2871 	g_signal_connect_object (tab->print_job,
2872 				 "printing",
2873 				 G_CALLBACK (printing_cb),
2874 				 tab,
2875 				 0);
2876 
2877 	g_signal_connect_object (tab->print_job,
2878 				 "show-preview",
2879 				 G_CALLBACK (show_preview_cb),
2880 				 tab,
2881 				 0);
2882 
2883 	g_signal_connect_object (tab->print_job,
2884 				 "done",
2885 				 G_CALLBACK (done_printing_cb),
2886 				 tab,
2887 				 0);
2888 
2889 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_PRINTING);
2890 
2891 	setup = get_page_setup (tab);
2892 	settings = get_print_settings (tab);
2893 
2894 	res = gedit_print_job_print (tab->print_job,
2895 				     GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
2896 				     setup,
2897 				     settings,
2898 				     GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))),
2899 				     &error);
2900 
2901 	/* TODO: manage res in the correct way */
2902 	if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
2903 	{
2904 		/* FIXME: go in error state */
2905 		g_warning ("Async print preview failed (%s)", error->message);
2906 		g_error_free (error);
2907 
2908 		close_printing (tab);
2909 	}
2910 
2911 	g_object_unref (setup);
2912 	g_object_unref (settings);
2913 }
2914 
2915 void
_gedit_tab_mark_for_closing(GeditTab * tab)2916 _gedit_tab_mark_for_closing (GeditTab *tab)
2917 {
2918 	g_return_if_fail (GEDIT_IS_TAB (tab));
2919 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2920 
2921 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_CLOSING);
2922 }
2923 
2924 gboolean
_gedit_tab_get_can_close(GeditTab * tab)2925 _gedit_tab_get_can_close (GeditTab *tab)
2926 {
2927 	GeditDocument *doc;
2928 
2929 	g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE);
2930 
2931 	/* if we are loading or reverting, the tab can be closed */
2932 	if (tab->state == GEDIT_TAB_STATE_LOADING ||
2933 	    tab->state == GEDIT_TAB_STATE_LOADING_ERROR ||
2934 	    tab->state == GEDIT_TAB_STATE_REVERTING ||
2935 	    tab->state == GEDIT_TAB_STATE_REVERTING_ERROR) /* CHECK: I'm not sure this is the right behavior for REVERTING ERROR */
2936 	{
2937 		return TRUE;
2938 	}
2939 
2940 	/* Do not close tab with saving errors */
2941 	if (tab->state == GEDIT_TAB_STATE_SAVING_ERROR)
2942 	{
2943 		return FALSE;
2944 	}
2945 
2946 	doc = gedit_tab_get_document (tab);
2947 
2948 	if (_gedit_document_needs_saving (doc))
2949 	{
2950 		return FALSE;
2951 	}
2952 
2953 	return TRUE;
2954 }
2955 
2956 /**
2957  * gedit_tab_get_auto_save_enabled:
2958  * @tab: a #GeditTab
2959  *
2960  * Gets the current state for the autosave feature
2961  *
2962  * Return value: %TRUE if the autosave is enabled, else %FALSE
2963  **/
2964 gboolean
gedit_tab_get_auto_save_enabled(GeditTab * tab)2965 gedit_tab_get_auto_save_enabled	(GeditTab *tab)
2966 {
2967 	gedit_debug (DEBUG_TAB);
2968 
2969 	g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE);
2970 
2971 	return tab->auto_save;
2972 }
2973 
2974 /**
2975  * gedit_tab_set_auto_save_enabled:
2976  * @tab: a #GeditTab
2977  * @enable: enable (%TRUE) or disable (%FALSE) auto save
2978  *
2979  * Enables or disables the autosave feature. It does not install an
2980  * autosave timeout if the document is new or is read-only
2981  **/
2982 void
gedit_tab_set_auto_save_enabled(GeditTab * tab,gboolean enable)2983 gedit_tab_set_auto_save_enabled	(GeditTab *tab,
2984 				 gboolean  enable)
2985 {
2986 	gedit_debug (DEBUG_TAB);
2987 
2988 	g_return_if_fail (GEDIT_IS_TAB (tab));
2989 
2990 	enable = enable != FALSE;
2991 
2992 	if (tab->auto_save != enable)
2993 	{
2994 		tab->auto_save = enable;
2995 		update_auto_save_timeout (tab);
2996 		return;
2997 	}
2998 }
2999 
3000 /**
3001  * gedit_tab_get_auto_save_interval:
3002  * @tab: a #GeditTab
3003  *
3004  * Gets the current interval for the autosaves
3005  *
3006  * Return value: the value of the autosave
3007  **/
3008 gint
gedit_tab_get_auto_save_interval(GeditTab * tab)3009 gedit_tab_get_auto_save_interval (GeditTab *tab)
3010 {
3011 	gedit_debug (DEBUG_TAB);
3012 
3013 	g_return_val_if_fail (GEDIT_IS_TAB (tab), 0);
3014 
3015 	return tab->auto_save_interval;
3016 }
3017 
3018 /**
3019  * gedit_tab_set_auto_save_interval:
3020  * @tab: a #GeditTab
3021  * @interval: the new interval
3022  *
3023  * Sets the interval for the autosave feature.
3024  */
3025 void
gedit_tab_set_auto_save_interval(GeditTab * tab,gint interval)3026 gedit_tab_set_auto_save_interval (GeditTab *tab,
3027 				  gint      interval)
3028 {
3029 	g_return_if_fail (GEDIT_IS_TAB (tab));
3030 	g_return_if_fail (interval > 0);
3031 
3032 	gedit_debug (DEBUG_TAB);
3033 
3034 	if (tab->auto_save_interval != interval)
3035 	{
3036 		tab->auto_save_interval = interval;
3037 		remove_auto_save_timeout (tab);
3038 		update_auto_save_timeout (tab);
3039 	}
3040 }
3041 
3042 void
gedit_tab_set_info_bar(GeditTab * tab,GtkWidget * info_bar)3043 gedit_tab_set_info_bar (GeditTab  *tab,
3044                         GtkWidget *info_bar)
3045 {
3046 	g_return_if_fail (GEDIT_IS_TAB (tab));
3047 	g_return_if_fail (info_bar == NULL || GTK_IS_WIDGET (info_bar));
3048 
3049 	/* FIXME: this can cause problems with the tab state machine */
3050 	set_info_bar (tab, info_bar, GTK_RESPONSE_NONE);
3051 }
3052 
3053 GeditViewFrame *
_gedit_tab_get_view_frame(GeditTab * tab)3054 _gedit_tab_get_view_frame (GeditTab *tab)
3055 {
3056 	return tab->frame;
3057 }
3058 
3059 /* ex:set ts=8 noet: */
3060