1 /*
2  * gedit-commands-file.c
3  * This file is part of gedit
4  *
5  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
6  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
7  * Copyright (C) 2002-2005 Paolo Maggi
8  * Copyright (C) 2014 Sébastien Wilmet
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "config.h"
25 
26 #include "gedit-commands.h"
27 #include "gedit-commands-private.h"
28 
29 #include <glib/gi18n.h>
30 #include <tepl/tepl.h>
31 
32 #include "gedit-app.h"
33 #include "gedit-debug.h"
34 #include "gedit-document.h"
35 #include "gedit-document-private.h"
36 #include "gedit-tab.h"
37 #include "gedit-tab-private.h"
38 #include "gedit-window.h"
39 #include "gedit-window-private.h"
40 #include "gedit-notebook.h"
41 #include "gedit-statusbar.h"
42 #include "gedit-utils.h"
43 #include "gedit-file-chooser-dialog.h"
44 #include "gedit-file-chooser-open.h"
45 #include "gedit-close-confirmation-dialog.h"
46 
47 /* useful macro */
48 #define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
49 #define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
50 
51 #define GEDIT_IS_CLOSING_ALL "gedit-is-closing-all"
52 #define GEDIT_NOTEBOOK_TO_CLOSE "gedit-notebook-to-close"
53 #define GEDIT_IS_QUITTING "gedit-is-quitting"
54 #define GEDIT_IS_QUITTING_ALL "gedit-is-quitting-all"
55 
56 void
_gedit_cmd_file_new(GSimpleAction * action,GVariant * parameter,gpointer user_data)57 _gedit_cmd_file_new (GSimpleAction *action,
58                      GVariant      *parameter,
59                      gpointer       user_data)
60 {
61 	GeditWindow *window = GEDIT_WINDOW (user_data);
62 
63 	gedit_debug (DEBUG_COMMANDS);
64 
65 	gedit_window_create_tab (window, TRUE);
66 }
67 
68 static GeditTab *
get_tab_from_file(GList * docs,GFile * file)69 get_tab_from_file (GList *docs,
70 		   GFile *file)
71 {
72 	GList *l;
73 
74 	for (l = docs; l != NULL; l = l->next)
75 	{
76 		GeditDocument *doc;
77 		GtkSourceFile *source_file;
78 		GFile *location;
79 
80 		doc = l->data;
81 		source_file = gedit_document_get_file (doc);
82 		location = gtk_source_file_get_location (source_file);
83 
84 		if (location != NULL && g_file_equal (location, file))
85 		{
86 			return gedit_tab_get_from_document (doc);
87 		}
88 	}
89 
90 	return NULL;
91 }
92 
93 static gboolean
is_duplicated_file(GSList * files,GFile * file)94 is_duplicated_file (GSList *files,
95 		    GFile  *file)
96 {
97 	GSList *l;
98 
99 	for (l = files; l != NULL; l = l->next)
100 	{
101 		if (g_file_equal (l->data, file))
102 		{
103 			return TRUE;
104 		}
105 	}
106 
107 	return FALSE;
108 }
109 
110 /* File loading */
111 static GSList *
load_file_list(GeditWindow * window,const GSList * files,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create)112 load_file_list (GeditWindow             *window,
113 		const GSList            *files,
114 		const GtkSourceEncoding *encoding,
115 		gint                     line_pos,
116 		gint                     column_pos,
117 		gboolean                 create)
118 {
119 	GList *win_docs;
120 	GSList *files_to_load = NULL;
121 	GSList *loaded_files = NULL;
122 	GeditTab *tab;
123 	gboolean jump_to = TRUE; /* Whether to jump to the new tab */
124 	const GSList *l;
125 	gint num_loaded_files = 0;
126 
127 	gedit_debug (DEBUG_COMMANDS);
128 
129 	win_docs = gedit_window_get_documents (window);
130 
131 	/* Remove the files corresponding to documents already opened in
132 	 * "window" and remove duplicates from the "files" list.
133 	 */
134 	for (l = files; l != NULL; l = l->next)
135 	{
136 		GFile *file = l->data;
137 
138 		if (is_duplicated_file (files_to_load, file))
139 		{
140 			continue;
141 		}
142 
143 		tab = get_tab_from_file (win_docs, file);
144 
145 		if (tab == NULL)
146 		{
147 			files_to_load = g_slist_prepend (files_to_load, file);
148 		}
149 		else
150 		{
151 			if (l == files)
152 			{
153 				TeplView *view;
154 
155 				gedit_window_set_active_tab (window, tab);
156 				jump_to = FALSE;
157 				view = TEPL_VIEW (gedit_tab_get_view (tab));
158 
159 				if (line_pos > 0)
160 				{
161 					if (column_pos > 0)
162 					{
163 						tepl_view_goto_line_offset (view,
164 									    line_pos - 1,
165 									    column_pos - 1);
166 					}
167 					else
168 					{
169 						tepl_view_goto_line (view, line_pos - 1);
170 					}
171 				}
172 			}
173 
174 			++num_loaded_files;
175 			loaded_files = g_slist_prepend (loaded_files,
176 			                                gedit_tab_get_document (tab));
177 		}
178 	}
179 
180 	g_list_free (win_docs);
181 
182 	if (files_to_load == NULL)
183 	{
184 		return g_slist_reverse (loaded_files);
185 	}
186 
187 	files_to_load = g_slist_reverse (files_to_load);
188 	l = files_to_load;
189 
190 	tab = gedit_window_get_active_tab (window);
191 	if (tab != NULL)
192 	{
193 		GeditDocument *doc;
194 
195 		doc = gedit_tab_get_document (tab);
196 
197 		if (tepl_buffer_is_untouched (TEPL_BUFFER (doc)) &&
198 		    gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)
199 		{
200 			_gedit_tab_load (tab,
201 					 l->data,
202 					 encoding,
203 					 line_pos,
204 					 column_pos,
205 					 create);
206 
207 			/* make sure the view has focus */
208 			gtk_widget_grab_focus (GTK_WIDGET (gedit_tab_get_view (tab)));
209 
210 			l = g_slist_next (l);
211 			jump_to = FALSE;
212 
213 			++num_loaded_files;
214 			loaded_files = g_slist_prepend (loaded_files,
215 			                                gedit_tab_get_document (tab));
216 		}
217 	}
218 
219 	while (l != NULL)
220 	{
221 		g_return_val_if_fail (l->data != NULL, NULL);
222 
223 		tab = gedit_window_create_tab_from_location (window,
224 							     l->data,
225 							     encoding,
226 							     line_pos,
227 							     column_pos,
228 							     create,
229 							     jump_to);
230 
231 		if (tab != NULL)
232 		{
233 			jump_to = FALSE;
234 
235 			++num_loaded_files;
236 			loaded_files = g_slist_prepend (loaded_files,
237 			                                gedit_tab_get_document (tab));
238 		}
239 
240 		l = g_slist_next (l);
241 	}
242 
243 	loaded_files = g_slist_reverse (loaded_files);
244 
245 	if (num_loaded_files == 1)
246 	{
247 		GeditDocument *doc;
248 		gchar *uri_for_display;
249 
250 		g_return_val_if_fail (tab != NULL, loaded_files);
251 
252 		doc = gedit_tab_get_document (tab);
253 		uri_for_display = _gedit_document_get_uri_for_display (doc);
254 
255 		gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
256 					       window->priv->generic_message_cid,
257 					       _("Loading file “%s”\342\200\246"),
258 					       uri_for_display);
259 
260 		g_free (uri_for_display);
261 	}
262 	else
263 	{
264 		gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
265 					       window->priv->generic_message_cid,
266 					       ngettext ("Loading %d file\342\200\246",
267 							 "Loading %d files\342\200\246",
268 							 num_loaded_files),
269 					       num_loaded_files);
270 	}
271 
272 	g_slist_free (files_to_load);
273 
274 	return loaded_files;
275 }
276 
277 /**
278  * gedit_commands_load_location:
279  * @window: a #GeditWindow
280  * @location: a #GFile to load
281  * @encoding: (allow-none): the #GtkSourceEncoding of @location
282  * @line_pos: the line position to place the cursor
283  * @column_pos: the line column to place the cursor
284  *
285  * Loads @location. Ignores non-existing locations.
286  */
287 void
gedit_commands_load_location(GeditWindow * window,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)288 gedit_commands_load_location (GeditWindow             *window,
289 			      GFile                   *location,
290 			      const GtkSourceEncoding *encoding,
291 			      gint                     line_pos,
292 			      gint                     column_pos)
293 {
294 	GSList *locations = NULL;
295 	gchar *uri;
296 	GSList *ret;
297 
298 	g_return_if_fail (GEDIT_IS_WINDOW (window));
299 	g_return_if_fail (G_IS_FILE (location));
300 	g_return_if_fail (gedit_utils_is_valid_location (location));
301 
302 	uri = g_file_get_uri (location);
303 	gedit_debug_message (DEBUG_COMMANDS, "Loading URI '%s'", uri);
304 	g_free (uri);
305 
306 	locations = g_slist_prepend (locations, location);
307 
308 	ret = load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
309 	g_slist_free (ret);
310 
311 	g_slist_free (locations);
312 }
313 
314 /**
315  * gedit_commands_load_locations:
316  * @window: a #GeditWindow
317  * @locations: (element-type Gio.File): the locations to load
318  * @encoding: (allow-none): the #GtkSourceEncoding
319  * @line_pos: the line position to place the cursor
320  * @column_pos: the line column to place the cursor
321  *
322  * Loads @locations. Ignore non-existing locations.
323  *
324  * Returns: (element-type Gedit.Document) (transfer container): the locations
325  * that were loaded.
326  */
327 GSList *
gedit_commands_load_locations(GeditWindow * window,const GSList * locations,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)328 gedit_commands_load_locations (GeditWindow             *window,
329 			       const GSList            *locations,
330 			       const GtkSourceEncoding *encoding,
331 			       gint                     line_pos,
332 			       gint                     column_pos)
333 {
334 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
335 	g_return_val_if_fail (locations != NULL && locations->data != NULL, NULL);
336 
337 	gedit_debug (DEBUG_COMMANDS);
338 
339 	return load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
340 }
341 
342 /*
343  * From the command line we can specify a line position for the
344  * first doc. Beside specifying a non-existing file creates a
345  * titled document.
346  */
347 GSList *
_gedit_cmd_load_files_from_prompt(GeditWindow * window,GSList * files,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)348 _gedit_cmd_load_files_from_prompt (GeditWindow             *window,
349 				   GSList                  *files,
350 				   const GtkSourceEncoding *encoding,
351 				   gint                     line_pos,
352 				   gint                     column_pos)
353 {
354 	gedit_debug (DEBUG_COMMANDS);
355 
356 	return load_file_list (window, files, encoding, line_pos, column_pos, TRUE);
357 }
358 
359 static void
file_chooser_open_done_cb(GeditFileChooserOpen * file_chooser,gboolean accept,GeditWindow * window)360 file_chooser_open_done_cb (GeditFileChooserOpen *file_chooser,
361 			   gboolean              accept,
362 			   GeditWindow          *window)
363 {
364 	GSList *files;
365 	const GtkSourceEncoding *encoding;
366 	gchar *folder_uri;
367 	GSList *loaded_documents;
368 
369 	gedit_debug (DEBUG_COMMANDS);
370 
371 	if (!accept)
372 	{
373 		g_object_unref (file_chooser);
374 		return;
375 	}
376 
377 	files = _gedit_file_chooser_open_get_files (file_chooser);
378 	encoding = _gedit_file_chooser_get_encoding (GEDIT_FILE_CHOOSER (file_chooser));
379 	folder_uri = _gedit_file_chooser_get_current_folder_uri (GEDIT_FILE_CHOOSER (file_chooser));
380 	g_object_unref (file_chooser);
381 
382 	if (window == NULL)
383 	{
384 		window = gedit_app_create_window (GEDIT_APP (g_application_get_default ()), NULL);
385 
386 		gtk_widget_show (GTK_WIDGET (window));
387 		gtk_window_present (GTK_WINDOW (window));
388 	}
389 
390 	/* Remember the folder we navigated to. */
391 	_gedit_window_set_file_chooser_folder_uri (window, GTK_FILE_CHOOSER_ACTION_OPEN, folder_uri);
392 	g_free (folder_uri);
393 
394 	loaded_documents = gedit_commands_load_locations (window, files, encoding, 0, 0);
395 
396 	g_slist_free (loaded_documents);
397 	g_slist_free_full (files, g_object_unref);
398 }
399 
400 const gchar*
_get_currrent_doc_location(GeditWindow * window)401 _get_currrent_doc_location (GeditWindow *window)
402 {
403 	GFile *default_path = NULL;
404 	const gchar *default_uri = NULL;
405 
406 	if (window != NULL)
407 	{
408 		GeditDocument *doc;
409 
410 		doc = gedit_window_get_active_document (window);
411 
412 		if (doc != NULL)
413 		{
414 			GtkSourceFile *file = gedit_document_get_file (doc);
415 			GFile *location = gtk_source_file_get_location (file);
416 
417 			if (location != NULL)
418 			{
419 				default_path = g_file_get_parent (location);
420 			}
421 		}
422 
423 		if (default_path != NULL)
424 		{
425 			default_uri = g_file_get_uri(default_path);
426 		}
427 	}
428 
429 	return default_uri;
430 }
431 
432 void
_gedit_cmd_file_open(GSimpleAction * action,GVariant * parameter,gpointer user_data)433 _gedit_cmd_file_open (GSimpleAction *action,
434                       GVariant      *parameter,
435                       gpointer       user_data)
436 {
437 	GeditWindow *window = NULL;
438 	GeditFileChooserOpen *file_chooser;
439 
440 	gedit_debug (DEBUG_COMMANDS);
441 
442 	if (user_data != NULL)
443 	{
444 		window = GEDIT_WINDOW (user_data);
445 	}
446 
447 	const gchar* default_uri = _get_currrent_doc_location (window);
448 
449 	file_chooser = _gedit_file_chooser_open_new ();
450 
451 	if (window != NULL)
452 	{
453 		const gchar *folder_uri;
454 
455 		_gedit_file_chooser_set_transient_for (GEDIT_FILE_CHOOSER (file_chooser),
456 						       GTK_WINDOW (window));
457 
458 		folder_uri = _gedit_window_get_file_chooser_folder_uri (window, GTK_FILE_CHOOSER_ACTION_OPEN);
459 
460 		if (default_uri != NULL)
461 		{
462 			folder_uri = default_uri;
463 		}
464 
465 		if (folder_uri != NULL)
466 		{
467 			_gedit_file_chooser_set_current_folder_uri (GEDIT_FILE_CHOOSER (file_chooser),
468 								    folder_uri);
469 		}
470 	}
471 
472 	g_signal_connect (file_chooser,
473 			  "done",
474 			  G_CALLBACK (file_chooser_open_done_cb),
475 			  window);
476 
477 	_gedit_file_chooser_show (GEDIT_FILE_CHOOSER (file_chooser));
478 }
479 
480 void
_gedit_cmd_file_reopen_closed_tab(GSimpleAction * action,GVariant * parameter,gpointer user_data)481 _gedit_cmd_file_reopen_closed_tab (GSimpleAction *action,
482 				   GVariant      *parameter,
483 				   gpointer       user_data)
484 {
485 	GeditWindow *window = GEDIT_WINDOW (user_data);
486 	GFile *file;
487 
488 	file = _gedit_window_pop_last_closed_doc (window);
489 	if (file != NULL)
490 	{
491 		gedit_commands_load_location (window, file, NULL, 0, 0);
492 	}
493 }
494 
495 /* File saving */
496 
497 /* FIXME: modify this dialog to be similar to the one provided by gtk+ for
498  * already existing files - Paolo (Oct. 11, 2005) */
499 static gboolean
replace_read_only_file(GtkWindow * parent,GFile * file)500 replace_read_only_file (GtkWindow *parent,
501 			GFile     *file)
502 {
503 	GtkWidget *dialog;
504 	gint ret;
505 	gchar *parse_name;
506 	gchar *name_for_display;
507 
508 	gedit_debug (DEBUG_COMMANDS);
509 
510 	parse_name = g_file_get_parse_name (file);
511 
512 	/* Truncate the name so it doesn't get insanely wide. Note that even
513 	 * though the dialog uses wrapped text, if the name doesn't contain
514 	 * white space then the text-wrapping code is too stupid to wrap it.
515 	 */
516 	name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
517 	g_free (parse_name);
518 
519 	dialog = gtk_message_dialog_new (parent,
520 					 GTK_DIALOG_DESTROY_WITH_PARENT,
521 					 GTK_MESSAGE_QUESTION,
522 					 GTK_BUTTONS_NONE,
523 					 _("The file “%s” is read-only."),
524 				         name_for_display);
525 	g_free (name_for_display);
526 
527 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
528 						  _("Do you want to try to replace it "
529 						    "with the one you are saving?"));
530 
531 	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
532 			        _("_Cancel"), GTK_RESPONSE_CANCEL,
533 				_("_Replace"), GTK_RESPONSE_YES,
534 				NULL);
535 
536 	gtk_dialog_set_default_response	(GTK_DIALOG (dialog),
537 					 GTK_RESPONSE_CANCEL);
538 
539 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
540 
541 	ret = gtk_dialog_run (GTK_DIALOG (dialog));
542 
543 	gtk_widget_destroy (dialog);
544 
545 	return ret == GTK_RESPONSE_YES;
546 }
547 
548 static gboolean
change_compression(GtkWindow * parent,GFile * file,gboolean compressed)549 change_compression (GtkWindow *parent,
550                     GFile     *file,
551                     gboolean   compressed)
552 {
553 	GtkWidget *dialog;
554 	gint ret;
555 	gchar *parse_name;
556 	gchar *name_for_display;
557 	const gchar *primary_message;
558 	const gchar *button_label;
559 
560 	gedit_debug (DEBUG_COMMANDS);
561 
562 	parse_name = g_file_get_parse_name (file);
563 
564 	/* Truncate the name so it doesn't get insanely wide. Note that even
565 	 * though the dialog uses wrapped text, if the name doesn't contain
566 	 * white space then the text-wrapping code is too stupid to wrap it.
567 	 */
568 	name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
569 	g_free (parse_name);
570 
571 	if (compressed)
572 	{
573 		primary_message = _("Save the file using compression?");
574 	}
575 	else
576 	{
577 		primary_message = _("Save the file as plain text?");
578 	}
579 
580 	dialog = gtk_message_dialog_new (parent,
581 					 GTK_DIALOG_DESTROY_WITH_PARENT,
582 					 GTK_MESSAGE_QUESTION,
583 					 GTK_BUTTONS_NONE,
584 					 "%s",
585 					 primary_message);
586 
587 	if (compressed)
588 	{
589 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
590 							  _("The file “%s” was previously saved as plain "
591 							    "text and will now be saved using compression."),
592 							  name_for_display);
593 
594 		button_label = _("_Save Using Compression");
595 	}
596 	else
597 	{
598 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
599 							  _("The file “%s” was previously saved "
600 							    "using compression and will now be saved as plain text."),
601 							  name_for_display);
602 		button_label = _("_Save As Plain Text");
603 	}
604 
605 	g_free (name_for_display);
606 
607 	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
608 			        _("_Cancel"), GTK_RESPONSE_CANCEL,
609 				button_label, GTK_RESPONSE_YES,
610 				NULL);
611 
612 	gtk_dialog_set_default_response	(GTK_DIALOG (dialog),
613 					 GTK_RESPONSE_CANCEL);
614 
615 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
616 
617 	ret = gtk_dialog_run (GTK_DIALOG (dialog));
618 
619 	gtk_widget_destroy (dialog);
620 
621 	return ret == GTK_RESPONSE_YES;
622 }
623 
624 static GtkSourceCompressionType
get_compression_type_from_file(GFile * file)625 get_compression_type_from_file (GFile *file)
626 {
627 	gchar *name;
628 	gchar *content_type;
629 	GtkSourceCompressionType type;
630 
631 	name = g_file_get_basename (file);
632 	content_type = g_content_type_guess (name, NULL, 0, NULL);
633 
634 	type = gedit_utils_get_compression_type_from_content_type (content_type);
635 
636 	g_free (name);
637 	g_free (content_type);
638 
639 	return type;
640 }
641 
642 static void
tab_save_as_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)643 tab_save_as_ready_cb (GeditTab     *tab,
644 		      GAsyncResult *result,
645 		      GTask        *task)
646 {
647 	gboolean success = _gedit_tab_save_finish (tab, result);
648 	g_task_return_boolean (task, success);
649 	g_object_unref (task);
650 }
651 
652 static void
save_dialog_response_cb(GeditFileChooserDialog * dialog,gint response_id,GTask * task)653 save_dialog_response_cb (GeditFileChooserDialog *dialog,
654 			 gint                    response_id,
655 			 GTask                  *task)
656 {
657 	GeditTab *tab;
658 	GeditWindow *window;
659 	GeditDocument *doc;
660 	GtkSourceFile *file;
661 	GFile *location;
662 	gchar *parse_name;
663 	GtkSourceNewlineType newline_type;
664 	GtkSourceCompressionType compression_type;
665 	GtkSourceCompressionType current_compression_type;
666 	const GtkSourceEncoding *encoding;
667 
668 	gedit_debug (DEBUG_COMMANDS);
669 
670 	tab = g_task_get_source_object (task);
671 	window = g_task_get_task_data (task);
672 
673 	if (response_id != GTK_RESPONSE_ACCEPT)
674 	{
675 		gedit_file_chooser_dialog_destroy (dialog);
676 		g_task_return_boolean (task, FALSE);
677 		g_object_unref (task);
678 		return;
679 	}
680 
681 	doc = gedit_tab_get_document (tab);
682 	file = gedit_document_get_file (doc);
683 
684 	location = gedit_file_chooser_dialog_get_file (dialog);
685 	g_return_if_fail (location != NULL);
686 
687 	compression_type = get_compression_type_from_file (location);
688 	current_compression_type = gtk_source_file_get_compression_type (file);
689 
690 	if ((compression_type == GTK_SOURCE_COMPRESSION_TYPE_NONE) !=
691 	    (current_compression_type == GTK_SOURCE_COMPRESSION_TYPE_NONE))
692 	{
693 		GtkWindow *dialog_window = gedit_file_chooser_dialog_get_window (dialog);
694 
695 		if (!change_compression (dialog_window,
696 					 location,
697 					 compression_type != GTK_SOURCE_COMPRESSION_TYPE_NONE))
698 		{
699 			gedit_file_chooser_dialog_destroy (dialog);
700 			g_object_unref (location);
701 
702 			g_task_return_boolean (task, FALSE);
703 			g_object_unref (task);
704 			return;
705 		}
706 	}
707 
708 	encoding = gedit_file_chooser_dialog_get_encoding (dialog);
709 	newline_type = gedit_file_chooser_dialog_get_newline_type (dialog);
710 
711 	gedit_file_chooser_dialog_destroy (dialog);
712 
713 	parse_name = g_file_get_parse_name (location);
714 
715 	gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
716 				       window->priv->generic_message_cid,
717 				       _("Saving file “%s”\342\200\246"),
718 				       parse_name);
719 
720 	g_free (parse_name);
721 
722 	/* Let's remember the dir we navigated to, even if the saving fails... */
723 	{
724 		GFile *folder;
725 
726 		folder = g_file_get_parent (location);
727 		if (folder != NULL)
728 		{
729 			gchar *folder_uri;
730 
731 			folder_uri = g_file_get_uri (folder);
732 			_gedit_window_set_file_chooser_folder_uri (window,
733 								   GTK_FILE_CHOOSER_ACTION_SAVE,
734 								   folder_uri);
735 
736 			g_object_unref (folder);
737 			g_free (folder_uri);
738 		}
739 	}
740 
741 	_gedit_tab_save_as_async (tab,
742 				  location,
743 				  encoding,
744 				  newline_type,
745 				  compression_type,
746 				  g_task_get_cancellable (task),
747 				  (GAsyncReadyCallback) tab_save_as_ready_cb,
748 				  task);
749 
750 	g_object_unref (location);
751 }
752 
753 static GtkFileChooserConfirmation
confirm_overwrite_callback(GeditFileChooserDialog * dialog,gpointer data)754 confirm_overwrite_callback (GeditFileChooserDialog *dialog,
755 			    gpointer                data)
756 {
757 	GtkFileChooserConfirmation res;
758 	GFile *file;
759 	GFileInfo *info;
760 
761 	gedit_debug (DEBUG_COMMANDS);
762 
763 	/* fall back to the default confirmation dialog */
764 	res = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
765 
766 	file = gedit_file_chooser_dialog_get_file (dialog);
767 
768 	info = g_file_query_info (file,
769 				  G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
770 				  G_FILE_QUERY_INFO_NONE,
771 				  NULL,
772 				  NULL);
773 
774 	if (info != NULL)
775 	{
776 		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) &&
777 		    !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
778 		{
779 			GtkWindow *win;
780 
781 			win = gedit_file_chooser_dialog_get_window (dialog);
782 
783 			if (replace_read_only_file (win, file))
784 			{
785 				res = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
786 			}
787 			else
788 			{
789 				res = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
790 			}
791 		}
792 
793 		g_object_unref (info);
794 	}
795 
796 	g_object_unref (file);
797 
798 	return res;
799 }
800 
801 /* Call save_as_tab_finish() in @callback. */
802 static void
save_as_tab_async(GeditTab * tab,GeditWindow * window,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)803 save_as_tab_async (GeditTab            *tab,
804 		   GeditWindow         *window,
805 		   GCancellable        *cancellable,
806 		   GAsyncReadyCallback  callback,
807 		   gpointer             user_data)
808 {
809 	GTask *task;
810 	GeditFileChooserDialog *save_dialog;
811 	GtkWindowGroup *window_group;
812 	GtkWindow *dialog_window;
813 	GeditDocument *doc;
814 	GtkSourceFile *file;
815 	GFile *location;
816 	const GtkSourceEncoding *encoding;
817 	GtkSourceNewlineType newline_type;
818 
819 	g_return_if_fail (GEDIT_IS_TAB (tab));
820 	g_return_if_fail (GEDIT_IS_WINDOW (window));
821 
822 	gedit_debug (DEBUG_COMMANDS);
823 
824 	task = g_task_new (tab, cancellable, callback, user_data);
825 	g_task_set_task_data (task, g_object_ref (window), g_object_unref);
826 
827 	/* Translators: "Save As" is the title of the file chooser window. */
828 	save_dialog = gedit_file_chooser_dialog_create (C_("window title", "Save As"),
829 							GTK_WINDOW (window),
830 							_("_Save"),
831 							_("_Cancel"));
832 
833 	gedit_file_chooser_dialog_set_do_overwrite_confirmation (save_dialog, TRUE);
834 
835 	g_signal_connect (save_dialog,
836 			  "confirm-overwrite",
837 			  G_CALLBACK (confirm_overwrite_callback),
838 			  NULL);
839 
840 	window_group = gedit_window_get_group (window);
841 
842 	dialog_window = gedit_file_chooser_dialog_get_window (save_dialog);
843 
844 	if (dialog_window != NULL)
845 	{
846 		gtk_window_group_add_window (window_group, dialog_window);
847 	}
848 
849 	/* Save As dialog is modal to its main window */
850 	gedit_file_chooser_dialog_set_modal (save_dialog, TRUE);
851 
852 	/* Set the suggested file name */
853 	doc = gedit_tab_get_document (tab);
854 	file = gedit_document_get_file (doc);
855 	location = gtk_source_file_get_location (file);
856 
857 	if (location != NULL)
858 	{
859 		gedit_file_chooser_dialog_set_file (save_dialog, location);
860 	}
861 	else
862 	{
863 		const gchar *default_folder_uri;
864 		GFile *default_folder;
865 		gchar *docname;
866 
867 		default_folder_uri = _gedit_window_get_file_chooser_folder_uri (window,
868 										GTK_FILE_CHOOSER_ACTION_SAVE);
869 		if (default_folder_uri != NULL)
870 		{
871 			default_folder = g_file_new_for_uri (default_folder_uri);
872 		}
873 		else
874 		{
875 			/* It's logical to take the home dir by default, and it fixes
876 			 * a problem on MS Windows (hang in C:\windows\system32).
877 			 *
878 			 * FIXME: it would be better to use GtkFileChooserNative
879 			 * to permanently fix the hang problem on MS Windows.
880 			 */
881 			default_folder = g_file_new_for_path (g_get_home_dir ());
882 		}
883 
884 		gedit_file_chooser_dialog_set_current_folder (save_dialog, default_folder);
885 		g_object_unref (default_folder);
886 
887 		docname = gedit_document_get_short_name_for_display (doc);
888 		gedit_file_chooser_dialog_set_current_name (save_dialog, docname);
889 		g_free (docname);
890 	}
891 
892 	/* Set suggested encoding and newline type. */
893 	encoding = gtk_source_file_get_encoding (file);
894 
895 	if (encoding == NULL)
896 	{
897 		encoding = gtk_source_encoding_get_utf8 ();
898 	}
899 
900 	newline_type = gtk_source_file_get_newline_type (file);
901 
902 	gedit_file_chooser_dialog_set_encoding (GEDIT_FILE_CHOOSER_DIALOG (save_dialog),
903 						encoding);
904 
905 	gedit_file_chooser_dialog_set_newline_type (GEDIT_FILE_CHOOSER_DIALOG (save_dialog),
906 	                                            newline_type);
907 
908 	g_signal_connect (save_dialog,
909 			  "response",
910 			  G_CALLBACK (save_dialog_response_cb),
911 			  task);
912 
913 	gedit_file_chooser_dialog_show (save_dialog);
914 }
915 
916 static gboolean
save_as_tab_finish(GeditTab * tab,GAsyncResult * result)917 save_as_tab_finish (GeditTab     *tab,
918 		    GAsyncResult *result)
919 {
920 	g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
921 
922 	return g_task_propagate_boolean (G_TASK (result), NULL);
923 }
924 
925 static void
save_as_tab_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)926 save_as_tab_ready_cb (GeditTab     *tab,
927 		      GAsyncResult *result,
928 		      GTask        *task)
929 {
930 	gboolean success = save_as_tab_finish (tab, result);
931 
932 	g_task_return_boolean (task, success);
933 	g_object_unref (task);
934 }
935 
936 static void
tab_save_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)937 tab_save_ready_cb (GeditTab     *tab,
938 		   GAsyncResult *result,
939 		   GTask        *task)
940 {
941 	gboolean success = _gedit_tab_save_finish (tab, result);
942 
943 	g_task_return_boolean (task, success);
944 	g_object_unref (task);
945 }
946 
947 /**
948  * gedit_commands_save_document_async:
949  * @document: the #GeditDocument to save.
950  * @window: a #GeditWindow.
951  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
952  * @callback: (scope async): a #GAsyncReadyCallback to call when the operation
953  *   is finished.
954  * @user_data: (closure): the data to pass to the @callback function.
955  *
956  * Asynchronously save the @document. @document must belong to @window. The
957  * source object of the async task is @document (which will be the first
958  * parameter of the #GAsyncReadyCallback).
959  *
960  * When the operation is finished, @callback will be called. You can then call
961  * gedit_commands_save_document_finish() to get the result of the operation.
962  *
963  * Since: 3.14
964  */
965 void
gedit_commands_save_document_async(GeditDocument * document,GeditWindow * window,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)966 gedit_commands_save_document_async (GeditDocument       *document,
967 				    GeditWindow         *window,
968 				    GCancellable        *cancellable,
969 				    GAsyncReadyCallback  callback,
970 				    gpointer             user_data)
971 {
972 	GTask *task;
973 	GeditTab *tab;
974 	GtkSourceFile *file;
975 	gchar *uri_for_display;
976 
977 	gedit_debug (DEBUG_COMMANDS);
978 
979 	g_return_if_fail (GEDIT_IS_DOCUMENT (document));
980 	g_return_if_fail (GEDIT_IS_WINDOW (window));
981 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
982 
983 	task = g_task_new (document, cancellable, callback, user_data);
984 
985 	tab = gedit_tab_get_from_document (document);
986 	file = gedit_document_get_file (document);
987 
988 	if (gedit_document_is_untitled (document) ||
989 	    gtk_source_file_is_readonly (file))
990 	{
991 		gedit_debug_message (DEBUG_COMMANDS, "Untitled or Readonly");
992 
993 		save_as_tab_async (tab,
994 				   window,
995 				   cancellable,
996 				   (GAsyncReadyCallback) save_as_tab_ready_cb,
997 				   task);
998 		return;
999 	}
1000 
1001 	uri_for_display = _gedit_document_get_uri_for_display (document);
1002 	gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
1003 				       window->priv->generic_message_cid,
1004 				       _("Saving file “%s”\342\200\246"),
1005 				       uri_for_display);
1006 
1007 	g_free (uri_for_display);
1008 
1009 	_gedit_tab_save_async (tab,
1010 			       cancellable,
1011 			       (GAsyncReadyCallback) tab_save_ready_cb,
1012 			       task);
1013 }
1014 
1015 /**
1016  * gedit_commands_save_document_finish:
1017  * @document: a #GeditDocument.
1018  * @result: a #GAsyncResult.
1019  *
1020  * Finishes an asynchronous document saving operation started with
1021  * gedit_commands_save_document_async().
1022  *
1023  * Note that there is no error parameter because the errors are already handled
1024  * by gedit.
1025  *
1026  * Returns: %TRUE if the document has been correctly saved, %FALSE otherwise.
1027  * Since: 3.14
1028  */
1029 gboolean
gedit_commands_save_document_finish(GeditDocument * document,GAsyncResult * result)1030 gedit_commands_save_document_finish (GeditDocument *document,
1031 				     GAsyncResult  *result)
1032 {
1033 	g_return_val_if_fail (g_task_is_valid (result, document), FALSE);
1034 
1035 	return g_task_propagate_boolean (G_TASK (result), NULL);
1036 }
1037 
1038 static void
save_tab_ready_cb(GeditDocument * doc,GAsyncResult * result,gpointer user_data)1039 save_tab_ready_cb (GeditDocument *doc,
1040 		   GAsyncResult  *result,
1041 		   gpointer       user_data)
1042 {
1043 	gedit_commands_save_document_finish (doc, result);
1044 }
1045 
1046 /* Save tab asynchronously, but without results. */
1047 static void
save_tab(GeditTab * tab,GeditWindow * window)1048 save_tab (GeditTab    *tab,
1049 	  GeditWindow *window)
1050 {
1051 	GeditDocument *doc = gedit_tab_get_document (tab);
1052 
1053 	gedit_commands_save_document_async (doc,
1054 					    window,
1055 					    NULL,
1056 					    (GAsyncReadyCallback) save_tab_ready_cb,
1057 					    NULL);
1058 }
1059 
1060 void
_gedit_cmd_file_save(GSimpleAction * action,GVariant * parameter,gpointer user_data)1061 _gedit_cmd_file_save (GSimpleAction *action,
1062                       GVariant      *parameter,
1063                       gpointer       user_data)
1064 {
1065 	GeditWindow *window = GEDIT_WINDOW (user_data);
1066 	GeditTab *tab;
1067 
1068 	gedit_debug (DEBUG_COMMANDS);
1069 
1070 	tab = gedit_window_get_active_tab (window);
1071 	if (tab != NULL)
1072 	{
1073 		save_tab (tab, window);
1074 	}
1075 }
1076 
1077 static void
_gedit_cmd_file_save_as_cb(GeditTab * tab,GAsyncResult * result,gpointer user_data)1078 _gedit_cmd_file_save_as_cb (GeditTab     *tab,
1079 			    GAsyncResult *result,
1080 			    gpointer      user_data)
1081 {
1082 	save_as_tab_finish (tab, result);
1083 }
1084 
1085 void
_gedit_cmd_file_save_as(GSimpleAction * action,GVariant * parameter,gpointer user_data)1086 _gedit_cmd_file_save_as (GSimpleAction *action,
1087                          GVariant      *parameter,
1088                          gpointer       user_data)
1089 {
1090 	GeditWindow *window = GEDIT_WINDOW (user_data);
1091 	GeditTab *tab;
1092 
1093 	gedit_debug (DEBUG_COMMANDS);
1094 
1095 	tab = gedit_window_get_active_tab (window);
1096 	if (tab != NULL)
1097 	{
1098 		save_as_tab_async (tab,
1099 				   window,
1100 				   NULL,
1101 				   (GAsyncReadyCallback) _gedit_cmd_file_save_as_cb,
1102 				   NULL);
1103 	}
1104 }
1105 
1106 static void
quit_if_needed(GeditWindow * window)1107 quit_if_needed (GeditWindow *window)
1108 {
1109 	gboolean is_quitting;
1110 	gboolean is_quitting_all;
1111 
1112 	is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1113 							      GEDIT_IS_QUITTING));
1114 
1115 	is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1116 							          GEDIT_IS_QUITTING_ALL));
1117 
1118 	if (is_quitting)
1119 	{
1120 		gtk_widget_destroy (GTK_WIDGET (window));
1121 	}
1122 
1123 	if (is_quitting_all)
1124 	{
1125 		GtkApplication *app;
1126 
1127 		app = GTK_APPLICATION (g_application_get_default ());
1128 
1129 		if (gtk_application_get_windows (app) == NULL)
1130 		{
1131 			g_application_quit (G_APPLICATION (app));
1132 		}
1133 	}
1134 }
1135 
1136 static gboolean
really_close_tab(GeditTab * tab)1137 really_close_tab (GeditTab *tab)
1138 {
1139 	GtkWidget *toplevel;
1140 	GeditWindow *window;
1141 
1142 	gedit_debug (DEBUG_COMMANDS);
1143 
1144 	g_return_val_if_fail (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_CLOSING,
1145 			      FALSE);
1146 
1147 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
1148 	g_return_val_if_fail (GEDIT_IS_WINDOW (toplevel), FALSE);
1149 
1150 	window = GEDIT_WINDOW (toplevel);
1151 
1152 	gedit_window_close_tab (window, tab);
1153 
1154 	if (gedit_window_get_active_tab (window) == NULL)
1155 	{
1156 		quit_if_needed (window);
1157 	}
1158 
1159 	return FALSE;
1160 }
1161 
1162 static void
close_tab(GeditTab * tab)1163 close_tab (GeditTab *tab)
1164 {
1165 	GeditDocument *doc;
1166 
1167 	doc = gedit_tab_get_document (tab);
1168 	g_return_if_fail (doc != NULL);
1169 
1170 	/* If the user has modified again the document, do not close the tab. */
1171 	if (_gedit_document_needs_saving (doc))
1172 	{
1173 		return;
1174 	}
1175 
1176 	/* Close the document only if it has been succesfully saved.
1177 	 * Tab state is set to CLOSING (it is a state without exiting
1178 	 * transitions) and the tab is closed in an idle handler.
1179 	 */
1180 	_gedit_tab_mark_for_closing (tab);
1181 
1182 	g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1183 			 (GSourceFunc) really_close_tab,
1184 			 tab,
1185 			 NULL);
1186 }
1187 
1188 typedef struct _SaveAsData SaveAsData;
1189 
1190 struct _SaveAsData
1191 {
1192 	/* Reffed */
1193 	GeditWindow *window;
1194 
1195 	/* List of reffed GeditTab's */
1196 	GSList *tabs_to_save_as;
1197 
1198 	guint close_tabs : 1;
1199 };
1200 
1201 static void save_as_documents_list (SaveAsData *data);
1202 
1203 static void
save_as_documents_list_cb(GeditTab * tab,GAsyncResult * result,SaveAsData * data)1204 save_as_documents_list_cb (GeditTab     *tab,
1205 			   GAsyncResult *result,
1206 			   SaveAsData   *data)
1207 {
1208 	gboolean saved = save_as_tab_finish (tab, result);
1209 
1210 	if (saved && data->close_tabs)
1211 	{
1212 		close_tab (tab);
1213 	}
1214 
1215 	g_return_if_fail (tab == GEDIT_TAB (data->tabs_to_save_as->data));
1216 	g_object_unref (data->tabs_to_save_as->data);
1217 	data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as,
1218 						     data->tabs_to_save_as);
1219 
1220 	if (data->tabs_to_save_as != NULL)
1221 	{
1222 		save_as_documents_list (data);
1223 	}
1224 	else
1225 	{
1226 		g_object_unref (data->window);
1227 		g_slice_free (SaveAsData, data);
1228 	}
1229 }
1230 
1231 static void
save_as_documents_list(SaveAsData * data)1232 save_as_documents_list (SaveAsData *data)
1233 {
1234 	GeditTab *next_tab = GEDIT_TAB (data->tabs_to_save_as->data);
1235 
1236 	gedit_window_set_active_tab (data->window, next_tab);
1237 
1238 	save_as_tab_async (next_tab,
1239 			   data->window,
1240 			   NULL,
1241 			   (GAsyncReadyCallback) save_as_documents_list_cb,
1242 			   data);
1243 }
1244 
1245 /*
1246  * The docs in the list must belong to the same GeditWindow.
1247  */
1248 static void
save_documents_list(GeditWindow * window,GList * docs)1249 save_documents_list (GeditWindow *window,
1250 		     GList       *docs)
1251 {
1252 	SaveAsData *data = NULL;
1253 	GList *l;
1254 
1255 	gedit_debug (DEBUG_COMMANDS);
1256 
1257 	g_return_if_fail ((gedit_window_get_state (window) & GEDIT_WINDOW_STATE_PRINTING) == 0);
1258 
1259 	for (l = docs; l != NULL; l = l->next)
1260 	{
1261 		GeditDocument *doc;
1262 		GeditTab *tab;
1263 		GeditTabState state;
1264 
1265 		g_return_if_fail (GEDIT_IS_DOCUMENT (l->data));
1266 		doc = l->data;
1267 
1268 		tab = gedit_tab_get_from_document (doc);
1269 		state = gedit_tab_get_state (tab);
1270 
1271 		g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING);
1272 		g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING);
1273 
1274 		if (state == GEDIT_TAB_STATE_NORMAL ||
1275 		    state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
1276 		{
1277 			if (_gedit_document_needs_saving (doc))
1278 			{
1279 				GtkSourceFile *file = gedit_document_get_file (doc);
1280 
1281 				/* FIXME: manage the case of local readonly files owned by the
1282 				   user is running gedit - Paolo (Dec. 8, 2005) */
1283 				if (gedit_document_is_untitled (doc) ||
1284 				    gtk_source_file_is_readonly (file))
1285 				{
1286 					if (data == NULL)
1287 					{
1288 						data = g_slice_new (SaveAsData);
1289 						data->window = g_object_ref (window);
1290 						data->tabs_to_save_as = NULL;
1291 						data->close_tabs = FALSE;
1292 					}
1293 
1294 					data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as,
1295 										 g_object_ref (tab));
1296 				}
1297 				else
1298 				{
1299 					save_tab (tab, window);
1300 				}
1301 			}
1302 		}
1303 		else
1304 		{
1305 			/* If the state is:
1306 			   - GEDIT_TAB_STATE_LOADING: we do not save since we are sure the file is unmodified
1307 			   - GEDIT_TAB_STATE_REVERTING: we do not save since the user wants
1308 			     to return back to the version of the file she previously saved
1309 			   - GEDIT_TAB_STATE_SAVING: well, we are already saving (no need to save again)
1310 			   - GEDIT_TAB_STATE_PRINTING: there is not a
1311 			     real reason for not saving in this case, we do not save to avoid to run
1312 			     two operations using the message area at the same time (may be we can remove
1313 			     this limitation in the future). Note that SaveAll, ClosAll
1314 			     and Quit are unsensitive if the window state is PRINTING.
1315 			   - GEDIT_TAB_STATE_GENERIC_ERROR: we do not save since the document contains
1316 			     errors (I don't think this is a very frequent case, we should probably remove
1317 			     this state)
1318 			   - GEDIT_TAB_STATE_LOADING_ERROR: there is nothing to save
1319 			   - GEDIT_TAB_STATE_REVERTING_ERROR: there is nothing to save and saving the current
1320 			     document will overwrite the copy of the file the user wants to go back to
1321 			   - GEDIT_TAB_STATE_SAVING_ERROR: we do not save since we just failed to save, so there is
1322 			     no reason to automatically retry... we wait for user intervention
1323 			   - GEDIT_TAB_STATE_CLOSING: this state is invalid in this case
1324 			*/
1325 
1326 			gchar *uri_for_display;
1327 
1328 			uri_for_display = _gedit_document_get_uri_for_display (doc);
1329 			gedit_debug_message (DEBUG_COMMANDS,
1330 					     "File '%s' not saved. State: %d",
1331 					     uri_for_display,
1332 					     state);
1333 			g_free (uri_for_display);
1334 		}
1335 	}
1336 
1337 	if (data != NULL)
1338 	{
1339 		data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
1340 		save_as_documents_list (data);
1341 	}
1342 }
1343 
1344 /**
1345  * gedit_commands_save_all_documents:
1346  * @window: a #GeditWindow.
1347  *
1348  * Asynchronously save all documents belonging to @window. The result of the
1349  * operation is not available, so it's difficult to know whether all the
1350  * documents are correctly saved.
1351  */
1352 void
gedit_commands_save_all_documents(GeditWindow * window)1353 gedit_commands_save_all_documents (GeditWindow *window)
1354 {
1355 	GList *docs;
1356 
1357 	g_return_if_fail (GEDIT_IS_WINDOW (window));
1358 
1359 	gedit_debug (DEBUG_COMMANDS);
1360 
1361 	docs = gedit_window_get_documents (window);
1362 
1363 	save_documents_list (window, docs);
1364 
1365 	g_list_free (docs);
1366 }
1367 
1368 void
_gedit_cmd_file_save_all(GSimpleAction * action,GVariant * parameter,gpointer user_data)1369 _gedit_cmd_file_save_all (GSimpleAction *action,
1370                           GVariant      *parameter,
1371                           gpointer       user_data)
1372 {
1373 	gedit_commands_save_all_documents (GEDIT_WINDOW (user_data));
1374 }
1375 
1376 /**
1377  * gedit_commands_save_document:
1378  * @window: a #GeditWindow.
1379  * @document: the #GeditDocument to save.
1380  *
1381  * Asynchronously save @document. @document must belong to @window. If you need
1382  * the result of the operation, use gedit_commands_save_document_async().
1383  */
1384 void
gedit_commands_save_document(GeditWindow * window,GeditDocument * document)1385 gedit_commands_save_document (GeditWindow   *window,
1386                               GeditDocument *document)
1387 {
1388 	GeditTab *tab;
1389 
1390 	g_return_if_fail (GEDIT_IS_WINDOW (window));
1391 	g_return_if_fail (GEDIT_IS_DOCUMENT (document));
1392 
1393 	gedit_debug (DEBUG_COMMANDS);
1394 
1395 	tab = gedit_tab_get_from_document (document);
1396 	save_tab (tab, window);
1397 }
1398 
1399 /* File revert */
1400 static void
do_revert(GeditWindow * window,GeditTab * tab)1401 do_revert (GeditWindow *window,
1402 	   GeditTab    *tab)
1403 {
1404 	GeditDocument *doc;
1405 	gchar *docname;
1406 
1407 	gedit_debug (DEBUG_COMMANDS);
1408 
1409 	doc = gedit_tab_get_document (tab);
1410 	docname = gedit_document_get_short_name_for_display (doc);
1411 
1412 	gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
1413 				       window->priv->generic_message_cid,
1414 				       _("Reverting the document “%s”\342\200\246"),
1415 				       docname);
1416 
1417 	g_free (docname);
1418 
1419 	_gedit_tab_revert (tab);
1420 }
1421 
1422 static void
revert_dialog_response_cb(GtkDialog * dialog,gint response_id,GeditWindow * window)1423 revert_dialog_response_cb (GtkDialog   *dialog,
1424 			   gint         response_id,
1425 			   GeditWindow *window)
1426 {
1427 	GeditTab *tab;
1428 
1429 	gedit_debug (DEBUG_COMMANDS);
1430 
1431 	/* FIXME: we are relying on the fact that the dialog is
1432 	   modal so the active tab can't be changed...
1433 	   not very nice - Paolo (Oct 11, 2005) */
1434 	tab = gedit_window_get_active_tab (window);
1435 	if (tab == NULL)
1436 	{
1437 		return;
1438 	}
1439 
1440 	gtk_widget_destroy (GTK_WIDGET (dialog));
1441 
1442 	if (response_id == GTK_RESPONSE_OK)
1443 	{
1444 		do_revert (window, tab);
1445 	}
1446 }
1447 
1448 static GtkWidget *
revert_dialog(GeditWindow * window,GeditDocument * doc)1449 revert_dialog (GeditWindow   *window,
1450 	       GeditDocument *doc)
1451 {
1452 	GtkWidget *dialog;
1453 	gchar *docname;
1454 	gchar *primary_msg;
1455 	gchar *secondary_msg;
1456 	glong seconds;
1457 
1458 	gedit_debug (DEBUG_COMMANDS);
1459 
1460 	docname = gedit_document_get_short_name_for_display (doc);
1461 	primary_msg = g_strdup_printf (_("Revert unsaved changes to document “%s”?"),
1462 	                               docname);
1463 	g_free (docname);
1464 
1465 	seconds = MAX (1, _gedit_document_get_seconds_since_last_save_or_load (doc));
1466 
1467 	if (seconds < 55)
1468 	{
1469 		secondary_msg = g_strdup_printf (
1470 					ngettext ("Changes made to the document in the last %ld second "
1471 					    	  "will be permanently lost.",
1472 						  "Changes made to the document in the last %ld seconds "
1473 					    	  "will be permanently lost.",
1474 						  seconds),
1475 					seconds);
1476 	}
1477 	else if (seconds < 75) /* 55 <= seconds < 75 */
1478 	{
1479 		secondary_msg = g_strdup (_("Changes made to the document in the last minute "
1480 					    "will be permanently lost."));
1481 	}
1482 	else if (seconds < 110) /* 75 <= seconds < 110 */
1483 	{
1484 		secondary_msg = g_strdup_printf (
1485 					ngettext ("Changes made to the document in the last minute and "
1486 						  "%ld second will be permanently lost.",
1487 						  "Changes made to the document in the last minute and "
1488 						  "%ld seconds will be permanently lost.",
1489 						  seconds - 60 ),
1490 					seconds - 60);
1491 	}
1492 	else if (seconds < 3600)
1493 	{
1494 		secondary_msg = g_strdup_printf (
1495 					ngettext ("Changes made to the document in the last %ld minute "
1496 					    	  "will be permanently lost.",
1497 						  "Changes made to the document in the last %ld minutes "
1498 					    	  "will be permanently lost.",
1499 						  seconds / 60),
1500 					seconds / 60);
1501 	}
1502 	else if (seconds < 7200)
1503 	{
1504 		gint minutes;
1505 		seconds -= 3600;
1506 
1507 		minutes = seconds / 60;
1508 		if (minutes < 5)
1509 		{
1510 			secondary_msg = g_strdup (_("Changes made to the document in the last hour "
1511 						    "will be permanently lost."));
1512 		}
1513 		else
1514 		{
1515 			secondary_msg = g_strdup_printf (
1516 					ngettext ("Changes made to the document in the last hour and "
1517 						  "%d minute will be permanently lost.",
1518 						  "Changes made to the document in the last hour and "
1519 						  "%d minutes will be permanently lost.",
1520 						  minutes),
1521 					minutes);
1522 		}
1523 	}
1524 	else
1525 	{
1526 		gint hours;
1527 
1528 		hours = seconds / 3600;
1529 
1530 		secondary_msg = g_strdup_printf (
1531 					ngettext ("Changes made to the document in the last %d hour "
1532 					    	  "will be permanently lost.",
1533 						  "Changes made to the document in the last %d hours "
1534 					    	  "will be permanently lost.",
1535 						  hours),
1536 					hours);
1537 	}
1538 
1539 	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
1540 					 GTK_DIALOG_DESTROY_WITH_PARENT,
1541 					 GTK_MESSAGE_QUESTION,
1542 					 GTK_BUTTONS_NONE,
1543 					 "%s", primary_msg);
1544 
1545 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1546 						  "%s", secondary_msg);
1547 	g_free (primary_msg);
1548 	g_free (secondary_msg);
1549 
1550 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1551 
1552 	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
1553 			        _("_Cancel"), GTK_RESPONSE_CANCEL,
1554 				_("_Revert"), GTK_RESPONSE_OK,
1555 				NULL);
1556 
1557 	gtk_dialog_set_default_response	(GTK_DIALOG (dialog),
1558 					 GTK_RESPONSE_CANCEL);
1559 
1560 	return dialog;
1561 }
1562 
1563 void
_gedit_cmd_file_revert(GSimpleAction * action,GVariant * parameter,gpointer user_data)1564 _gedit_cmd_file_revert (GSimpleAction *action,
1565                         GVariant      *parameter,
1566                         gpointer       user_data)
1567 {
1568 	GeditWindow *window = GEDIT_WINDOW (user_data);
1569 	GeditTab *tab;
1570 	GeditDocument *doc;
1571 	GtkWidget *dialog;
1572 	GtkWindowGroup *window_group;
1573 
1574 	gedit_debug (DEBUG_COMMANDS);
1575 
1576 	tab = gedit_window_get_active_tab (window);
1577 	g_return_if_fail (tab != NULL);
1578 
1579 	/* If we are already displaying a notification reverting will drop local
1580 	 * modifications or if the document has not been modified, do not bug
1581 	 * the user further.
1582 	 */
1583 	if (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
1584 	    _gedit_tab_get_can_close (tab))
1585 	{
1586 		do_revert (window, tab);
1587 		return;
1588 	}
1589 
1590 	doc = gedit_tab_get_document (tab);
1591 	g_return_if_fail (doc != NULL);
1592 	g_return_if_fail (!gedit_document_is_untitled (doc));
1593 
1594 	dialog = revert_dialog (window, doc);
1595 
1596 	window_group = gedit_window_get_group (window);
1597 
1598 	gtk_window_group_add_window (window_group, GTK_WINDOW (dialog));
1599 
1600 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1601 
1602 	g_signal_connect (dialog,
1603 			  "response",
1604 			  G_CALLBACK (revert_dialog_response_cb),
1605 			  window);
1606 
1607 	gtk_widget_show (dialog);
1608 }
1609 
1610 static void
tab_state_changed_while_saving(GeditTab * tab,GParamSpec * pspec,GeditWindow * window)1611 tab_state_changed_while_saving (GeditTab    *tab,
1612 				GParamSpec  *pspec,
1613 				GeditWindow *window)
1614 {
1615 	GeditTabState state;
1616 
1617 	state = gedit_tab_get_state (tab);
1618 
1619 	gedit_debug_message (DEBUG_COMMANDS, "State while saving: %d\n", state);
1620 
1621 	/* When the state becomes NORMAL, it means the saving operation is
1622 	 * finished.
1623 	 */
1624 	if (state == GEDIT_TAB_STATE_NORMAL)
1625 	{
1626 		g_signal_handlers_disconnect_by_func (tab,
1627 						      G_CALLBACK (tab_state_changed_while_saving),
1628 					      	      window);
1629 
1630 		close_tab (tab);
1631 	}
1632 }
1633 
1634 static void
save_and_close(GeditTab * tab,GeditWindow * window)1635 save_and_close (GeditTab    *tab,
1636 		GeditWindow *window)
1637 {
1638 	gedit_debug (DEBUG_COMMANDS);
1639 
1640 	/* Trace tab state changes */
1641 	g_signal_connect (tab,
1642 			  "notify::state",
1643 			  G_CALLBACK (tab_state_changed_while_saving),
1644 			  window);
1645 
1646 	save_tab (tab, window);
1647 }
1648 
1649 static void
save_and_close_documents(GList * docs,GeditWindow * window,GeditNotebook * notebook)1650 save_and_close_documents (GList         *docs,
1651                           GeditWindow   *window,
1652                           GeditNotebook *notebook)
1653 {
1654 	GList *tabs;
1655 	GList *l;
1656 	GSList *sl;
1657 	SaveAsData *data = NULL;
1658 	GSList *tabs_to_save_and_close = NULL;
1659 	GList *tabs_to_close = NULL;
1660 
1661 	gedit_debug (DEBUG_COMMANDS);
1662 
1663 	g_return_if_fail ((gedit_window_get_state (window) & GEDIT_WINDOW_STATE_PRINTING) == 0);
1664 
1665 	if (notebook != NULL)
1666 	{
1667 		tabs = gtk_container_get_children (GTK_CONTAINER (notebook));
1668 	}
1669 	else
1670 	{
1671 		tabs = _gedit_window_get_all_tabs (window);
1672 	}
1673 
1674 	for (l = tabs; l != NULL; l = l->next)
1675 	{
1676 		GeditTab *tab = GEDIT_TAB (l->data);
1677 		GeditTabState state;
1678 		GeditDocument *doc;
1679 
1680 		state = gedit_tab_get_state (tab);
1681 		doc = gedit_tab_get_document (tab);
1682 
1683 		/* If the state is: ([*] invalid states)
1684 		   - GEDIT_TAB_STATE_NORMAL: close (and if needed save)
1685 		   - GEDIT_TAB_STATE_LOADING: close, we are sure the file is unmodified
1686 		   - GEDIT_TAB_STATE_REVERTING: since the user wants
1687 		     to return back to the version of the file she previously saved, we can close
1688 		     without saving (CHECK: are we sure this is the right behavior, suppose the case
1689 		     the original file has been deleted)
1690 		   - [*] GEDIT_TAB_STATE_SAVING: invalid, ClosAll
1691 		     and Quit are unsensitive if the window state is SAVING.
1692 		   - [*] GEDIT_TAB_STATE_PRINTING: there is not a
1693 		     real reason for not closing in this case, we do not save to avoid to run
1694 		     two operations using the message area at the same time (may be we can remove
1695 		     this limitation in the future). Note that ClosAll
1696 		     and Quit are unsensitive if the window state is PRINTING.
1697 		   - GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW: close (and if needed save)
1698 		   - GEDIT_TAB_STATE_LOADING_ERROR: close without saving (if the state is LOADING_ERROR then the
1699 		     document is not modified)
1700 		   - GEDIT_TAB_STATE_REVERTING_ERROR: we do not close since the document contains errors
1701 		   - GEDIT_TAB_STATE_SAVING_ERROR: we do not close since the document contains errors
1702 		   - GEDIT_TAB_STATE_GENERIC_ERROR: we do not close since the document contains
1703 		     errors (CHECK: we should problably remove this state)
1704 		   - [*] GEDIT_TAB_STATE_CLOSING: this state is invalid in this case
1705 		*/
1706 
1707 		g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING);
1708 		g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING);
1709 		g_return_if_fail (state != GEDIT_TAB_STATE_SAVING);
1710 
1711 		if (state != GEDIT_TAB_STATE_SAVING_ERROR &&
1712 		    state != GEDIT_TAB_STATE_GENERIC_ERROR &&
1713 		    state != GEDIT_TAB_STATE_REVERTING_ERROR)
1714 		{
1715 			if (g_list_index (docs, doc) >= 0 &&
1716 			    state != GEDIT_TAB_STATE_LOADING &&
1717 			    state != GEDIT_TAB_STATE_LOADING_ERROR &&
1718 			    state != GEDIT_TAB_STATE_REVERTING) /* FIXME: is this the right behavior with REVERTING ?*/
1719 			{
1720 				GtkSourceFile *file = gedit_document_get_file (doc);
1721 
1722 				/* The document must be saved before closing */
1723 				g_return_if_fail (_gedit_document_needs_saving (doc));
1724 
1725 				/* FIXME: manage the case of local readonly files owned by the
1726 				 * user is running gedit - Paolo (Dec. 8, 2005) */
1727 				if (gedit_document_is_untitled (doc) ||
1728 				    gtk_source_file_is_readonly (file))
1729 				{
1730 					if (data == NULL)
1731 					{
1732 						data = g_slice_new (SaveAsData);
1733 						data->window = g_object_ref (window);
1734 						data->tabs_to_save_as = NULL;
1735 						data->close_tabs = TRUE;
1736 					}
1737 
1738 					data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as,
1739 										 g_object_ref (tab));
1740 				}
1741 				else
1742 				{
1743 					tabs_to_save_and_close = g_slist_prepend (tabs_to_save_and_close, tab);
1744 				}
1745 			}
1746 			else
1747 			{
1748 				/* The document can be closed without saving */
1749 				tabs_to_close = g_list_prepend (tabs_to_close, tab);
1750 			}
1751 		}
1752 	}
1753 
1754 	g_list_free (tabs);
1755 
1756 	/* Close all tabs to close (in a sync way) */
1757 	gedit_window_close_tabs (window, tabs_to_close);
1758 	g_list_free (tabs_to_close);
1759 
1760 	/* Save and close all the files in tabs_to_save_and_close */
1761 	for (sl = tabs_to_save_and_close; sl != NULL; sl = sl->next)
1762 	{
1763 		save_and_close (GEDIT_TAB (sl->data), window);
1764 	}
1765 
1766 	g_slist_free (tabs_to_save_and_close);
1767 
1768 	/* Save As and close all the files in data->tabs_to_save_as. */
1769 	if (data != NULL)
1770 	{
1771 		data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
1772 		save_as_documents_list (data);
1773 	}
1774 }
1775 
1776 static void
save_and_close_document(const GList * docs,GeditWindow * window)1777 save_and_close_document (const GList *docs,
1778 			 GeditWindow *window)
1779 {
1780 	GeditTab *tab;
1781 
1782 	gedit_debug (DEBUG_COMMANDS);
1783 
1784 	g_return_if_fail (docs->next == NULL);
1785 
1786 	tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (docs->data));
1787 	g_return_if_fail (tab != NULL);
1788 
1789 	save_and_close (tab, window);
1790 }
1791 
1792 static void
close_all_tabs(GeditWindow * window)1793 close_all_tabs (GeditWindow *window)
1794 {
1795 	gedit_debug (DEBUG_COMMANDS);
1796 
1797 	/* There is no document to save -> close all tabs */
1798 	gedit_window_close_all_tabs (window);
1799 
1800 	quit_if_needed (window);
1801 }
1802 
1803 static void
close_document(GeditWindow * window,GeditDocument * doc)1804 close_document (GeditWindow   *window,
1805 		GeditDocument *doc)
1806 {
1807 	GeditTab *tab;
1808 
1809 	gedit_debug (DEBUG_COMMANDS);
1810 
1811 	tab = gedit_tab_get_from_document (doc);
1812 	g_return_if_fail (tab != NULL);
1813 
1814 	gedit_window_close_tab (window, tab);
1815 }
1816 
1817 static void
close_confirmation_dialog_response_handler(GeditCloseConfirmationDialog * dlg,gint response_id,GeditWindow * window)1818 close_confirmation_dialog_response_handler (GeditCloseConfirmationDialog *dlg,
1819                                             gint                          response_id,
1820                                             GeditWindow                  *window)
1821 {
1822 	GList *selected_documents;
1823 	gboolean is_closing_all;
1824 	GeditNotebook *notebook_to_close;
1825 
1826 	gedit_debug (DEBUG_COMMANDS);
1827 
1828 	is_closing_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1829 	                                                         GEDIT_IS_CLOSING_ALL));
1830 
1831 	notebook_to_close = g_object_get_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE);
1832 
1833 	gtk_widget_hide (GTK_WIDGET (dlg));
1834 
1835 	switch (response_id)
1836 	{
1837 		/* Save and Close */
1838 		case GTK_RESPONSE_YES:
1839 			selected_documents = gedit_close_confirmation_dialog_get_selected_documents (dlg);
1840 
1841 			if (selected_documents == NULL)
1842 			{
1843 				if (is_closing_all)
1844 				{
1845 					/* There is no document to save -> close all tabs */
1846 					/* We call gtk_widget_destroy before close_all_tabs
1847 					 * because close_all_tabs could destroy the gedit window */
1848 					gtk_widget_destroy (GTK_WIDGET (dlg));
1849 
1850 					close_all_tabs (window);
1851 					return;
1852 				}
1853 				else if (notebook_to_close)
1854 				{
1855 					gedit_notebook_remove_all_tabs (notebook_to_close);
1856 				}
1857 				else
1858 				{
1859 					g_return_if_reached ();
1860 				}
1861 			}
1862 			else
1863 			{
1864 				if (is_closing_all || notebook_to_close)
1865 				{
1866 					GeditNotebook *notebook = is_closing_all ? NULL : notebook_to_close;
1867 
1868 					save_and_close_documents (selected_documents, window, notebook);
1869 				}
1870 				else
1871 				{
1872 					save_and_close_document (selected_documents, window);
1873 				}
1874 			}
1875 
1876 			g_list_free (selected_documents);
1877 			break;
1878 
1879 		/* Close without Saving */
1880 		case GTK_RESPONSE_NO:
1881 			if (is_closing_all)
1882 			{
1883 				/* We call gtk_widget_destroy before close_all_tabs
1884 				 * because close_all_tabs could destroy the gedit window */
1885 				gtk_widget_destroy (GTK_WIDGET (dlg));
1886 
1887 				close_all_tabs (window);
1888 				return;
1889 			}
1890 			else if (notebook_to_close)
1891 			{
1892 				gedit_notebook_remove_all_tabs (notebook_to_close);
1893 			}
1894 			else
1895 			{
1896 				const GList *unsaved_documents;
1897 
1898 				unsaved_documents = gedit_close_confirmation_dialog_get_unsaved_documents (dlg);
1899 				g_return_if_fail (unsaved_documents->next == NULL);
1900 
1901 				close_document (window, GEDIT_DOCUMENT (unsaved_documents->data));
1902 			}
1903 
1904 			break;
1905 
1906 		/* Do not close */
1907 		default:
1908 			/* Reset is_quitting flag */
1909 			g_object_set_data (G_OBJECT (window),
1910 			                   GEDIT_IS_QUITTING,
1911 			                   GBOOLEAN_TO_POINTER (FALSE));
1912 
1913 			g_object_set_data (G_OBJECT (window),
1914 			                   GEDIT_IS_QUITTING_ALL,
1915 			                   GBOOLEAN_TO_POINTER (FALSE));
1916 			break;
1917 	}
1918 
1919 	g_object_set_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE, NULL);
1920 
1921 	gtk_widget_destroy (GTK_WIDGET (dlg));
1922 }
1923 
1924 /* Returns TRUE if the tab can be immediately closed */
1925 static gboolean
tab_can_close(GeditTab * tab,GtkWindow * window)1926 tab_can_close (GeditTab  *tab,
1927 	       GtkWindow *window)
1928 {
1929 	GeditDocument *doc;
1930 
1931 	gedit_debug (DEBUG_COMMANDS);
1932 
1933 	doc = gedit_tab_get_document (tab);
1934 
1935 	if (!_gedit_tab_get_can_close (tab))
1936 	{
1937 		GtkWidget *dlg;
1938 
1939 		dlg = gedit_close_confirmation_dialog_new_single (window, doc);
1940 		g_signal_connect (dlg,
1941 				  "response",
1942 				  G_CALLBACK (close_confirmation_dialog_response_handler),
1943 				  window);
1944 
1945 		gtk_widget_show (dlg);
1946 
1947 		return FALSE;
1948 	}
1949 
1950 	return TRUE;
1951 }
1952 
1953 /* FIXME: we probably need this one public for plugins...
1954  * maybe even a _list variant. Or maybe it's better make
1955  * gedit_window_close_tab always run the confirm dialog?
1956  * we should not allow closing a tab without resetting the
1957  * GEDIT_IS_CLOSING_ALL flag!
1958  */
1959 void
_gedit_cmd_file_close_tab(GeditTab * tab,GeditWindow * window)1960 _gedit_cmd_file_close_tab (GeditTab    *tab,
1961 			   GeditWindow *window)
1962 {
1963 	gedit_debug (DEBUG_COMMANDS);
1964 
1965 	g_return_if_fail (GTK_WIDGET (window) == gtk_widget_get_toplevel (GTK_WIDGET (tab)));
1966 
1967 	g_object_set_data (G_OBJECT (window),
1968 			   GEDIT_IS_CLOSING_ALL,
1969 			   GBOOLEAN_TO_POINTER (FALSE));
1970 
1971 	g_object_set_data (G_OBJECT (window),
1972 			   GEDIT_IS_QUITTING,
1973 			   GBOOLEAN_TO_POINTER (FALSE));
1974 
1975 	g_object_set_data (G_OBJECT (window),
1976 	                   GEDIT_IS_QUITTING_ALL,
1977 	                   GBOOLEAN_TO_POINTER (FALSE));
1978 
1979 	if (tab_can_close (tab, GTK_WINDOW (window)))
1980 	{
1981 		gedit_window_close_tab (window, tab);
1982 	}
1983 }
1984 
1985 void
_gedit_cmd_file_close(GSimpleAction * action,GVariant * parameter,gpointer user_data)1986 _gedit_cmd_file_close (GSimpleAction *action,
1987                        GVariant      *parameter,
1988                        gpointer       user_data)
1989 {
1990 	GeditWindow *window = GEDIT_WINDOW (user_data);
1991 	GeditTab *active_tab;
1992 
1993 	gedit_debug (DEBUG_COMMANDS);
1994 
1995 	active_tab = gedit_window_get_active_tab (window);
1996 
1997 	if (active_tab == NULL)
1998 	{
1999 		gtk_widget_destroy (GTK_WIDGET (window));
2000 		return;
2001 	}
2002 
2003 	_gedit_cmd_file_close_tab (active_tab, window);
2004 }
2005 
2006 static void
file_close_dialog(GeditWindow * window,GList * unsaved_docs)2007 file_close_dialog (GeditWindow *window,
2008                    GList       *unsaved_docs)
2009 {
2010 	GtkWidget *dlg;
2011 
2012 	if (unsaved_docs->next == NULL)
2013 	{
2014 		/* There is only one unsaved document */
2015 		GeditTab *tab;
2016 		GeditDocument *doc;
2017 
2018 		doc = GEDIT_DOCUMENT (unsaved_docs->data);
2019 
2020 		tab = gedit_tab_get_from_document (doc);
2021 		g_return_if_fail (tab != NULL);
2022 
2023 		gedit_window_set_active_tab (window, tab);
2024 
2025 		dlg = gedit_close_confirmation_dialog_new_single (GTK_WINDOW (window), doc);
2026 	}
2027 	else
2028 	{
2029 		dlg = gedit_close_confirmation_dialog_new (GTK_WINDOW (window), unsaved_docs);
2030 	}
2031 
2032 	g_signal_connect (dlg,
2033 	                  "response",
2034 	                  G_CALLBACK (close_confirmation_dialog_response_handler),
2035 	                  window);
2036 
2037 	gtk_widget_show (dlg);
2038 }
2039 
2040 static GList *
notebook_get_unsaved_documents(GeditNotebook * notebook)2041 notebook_get_unsaved_documents (GeditNotebook *notebook)
2042 {
2043 	GList *children;
2044 	GList *unsaved_docs = NULL;
2045 	GList *l;
2046 
2047 	children = gtk_container_get_children (GTK_CONTAINER (notebook));
2048 
2049 	for (l = children; l != NULL; l = g_list_next (l))
2050 	{
2051 		GeditTab *tab = GEDIT_TAB (l->data);
2052 
2053 		if (!_gedit_tab_get_can_close (tab))
2054 		{
2055 			GeditDocument *doc;
2056 
2057 			doc = gedit_tab_get_document (tab);
2058 			unsaved_docs = g_list_prepend (unsaved_docs, doc);
2059 		}
2060 	}
2061 
2062 	g_list_free (children);
2063 
2064 	return g_list_reverse (unsaved_docs);
2065 }
2066 
2067 /* Close a notebook */
2068 void
_gedit_cmd_file_close_notebook(GeditWindow * window,GeditNotebook * notebook)2069 _gedit_cmd_file_close_notebook (GeditWindow   *window,
2070                                 GeditNotebook *notebook)
2071 {
2072 	GList *unsaved_docs;
2073 
2074 	g_object_set_data (G_OBJECT (window), GEDIT_IS_CLOSING_ALL, GBOOLEAN_TO_POINTER (FALSE));
2075 	g_object_set_data (G_OBJECT (window), GEDIT_IS_QUITTING, GBOOLEAN_TO_POINTER (FALSE));
2076 	g_object_set_data (G_OBJECT (window), GEDIT_IS_QUITTING_ALL, GBOOLEAN_TO_POINTER (FALSE));
2077 
2078 	g_object_set_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE, notebook);
2079 
2080 	unsaved_docs = notebook_get_unsaved_documents (notebook);
2081 
2082 	if (unsaved_docs == NULL)
2083 	{
2084 		/* There is no document to save -> close the notebook */
2085 		gedit_notebook_remove_all_tabs (GEDIT_NOTEBOOK (notebook));
2086 	}
2087 	else
2088 	{
2089 		file_close_dialog (window, unsaved_docs);
2090 
2091 		g_list_free (unsaved_docs);
2092 	}
2093 }
2094 
2095 /* Close all tabs */
2096 static void
file_close_all(GeditWindow * window,gboolean is_quitting)2097 file_close_all (GeditWindow *window,
2098                 gboolean     is_quitting)
2099 {
2100 	GList *unsaved_docs;
2101 
2102 	gedit_debug (DEBUG_COMMANDS);
2103 
2104 	g_return_if_fail (!(gedit_window_get_state (window) &
2105 	                    (GEDIT_WINDOW_STATE_SAVING |
2106 	                     GEDIT_WINDOW_STATE_PRINTING)));
2107 
2108 	g_object_set_data (G_OBJECT (window),
2109 			   GEDIT_IS_CLOSING_ALL,
2110 			   GBOOLEAN_TO_POINTER (TRUE));
2111 
2112 	g_object_set_data (G_OBJECT (window),
2113 			   GEDIT_IS_QUITTING,
2114 			   GBOOLEAN_TO_POINTER (is_quitting));
2115 
2116 	unsaved_docs = gedit_window_get_unsaved_documents (window);
2117 
2118 	if (unsaved_docs != NULL)
2119 	{
2120 		file_close_dialog (window, unsaved_docs);
2121 
2122 		g_list_free (unsaved_docs);
2123 	}
2124 	else
2125 	{
2126 		/* There is no document to save -> close all tabs */
2127 		gedit_window_close_all_tabs (window);
2128 		quit_if_needed (window);
2129 	}
2130 }
2131 
2132 void
_gedit_cmd_file_close_all(GSimpleAction * action,GVariant * parameter,gpointer user_data)2133 _gedit_cmd_file_close_all (GSimpleAction *action,
2134                            GVariant      *parameter,
2135                            gpointer       user_data)
2136 {
2137 	GeditWindow *window = GEDIT_WINDOW (user_data);
2138 
2139 	gedit_debug (DEBUG_COMMANDS);
2140 
2141 	g_return_if_fail (!(gedit_window_get_state (window) &
2142 			    (GEDIT_WINDOW_STATE_SAVING |
2143 			     GEDIT_WINDOW_STATE_PRINTING)));
2144 
2145 	file_close_all (window, FALSE);
2146 }
2147 
2148 /* Quit */
2149 static void
quit_all(void)2150 quit_all (void)
2151 {
2152 	GList *windows;
2153 	GList *l;
2154 	GApplication *app;
2155 
2156 	app = g_application_get_default ();
2157 	windows = gedit_app_get_main_windows (GEDIT_APP (app));
2158 
2159 	if (windows == NULL)
2160 	{
2161 		g_application_quit (app);
2162 		return;
2163 	}
2164 
2165 	for (l = windows; l != NULL; l = g_list_next (l))
2166 	{
2167 		GeditWindow *window = l->data;
2168 
2169 		g_object_set_data (G_OBJECT (window),
2170 		                   GEDIT_IS_QUITTING_ALL,
2171 		                   GBOOLEAN_TO_POINTER (TRUE));
2172 
2173 		if (!(gedit_window_get_state (window) &
2174 		      (GEDIT_WINDOW_STATE_SAVING | GEDIT_WINDOW_STATE_PRINTING)))
2175 		{
2176 			file_close_all (window, TRUE);
2177 		}
2178 	}
2179 
2180 	g_list_free (windows);
2181 }
2182 
2183 void
_gedit_cmd_file_quit(GSimpleAction * action,GVariant * parameter,gpointer user_data)2184 _gedit_cmd_file_quit (GSimpleAction *action,
2185                       GVariant      *parameter,
2186                       gpointer       user_data)
2187 {
2188 	GeditWindow *window = GEDIT_WINDOW (user_data);
2189 
2190 	gedit_debug (DEBUG_COMMANDS);
2191 
2192 	if (window == NULL)
2193 	{
2194 		quit_all ();
2195 		return;
2196 	}
2197 
2198 	g_return_if_fail (!(gedit_window_get_state (window) &
2199 	                    (GEDIT_WINDOW_STATE_SAVING |
2200 	                     GEDIT_WINDOW_STATE_PRINTING)));
2201 
2202 	file_close_all (window, TRUE);
2203 }
2204 
2205 /* ex:set ts=8 noet: */
2206