1 /*
2  * gedit-window.c
3  * This file is part of gedit
4  *
5  * Copyright (C) 2005 - Paolo Maggi
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include "gedit-window.h"
24 
25 #include <time.h>
26 #include <sys/types.h>
27 #include <string.h>
28 
29 #include <glib/gi18n.h>
30 #include <libpeas/peas-extension-set.h>
31 #include <tepl/tepl.h>
32 
33 #include "gedit-window-private.h"
34 #include "gedit-app.h"
35 #include "gedit-app-private.h"
36 #include "gedit-notebook.h"
37 #include "gedit-notebook-popup-menu.h"
38 #include "gedit-multi-notebook.h"
39 #include "gedit-statusbar.h"
40 #include "gedit-tab.h"
41 #include "gedit-tab-private.h"
42 #include "gedit-view-frame.h"
43 #include "gedit-utils.h"
44 #include "gedit-commands.h"
45 #include "gedit-commands-private.h"
46 #include "gedit-debug.h"
47 #include "gedit-document.h"
48 #include "gedit-document-private.h"
49 #include "gedit-documents-panel.h"
50 #include "gedit-plugins-engine.h"
51 #include "gedit-window-activatable.h"
52 #include "gedit-enum-types.h"
53 #include "gedit-dirs.h"
54 #include "gedit-status-menu-button.h"
55 #include "gedit-settings.h"
56 #include "gedit-menu-stack-switcher.h"
57 
58 enum
59 {
60 	PROP_0,
61 	PROP_STATE,
62 	LAST_PROP
63 };
64 
65 static GParamSpec *properties[LAST_PROP];
66 
67 enum
68 {
69 	TAB_ADDED,
70 	TAB_REMOVED,
71 	TABS_REORDERED,
72 	ACTIVE_TAB_CHANGED,
73 	ACTIVE_TAB_STATE_CHANGED,
74 	LAST_SIGNAL
75 };
76 
77 static guint signals[LAST_SIGNAL];
78 
79 enum
80 {
81 	TARGET_URI_LIST = 100,
82 	TARGET_XDNDDIRECTSAVE
83 };
84 
85 static const GtkTargetEntry drop_types [] = {
86 	{ "XdndDirectSave0", 0, TARGET_XDNDDIRECTSAVE }, /* XDS Protocol Type */
87 	{ "text/uri-list", 0, TARGET_URI_LIST}
88 };
89 
90 G_DEFINE_TYPE_WITH_PRIVATE (GeditWindow, gedit_window, GTK_TYPE_APPLICATION_WINDOW)
91 
92 /* Prototypes */
93 static void remove_actions (GeditWindow *window);
94 
95 static void
gedit_window_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)96 gedit_window_get_property (GObject    *object,
97 			   guint       prop_id,
98 			   GValue     *value,
99 			   GParamSpec *pspec)
100 {
101 	GeditWindow *window = GEDIT_WINDOW (object);
102 
103 	switch (prop_id)
104 	{
105 		case PROP_STATE:
106 			g_value_set_flags (value,
107 					   gedit_window_get_state (window));
108 			break;
109 		default:
110 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111 			break;
112 	}
113 }
114 
115 static void
save_panels_state(GeditWindow * window)116 save_panels_state (GeditWindow *window)
117 {
118 	const gchar *panel_page;
119 
120 	gedit_debug (DEBUG_WINDOW);
121 
122 	if (window->priv->side_panel_size > 0)
123 	{
124 		g_settings_set_int (window->priv->window_settings,
125 				    GEDIT_SETTINGS_SIDE_PANEL_SIZE,
126 				    window->priv->side_panel_size);
127 	}
128 
129 	panel_page = gtk_stack_get_visible_child_name (GTK_STACK (window->priv->side_panel));
130 	if (panel_page != NULL)
131 	{
132 		g_settings_set_string (window->priv->window_settings,
133 				       GEDIT_SETTINGS_SIDE_PANEL_ACTIVE_PAGE,
134 				       panel_page);
135 	}
136 
137 	if (window->priv->bottom_panel_size > 0)
138 	{
139 		g_settings_set_int (window->priv->window_settings,
140 				    GEDIT_SETTINGS_BOTTOM_PANEL_SIZE,
141 				    window->priv->bottom_panel_size);
142 	}
143 
144 	panel_page = gtk_stack_get_visible_child_name (GTK_STACK (window->priv->bottom_panel));
145 	if (panel_page != NULL)
146 	{
147 		g_settings_set_string (window->priv->window_settings,
148 				       GEDIT_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE,
149 				       panel_page);
150 	}
151 
152 	g_settings_apply (window->priv->window_settings);
153 }
154 
155 static void
save_window_state(GtkWidget * widget)156 save_window_state (GtkWidget *widget)
157 {
158 	GeditWindow *window = GEDIT_WINDOW (widget);
159 
160 	if ((window->priv->window_state &
161 	     (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
162 	{
163 		gtk_window_get_size (GTK_WINDOW (widget), &window->priv->width, &window->priv->height);
164 
165 		g_settings_set (window->priv->window_settings, GEDIT_SETTINGS_WINDOW_SIZE,
166 				"(ii)", window->priv->width, window->priv->height);
167 	}
168 }
169 
170 static void
gedit_window_dispose(GObject * object)171 gedit_window_dispose (GObject *object)
172 {
173 	GeditWindow *window;
174 
175 	gedit_debug (DEBUG_WINDOW);
176 
177 	window = GEDIT_WINDOW (object);
178 
179 	/* Stop tracking removal of panels otherwise we always
180 	 * end up with thinking we had no panel active, since they
181 	 * should all be removed below */
182 	if (window->priv->bottom_panel_item_removed_handler_id != 0)
183 	{
184 		g_signal_handler_disconnect (window->priv->bottom_panel,
185 					     window->priv->bottom_panel_item_removed_handler_id);
186 		window->priv->bottom_panel_item_removed_handler_id = 0;
187 	}
188 
189 	/* First of all, force collection so that plugins
190 	 * really drop some of the references.
191 	 */
192 	peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
193 
194 	/* save the panels position and make sure to deactivate plugins
195 	 * for this window, but only once */
196 	if (!window->priv->dispose_has_run)
197 	{
198 		save_window_state (GTK_WIDGET (window));
199 		save_panels_state (window);
200 
201 		/* Note that unreffing the extensions will automatically remove
202 		   all extensions which in turn will deactivate the extension */
203 		g_object_unref (window->priv->extensions);
204 
205 		peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
206 
207 		window->priv->dispose_has_run = TRUE;
208 	}
209 
210 	g_clear_object (&window->priv->message_bus);
211 	g_clear_object (&window->priv->window_group);
212 
213 	/* We must free the settings after saving the panels */
214 	g_clear_object (&window->priv->editor_settings);
215 	g_clear_object (&window->priv->ui_settings);
216 	g_clear_object (&window->priv->window_settings);
217 
218 	/* Now that there have broken some reference loops,
219 	 * force collection again.
220 	 */
221 	peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
222 
223 	g_clear_object (&window->priv->side_stack_switcher);
224 
225 	/* GTK+/GIO unref the action map in an idle. For the last GeditWindow,
226 	 * the application quits before the idle, so the action map is not
227 	 * unreffed, and some objects are not finalized on application shutdown
228 	 * (GeditView for example).
229 	 * So this is just for making the debugging of object references a bit
230 	 * nicer.
231 	 */
232 	remove_actions (window);
233 
234 	window->priv->fullscreen_open_recent_button = NULL;
235 
236 	G_OBJECT_CLASS (gedit_window_parent_class)->dispose (object);
237 }
238 
239 static void
gedit_window_finalize(GObject * object)240 gedit_window_finalize (GObject *object)
241 {
242 	GeditWindow *window = GEDIT_WINDOW (object);
243 
244 	g_free (window->priv->file_chooser_folder_uri);
245 	g_slist_free_full (window->priv->closed_docs_stack, (GDestroyNotify)g_object_unref);
246 
247 	G_OBJECT_CLASS (gedit_window_parent_class)->finalize (object);
248 }
249 
250 static void
update_fullscreen(GeditWindow * window,gboolean is_fullscreen)251 update_fullscreen (GeditWindow *window,
252                    gboolean     is_fullscreen)
253 {
254 	GAction *fullscreen_action;
255 
256 	_gedit_multi_notebook_set_show_tabs (window->priv->multi_notebook, !is_fullscreen);
257 
258 	if (is_fullscreen)
259 	{
260 		gtk_widget_hide (window->priv->statusbar);
261 	}
262 	else
263 	{
264 		if (g_settings_get_boolean (window->priv->ui_settings, "statusbar-visible"))
265 		{
266 			gtk_widget_show (window->priv->statusbar);
267 		}
268 	}
269 
270 #ifndef OS_OSX
271 	if (is_fullscreen)
272 	{
273 		gtk_widget_show_all (window->priv->fullscreen_eventbox);
274 	}
275 	else
276 	{
277 		gtk_widget_hide (window->priv->fullscreen_eventbox);
278 	}
279 #endif
280 
281 	fullscreen_action = g_action_map_lookup_action (G_ACTION_MAP (window),
282 	                                                "fullscreen");
283 
284 	g_simple_action_set_state (G_SIMPLE_ACTION (fullscreen_action),
285 	                           g_variant_new_boolean (is_fullscreen));
286 }
287 
288 static gboolean
gedit_window_window_state_event(GtkWidget * widget,GdkEventWindowState * event)289 gedit_window_window_state_event (GtkWidget           *widget,
290 				 GdkEventWindowState *event)
291 {
292 	GeditWindow *window = GEDIT_WINDOW (widget);
293 
294 	window->priv->window_state = event->new_window_state;
295 
296 	g_settings_set_int (window->priv->window_settings, GEDIT_SETTINGS_WINDOW_STATE,
297 			    window->priv->window_state);
298 
299 	if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) != 0)
300 	{
301 		update_fullscreen (window, (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0);
302 	}
303 
304 	return GTK_WIDGET_CLASS (gedit_window_parent_class)->window_state_event (widget, event);
305 }
306 
307 static gboolean
gedit_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)308 gedit_window_configure_event (GtkWidget         *widget,
309 			      GdkEventConfigure *event)
310 {
311 	GeditWindow *window = GEDIT_WINDOW (widget);
312 
313 	if (gtk_widget_get_realized (widget) &&
314 	    (window->priv->window_state &
315 	     (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
316 	{
317 		save_window_state (widget);
318 	}
319 
320 	return GTK_WIDGET_CLASS (gedit_window_parent_class)->configure_event (widget, event);
321 }
322 
323 /*
324  * GtkWindow catches keybindings for the menu items _before_ passing them to
325  * the focused widget. This is unfortunate and means that pressing ctrl+V
326  * in an entry on a panel ends up pasting text in the TextView.
327  * Here we override GtkWindow's handler to do the same things that it
328  * does, but in the opposite order and then we chain up to the grand
329  * parent handler, skipping gtk_window_key_press_event.
330  */
331 static gboolean
gedit_window_key_press_event(GtkWidget * widget,GdkEventKey * event)332 gedit_window_key_press_event (GtkWidget   *widget,
333 			      GdkEventKey *event)
334 {
335 	static gpointer grand_parent_class = NULL;
336 
337 	GtkWindow *window = GTK_WINDOW (widget);
338 	gboolean handled = FALSE;
339 
340 	if (grand_parent_class == NULL)
341 	{
342 		grand_parent_class = g_type_class_peek_parent (gedit_window_parent_class);
343 	}
344 
345 	/* handle focus widget key events */
346 	if (!handled)
347 	{
348 		handled = gtk_window_propagate_key_event (window, event);
349 	}
350 
351 	/* handle mnemonics and accelerators */
352 	if (!handled)
353 	{
354 		handled = gtk_window_activate_key (window, event);
355 	}
356 
357 	/* Chain up, invokes binding set on window */
358 	if (!handled)
359 	{
360 		handled = GTK_WIDGET_CLASS (grand_parent_class)->key_press_event (widget, event);
361 	}
362 
363 	if (!handled)
364 	{
365 		return gedit_app_process_window_event (GEDIT_APP (g_application_get_default ()),
366 		                                       GEDIT_WINDOW (widget),
367 		                                       (GdkEvent *)event);
368 	}
369 
370 	return TRUE;
371 }
372 
373 static void
gedit_window_tab_removed(GeditWindow * window,GeditTab * tab)374 gedit_window_tab_removed (GeditWindow *window,
375 			  GeditTab    *tab)
376 {
377 	peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
378 }
379 
380 static void
gedit_window_class_init(GeditWindowClass * klass)381 gedit_window_class_init (GeditWindowClass *klass)
382 {
383 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
384 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
385 
386 	klass->tab_removed = gedit_window_tab_removed;
387 
388 	object_class->dispose = gedit_window_dispose;
389 	object_class->finalize = gedit_window_finalize;
390 	object_class->get_property = gedit_window_get_property;
391 
392 	widget_class->window_state_event = gedit_window_window_state_event;
393 	widget_class->configure_event = gedit_window_configure_event;
394 	widget_class->key_press_event = gedit_window_key_press_event;
395 
396 	properties[PROP_STATE] =
397 		g_param_spec_flags ("state",
398 		                    "State",
399 		                    "The window's state",
400 		                    GEDIT_TYPE_WINDOW_STATE,
401 		                    GEDIT_WINDOW_STATE_NORMAL,
402 		                    G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
403 
404 	g_object_class_install_properties (object_class, LAST_PROP, properties);
405 
406 	signals[TAB_ADDED] =
407 		g_signal_new ("tab-added",
408 			      G_OBJECT_CLASS_TYPE (object_class),
409 			      G_SIGNAL_RUN_FIRST,
410 			      G_STRUCT_OFFSET (GeditWindowClass, tab_added),
411 			      NULL, NULL, NULL,
412 			      G_TYPE_NONE,
413 			      1,
414 			      GEDIT_TYPE_TAB);
415 	signals[TAB_REMOVED] =
416 		g_signal_new ("tab-removed",
417 			      G_OBJECT_CLASS_TYPE (object_class),
418 			      G_SIGNAL_RUN_FIRST,
419 			      G_STRUCT_OFFSET (GeditWindowClass, tab_removed),
420 			      NULL, NULL, NULL,
421 			      G_TYPE_NONE,
422 			      1,
423 			      GEDIT_TYPE_TAB);
424 	signals[TABS_REORDERED] =
425 		g_signal_new ("tabs-reordered",
426 			      G_OBJECT_CLASS_TYPE (object_class),
427 			      G_SIGNAL_RUN_FIRST,
428 			      G_STRUCT_OFFSET (GeditWindowClass, tabs_reordered),
429 			      NULL, NULL, NULL,
430 			      G_TYPE_NONE,
431 			      0);
432 	signals[ACTIVE_TAB_CHANGED] =
433 		g_signal_new ("active-tab-changed",
434 			      G_OBJECT_CLASS_TYPE (object_class),
435 			      G_SIGNAL_RUN_FIRST,
436 			      G_STRUCT_OFFSET (GeditWindowClass, active_tab_changed),
437 			      NULL, NULL, NULL,
438 			      G_TYPE_NONE,
439 			      1,
440 			      GEDIT_TYPE_TAB);
441 	signals[ACTIVE_TAB_STATE_CHANGED] =
442 		g_signal_new ("active-tab-state-changed",
443 			      G_OBJECT_CLASS_TYPE (object_class),
444 			      G_SIGNAL_RUN_FIRST,
445 			      G_STRUCT_OFFSET (GeditWindowClass, active_tab_state_changed),
446 			      NULL, NULL, NULL,
447 			      G_TYPE_NONE,
448 			      0);
449 
450 	/* Bind class to template */
451 	gtk_widget_class_set_template_from_resource (widget_class,
452 	                                             "/org/gnome/gedit/ui/gedit-window.ui");
453 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, titlebar_paned);
454 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_headerbar);
455 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, headerbar);
456 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, new_button);
457 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_button);
458 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, hpaned);
459 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel);
460 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel_inline_stack_switcher);
461 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, vpaned);
462 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, multi_notebook);
463 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, bottom_panel_box);
464 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, bottom_panel);
465 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, statusbar);
466 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, language_button);
467 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, tab_width_button);
468 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, line_col_button);
469 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_eventbox);
470 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_revealer);
471 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_headerbar);
472 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_new_button);
473 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_gear_button);
474 }
475 
476 static void
received_clipboard_contents(GtkClipboard * clipboard,GtkSelectionData * selection_data,GeditWindow * window)477 received_clipboard_contents (GtkClipboard     *clipboard,
478 			     GtkSelectionData *selection_data,
479 			     GeditWindow      *window)
480 {
481 	GeditTab *tab;
482 	gboolean enabled;
483 	GAction *action;
484 
485 	/* getting clipboard contents is async, so we need to
486 	 * get the current tab and its state */
487 
488 	tab = gedit_window_get_active_tab (window);
489 
490 	if (tab != NULL)
491 	{
492 		GeditTabState state;
493 		gboolean state_normal;
494 
495 		state = gedit_tab_get_state (tab);
496 		state_normal = (state == GEDIT_TAB_STATE_NORMAL);
497 
498 		enabled = state_normal &&
499 		          gtk_selection_data_targets_include_text (selection_data);
500 	}
501 	else
502 	{
503 		enabled = FALSE;
504 	}
505 
506 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "paste");
507 
508 	/* Since this is emitted async, the disposal of the actions may have
509 	 * already happened. Ensure that we have an action before setting the
510 	 * state.
511 	 */
512 	if (action != NULL)
513 	{
514 		g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
515 	}
516 
517 	g_object_unref (window);
518 }
519 
520 static void
set_paste_sensitivity_according_to_clipboard(GeditWindow * window,GtkClipboard * clipboard)521 set_paste_sensitivity_according_to_clipboard (GeditWindow  *window,
522 					      GtkClipboard *clipboard)
523 {
524 	GdkDisplay *display;
525 
526 	display = gtk_clipboard_get_display (clipboard);
527 
528 	if (gdk_display_supports_selection_notification (display))
529 	{
530 		gtk_clipboard_request_contents (clipboard,
531 						gdk_atom_intern_static_string ("TARGETS"),
532 						(GtkClipboardReceivedFunc) received_clipboard_contents,
533 						g_object_ref (window));
534 	}
535 	else
536 	{
537 		GAction *action;
538 
539 		action = g_action_map_lookup_action (G_ACTION_MAP (window), "paste");
540 		/* XFIXES extension not availbale, make
541 		 * Paste always sensitive */
542 		g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);
543 	}
544 }
545 
546 static void
extension_update_state(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,GeditWindow * window)547 extension_update_state (PeasExtensionSet *extensions,
548 		        PeasPluginInfo   *info,
549 		        PeasExtension    *exten,
550 		        GeditWindow      *window)
551 {
552 	gedit_window_activatable_update_state (GEDIT_WINDOW_ACTIVATABLE (exten));
553 }
554 
555 static void
update_actions_sensitivity(GeditWindow * window)556 update_actions_sensitivity (GeditWindow *window)
557 {
558 	GeditNotebook *notebook;
559 	GeditTab *tab;
560 	gint num_notebooks;
561 	gint num_tabs;
562 	GeditTabState state = GEDIT_TAB_STATE_NORMAL;
563 	GeditDocument *doc = NULL;
564 	GtkSourceFile *file = NULL;
565 	GeditView *view = NULL;
566 	gint tab_number = -1;
567 	GAction *action;
568 	gboolean editable = FALSE;
569 	gboolean empty_search = FALSE;
570 	GtkClipboard *clipboard;
571 	gboolean enable_syntax_highlighting;
572 
573 	gedit_debug (DEBUG_WINDOW);
574 
575 	notebook = gedit_multi_notebook_get_active_notebook (window->priv->multi_notebook);
576 	tab = gedit_multi_notebook_get_active_tab (window->priv->multi_notebook);
577 	num_notebooks = gedit_multi_notebook_get_n_notebooks (window->priv->multi_notebook);
578 	num_tabs = gedit_multi_notebook_get_n_tabs (window->priv->multi_notebook);
579 
580 	if (notebook != NULL && tab != NULL)
581 	{
582 		state = gedit_tab_get_state (tab);
583 		view = gedit_tab_get_view (tab);
584 		doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
585 		file = gedit_document_get_file (doc);
586 		tab_number = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (tab));
587 		editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (view));
588 		empty_search = _gedit_document_get_empty_search (doc);
589 	}
590 
591 	clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
592 
593 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "save");
594 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
595 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
596 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
597 	                             (file != NULL) && !gtk_source_file_is_readonly (file));
598 
599 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "save-as");
600 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
601 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
602 	                              (state == GEDIT_TAB_STATE_SAVING_ERROR) ||
603 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
604 	                             (doc != NULL));
605 
606 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "revert");
607 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
608 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
609 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
610 	                             (doc != NULL) && !gedit_document_is_untitled (doc));
611 
612 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "reopen-closed-tab");
613 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (window->priv->closed_docs_stack != NULL));
614 
615 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "print");
616 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
617 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
618 	                              (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
619 	                             (doc != NULL));
620 
621 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "close");
622 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
623 	                             (state != GEDIT_TAB_STATE_CLOSING) &&
624 	                             (state != GEDIT_TAB_STATE_SAVING) &&
625 	                             (state != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) &&
626 	                             (state != GEDIT_TAB_STATE_PRINTING) &&
627 	                             (state != GEDIT_TAB_STATE_SAVING_ERROR));
628 
629 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "undo");
630 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
631 	                             (state == GEDIT_TAB_STATE_NORMAL) &&
632 	                             (doc != NULL) && gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER (doc)));
633 
634 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "redo");
635 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
636 	                             (state == GEDIT_TAB_STATE_NORMAL) &&
637 	                             (doc != NULL) && gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER (doc)));
638 
639 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "cut");
640 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
641 	                             (state == GEDIT_TAB_STATE_NORMAL) &&
642 	                             editable &&
643 	                             (doc != NULL) && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)));
644 
645 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "copy");
646 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
647 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
648 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
649 	                             (doc != NULL) && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)));
650 
651 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "paste");
652 	if (num_tabs > 0 && (state == GEDIT_TAB_STATE_NORMAL) && editable)
653 	{
654 		set_paste_sensitivity_according_to_clipboard (window, clipboard);
655 	}
656 	else
657 	{
658 		g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
659 	}
660 
661 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "delete");
662 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
663 	                             (state == GEDIT_TAB_STATE_NORMAL) &&
664 	                             editable &&
665 	                             (doc != NULL) && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)));
666 
667 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "overwrite-mode");
668 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action), doc != NULL);
669 
670 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "find");
671 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
672 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
673 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
674 	                             (doc != NULL));
675 
676 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "replace");
677 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
678 	                             (state == GEDIT_TAB_STATE_NORMAL) &&
679 	                             (doc != NULL) && editable);
680 
681 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "find-next");
682 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
683 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
684 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
685 	                              (doc != NULL) && !empty_search);
686 
687 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "find-prev");
688 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
689 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
690 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
691 	                              (doc != NULL) && !empty_search);
692 
693 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "clear-highlight");
694 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
695 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
696 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
697 	                              (doc != NULL) && !empty_search);
698 
699 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "goto-line");
700 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
701 	                             ((state == GEDIT_TAB_STATE_NORMAL) ||
702 	                              (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
703 	                             (doc != NULL));
704 
705 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "highlight-mode");
706 	enable_syntax_highlighting = g_settings_get_boolean (window->priv->editor_settings,
707 	                                                     GEDIT_SETTINGS_SYNTAX_HIGHLIGHTING);
708 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
709 	                             (state != GEDIT_TAB_STATE_CLOSING) &&
710 	                             (doc != NULL) && enable_syntax_highlighting);
711 
712 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "move-to-new-window");
713 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
714 	                             num_tabs > 1);
715 
716 	action = g_action_map_lookup_action (G_ACTION_MAP (window),
717 	                                     "previous-document");
718 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
719 	                             tab_number > 0);
720 
721 	action = g_action_map_lookup_action (G_ACTION_MAP (window),
722 	                                     "next-document");
723 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
724 	                             tab_number >= 0 &&
725 	                             tab_number < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) - 1);
726 
727 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "new-tab-group");
728 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
729 	                             num_tabs > 0);
730 
731 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "previous-tab-group");
732 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
733 	                             num_notebooks > 1);
734 
735 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "next-tab-group");
736 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
737 	                             num_notebooks > 1);
738 
739 	/* We disable File->Quit/SaveAll/CloseAll while printing to avoid to have two
740 	   operations (save and print/print preview) that uses the message area at
741 	   the same time (may be we can remove this limitation in the future) */
742 	/* We disable File->Quit/CloseAll if state is saving since saving cannot be
743 	   cancelled (may be we can remove this limitation in the future) */
744 	action = g_action_map_lookup_action (G_ACTION_MAP (g_application_get_default ()),
745 	                                     "quit");
746 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
747 	                             !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) &&
748 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING));
749 
750 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "save-all");
751 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
752 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING) &&
753 	                             num_tabs > 0);
754 
755 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "close-all");
756 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
757 	                             num_tabs > 0 &&
758 	                             !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) &&
759 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING) &&
760 	                             num_tabs > 0);
761 
762 	peas_extension_set_foreach (window->priv->extensions,
763 	                            (PeasExtensionSetForeachFunc) extension_update_state,
764 	                            window);
765 }
766 
767 static void
language_chooser_show_cb(TeplLanguageChooser * language_chooser,GeditWindow * window)768 language_chooser_show_cb (TeplLanguageChooser *language_chooser,
769 			  GeditWindow         *window)
770 {
771 	GeditDocument *active_document;
772 
773 	active_document = gedit_window_get_active_document (window);
774 	if (active_document != NULL)
775 	{
776 		GtkSourceLanguage *language;
777 
778 		language = gedit_document_get_language (active_document);
779 		tepl_language_chooser_select_language (language_chooser, language);
780 	}
781 }
782 
783 static void
language_activated_cb(TeplLanguageChooser * language_chooser,GtkSourceLanguage * language,GeditWindow * window)784 language_activated_cb (TeplLanguageChooser *language_chooser,
785 		       GtkSourceLanguage   *language,
786 		       GeditWindow         *window)
787 {
788 	GeditDocument *active_document;
789 
790 	active_document = gedit_window_get_active_document (window);
791 	if (active_document != NULL)
792 	{
793 		gedit_document_set_language (active_document, language);
794 	}
795 
796 	gtk_widget_hide (window->priv->language_popover);
797 }
798 
799 static void
setup_statusbar(GeditWindow * window)800 setup_statusbar (GeditWindow *window)
801 {
802 	TeplLanguageChooserWidget *language_chooser;
803 
804 	gedit_debug (DEBUG_WINDOW);
805 
806 	window->priv->generic_message_cid = gtk_statusbar_get_context_id
807 		(GTK_STATUSBAR (window->priv->statusbar), "generic_message");
808 	window->priv->tip_message_cid = gtk_statusbar_get_context_id
809 		(GTK_STATUSBAR (window->priv->statusbar), "tip_message");
810 	window->priv->bracket_match_message_cid = gtk_statusbar_get_context_id
811 		(GTK_STATUSBAR (window->priv->statusbar), "bracket_match_message");
812 
813 	g_settings_bind (window->priv->ui_settings,
814 	                 "statusbar-visible",
815 	                 window->priv->statusbar,
816 	                 "visible",
817 	                 G_SETTINGS_BIND_GET);
818 
819 	/* Line Col button */
820 	gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (window->priv->line_col_button),
821 	                                _gedit_app_get_line_col_menu (GEDIT_APP (g_application_get_default ())));
822 
823 	/* Tab Width button */
824 	gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (window->priv->tab_width_button),
825 	                                _gedit_app_get_tab_width_menu (GEDIT_APP (g_application_get_default ())));
826 
827 	/* Language button */
828 	window->priv->language_popover = gtk_popover_new (window->priv->language_button);
829 	gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->language_button),
830 	                             window->priv->language_popover);
831 
832 	language_chooser = tepl_language_chooser_widget_new ();
833 
834 	g_signal_connect (language_chooser,
835 	                  "show",
836 	                  G_CALLBACK (language_chooser_show_cb),
837 	                  window);
838 
839 	g_signal_connect (language_chooser,
840 	                  "language-activated",
841 	                  G_CALLBACK (language_activated_cb),
842 	                  window);
843 
844 	gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (language_chooser));
845 	gtk_widget_show (GTK_WIDGET (language_chooser));
846 }
847 
848 static GeditWindow *
clone_window(GeditWindow * origin)849 clone_window (GeditWindow *origin)
850 {
851 	GeditWindow *window;
852 	GdkScreen *screen;
853 	GeditApp  *app;
854 	const gchar *panel_page;
855 
856 	gedit_debug (DEBUG_WINDOW);
857 
858 	app = GEDIT_APP (g_application_get_default ());
859 
860 	screen = gtk_window_get_screen (GTK_WINDOW (origin));
861 	window = gedit_app_create_window (app, screen);
862 
863 	gtk_window_set_default_size (GTK_WINDOW (window),
864 				     origin->priv->width,
865 				     origin->priv->height);
866 
867 	if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
868 		gtk_window_maximize (GTK_WINDOW (window));
869 	else
870 		gtk_window_unmaximize (GTK_WINDOW (window));
871 
872 	if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY) != 0)
873 		gtk_window_stick (GTK_WINDOW (window));
874 	else
875 		gtk_window_unstick (GTK_WINDOW (window));
876 
877 	/* set the panels size, the paned position will be set when
878 	 * they are mapped */
879 	window->priv->side_panel_size = origin->priv->side_panel_size;
880 	window->priv->bottom_panel_size = origin->priv->bottom_panel_size;
881 
882 	panel_page = gtk_stack_get_visible_child_name (GTK_STACK (origin->priv->side_panel));
883 
884 	if (panel_page)
885 	{
886 		gtk_stack_set_visible_child_name (GTK_STACK (window->priv->side_panel), panel_page);
887 	}
888 
889 	panel_page = gtk_stack_get_visible_child_name (GTK_STACK (origin->priv->bottom_panel));
890 
891 	if (panel_page)
892 	{
893 		gtk_stack_set_visible_child_name (GTK_STACK (window->priv->bottom_panel), panel_page);
894 	}
895 
896 	gtk_widget_set_visible (window->priv->side_panel,
897 	                        gtk_widget_get_visible (origin->priv->side_panel));
898 	gtk_widget_set_visible (window->priv->bottom_panel,
899 	                        gtk_widget_get_visible (origin->priv->bottom_panel));
900 
901 	return window;
902 }
903 
904 static void
bracket_matched_cb(GtkSourceBuffer * buffer,GtkTextIter * iter,GtkSourceBracketMatchType result,GeditWindow * window)905 bracket_matched_cb (GtkSourceBuffer           *buffer,
906 		    GtkTextIter               *iter,
907 		    GtkSourceBracketMatchType  result,
908 		    GeditWindow               *window)
909 {
910 	if (buffer != GTK_SOURCE_BUFFER (gedit_window_get_active_document (window)))
911 		return;
912 
913 	switch (result)
914 	{
915 		case GTK_SOURCE_BRACKET_MATCH_NONE:
916 			gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
917 					   window->priv->bracket_match_message_cid);
918 			break;
919 		case GTK_SOURCE_BRACKET_MATCH_OUT_OF_RANGE:
920 			gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
921 						       window->priv->bracket_match_message_cid,
922 						       _("Bracket match is out of range"));
923 			break;
924 		case GTK_SOURCE_BRACKET_MATCH_NOT_FOUND:
925 			gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
926 						       window->priv->bracket_match_message_cid,
927 						       _("Bracket match not found"));
928 			break;
929 		case GTK_SOURCE_BRACKET_MATCH_FOUND:
930 			gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
931 						       window->priv->bracket_match_message_cid,
932 						       _("Bracket match found on line: %d"),
933 						       gtk_text_iter_get_line (iter) + 1);
934 			break;
935 		default:
936 			g_assert_not_reached ();
937 	}
938 }
939 
940 static void
update_cursor_position_statusbar(GtkTextBuffer * buffer,GeditWindow * window)941 update_cursor_position_statusbar (GtkTextBuffer *buffer,
942 				  GeditWindow   *window)
943 {
944 	gint line, col;
945 	GtkTextIter iter;
946 	GeditView *view;
947 	gchar *msg = NULL;
948 
949 	gedit_debug (DEBUG_WINDOW);
950 
951  	if (buffer != GTK_TEXT_BUFFER (gedit_window_get_active_document (window)))
952  		return;
953 
954  	view = gedit_window_get_active_view (window);
955 
956 	gtk_text_buffer_get_iter_at_mark (buffer,
957 					  &iter,
958 					  gtk_text_buffer_get_insert (buffer));
959 
960 	line = 1 + gtk_text_iter_get_line (&iter);
961 	col = 1 + gtk_source_view_get_visual_column (GTK_SOURCE_VIEW (view), &iter);
962 
963 	if ((line >= 0) || (col >= 0))
964 	{
965 		/* Translators: "Ln" is an abbreviation for "Line", Col is an abbreviation for "Column". Please,
966 		use abbreviations if possible to avoid space problems. */
967 		msg = g_strdup_printf (_("  Ln %d, Col %d"), line, col);
968 	}
969 
970 	gedit_status_menu_button_set_label (GEDIT_STATUS_MENU_BUTTON (window->priv->line_col_button), msg);
971 
972 	g_free (msg);
973 }
974 
975 static void
set_overwrite_mode(GeditWindow * window,gboolean overwrite)976 set_overwrite_mode (GeditWindow *window,
977                     gboolean     overwrite)
978 {
979 	GAction *action;
980 
981 	gedit_statusbar_set_overwrite (GEDIT_STATUSBAR (window->priv->statusbar), overwrite);
982 
983 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "overwrite-mode");
984 	g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (overwrite));
985 }
986 
987 static void
overwrite_mode_changed(GtkTextView * view,GParamSpec * pspec,GeditWindow * window)988 overwrite_mode_changed (GtkTextView *view,
989 			GParamSpec  *pspec,
990 			GeditWindow *window)
991 {
992 	if (view != GTK_TEXT_VIEW (gedit_window_get_active_view (window)))
993 		return;
994 
995 	set_overwrite_mode (window, gtk_text_view_get_overwrite (view));
996 }
997 
998 #define MAX_TITLE_LENGTH 100
999 
1000 static void
set_title(GeditWindow * window)1001 set_title (GeditWindow *window)
1002 {
1003 	GeditTab *tab;
1004 	GeditDocument *doc = NULL;
1005 	GtkSourceFile *file;
1006 	gchar *name;
1007 	gchar *dirname = NULL;
1008 	gchar *main_title = NULL;
1009 	gchar *title = NULL;
1010 	gchar *subtitle = NULL;
1011 	gint len;
1012 
1013 	tab = gedit_window_get_active_tab (window);
1014 
1015 	if (tab == NULL)
1016 	{
1017 		gedit_app_set_window_title (GEDIT_APP (g_application_get_default ()),
1018 		                            window,
1019 		                            "gedit");
1020 		gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->headerbar),
1021 		                          "gedit");
1022 		gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->headerbar),
1023 		                             NULL);
1024 		gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
1025 		                          "gedit");
1026 		gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
1027 		                             NULL);
1028 		return;
1029 	}
1030 
1031 	doc = gedit_tab_get_document (tab);
1032 	g_return_if_fail (doc != NULL);
1033 
1034 	file = gedit_document_get_file (doc);
1035 
1036 	name = gedit_document_get_short_name_for_display (doc);
1037 
1038 	len = g_utf8_strlen (name, -1);
1039 
1040 	/* if the name is awfully long, truncate it and be done with it,
1041 	 * otherwise also show the directory (ellipsized if needed)
1042 	 */
1043 	if (len > MAX_TITLE_LENGTH)
1044 	{
1045 		gchar *tmp;
1046 
1047 		tmp = tepl_utils_str_middle_truncate (name,
1048 						      MAX_TITLE_LENGTH);
1049 		g_free (name);
1050 		name = tmp;
1051 	}
1052 	else
1053 	{
1054 		GFile *location = gtk_source_file_get_location (file);
1055 
1056 		if (location != NULL)
1057 		{
1058 			gchar *str = gedit_utils_location_get_dirname_for_display (location);
1059 
1060 			/* use the remaining space for the dir, but use a min of 20 chars
1061 			 * so that we do not end up with a dirname like "(a...b)".
1062 			 * This means that in the worst case when the filename is long 99
1063 			 * we have a title long 99 + 20, but I think it's a rare enough
1064 			 * case to be acceptable. It's justa darn title afterall :)
1065 			 */
1066 			dirname = tepl_utils_str_middle_truncate (str,
1067 								  MAX (20, MAX_TITLE_LENGTH - len));
1068 			g_free (str);
1069 		}
1070 	}
1071 
1072 	if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
1073 	{
1074 		gchar *tmp_name;
1075 
1076 		tmp_name = g_strdup_printf ("*%s", name);
1077 		g_free (name);
1078 
1079 		name = tmp_name;
1080 	}
1081 
1082 	if (gtk_source_file_is_readonly (file))
1083 	{
1084 		title = g_strdup_printf ("%s [%s]",
1085 		                         name, _("Read-Only"));
1086 
1087 		if (dirname != NULL)
1088 		{
1089 			main_title = g_strdup_printf ("%s [%s] (%s) - gedit",
1090 			                              name,
1091 			                              _("Read-Only"),
1092 			                              dirname);
1093 			subtitle = dirname;
1094 		}
1095 		else
1096 		{
1097 			main_title = g_strdup_printf ("%s [%s] - gedit",
1098 			                              name,
1099 			                              _("Read-Only"));
1100 		}
1101 	}
1102 	else
1103 	{
1104 		title = g_strdup (name);
1105 
1106 		if (dirname != NULL)
1107 		{
1108 			main_title = g_strdup_printf ("%s (%s) - gedit",
1109 			                              name,
1110 			                              dirname);
1111 			subtitle = dirname;
1112 		}
1113 		else
1114 		{
1115 			main_title = g_strdup_printf ("%s - gedit",
1116 			                              name);
1117 		}
1118 	}
1119 
1120 	gedit_app_set_window_title (GEDIT_APP (g_application_get_default ()),
1121 				    window,
1122 				    main_title);
1123 
1124 	gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->headerbar),
1125 	                          title);
1126 	gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->headerbar),
1127 	                             subtitle);
1128 	gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
1129 	                          title);
1130 	gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
1131 	                             subtitle);
1132 
1133 	g_free (dirname);
1134 	g_free (name);
1135 	g_free (title);
1136 	g_free (main_title);
1137 }
1138 
1139 #undef MAX_TITLE_LENGTH
1140 
1141 static void
tab_width_changed(GObject * object,GParamSpec * pspec,GeditWindow * window)1142 tab_width_changed (GObject     *object,
1143 		   GParamSpec  *pspec,
1144 		   GeditWindow *window)
1145 {
1146 	guint new_tab_width;
1147 	gchar *label;
1148 
1149 	new_tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (object));
1150 
1151 	label = g_strdup_printf (_("Tab Width: %u"), new_tab_width);
1152 	gedit_status_menu_button_set_label (GEDIT_STATUS_MENU_BUTTON (window->priv->tab_width_button), label);
1153 	g_free (label);
1154 }
1155 
1156 static void
language_changed(GObject * object,GParamSpec * pspec,GeditWindow * window)1157 language_changed (GObject     *object,
1158 		  GParamSpec  *pspec,
1159 		  GeditWindow *window)
1160 {
1161 	GtkSourceLanguage *new_language;
1162 	const gchar *label;
1163 
1164 	new_language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (object));
1165 
1166 	if (new_language)
1167 		label = gtk_source_language_get_name (new_language);
1168 	else
1169 		label = _("Plain Text");
1170 
1171 	gedit_status_menu_button_set_label (GEDIT_STATUS_MENU_BUTTON (window->priv->language_button), label);
1172 
1173 	peas_extension_set_foreach (window->priv->extensions,
1174 	                            (PeasExtensionSetForeachFunc) extension_update_state,
1175 	                            window);
1176 }
1177 
1178 static void
update_statusbar_wrap_mode_checkbox_from_view(GeditWindow * window,GeditView * view)1179 update_statusbar_wrap_mode_checkbox_from_view (GeditWindow *window,
1180                                                GeditView   *view)
1181 {
1182 	GtkWrapMode wrap_mode;
1183 	GSimpleAction *simple_action;
1184 
1185 	wrap_mode = gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view));
1186 
1187 	simple_action = G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (window), "wrap-mode"));
1188 	g_simple_action_set_state (simple_action, g_variant_new_boolean (wrap_mode != GTK_WRAP_NONE));
1189 }
1190 static void
on_view_wrap_mode_changed(GObject * object,GParamSpec * pspec,GeditWindow * window)1191 on_view_wrap_mode_changed (GObject     *object,
1192                            GParamSpec  *pspec,
1193                            GeditWindow *window)
1194 {
1195 	GeditView *view = gedit_window_get_active_view (window);
1196 
1197 	update_statusbar_wrap_mode_checkbox_from_view (window, view);
1198 }
1199 
1200 static void
_gedit_window_text_wrapping_change_state(GSimpleAction * simple,GVariant * value,gpointer window)1201 _gedit_window_text_wrapping_change_state (GSimpleAction *simple,
1202                                           GVariant      *value,
1203                                           gpointer       window)
1204 {
1205 	gboolean result;
1206 	GeditView *view;
1207 	GtkWrapMode wrap_mode;
1208 	GtkWrapMode current_wrap_mode;
1209 
1210 	g_simple_action_set_state (simple, value);
1211 
1212 	wrap_mode = g_settings_get_enum (GEDIT_WINDOW (window)->priv->editor_settings,
1213 	                                 GEDIT_SETTINGS_WRAP_MODE);
1214 
1215 	current_wrap_mode = wrap_mode;
1216 	result = g_variant_get_boolean (value);
1217 
1218 	if (result && wrap_mode == GTK_WRAP_NONE)
1219 	{
1220 		current_wrap_mode = g_settings_get_enum (GEDIT_WINDOW (window)->priv->editor_settings,
1221 		                                         GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE);
1222 	}
1223 	else if (!result)
1224 	{
1225 		current_wrap_mode = GTK_WRAP_NONE;
1226 	}
1227 
1228 	view = gedit_window_get_active_view (GEDIT_WINDOW (window));
1229 
1230 	g_signal_handler_block (view, GEDIT_WINDOW (window)->priv->wrap_mode_changed_id);
1231 	gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), current_wrap_mode);
1232 	g_signal_handler_unblock (view, GEDIT_WINDOW (window)->priv->wrap_mode_changed_id);
1233 }
1234 
1235 static GActionEntry text_wrapping_entrie[] = {
1236 	{"wrap-mode", NULL, NULL, "false", _gedit_window_text_wrapping_change_state},
1237 };
1238 
1239 static void
remove_actions(GeditWindow * window)1240 remove_actions (GeditWindow *window)
1241 {
1242 	g_action_map_remove_action (G_ACTION_MAP (window), "auto-indent");
1243 	g_action_map_remove_action (G_ACTION_MAP (window), "tab-width");
1244 	g_action_map_remove_action (G_ACTION_MAP (window), "use-spaces");
1245 	g_action_map_remove_action (G_ACTION_MAP (window), "show-line-numbers");
1246 	g_action_map_remove_action (G_ACTION_MAP (window), "display-right-margin");
1247 	g_action_map_remove_action (G_ACTION_MAP (window), "highlight-current-line");
1248 	g_action_map_remove_action (G_ACTION_MAP (window), "wrap-mode");
1249 }
1250 
1251 static void
sync_current_tab_actions(GeditWindow * window,GeditView * old_view,GeditView * new_view)1252 sync_current_tab_actions (GeditWindow *window,
1253 			  GeditView   *old_view,
1254 			  GeditView   *new_view)
1255 {
1256 	if (old_view != NULL)
1257 	{
1258 		remove_actions (window);
1259 
1260 		g_signal_handler_disconnect (old_view, window->priv->wrap_mode_changed_id);
1261 	}
1262 
1263 	if (new_view != NULL)
1264 	{
1265 		GPropertyAction *action;
1266 
1267 		action = g_property_action_new ("auto-indent", new_view, "auto-indent");
1268 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1269 		g_object_unref (action);
1270 
1271 		action = g_property_action_new ("tab-width", new_view, "tab-width");
1272 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1273 		g_object_unref (action);
1274 
1275 		action = g_property_action_new ("use-spaces", new_view, "insert-spaces-instead-of-tabs");
1276 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1277 		g_object_unref (action);
1278 
1279 		action = g_property_action_new ("show-line-numbers", new_view, "show-line-numbers");
1280 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1281 		g_object_unref (action);
1282 
1283 		action = g_property_action_new ("display-right-margin", new_view, "show-right-margin");
1284 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1285 		g_object_unref (action);
1286 
1287 		action = g_property_action_new ("highlight-current-line", new_view, "highlight-current-line");
1288 		g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
1289 		g_object_unref (action);
1290 
1291 		g_action_map_add_action_entries (G_ACTION_MAP (window),
1292 		                                 text_wrapping_entrie,
1293 		                                 G_N_ELEMENTS (text_wrapping_entrie),
1294 		                                 window);
1295 
1296 		update_statusbar_wrap_mode_checkbox_from_view (window, new_view);
1297 
1298 		window->priv->wrap_mode_changed_id = g_signal_connect (new_view,
1299 		                                                       "notify::wrap-mode",
1300 		                                                       G_CALLBACK (on_view_wrap_mode_changed),
1301 		                                                       window);
1302 	}
1303 }
1304 
1305 static void
update_statusbar(GeditWindow * window,GeditView * old_view,GeditView * new_view)1306 update_statusbar (GeditWindow *window,
1307 		  GeditView   *old_view,
1308 		  GeditView   *new_view)
1309 {
1310 	if (old_view)
1311 	{
1312 		if (window->priv->tab_width_id)
1313 		{
1314 			g_signal_handler_disconnect (old_view,
1315 						     window->priv->tab_width_id);
1316 
1317 			window->priv->tab_width_id = 0;
1318 		}
1319 
1320 		if (window->priv->language_changed_id)
1321 		{
1322 			g_signal_handler_disconnect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (old_view)),
1323 						     window->priv->language_changed_id);
1324 
1325 			window->priv->language_changed_id = 0;
1326 		}
1327 	}
1328 
1329 	if (new_view)
1330 	{
1331 		GeditDocument *doc;
1332 
1333 		doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (new_view)));
1334 
1335 		/* sync the statusbar */
1336 		update_cursor_position_statusbar (GTK_TEXT_BUFFER (doc),
1337 						  window);
1338 
1339 		set_overwrite_mode (window, gtk_text_view_get_overwrite (GTK_TEXT_VIEW (new_view)));
1340 
1341 		gtk_widget_show (window->priv->line_col_button);
1342 		gtk_widget_show (window->priv->tab_width_button);
1343 		gtk_widget_show (window->priv->language_button);
1344 
1345 		window->priv->tab_width_id = g_signal_connect (new_view,
1346 							       "notify::tab-width",
1347 							       G_CALLBACK (tab_width_changed),
1348 							       window);
1349 
1350 		window->priv->language_changed_id = g_signal_connect (doc,
1351 								      "notify::language",
1352 								      G_CALLBACK (language_changed),
1353 								      window);
1354 
1355 		/* call it for the first time */
1356 		tab_width_changed (G_OBJECT (new_view), NULL, window);
1357 		language_changed (G_OBJECT (doc), NULL, window);
1358 	}
1359 }
1360 
1361 static void
tab_switched(GeditMultiNotebook * mnb,GeditNotebook * old_notebook,GeditTab * old_tab,GeditNotebook * new_notebook,GeditTab * new_tab,GeditWindow * window)1362 tab_switched (GeditMultiNotebook *mnb,
1363 	      GeditNotebook      *old_notebook,
1364 	      GeditTab           *old_tab,
1365 	      GeditNotebook      *new_notebook,
1366 	      GeditTab           *new_tab,
1367 	      GeditWindow        *window)
1368 {
1369 	GeditView *old_view, *new_view;
1370 
1371 	old_view = old_tab ? gedit_tab_get_view (old_tab) : NULL;
1372 	new_view = new_tab ? gedit_tab_get_view (new_tab) : NULL;
1373 
1374 	sync_current_tab_actions (window, old_view, new_view);
1375 	update_statusbar (window, old_view, new_view);
1376 
1377 	if (new_tab == NULL || window->priv->dispose_has_run)
1378 		return;
1379 
1380 	set_title (window);
1381 	update_actions_sensitivity (window);
1382 
1383 	g_signal_emit (G_OBJECT (window),
1384 		       signals[ACTIVE_TAB_CHANGED],
1385 		       0,
1386 		       new_tab);
1387 }
1388 
1389 static void
analyze_tab_state(GeditTab * tab,GeditWindow * window)1390 analyze_tab_state (GeditTab    *tab,
1391 		   GeditWindow *window)
1392 {
1393 	GeditTabState ts;
1394 
1395 	ts = gedit_tab_get_state (tab);
1396 
1397 	switch (ts)
1398 	{
1399 		case GEDIT_TAB_STATE_LOADING:
1400 		case GEDIT_TAB_STATE_REVERTING:
1401 			window->priv->state |= GEDIT_WINDOW_STATE_LOADING;
1402 			break;
1403 
1404 		case GEDIT_TAB_STATE_SAVING:
1405 			window->priv->state |= GEDIT_WINDOW_STATE_SAVING;
1406 			break;
1407 
1408 		case GEDIT_TAB_STATE_PRINTING:
1409 			window->priv->state |= GEDIT_WINDOW_STATE_PRINTING;
1410 			break;
1411 
1412 		case GEDIT_TAB_STATE_LOADING_ERROR:
1413 		case GEDIT_TAB_STATE_REVERTING_ERROR:
1414 		case GEDIT_TAB_STATE_SAVING_ERROR:
1415 		case GEDIT_TAB_STATE_GENERIC_ERROR:
1416 			window->priv->state |= GEDIT_WINDOW_STATE_ERROR;
1417 			++window->priv->num_tabs_with_error;
1418 		default:
1419 			/* NOP */
1420 			break;
1421 	}
1422 }
1423 
1424 static void
update_window_state(GeditWindow * window)1425 update_window_state (GeditWindow *window)
1426 {
1427 	GeditWindowState old_ws;
1428 	gint old_num_of_errors;
1429 
1430 	gedit_debug_message (DEBUG_WINDOW, "Old state: %x", window->priv->state);
1431 
1432 	old_ws = window->priv->state;
1433 	old_num_of_errors = window->priv->num_tabs_with_error;
1434 
1435 	window->priv->state = 0;
1436 	window->priv->num_tabs_with_error = 0;
1437 
1438 	gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
1439 					  (GtkCallback)analyze_tab_state,
1440 					  window);
1441 
1442 	gedit_debug_message (DEBUG_WINDOW, "New state: %x", window->priv->state);
1443 
1444 	if (old_ws != window->priv->state)
1445 	{
1446 		update_actions_sensitivity (window);
1447 
1448 		gedit_statusbar_set_window_state (GEDIT_STATUSBAR (window->priv->statusbar),
1449 						  window->priv->state,
1450 						  window->priv->num_tabs_with_error);
1451 
1452 		g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
1453 	}
1454 	else if (old_num_of_errors != window->priv->num_tabs_with_error)
1455 	{
1456 		gedit_statusbar_set_window_state (GEDIT_STATUSBAR (window->priv->statusbar),
1457 						  window->priv->state,
1458 						  window->priv->num_tabs_with_error);
1459 	}
1460 }
1461 
1462 static void
update_can_close(GeditWindow * window)1463 update_can_close (GeditWindow *window)
1464 {
1465 	GeditWindowPrivate *priv = window->priv;
1466 	GList *tabs;
1467 	GList *l;
1468 	gboolean can_close = TRUE;
1469 
1470 	gedit_debug (DEBUG_WINDOW);
1471 
1472 	tabs = gedit_multi_notebook_get_all_tabs (priv->multi_notebook);
1473 
1474 	for (l = tabs; l != NULL; l = g_list_next (l))
1475 	{
1476 		GeditTab *tab = l->data;
1477 
1478 		if (!_gedit_tab_get_can_close (tab))
1479 		{
1480 			can_close = FALSE;
1481 			break;
1482 		}
1483 	}
1484 
1485 	if (can_close && (priv->inhibition_cookie != 0))
1486 	{
1487 		gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ()),
1488 					   priv->inhibition_cookie);
1489 		priv->inhibition_cookie = 0;
1490 	}
1491 	else if (!can_close && (priv->inhibition_cookie == 0))
1492 	{
1493 		priv->inhibition_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
1494 		                                                   GTK_WINDOW (window),
1495 		                                                   GTK_APPLICATION_INHIBIT_LOGOUT,
1496 		                                                   _("There are unsaved documents"));
1497 	}
1498 
1499 	g_list_free (tabs);
1500 }
1501 
1502 static void
sync_state(GeditTab * tab,GParamSpec * pspec,GeditWindow * window)1503 sync_state (GeditTab    *tab,
1504 	    GParamSpec  *pspec,
1505 	    GeditWindow *window)
1506 {
1507 	gedit_debug (DEBUG_WINDOW);
1508 
1509 	update_window_state (window);
1510 
1511 	if (tab == gedit_window_get_active_tab (window))
1512 	{
1513 		update_actions_sensitivity (window);
1514 
1515 		g_signal_emit (G_OBJECT (window), signals[ACTIVE_TAB_STATE_CHANGED], 0);
1516 	}
1517 }
1518 
1519 static void
sync_name(GeditTab * tab,GParamSpec * pspec,GeditWindow * window)1520 sync_name (GeditTab    *tab,
1521 	   GParamSpec  *pspec,
1522 	   GeditWindow *window)
1523 {
1524 	if (tab == gedit_window_get_active_tab (window))
1525 	{
1526 		set_title (window);
1527 		update_actions_sensitivity (window);
1528 	}
1529 }
1530 
1531 static void
sync_can_close(GeditTab * tab,GParamSpec * pspec,GeditWindow * window)1532 sync_can_close (GeditTab    *tab,
1533 		GParamSpec  *pspec,
1534 		GeditWindow *window)
1535 {
1536 	update_can_close (window);
1537 }
1538 
1539 static GeditWindow *
get_drop_window(GtkWidget * widget)1540 get_drop_window (GtkWidget *widget)
1541 {
1542 	GtkWidget *target_window;
1543 
1544 	target_window = gtk_widget_get_toplevel (widget);
1545 	g_return_val_if_fail (GEDIT_IS_WINDOW (target_window), NULL);
1546 
1547 	return GEDIT_WINDOW (target_window);
1548 }
1549 
1550 static void
load_uris_from_drop(GeditWindow * window,gchar ** uri_list)1551 load_uris_from_drop (GeditWindow  *window,
1552 		     gchar       **uri_list)
1553 {
1554 	GSList *locations = NULL;
1555 	gint i;
1556 	GSList *loaded;
1557 
1558 	if (uri_list == NULL)
1559 		return;
1560 
1561 	for (i = 0; uri_list[i] != NULL; ++i)
1562 	{
1563 		locations = g_slist_prepend (locations, g_file_new_for_uri (uri_list[i]));
1564 	}
1565 
1566 	locations = g_slist_reverse (locations);
1567 	loaded = gedit_commands_load_locations (window,
1568 	                                        locations,
1569 	                                        NULL,
1570 	                                        0,
1571 	                                        0);
1572 
1573 	g_slist_free (loaded);
1574 	g_slist_free_full (locations, g_object_unref);
1575 }
1576 
1577 /* Handle drops on the GeditWindow */
1578 static void
drag_data_received_cb(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint timestamp,gpointer data)1579 drag_data_received_cb (GtkWidget        *widget,
1580 		       GdkDragContext   *context,
1581 		       gint              x,
1582 		       gint              y,
1583 		       GtkSelectionData *selection_data,
1584 		       guint             info,
1585 		       guint             timestamp,
1586 		       gpointer          data)
1587 {
1588 	GeditWindow *window;
1589 	gchar **uri_list;
1590 
1591 	window = get_drop_window (widget);
1592 
1593 	if (window == NULL)
1594 		return;
1595 
1596 	switch (info)
1597 	{
1598 		case TARGET_URI_LIST:
1599 			uri_list = gedit_utils_drop_get_uris(selection_data);
1600 			load_uris_from_drop (window, uri_list);
1601 			g_strfreev (uri_list);
1602 
1603 			gtk_drag_finish (context, TRUE, FALSE, timestamp);
1604 
1605 			break;
1606 
1607 		case TARGET_XDNDDIRECTSAVE:
1608 			/* Indicate that we don't provide "F" fallback */
1609 			if (gtk_selection_data_get_format (selection_data) == 8 &&
1610 			    gtk_selection_data_get_length (selection_data) == 1 &&
1611 			    gtk_selection_data_get_data (selection_data)[0] == 'F')
1612 			{
1613 				gdk_property_change (gdk_drag_context_get_source_window (context),
1614 						     gdk_atom_intern ("XdndDirectSave0", FALSE),
1615 						     gdk_atom_intern ("text/plain", FALSE), 8,
1616 						     GDK_PROP_MODE_REPLACE, (const guchar *) "", 0);
1617 			}
1618 			else if (gtk_selection_data_get_format (selection_data) == 8 &&
1619 				 gtk_selection_data_get_length (selection_data) == 1 &&
1620 				 gtk_selection_data_get_data (selection_data)[0] == 'S' &&
1621 				 window->priv->direct_save_uri != NULL)
1622 			{
1623 				gchar **uris;
1624 
1625 				uris = g_new (gchar *, 2);
1626 				uris[0] = window->priv->direct_save_uri;
1627 				uris[1] = NULL;
1628 
1629 				load_uris_from_drop (window, uris);
1630 				g_free (uris);
1631 			}
1632 
1633 			g_free (window->priv->direct_save_uri);
1634 			window->priv->direct_save_uri = NULL;
1635 
1636 			gtk_drag_finish (context, TRUE, FALSE, timestamp);
1637 
1638 			break;
1639 	}
1640 }
1641 
1642 static void
drag_drop_cb(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time,gpointer user_data)1643 drag_drop_cb (GtkWidget      *widget,
1644 	      GdkDragContext *context,
1645 	      gint            x,
1646 	      gint            y,
1647 	      guint           time,
1648 	      gpointer        user_data)
1649 {
1650 	GeditWindow *window;
1651 	GtkTargetList *target_list;
1652 	GdkAtom target;
1653 
1654 	window = get_drop_window (widget);
1655 
1656 	target_list = gtk_drag_dest_get_target_list (widget);
1657 	target = gtk_drag_dest_find_target (widget, context, target_list);
1658 
1659 	if (target != GDK_NONE)
1660 	{
1661 		guint info;
1662 		gboolean found;
1663 
1664 		found = gtk_target_list_find (target_list, target, &info);
1665 		g_assert (found);
1666 
1667 		if (info == TARGET_XDNDDIRECTSAVE)
1668 		{
1669 			gchar *uri;
1670 			uri = gedit_utils_set_direct_save_filename (context);
1671 
1672 			if (uri != NULL)
1673 			{
1674 				g_free (window->priv->direct_save_uri);
1675 				window->priv->direct_save_uri = uri;
1676 			}
1677 		}
1678 
1679 		gtk_drag_get_data (GTK_WIDGET (widget), context,
1680 				   target, time);
1681 	}
1682 }
1683 
1684 /* Handle drops on the GeditView */
1685 static void
drop_uris_cb(GtkWidget * widget,gchar ** uri_list,GeditWindow * window)1686 drop_uris_cb (GtkWidget    *widget,
1687 	      gchar       **uri_list,
1688 	      GeditWindow  *window)
1689 {
1690 	load_uris_from_drop (window, uri_list);
1691 }
1692 
1693 static void
update_fullscreen_revealer_state(GeditWindow * window)1694 update_fullscreen_revealer_state (GeditWindow *window)
1695 {
1696 	gboolean open_recent_menu_is_active;
1697 	gboolean hamburger_menu_is_active;
1698 
1699 	open_recent_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_recent_button));
1700 	hamburger_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window->priv->fullscreen_gear_button));
1701 
1702 	gtk_revealer_set_reveal_child (window->priv->fullscreen_revealer,
1703 				       (window->priv->in_fullscreen_eventbox ||
1704 					open_recent_menu_is_active ||
1705 					hamburger_menu_is_active));
1706 }
1707 
1708 static gboolean
on_fullscreen_eventbox_enter_notify_event(GtkWidget * fullscreen_eventbox,GdkEventCrossing * event,GeditWindow * window)1709 on_fullscreen_eventbox_enter_notify_event (GtkWidget        *fullscreen_eventbox,
1710 					   GdkEventCrossing *event,
1711 					   GeditWindow      *window)
1712 {
1713 	window->priv->in_fullscreen_eventbox = TRUE;
1714 	update_fullscreen_revealer_state (window);
1715 
1716 	return GDK_EVENT_PROPAGATE;
1717 }
1718 
1719 static gboolean
on_fullscreen_eventbox_leave_notify_event(GtkWidget * fullscreen_eventbox,GdkEventCrossing * event,GeditWindow * window)1720 on_fullscreen_eventbox_leave_notify_event (GtkWidget        *fullscreen_eventbox,
1721 					   GdkEventCrossing *event,
1722 					   GeditWindow      *window)
1723 {
1724 	if (-1.0 <= event->y && event->y <= 0.0)
1725 	{
1726 		/* Ignore the event.
1727 		 *
1728 		 * Leave notify events are received with -1 <= y <= 0
1729 		 * coordinates, although the GeditWindow is in fullscreen mode
1730 		 * and when there are no screens above (it's maybe a bug in an
1731 		 * underlying library).
1732 		 * If we hide the headerbar when those events happen, then it
1733 		 * makes the headerbar to be shown/hidden a lot of time in a
1734 		 * short period of time, i.e. a "stuttering". In other words
1735 		 * lots of leave/enter events are received when moving the mouse
1736 		 * upwards on the screen when the mouse is already at the top.
1737 		 * The expected leave event has a positive event->y value being
1738 		 * >= to the height of the headerbar (approximately
1739 		 * 40 <= y <= 50). So clearly when we receive a leave event with
1740 		 * event->y <= 0, it means that the mouse has left the eventbox
1741 		 * on the wrong side.
1742 		 * The -1.0 <= event->y is there (instead of just <= 0.0) in the
1743 		 * case that there is another screen *above*, even if this
1744 		 * heuristic/workaround is not perfect in that case. But that
1745 		 * case is quite rare, so it's probably a good enough solution.
1746 		 *
1747 		 * Note that apparently the "stuttering" occurs only on an Xorg
1748 		 * session, not on Wayland (tested with GNOME).
1749 		 *
1750 		 * If you see a better solution...
1751 		 */
1752 		return GDK_EVENT_PROPAGATE;
1753 	}
1754 
1755 	window->priv->in_fullscreen_eventbox = FALSE;
1756 	update_fullscreen_revealer_state (window);
1757 
1758 	return GDK_EVENT_PROPAGATE;
1759 }
1760 
1761 static void
setup_fullscreen_eventbox(GeditWindow * window)1762 setup_fullscreen_eventbox (GeditWindow *window)
1763 {
1764 	gtk_widget_set_size_request (window->priv->fullscreen_eventbox, -1, 1);
1765 	gtk_widget_hide (window->priv->fullscreen_eventbox);
1766 
1767 	g_signal_connect (window->priv->fullscreen_eventbox,
1768 	                  "enter-notify-event",
1769 	                  G_CALLBACK (on_fullscreen_eventbox_enter_notify_event),
1770 	                  window);
1771 
1772 	g_signal_connect (window->priv->fullscreen_eventbox,
1773 	                  "leave-notify-event",
1774 	                  G_CALLBACK (on_fullscreen_eventbox_leave_notify_event),
1775 	                  window);
1776 }
1777 
1778 static void
empty_search_notify_cb(GeditDocument * doc,GParamSpec * pspec,GeditWindow * window)1779 empty_search_notify_cb (GeditDocument *doc,
1780 			GParamSpec    *pspec,
1781 			GeditWindow   *window)
1782 {
1783 	if (doc == gedit_window_get_active_document (window))
1784 	{
1785 		update_actions_sensitivity (window);
1786 	}
1787 }
1788 
1789 static void
can_undo(GeditDocument * doc,GParamSpec * pspec,GeditWindow * window)1790 can_undo (GeditDocument *doc,
1791 	  GParamSpec    *pspec,
1792 	  GeditWindow   *window)
1793 {
1794 	if (doc == gedit_window_get_active_document (window))
1795 	{
1796 		update_actions_sensitivity (window);
1797 	}
1798 }
1799 
1800 static void
can_redo(GeditDocument * doc,GParamSpec * pspec,GeditWindow * window)1801 can_redo (GeditDocument *doc,
1802 	  GParamSpec    *pspec,
1803 	  GeditWindow   *window)
1804 {
1805 	if (doc == gedit_window_get_active_document (window))
1806 	{
1807 		update_actions_sensitivity (window);
1808 	}
1809 }
1810 
1811 static void
selection_changed(GeditDocument * doc,GParamSpec * pspec,GeditWindow * window)1812 selection_changed (GeditDocument *doc,
1813 		   GParamSpec    *pspec,
1814 		   GeditWindow   *window)
1815 {
1816 	if (doc == gedit_window_get_active_document (window))
1817 	{
1818 		update_actions_sensitivity (window);
1819 	}
1820 }
1821 
1822 static void
readonly_changed(GtkSourceFile * file,GParamSpec * pspec,GeditWindow * window)1823 readonly_changed (GtkSourceFile *file,
1824 		  GParamSpec    *pspec,
1825 		  GeditWindow   *window)
1826 {
1827 	update_actions_sensitivity (window);
1828 
1829 	sync_name (gedit_window_get_active_tab (window), NULL, window);
1830 
1831 	peas_extension_set_foreach (window->priv->extensions,
1832 	                            (PeasExtensionSetForeachFunc) extension_update_state,
1833 	                            window);
1834 }
1835 
1836 static void
editable_changed(GeditView * view,GParamSpec * arg1,GeditWindow * window)1837 editable_changed (GeditView  *view,
1838                   GParamSpec  *arg1,
1839                   GeditWindow *window)
1840 {
1841 	peas_extension_set_foreach (window->priv->extensions,
1842 	                            (PeasExtensionSetForeachFunc) extension_update_state,
1843 	                            window);
1844 }
1845 
1846 static void
on_tab_added(GeditMultiNotebook * multi,GeditNotebook * notebook,GeditTab * tab,GeditWindow * window)1847 on_tab_added (GeditMultiNotebook *multi,
1848 	      GeditNotebook      *notebook,
1849 	      GeditTab           *tab,
1850 	      GeditWindow        *window)
1851 {
1852 	GeditView *view;
1853 	GeditDocument *doc;
1854 	GtkSourceFile *file;
1855 
1856 	gedit_debug (DEBUG_WINDOW);
1857 
1858 	update_actions_sensitivity (window);
1859 
1860 	view = gedit_tab_get_view (tab);
1861 	doc = gedit_tab_get_document (tab);
1862 	file = gedit_document_get_file (doc);
1863 
1864 	/* IMPORTANT: remember to disconnect the signal in notebook_tab_removed
1865 	 * if a new signal is connected here */
1866 
1867 	g_signal_connect (tab,
1868 			 "notify::name",
1869 			  G_CALLBACK (sync_name),
1870 			  window);
1871 	g_signal_connect (tab,
1872 			 "notify::state",
1873 			  G_CALLBACK (sync_state),
1874 			  window);
1875 	g_signal_connect (tab,
1876 			  "notify::can-close",
1877 			  G_CALLBACK (sync_can_close),
1878 			  window);
1879 	g_signal_connect (tab,
1880 			  "drop_uris",
1881 			  G_CALLBACK (drop_uris_cb),
1882 			  window);
1883 	g_signal_connect (doc,
1884 			  "bracket-matched",
1885 			  G_CALLBACK (bracket_matched_cb),
1886 			  window);
1887 	g_signal_connect (doc,
1888 			  "tepl-cursor-moved",
1889 			  G_CALLBACK (update_cursor_position_statusbar),
1890 			  window);
1891 	g_signal_connect (doc,
1892 			  "notify::empty-search",
1893 			  G_CALLBACK (empty_search_notify_cb),
1894 			  window);
1895 	g_signal_connect (doc,
1896 			  "notify::can-undo",
1897 			  G_CALLBACK (can_undo),
1898 			  window);
1899 	g_signal_connect (doc,
1900 			  "notify::can-redo",
1901 			  G_CALLBACK (can_redo),
1902 			  window);
1903 	g_signal_connect (doc,
1904 			  "notify::has-selection",
1905 			  G_CALLBACK (selection_changed),
1906 			  window);
1907 	g_signal_connect (view,
1908 			  "notify::overwrite",
1909 			  G_CALLBACK (overwrite_mode_changed),
1910 			  window);
1911 	g_signal_connect (view,
1912 			  "notify::editable",
1913 			  G_CALLBACK (editable_changed),
1914 			  window);
1915 	g_signal_connect (file,
1916 			  "notify::read-only",
1917 			  G_CALLBACK (readonly_changed),
1918 			  window);
1919 
1920 	update_window_state (window);
1921 	update_can_close (window);
1922 
1923 	g_signal_emit (G_OBJECT (window), signals[TAB_ADDED], 0, tab);
1924 }
1925 
1926 static void
push_last_closed_doc(GeditWindow * window,GeditDocument * doc)1927 push_last_closed_doc (GeditWindow   *window,
1928                       GeditDocument *doc)
1929 {
1930 	GeditWindowPrivate *priv = window->priv;
1931 	GtkSourceFile *file = gedit_document_get_file (doc);
1932 	GFile *location = gtk_source_file_get_location (file);
1933 
1934 	if (location != NULL)
1935 	{
1936 		priv->closed_docs_stack = g_slist_prepend (priv->closed_docs_stack, location);
1937 		g_object_ref (location);
1938 	}
1939 }
1940 
1941 GFile *
_gedit_window_pop_last_closed_doc(GeditWindow * window)1942 _gedit_window_pop_last_closed_doc (GeditWindow *window)
1943 {
1944 	GeditWindowPrivate *priv = window->priv;
1945 	GFile *f = NULL;
1946 
1947 	if (window->priv->closed_docs_stack != NULL)
1948 	{
1949 		f = priv->closed_docs_stack->data;
1950 		priv->closed_docs_stack = g_slist_remove (priv->closed_docs_stack, f);
1951 	}
1952 
1953 	return f;
1954 }
1955 
1956 static void
on_tab_removed(GeditMultiNotebook * multi,GeditNotebook * notebook,GeditTab * tab,GeditWindow * window)1957 on_tab_removed (GeditMultiNotebook *multi,
1958 		GeditNotebook      *notebook,
1959 		GeditTab           *tab,
1960 		GeditWindow        *window)
1961 {
1962 	GeditView *view;
1963 	GeditDocument *doc;
1964 	gint num_tabs;
1965 
1966 	gedit_debug (DEBUG_WINDOW);
1967 
1968 	num_tabs = gedit_multi_notebook_get_n_tabs (multi);
1969 
1970 	view = gedit_tab_get_view (tab);
1971 	doc = gedit_tab_get_document (tab);
1972 
1973 	g_signal_handlers_disconnect_by_func (tab,
1974 					      G_CALLBACK (sync_name),
1975 					      window);
1976 	g_signal_handlers_disconnect_by_func (tab,
1977 					      G_CALLBACK (sync_state),
1978 					      window);
1979 	g_signal_handlers_disconnect_by_func (tab,
1980 					      G_CALLBACK (sync_can_close),
1981 					      window);
1982 	g_signal_handlers_disconnect_by_func (tab,
1983 					      G_CALLBACK (drop_uris_cb),
1984 					      window);
1985 	g_signal_handlers_disconnect_by_func (doc,
1986 					      G_CALLBACK (bracket_matched_cb),
1987 					      window);
1988 	g_signal_handlers_disconnect_by_func (doc,
1989 					      G_CALLBACK (update_cursor_position_statusbar),
1990 					      window);
1991 	g_signal_handlers_disconnect_by_func (doc,
1992 					      G_CALLBACK (empty_search_notify_cb),
1993 					      window);
1994 	g_signal_handlers_disconnect_by_func (doc,
1995 					      G_CALLBACK (can_undo),
1996 					      window);
1997 	g_signal_handlers_disconnect_by_func (doc,
1998 					      G_CALLBACK (can_redo),
1999 					      window);
2000 	g_signal_handlers_disconnect_by_func (doc,
2001 					      G_CALLBACK (selection_changed),
2002 					      window);
2003 	g_signal_handlers_disconnect_by_func (doc,
2004 					      G_CALLBACK (readonly_changed),
2005 					      window);
2006 	g_signal_handlers_disconnect_by_func (view,
2007 					      G_CALLBACK (overwrite_mode_changed),
2008 					      window);
2009 	g_signal_handlers_disconnect_by_func (view,
2010 					      G_CALLBACK (editable_changed),
2011 					      window);
2012 
2013 	if (tab == gedit_multi_notebook_get_active_tab (multi))
2014 	{
2015 		if (window->priv->tab_width_id)
2016 		{
2017 			g_signal_handler_disconnect (view, window->priv->tab_width_id);
2018 			window->priv->tab_width_id = 0;
2019 		}
2020 
2021 		if (window->priv->language_changed_id)
2022 		{
2023 			g_signal_handler_disconnect (doc, window->priv->language_changed_id);
2024 			window->priv->language_changed_id = 0;
2025 		}
2026 
2027 		gedit_multi_notebook_set_active_tab (multi, NULL);
2028 	}
2029 
2030 	g_return_if_fail (num_tabs >= 0);
2031 	if (num_tabs == 0)
2032 	{
2033 		set_title (window);
2034 
2035 		gedit_statusbar_clear_overwrite (
2036 				GEDIT_STATUSBAR (window->priv->statusbar));
2037 
2038 		/* hide the combos */
2039 		gtk_widget_hide (window->priv->line_col_button);
2040 		gtk_widget_hide (window->priv->tab_width_button);
2041 		gtk_widget_hide (window->priv->language_button);
2042 	}
2043 
2044 	if (!window->priv->dispose_has_run)
2045 	{
2046 		push_last_closed_doc (window, doc);
2047 
2048 		if ((!window->priv->removing_tabs &&
2049 		    gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) > 0) ||
2050 		    num_tabs == 0)
2051 		{
2052 			update_actions_sensitivity (window);
2053 		}
2054 	}
2055 
2056 	update_window_state (window);
2057 	update_can_close (window);
2058 
2059 	g_signal_emit (G_OBJECT (window), signals[TAB_REMOVED], 0, tab);
2060 }
2061 
2062 static void
on_page_reordered(GeditMultiNotebook * multi,GeditNotebook * notebook,GtkWidget * page,gint page_num,GeditWindow * window)2063 on_page_reordered (GeditMultiNotebook *multi,
2064                    GeditNotebook      *notebook,
2065                    GtkWidget          *page,
2066                    gint                page_num,
2067                    GeditWindow        *window)
2068 {
2069 	update_actions_sensitivity (window);
2070 
2071 	g_signal_emit (G_OBJECT (window), signals[TABS_REORDERED], 0);
2072 }
2073 
2074 static GtkNotebook *
on_notebook_create_window(GeditMultiNotebook * mnb,GtkNotebook * notebook,GtkWidget * page,gint x,gint y,GeditWindow * window)2075 on_notebook_create_window (GeditMultiNotebook *mnb,
2076                            GtkNotebook        *notebook,
2077                            GtkWidget          *page,
2078                            gint                x,
2079                            gint                y,
2080                            GeditWindow        *window)
2081 {
2082 	GeditWindow *new_window;
2083 	GtkWidget *new_notebook;
2084 
2085 	new_window = clone_window (window);
2086 
2087 	gtk_window_move (GTK_WINDOW (new_window), x, y);
2088 	gtk_widget_show (GTK_WIDGET (new_window));
2089 
2090 	new_notebook = _gedit_window_get_notebook (GEDIT_WINDOW (new_window));
2091 
2092 	return GTK_NOTEBOOK (new_notebook);
2093 }
2094 
2095 static void
on_tab_close_request(GeditMultiNotebook * multi,GeditNotebook * notebook,GeditTab * tab,GtkWindow * window)2096 on_tab_close_request (GeditMultiNotebook *multi,
2097 		      GeditNotebook      *notebook,
2098 		      GeditTab           *tab,
2099 		      GtkWindow          *window)
2100 {
2101 	/* Note: we are destroying the tab before the default handler
2102 	 * seems to be ok, but we need to keep an eye on this. */
2103 	_gedit_cmd_file_close_tab (tab, GEDIT_WINDOW (window));
2104 }
2105 
2106 static void
on_show_popup_menu(GeditMultiNotebook * multi,GdkEventButton * event,GeditTab * tab,GeditWindow * window)2107 on_show_popup_menu (GeditMultiNotebook *multi,
2108                     GdkEventButton     *event,
2109                     GeditTab           *tab,
2110                     GeditWindow        *window)
2111 {
2112 	GtkWidget *menu;
2113 
2114 	if (event == NULL)
2115 	{
2116 		return;
2117 	}
2118 
2119 	menu = gedit_notebook_popup_menu_new (window, tab);
2120 
2121 	g_signal_connect (menu,
2122 			  "selection-done",
2123 			  G_CALLBACK (gtk_widget_destroy),
2124 			  NULL);
2125 
2126 	gtk_widget_show (menu);
2127 	gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
2128 }
2129 
2130 static void
on_notebook_changed(GeditMultiNotebook * mnb,GParamSpec * pspec,GeditWindow * window)2131 on_notebook_changed (GeditMultiNotebook *mnb,
2132 		     GParamSpec         *pspec,
2133 		     GeditWindow        *window)
2134 {
2135 	update_actions_sensitivity (window);
2136 }
2137 
2138 static void
on_notebook_removed(GeditMultiNotebook * mnb,GeditNotebook * notebook,GeditWindow * window)2139 on_notebook_removed (GeditMultiNotebook *mnb,
2140 		     GeditNotebook      *notebook,
2141 		     GeditWindow        *window)
2142 {
2143 	update_actions_sensitivity (window);
2144 }
2145 
2146 static void
on_fullscreen_toggle_button_toggled(GtkToggleButton * fullscreen_toggle_button,GeditWindow * window)2147 on_fullscreen_toggle_button_toggled (GtkToggleButton *fullscreen_toggle_button,
2148 				     GeditWindow     *window)
2149 {
2150 	update_fullscreen_revealer_state (window);
2151 }
2152 
2153 static void
side_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,GeditWindow * window)2154 side_panel_size_allocate (GtkWidget     *widget,
2155 			  GtkAllocation *allocation,
2156 			  GeditWindow   *window)
2157 {
2158 	window->priv->side_panel_size = allocation->width;
2159 }
2160 
2161 static void
bottom_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,GeditWindow * window)2162 bottom_panel_size_allocate (GtkWidget     *widget,
2163 			    GtkAllocation *allocation,
2164 			    GeditWindow   *window)
2165 {
2166 	window->priv->bottom_panel_size = allocation->height;
2167 }
2168 
2169 static void
hpaned_restore_position(GtkWidget * widget,GeditWindow * window)2170 hpaned_restore_position (GtkWidget   *widget,
2171 			 GeditWindow *window)
2172 {
2173 	gint pos;
2174 
2175 	gedit_debug_message (DEBUG_WINDOW,
2176 			     "Restoring hpaned position: side panel size %d",
2177 			     window->priv->side_panel_size);
2178 
2179 	pos = MAX (100, window->priv->side_panel_size);
2180 	gtk_paned_set_position (GTK_PANED (window->priv->hpaned), pos);
2181 
2182 	/* start monitoring the size */
2183 	g_signal_connect (window->priv->side_panel,
2184 			  "size-allocate",
2185 			  G_CALLBACK (side_panel_size_allocate),
2186 			  window);
2187 
2188 	/* run this only once */
2189 	g_signal_handlers_disconnect_by_func (widget, hpaned_restore_position, window);
2190 }
2191 
2192 static void
vpaned_restore_position(GtkWidget * widget,GeditWindow * window)2193 vpaned_restore_position (GtkWidget   *widget,
2194 			 GeditWindow *window)
2195 {
2196 	gint pos;
2197 	GtkAllocation allocation;
2198 
2199 	gedit_debug_message (DEBUG_WINDOW,
2200 			     "Restoring vpaned position: bottom panel size %d",
2201 			     window->priv->bottom_panel_size);
2202 
2203 	gtk_widget_get_allocation (widget, &allocation);
2204 	pos = allocation.height -
2205 	      MAX (50, window->priv->bottom_panel_size);
2206 	gtk_paned_set_position (GTK_PANED (window->priv->vpaned), pos);
2207 
2208 	/* start monitoring the size */
2209 	g_signal_connect (window->priv->bottom_panel,
2210 			  "size-allocate",
2211 			  G_CALLBACK (bottom_panel_size_allocate),
2212 			  window);
2213 
2214 	/* run this only once */
2215 	g_signal_handlers_disconnect_by_func (widget, vpaned_restore_position, window);
2216 }
2217 
2218 static void
side_panel_visibility_changed(GtkWidget * panel,GParamSpec * pspec,GeditWindow * window)2219 side_panel_visibility_changed (GtkWidget   *panel,
2220                                GParamSpec  *pspec,
2221                                GeditWindow *window)
2222 {
2223 	gboolean visible;
2224 	GAction *action;
2225 	gchar *layout_desc;
2226 
2227 	visible = gtk_widget_get_visible (panel);
2228 
2229 	g_settings_set_boolean (window->priv->ui_settings,
2230 				GEDIT_SETTINGS_SIDE_PANEL_VISIBLE,
2231 				visible);
2232 
2233 	/* sync the action state if the panel visibility was changed programmatically */
2234 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "side-panel");
2235 	g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (visible));
2236 
2237 	/* focus the right widget and set the right styles */
2238 	if (visible)
2239 	{
2240 		gtk_widget_grab_focus (window->priv->side_panel);
2241 	}
2242 	else
2243 	{
2244 		gtk_widget_grab_focus (GTK_WIDGET (window->priv->multi_notebook));
2245 	}
2246 
2247 	g_object_get (gtk_settings_get_default (),
2248 		      "gtk-decoration-layout", &layout_desc,
2249 		      NULL);
2250 	if (visible)
2251 	{
2252 		gchar **tokens;
2253 
2254 		tokens = g_strsplit (layout_desc, ":", 2);
2255 		if (tokens)
2256 		{
2257 			gchar *layout_headerbar;
2258 
2259 			layout_headerbar = g_strdup_printf ("%c%s", ':', tokens[1]);
2260 			gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (window->priv->headerbar), layout_headerbar);
2261 			gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (window->priv->side_headerbar), tokens[0]);
2262 
2263 			g_free (layout_headerbar);
2264 			g_strfreev (tokens);
2265 		}
2266 	}
2267 	else
2268 	{
2269 		gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (window->priv->headerbar), layout_desc);
2270 		gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (window->priv->side_headerbar), NULL);
2271 	}
2272 
2273 	g_free (layout_desc);
2274 }
2275 
2276 static void
on_side_panel_stack_children_number_changed(GtkStack * stack,GtkWidget * widget,GeditWindow * window)2277 on_side_panel_stack_children_number_changed (GtkStack    *stack,
2278                                              GtkWidget   *widget,
2279                                              GeditWindow *window)
2280 {
2281 	GeditWindowPrivate *priv = window->priv;
2282 	GList *children;
2283 
2284 	children = gtk_container_get_children (GTK_CONTAINER (priv->side_panel));
2285 
2286 	if (children != NULL && children->next != NULL)
2287 	{
2288 		gtk_widget_show (priv->side_stack_switcher);
2289 
2290 #ifndef OS_OSX
2291 		gtk_header_bar_set_custom_title (GTK_HEADER_BAR (priv->side_headerbar), priv->side_stack_switcher);
2292 #endif
2293 	}
2294 	else
2295 	{
2296 		/* side_stack_switcher can get NULL in dispose, before stack children
2297 		   are being removed */
2298 		if (priv->side_stack_switcher != NULL)
2299 		{
2300 			gtk_widget_hide (priv->side_stack_switcher);
2301 		}
2302 
2303 #ifndef OS_OSX
2304 		gtk_header_bar_set_custom_title (GTK_HEADER_BAR (priv->side_headerbar), NULL);
2305 #endif
2306 	}
2307 
2308 	g_list_free (children);
2309 }
2310 
2311 static void
setup_side_panel(GeditWindow * window)2312 setup_side_panel (GeditWindow *window)
2313 {
2314 	GeditWindowPrivate *priv = window->priv;
2315 	GtkWidget *documents_panel;
2316 
2317 	gedit_debug (DEBUG_WINDOW);
2318 
2319 	g_signal_connect_after (priv->side_panel,
2320 	                        "notify::visible",
2321 	                        G_CALLBACK (side_panel_visibility_changed),
2322 	                        window);
2323 
2324 #ifdef OS_OSX
2325 	priv->side_stack_switcher = priv->side_panel_inline_stack_switcher;
2326 #else
2327 	priv->side_stack_switcher = gedit_menu_stack_switcher_new ();
2328 #endif
2329 
2330 	gtk_button_set_relief (GTK_BUTTON (priv->side_stack_switcher), GTK_RELIEF_NONE);
2331 	g_object_ref_sink (priv->side_stack_switcher);
2332 
2333 	gedit_utils_set_atk_name_description (priv->side_stack_switcher, _("Change side panel page"),  NULL);
2334 
2335 	gedit_menu_stack_switcher_set_stack (GEDIT_MENU_STACK_SWITCHER (priv->side_stack_switcher),
2336 	                                     GTK_STACK (priv->side_panel));
2337 
2338 	g_signal_connect (priv->side_panel,
2339 	                  "add",
2340 	                  G_CALLBACK (on_side_panel_stack_children_number_changed),
2341 	                  window);
2342 
2343 	g_signal_connect (priv->side_panel,
2344 	                  "remove",
2345 	                  G_CALLBACK (on_side_panel_stack_children_number_changed),
2346 	                  window);
2347 
2348 	documents_panel = gedit_documents_panel_new (window);
2349 	gtk_widget_show_all (documents_panel);
2350 	gtk_stack_add_titled (GTK_STACK (priv->side_panel),
2351 	                      documents_panel,
2352 	                      "GeditWindowDocumentsPanel",
2353 	                      _("Documents"));
2354 }
2355 
2356 static void
bottom_panel_visibility_changed(GtkWidget * panel_box,GParamSpec * pspec,GeditWindow * window)2357 bottom_panel_visibility_changed (GtkWidget   *panel_box,
2358                                  GParamSpec  *pspec,
2359                                  GeditWindow *window)
2360 {
2361 	gboolean visible;
2362 	GAction *action;
2363 
2364 	visible = gtk_widget_get_visible (panel_box);
2365 
2366 	g_settings_set_boolean (window->priv->ui_settings,
2367 				GEDIT_SETTINGS_BOTTOM_PANEL_VISIBLE,
2368 				visible);
2369 
2370 	/* sync the action state if the panel visibility was changed programmatically */
2371 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "bottom-panel");
2372 	g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (visible));
2373 
2374 	/* focus the right widget */
2375 	if (visible)
2376 	{
2377 		gtk_widget_grab_focus (window->priv->side_panel);
2378 	}
2379 	else
2380 	{
2381 		gtk_widget_grab_focus (GTK_WIDGET (window->priv->multi_notebook));
2382 	}
2383 }
2384 
2385 static void
bottom_panel_item_removed(GtkStack * panel,GtkWidget * item,GeditWindow * window)2386 bottom_panel_item_removed (GtkStack    *panel,
2387 			   GtkWidget   *item,
2388 			   GeditWindow *window)
2389 {
2390 	gtk_widget_set_visible (window->priv->bottom_panel,
2391 				gtk_stack_get_visible_child (panel) != NULL);
2392 
2393 	update_actions_sensitivity (window);
2394 }
2395 
2396 static void
bottom_panel_item_added(GtkStack * panel,GtkWidget * item,GeditWindow * window)2397 bottom_panel_item_added (GtkStack    *panel,
2398 			 GtkWidget   *item,
2399 			 GeditWindow *window)
2400 {
2401 	GList *children;
2402 	int n_children;
2403 
2404 	children = gtk_container_get_children (GTK_CONTAINER (panel));
2405 	n_children = g_list_length (children);
2406 	g_list_free (children);
2407 
2408 	/* First item added. */
2409 	if (n_children == 1)
2410 	{
2411 		gboolean show;
2412 
2413 		show = g_settings_get_boolean (window->priv->ui_settings,
2414 		                               "bottom-panel-visible");
2415 		if (show)
2416 		{
2417 			gtk_widget_show (window->priv->bottom_panel);
2418 		}
2419 
2420 		update_actions_sensitivity (window);
2421 	}
2422 }
2423 
2424 static void
setup_bottom_panel(GeditWindow * window)2425 setup_bottom_panel (GeditWindow *window)
2426 {
2427 	gedit_debug (DEBUG_WINDOW);
2428 
2429 	g_signal_connect_after (window->priv->bottom_panel,
2430 	                        "notify::visible",
2431 	                        G_CALLBACK (bottom_panel_visibility_changed),
2432 	                        window);
2433 }
2434 
2435 static void
init_panels_visibility(GeditWindow * window)2436 init_panels_visibility (GeditWindow *window)
2437 {
2438 	gchar *panel_page;
2439 	GtkWidget *panel_child;
2440 	gboolean side_panel_visible;
2441 	gboolean bottom_panel_visible;
2442 
2443 	gedit_debug (DEBUG_WINDOW);
2444 
2445 	/* side panel */
2446 	panel_page = g_settings_get_string (window->priv->window_settings,
2447 	                                    GEDIT_SETTINGS_SIDE_PANEL_ACTIVE_PAGE);
2448 	panel_child = gtk_stack_get_child_by_name (GTK_STACK (window->priv->side_panel),
2449 	                                           panel_page);
2450 	if (panel_child != NULL)
2451 	{
2452 		gtk_stack_set_visible_child (GTK_STACK (window->priv->side_panel),
2453 		                             panel_child);
2454 	}
2455 
2456 	g_free (panel_page);
2457 
2458 	side_panel_visible = g_settings_get_boolean (window->priv->ui_settings,
2459 						    GEDIT_SETTINGS_SIDE_PANEL_VISIBLE);
2460 	bottom_panel_visible = g_settings_get_boolean (window->priv->ui_settings,
2461 						      GEDIT_SETTINGS_BOTTOM_PANEL_VISIBLE);
2462 
2463 	if (side_panel_visible)
2464 	{
2465 		gtk_widget_show (window->priv->side_panel);
2466 	}
2467 
2468 	/* bottom pane, it can be empty */
2469 	if (gtk_stack_get_visible_child (GTK_STACK (window->priv->bottom_panel)) != NULL)
2470 	{
2471 		panel_page = g_settings_get_string (window->priv->window_settings,
2472 		                                    GEDIT_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE);
2473 		panel_child = gtk_stack_get_child_by_name (GTK_STACK (window->priv->side_panel),
2474 		                                           panel_page);
2475 		if (panel_child)
2476 		{
2477 			gtk_stack_set_visible_child (GTK_STACK (window->priv->bottom_panel),
2478 			                             panel_child);
2479 		}
2480 
2481 		if (bottom_panel_visible)
2482 		{
2483 			gtk_widget_show (window->priv->bottom_panel);
2484 		}
2485 
2486 		g_free (panel_page);
2487 	}
2488 
2489 	/* start track sensitivity after the initial state is set */
2490 	window->priv->bottom_panel_item_removed_handler_id =
2491 		g_signal_connect (window->priv->bottom_panel,
2492 				  "remove",
2493 				  G_CALLBACK (bottom_panel_item_removed),
2494 				  window);
2495 
2496 	g_signal_connect_after (window->priv->bottom_panel,
2497 	                        "add",
2498 	                        G_CALLBACK (bottom_panel_item_added),
2499 	                        window);
2500 }
2501 
2502 static void
clipboard_owner_change(GtkClipboard * clipboard,GdkEventOwnerChange * event,GeditWindow * window)2503 clipboard_owner_change (GtkClipboard        *clipboard,
2504 			GdkEventOwnerChange *event,
2505 			GeditWindow         *window)
2506 {
2507 	set_paste_sensitivity_according_to_clipboard (window,
2508 						      clipboard);
2509 }
2510 
2511 static void
window_realized(GtkWidget * window,gpointer * data)2512 window_realized (GtkWidget *window,
2513 		 gpointer  *data)
2514 {
2515 	GtkClipboard *clipboard;
2516 
2517 	clipboard = gtk_widget_get_clipboard (window,
2518 					      GDK_SELECTION_CLIPBOARD);
2519 
2520 	g_signal_connect (clipboard,
2521 			  "owner_change",
2522 			  G_CALLBACK (clipboard_owner_change),
2523 			  window);
2524 }
2525 
2526 static void
window_unrealized(GtkWidget * window,gpointer * data)2527 window_unrealized (GtkWidget *window,
2528 		   gpointer  *data)
2529 {
2530 	GtkClipboard *clipboard;
2531 
2532 	clipboard = gtk_widget_get_clipboard (window,
2533 					      GDK_SELECTION_CLIPBOARD);
2534 
2535 	g_signal_handlers_disconnect_by_func (clipboard,
2536 					      G_CALLBACK (clipboard_owner_change),
2537 					      window);
2538 }
2539 
2540 static void
extension_added(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,GeditWindow * window)2541 extension_added (PeasExtensionSet *extensions,
2542 		 PeasPluginInfo   *info,
2543 		 PeasExtension    *exten,
2544 		 GeditWindow      *window)
2545 {
2546 	gedit_window_activatable_activate (GEDIT_WINDOW_ACTIVATABLE (exten));
2547 }
2548 
2549 static void
extension_removed(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,GeditWindow * window)2550 extension_removed (PeasExtensionSet *extensions,
2551 		   PeasPluginInfo   *info,
2552 		   PeasExtension    *exten,
2553 		   GeditWindow      *window)
2554 {
2555 	gedit_window_activatable_deactivate (GEDIT_WINDOW_ACTIVATABLE (exten));
2556 }
2557 
2558 static GActionEntry win_entries[] = {
2559 	{ "new-tab", _gedit_cmd_file_new },
2560 	{ "open", _gedit_cmd_file_open },
2561 	{ "revert", _gedit_cmd_file_revert },
2562 	{ "reopen-closed-tab", _gedit_cmd_file_reopen_closed_tab },
2563 	{ "save", _gedit_cmd_file_save },
2564 	{ "save-as", _gedit_cmd_file_save_as },
2565 	{ "save-all", _gedit_cmd_file_save_all },
2566 	{ "close", _gedit_cmd_file_close },
2567 	{ "close-all", _gedit_cmd_file_close_all },
2568 	{ "print", _gedit_cmd_file_print },
2569 	{ "focus-active-view", NULL, NULL, "false", _gedit_cmd_view_focus_active },
2570 	{ "side-panel", NULL, NULL, "false", _gedit_cmd_view_toggle_side_panel },
2571 	{ "bottom-panel", NULL, NULL, "false", _gedit_cmd_view_toggle_bottom_panel },
2572 	{ "fullscreen", NULL, NULL, "false", _gedit_cmd_view_toggle_fullscreen_mode },
2573 	{ "leave-fullscreen", _gedit_cmd_view_leave_fullscreen_mode },
2574 	{ "find", _gedit_cmd_search_find },
2575 	{ "find-next", _gedit_cmd_search_find_next },
2576 	{ "find-prev", _gedit_cmd_search_find_prev },
2577 	{ "replace", _gedit_cmd_search_replace },
2578 	{ "clear-highlight", _gedit_cmd_search_clear_highlight },
2579 	{ "goto-line", _gedit_cmd_search_goto_line },
2580 	{ "new-tab-group", _gedit_cmd_documents_new_tab_group },
2581 	{ "previous-tab-group", _gedit_cmd_documents_previous_tab_group },
2582 	{ "next-tab-group", _gedit_cmd_documents_next_tab_group },
2583 	{ "previous-document", _gedit_cmd_documents_previous_document },
2584 	{ "next-document", _gedit_cmd_documents_next_document },
2585 	{ "move-to-new-window", _gedit_cmd_documents_move_to_new_window },
2586 	{ "undo", _gedit_cmd_edit_undo },
2587 	{ "redo", _gedit_cmd_edit_redo },
2588 	{ "cut", _gedit_cmd_edit_cut },
2589 	{ "copy", _gedit_cmd_edit_copy },
2590 	{ "paste", _gedit_cmd_edit_paste },
2591 	{ "delete", _gedit_cmd_edit_delete },
2592 	{ "select-all", _gedit_cmd_edit_select_all },
2593 	{ "highlight-mode", _gedit_cmd_view_highlight_mode },
2594 	{ "overwrite-mode", NULL, NULL, "false", _gedit_cmd_edit_overwrite_mode }
2595 };
2596 
2597 static void
sync_fullscreen_actions(GeditWindow * window,gboolean fullscreen)2598 sync_fullscreen_actions (GeditWindow *window,
2599 			 gboolean     fullscreen)
2600 {
2601 	GtkMenuButton *button;
2602 	GPropertyAction *action;
2603 
2604 	button = fullscreen ? window->priv->fullscreen_gear_button : window->priv->gear_button;
2605 	g_action_map_remove_action (G_ACTION_MAP (window), "hamburger-menu");
2606 	action = g_property_action_new ("hamburger-menu", button, "active");
2607 	g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
2608 	g_object_unref (action);
2609 }
2610 
2611 static void
init_amtk_application_window(GeditWindow * gedit_window)2612 init_amtk_application_window (GeditWindow *gedit_window)
2613 {
2614 	AmtkApplicationWindow *amtk_window;
2615 
2616 	amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW (gedit_window));
2617 	amtk_application_window_set_statusbar (amtk_window, GTK_STATUSBAR (gedit_window->priv->statusbar));
2618 }
2619 
2620 static GtkWidget *
create_open_buttons(GeditWindow * window,GtkMenuButton ** open_recent_button)2621 create_open_buttons (GeditWindow    *window,
2622 		     GtkMenuButton **open_recent_button)
2623 {
2624 	GtkWidget *hbox;
2625 	GtkStyleContext *style_context;
2626 	GtkWidget *open_dialog_button;
2627 	GtkWidget *my_open_recent_button;
2628 	AmtkApplicationWindow *amtk_window;
2629 	GtkWidget *recent_menu;
2630 
2631 	/* It currently needs to be a GtkBox, not a GtkGrid, because GtkGrid and
2632 	 * GTK_STYLE_CLASS_LINKED doesn't work as expected in a RTL locale.
2633 	 * Probably a GtkGrid bug.
2634 	 */
2635 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2636 	style_context = gtk_widget_get_style_context (hbox);
2637 	gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
2638 
2639 	open_dialog_button = gtk_button_new_with_mnemonic (_("_Open"));
2640 	gtk_widget_set_tooltip_text (open_dialog_button, _("Open a file"));
2641 	gtk_actionable_set_action_name (GTK_ACTIONABLE (open_dialog_button), "win.open");
2642 
2643 	my_open_recent_button = gtk_menu_button_new ();
2644 	gtk_widget_set_tooltip_text (my_open_recent_button, _("Open a recently used file"));
2645 
2646 	amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW (window));
2647 	recent_menu = amtk_application_window_create_open_recent_menu (amtk_window);
2648 	gtk_menu_button_set_popup (GTK_MENU_BUTTON (my_open_recent_button), recent_menu);
2649 
2650 	gtk_container_add (GTK_CONTAINER (hbox), open_dialog_button);
2651 	gtk_container_add (GTK_CONTAINER (hbox), my_open_recent_button);
2652 	gtk_widget_show_all (hbox);
2653 
2654 	if (open_recent_button != NULL)
2655 	{
2656 		*open_recent_button = GTK_MENU_BUTTON (my_open_recent_button);
2657 	}
2658 
2659 	return hbox;
2660 }
2661 
2662 static void
init_open_buttons(GeditWindow * window)2663 init_open_buttons (GeditWindow *window)
2664 {
2665 	gtk_container_add_with_properties (GTK_CONTAINER (window->priv->headerbar),
2666 					   create_open_buttons (window, NULL),
2667 					   "position", 0, /* The first on the left. */
2668 					   NULL);
2669 
2670 	gtk_container_add_with_properties (GTK_CONTAINER (window->priv->fullscreen_headerbar),
2671 					   create_open_buttons (window, &(window->priv->fullscreen_open_recent_button)),
2672 					   "position", 0, /* The first on the left. */
2673 					   NULL);
2674 
2675 	g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_recent_button),
2676 	                  "toggled",
2677 	                  G_CALLBACK (on_fullscreen_toggle_button_toggled),
2678 	                  window);
2679 }
2680 
2681 static void
gedit_window_init(GeditWindow * window)2682 gedit_window_init (GeditWindow *window)
2683 {
2684 	GtkTargetList *tl;
2685 	GMenuModel *hamburger_menu;
2686 
2687 	gedit_debug (DEBUG_WINDOW);
2688 
2689 	window->priv = gedit_window_get_instance_private (window);
2690 
2691 	window->priv->removing_tabs = FALSE;
2692 	window->priv->state = GEDIT_WINDOW_STATE_NORMAL;
2693 	window->priv->inhibition_cookie = 0;
2694 	window->priv->dispose_has_run = FALSE;
2695 	window->priv->direct_save_uri = NULL;
2696 	window->priv->closed_docs_stack = NULL;
2697 	window->priv->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
2698 	window->priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");
2699 
2700 	/* window settings are applied only once the window is closed. We do not
2701 	   want to keep writing to disk when the window is dragged around */
2702 	window->priv->window_settings = g_settings_new ("org.gnome.gedit.state.window");
2703 	g_settings_delay (window->priv->window_settings);
2704 
2705 	window->priv->message_bus = gedit_message_bus_new ();
2706 
2707 	gtk_widget_init_template (GTK_WIDGET (window));
2708 	init_amtk_application_window (window);
2709 	init_open_buttons (window);
2710 
2711 	g_action_map_add_action_entries (G_ACTION_MAP (window),
2712 	                                 win_entries,
2713 	                                 G_N_ELEMENTS (win_entries),
2714 	                                 window);
2715 
2716 	window->priv->window_group = gtk_window_group_new ();
2717 	gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
2718 
2719 	setup_fullscreen_eventbox (window);
2720 	sync_fullscreen_actions (window, FALSE);
2721 
2722 	hamburger_menu = _gedit_app_get_hamburger_menu (GEDIT_APP (g_application_get_default ()));
2723 	if (hamburger_menu)
2724 	{
2725 		gtk_menu_button_set_menu_model (window->priv->gear_button, hamburger_menu);
2726 		gtk_menu_button_set_menu_model (window->priv->fullscreen_gear_button, hamburger_menu);
2727 	}
2728 	else
2729 	{
2730 		gtk_widget_hide (GTK_WIDGET (window->priv->gear_button));
2731 		gtk_widget_hide (GTK_WIDGET (window->priv->fullscreen_gear_button));
2732 		gtk_widget_set_no_show_all (GTK_WIDGET (window->priv->gear_button), TRUE);
2733 		gtk_widget_set_no_show_all (GTK_WIDGET (window->priv->fullscreen_gear_button), TRUE);
2734 	}
2735 
2736 	g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_gear_button),
2737 	                  "toggled",
2738 	                  G_CALLBACK (on_fullscreen_toggle_button_toggled),
2739 	                  window);
2740 
2741 	/* Setup status bar */
2742 	setup_statusbar (window);
2743 
2744 	/* Setup main area */
2745 	g_signal_connect (window->priv->multi_notebook,
2746 			  "notebook-removed",
2747 			  G_CALLBACK (on_notebook_removed),
2748 			  window);
2749 	g_signal_connect (window->priv->multi_notebook,
2750 			  "notify::active-notebook",
2751 			  G_CALLBACK (on_notebook_changed),
2752 			  window);
2753 
2754 	g_signal_connect (window->priv->multi_notebook,
2755 			  "tab-added",
2756 			  G_CALLBACK (on_tab_added),
2757 			  window);
2758 
2759 	g_signal_connect (window->priv->multi_notebook,
2760 			  "tab-removed",
2761 			  G_CALLBACK (on_tab_removed),
2762 			  window);
2763 
2764 	g_signal_connect (window->priv->multi_notebook,
2765 			  "switch-tab",
2766 			  G_CALLBACK (tab_switched),
2767 			  window);
2768 
2769 	g_signal_connect (window->priv->multi_notebook,
2770 			  "tab-close-request",
2771 			  G_CALLBACK (on_tab_close_request),
2772 			  window);
2773 
2774 	g_signal_connect (window->priv->multi_notebook,
2775 			  "page-reordered",
2776 			  G_CALLBACK (on_page_reordered),
2777 			  window);
2778 
2779 	g_signal_connect (window->priv->multi_notebook,
2780 	                  "create-window",
2781 	                  G_CALLBACK (on_notebook_create_window),
2782 	                  window);
2783 
2784 	g_signal_connect (window->priv->multi_notebook,
2785 			  "show-popup-menu",
2786 			  G_CALLBACK (on_show_popup_menu),
2787 			  window);
2788 
2789 	/* side and bottom panels */
2790 	setup_side_panel (window);
2791 	setup_bottom_panel (window);
2792 
2793 	/* panels' state must be restored after panels have been mapped,
2794 	 * since the bottom panel position depends on the size of the vpaned. */
2795 	window->priv->side_panel_size = g_settings_get_int (window->priv->window_settings,
2796 							    GEDIT_SETTINGS_SIDE_PANEL_SIZE);
2797 	window->priv->bottom_panel_size = g_settings_get_int (window->priv->window_settings,
2798 							      GEDIT_SETTINGS_BOTTOM_PANEL_SIZE);
2799 
2800 	g_signal_connect_after (window->priv->hpaned,
2801 				"map",
2802 				G_CALLBACK (hpaned_restore_position),
2803 				window);
2804 	g_signal_connect_after (window->priv->vpaned,
2805 				"map",
2806 				G_CALLBACK (vpaned_restore_position),
2807 				window);
2808 
2809 	/* Drag and drop support */
2810 	gtk_drag_dest_set (GTK_WIDGET (window),
2811 			   GTK_DEST_DEFAULT_MOTION |
2812 			   GTK_DEST_DEFAULT_HIGHLIGHT |
2813 			   GTK_DEST_DEFAULT_DROP,
2814 			   drop_types,
2815 			   G_N_ELEMENTS (drop_types),
2816 			   GDK_ACTION_COPY);
2817 
2818 	/* Add uri targets */
2819 	tl = gtk_drag_dest_get_target_list (GTK_WIDGET (window));
2820 
2821 	if (tl == NULL)
2822 	{
2823 		tl = gtk_target_list_new (drop_types, G_N_ELEMENTS (drop_types));
2824 		gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
2825 		gtk_target_list_unref (tl);
2826 	}
2827 
2828 	gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
2829 
2830 	/* connect instead of override, so that we can
2831 	 * share the cb code with the view */
2832 	g_signal_connect (window,
2833 			  "drag_data_received",
2834 	                  G_CALLBACK (drag_data_received_cb),
2835 	                  NULL);
2836 	g_signal_connect (window,
2837 			  "drag_drop",
2838 	                  G_CALLBACK (drag_drop_cb),
2839 	                  NULL);
2840 
2841 	/* we can get the clipboard only after the widget
2842 	 * is realized */
2843 	g_signal_connect (window,
2844 			  "realize",
2845 			  G_CALLBACK (window_realized),
2846 			  NULL);
2847 	g_signal_connect (window,
2848 			  "unrealize",
2849 			  G_CALLBACK (window_unrealized),
2850 			  NULL);
2851 
2852 	gedit_debug_message (DEBUG_WINDOW, "Update plugins ui");
2853 
2854 	window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (gedit_plugins_engine_get_default ()),
2855 							   GEDIT_TYPE_WINDOW_ACTIVATABLE,
2856 							   "window", window,
2857 							   NULL);
2858 	g_signal_connect (window->priv->extensions,
2859 			  "extension-added",
2860 			  G_CALLBACK (extension_added),
2861 			  window);
2862 	g_signal_connect (window->priv->extensions,
2863 			  "extension-removed",
2864 			  G_CALLBACK (extension_removed),
2865 			  window);
2866 	peas_extension_set_foreach (window->priv->extensions,
2867 	                            (PeasExtensionSetForeachFunc) extension_added,
2868 	                            window);
2869 
2870 	/* set visibility of panels.
2871 	 * This needs to be done after plugins activatation */
2872 	init_panels_visibility (window);
2873 
2874 	update_actions_sensitivity (window);
2875 
2876 	gedit_debug_message (DEBUG_WINDOW, "END");
2877 }
2878 
2879 /**
2880  * gedit_window_get_active_view:
2881  * @window: a #GeditWindow
2882  *
2883  * Gets the active #GeditView.
2884  *
2885  * Returns: (transfer none): the active #GeditView
2886  */
2887 GeditView *
gedit_window_get_active_view(GeditWindow * window)2888 gedit_window_get_active_view (GeditWindow *window)
2889 {
2890 	GeditTab *tab;
2891 	GeditView *view;
2892 
2893 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
2894 
2895 	tab = gedit_window_get_active_tab (window);
2896 
2897 	if (tab == NULL)
2898 		return NULL;
2899 
2900 	view = gedit_tab_get_view (tab);
2901 
2902 	return view;
2903 }
2904 
2905 /**
2906  * gedit_window_get_active_document:
2907  * @window: a #GeditWindow
2908  *
2909  * Gets the active #GeditDocument.
2910  *
2911  * Returns: (transfer none): the active #GeditDocument
2912  */
2913 GeditDocument *
gedit_window_get_active_document(GeditWindow * window)2914 gedit_window_get_active_document (GeditWindow *window)
2915 {
2916 	GeditView *view;
2917 
2918 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
2919 
2920 	view = gedit_window_get_active_view (window);
2921 	if (view == NULL)
2922 		return NULL;
2923 
2924 	return GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
2925 }
2926 
2927 GtkWidget *
_gedit_window_get_multi_notebook(GeditWindow * window)2928 _gedit_window_get_multi_notebook (GeditWindow *window)
2929 {
2930 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
2931 
2932 	return GTK_WIDGET (window->priv->multi_notebook);
2933 }
2934 
2935 GtkWidget *
_gedit_window_get_notebook(GeditWindow * window)2936 _gedit_window_get_notebook (GeditWindow *window)
2937 {
2938 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
2939 
2940 	return GTK_WIDGET (gedit_multi_notebook_get_active_notebook (window->priv->multi_notebook));
2941 }
2942 
2943 static GeditTab *
process_create_tab(GeditWindow * window,GtkWidget * notebook,GeditTab * tab,gboolean jump_to)2944 process_create_tab (GeditWindow *window,
2945                     GtkWidget   *notebook,
2946                     GeditTab    *tab,
2947                     gboolean     jump_to)
2948 {
2949 	if (tab == NULL)
2950 	{
2951 		return NULL;
2952 	}
2953 
2954 	gedit_debug (DEBUG_WINDOW);
2955 
2956 	gtk_widget_show (GTK_WIDGET (tab));
2957 	gedit_notebook_add_tab (GEDIT_NOTEBOOK (notebook),
2958 	                        tab,
2959 	                        -1,
2960 	                        jump_to);
2961 
2962 	if (!gtk_widget_get_visible (GTK_WIDGET (window)))
2963 	{
2964 		gtk_window_present (GTK_WINDOW (window));
2965 	}
2966 
2967 	return tab;
2968 }
2969 
2970 /**
2971  * gedit_window_create_tab:
2972  * @window: a #GeditWindow
2973  * @jump_to: %TRUE to set the new #GeditTab as active
2974  *
2975  * Creates a new #GeditTab and adds the new tab to the #GtkNotebook.
2976  * In case @jump_to is %TRUE the #GtkNotebook switches to that new #GeditTab.
2977  *
2978  * Returns: (transfer none): a new #GeditTab
2979  */
2980 GeditTab *
gedit_window_create_tab(GeditWindow * window,gboolean jump_to)2981 gedit_window_create_tab (GeditWindow *window,
2982 			 gboolean     jump_to)
2983 {
2984 	GtkWidget *notebook;
2985 	GeditTab *tab;
2986 
2987 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
2988 
2989 	gedit_debug (DEBUG_WINDOW);
2990 
2991 	notebook = _gedit_window_get_notebook (window);
2992 	tab = _gedit_tab_new ();
2993 	gtk_widget_show (GTK_WIDGET (tab));
2994 
2995 	return process_create_tab (window, notebook, tab, jump_to);
2996 }
2997 
2998 /**
2999  * gedit_window_create_tab_from_location:
3000  * @window: a #GeditWindow
3001  * @location: the location of the document
3002  * @encoding: (allow-none): a #GtkSourceEncoding, or %NULL
3003  * @line_pos: the line position to visualize
3004  * @column_pos: the column position to visualize
3005  * @create: %TRUE to create a new document in case @uri does exist
3006  * @jump_to: %TRUE to set the new #GeditTab as active
3007  *
3008  * Creates a new #GeditTab loading the document specified by @uri.
3009  * In case @jump_to is %TRUE the #GtkNotebook swithes to that new #GeditTab.
3010  * Whether @create is %TRUE, creates a new empty document if location does
3011  * not refer to an existing file
3012  *
3013  * Returns: (transfer none): a new #GeditTab
3014  */
3015 GeditTab *
gedit_window_create_tab_from_location(GeditWindow * window,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create,gboolean jump_to)3016 gedit_window_create_tab_from_location (GeditWindow             *window,
3017 				       GFile                   *location,
3018 				       const GtkSourceEncoding *encoding,
3019 				       gint                     line_pos,
3020 				       gint                     column_pos,
3021 				       gboolean                 create,
3022 				       gboolean                 jump_to)
3023 {
3024 	GtkWidget *notebook;
3025 	GeditTab *tab;
3026 
3027 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3028 	g_return_val_if_fail (G_IS_FILE (location), NULL);
3029 
3030 	gedit_debug (DEBUG_WINDOW);
3031 
3032 	tab = _gedit_tab_new ();
3033 
3034 	_gedit_tab_load (tab,
3035 			 location,
3036 			 encoding,
3037 			 line_pos,
3038 			 column_pos,
3039 			 create);
3040 
3041 	notebook = _gedit_window_get_notebook (window);
3042 
3043 	return process_create_tab (window, notebook, tab, jump_to);
3044 }
3045 
3046 /**
3047  * gedit_window_create_tab_from_stream:
3048  * @window: a #GeditWindow
3049  * @stream: a #GInputStream
3050  * @encoding: (allow-none): a #GtkSourceEncoding, or %NULL
3051  * @line_pos: the line position to visualize
3052  * @column_pos: the column position to visualize
3053  * @jump_to: %TRUE to set the new #GeditTab as active
3054  *
3055  * Returns: (transfer none): a new #GeditTab
3056  */
3057 GeditTab *
gedit_window_create_tab_from_stream(GeditWindow * window,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean jump_to)3058 gedit_window_create_tab_from_stream (GeditWindow             *window,
3059 				     GInputStream            *stream,
3060 				     const GtkSourceEncoding *encoding,
3061 				     gint                     line_pos,
3062 				     gint                     column_pos,
3063 				     gboolean                 jump_to)
3064 {
3065 	GtkWidget *notebook;
3066 	GeditTab *tab;
3067 
3068 	gedit_debug (DEBUG_WINDOW);
3069 
3070 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3071 	g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
3072 
3073 	tab = _gedit_tab_new ();
3074 
3075 	_gedit_tab_load_stream (tab,
3076 				stream,
3077 				encoding,
3078 				line_pos,
3079 				column_pos);
3080 
3081 	notebook = _gedit_window_get_notebook (window);
3082 
3083 	return process_create_tab (window, notebook, tab, jump_to);
3084 }
3085 
3086 /**
3087  * gedit_window_get_active_tab:
3088  * @window: a GeditWindow
3089  *
3090  * Gets the active #GeditTab in the @window.
3091  *
3092  * Returns: (transfer none): the active #GeditTab in the @window.
3093  */
3094 GeditTab *
gedit_window_get_active_tab(GeditWindow * window)3095 gedit_window_get_active_tab (GeditWindow *window)
3096 {
3097 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3098 
3099 	return (window->priv->multi_notebook == NULL) ? NULL :
3100 			gedit_multi_notebook_get_active_tab (window->priv->multi_notebook);
3101 }
3102 
3103 static void
add_document(GeditTab * tab,GList ** res)3104 add_document (GeditTab  *tab,
3105 	      GList    **res)
3106 {
3107 	GeditDocument *doc;
3108 
3109 	doc = gedit_tab_get_document (tab);
3110 
3111 	*res = g_list_prepend (*res, doc);
3112 }
3113 
3114 /**
3115  * gedit_window_get_documents:
3116  * @window: a #GeditWindow
3117  *
3118  * Gets a newly allocated list with all the documents in the window.
3119  * This list must be freed.
3120  *
3121  * Returns: (element-type Gedit.Document) (transfer container): a newly
3122  * allocated list with all the documents in the window
3123  */
3124 GList *
gedit_window_get_documents(GeditWindow * window)3125 gedit_window_get_documents (GeditWindow *window)
3126 {
3127 	GList *res = NULL;
3128 
3129 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3130 
3131 	gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
3132 					  (GtkCallback)add_document,
3133 					  &res);
3134 
3135 	res = g_list_reverse (res);
3136 
3137 	return res;
3138 }
3139 
3140 static void
add_view(GeditTab * tab,GList ** res)3141 add_view (GeditTab  *tab,
3142 	  GList    **res)
3143 {
3144 	GeditView *view;
3145 
3146 	view = gedit_tab_get_view (tab);
3147 
3148 	*res = g_list_prepend (*res, view);
3149 }
3150 
3151 /**
3152  * gedit_window_get_views:
3153  * @window: a #GeditWindow
3154  *
3155  * Gets a list with all the views in the window. This list must be freed.
3156  *
3157  * Returns: (element-type Gedit.View) (transfer container): a newly allocated
3158  * list with all the views in the window
3159  */
3160 GList *
gedit_window_get_views(GeditWindow * window)3161 gedit_window_get_views (GeditWindow *window)
3162 {
3163 	GList *res = NULL;
3164 
3165 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3166 
3167 	gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
3168 					  (GtkCallback)add_view,
3169 					  &res);
3170 
3171 	res = g_list_reverse (res);
3172 
3173 	return res;
3174 }
3175 
3176 /**
3177  * gedit_window_close_tab:
3178  * @window: a #GeditWindow
3179  * @tab: the #GeditTab to close
3180  *
3181  * Closes the @tab.
3182  */
3183 void
gedit_window_close_tab(GeditWindow * window,GeditTab * tab)3184 gedit_window_close_tab (GeditWindow *window,
3185 			GeditTab    *tab)
3186 {
3187 	GList *tabs = NULL;
3188 
3189 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3190 	g_return_if_fail (GEDIT_IS_TAB (tab));
3191 	g_return_if_fail ((gedit_tab_get_state (tab) != GEDIT_TAB_STATE_SAVING) &&
3192 			  (gedit_tab_get_state (tab) != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW));
3193 
3194 	tabs = g_list_append (tabs, tab);
3195 	gedit_multi_notebook_close_tabs (window->priv->multi_notebook, tabs);
3196 	g_list_free (tabs);
3197 }
3198 
3199 /**
3200  * gedit_window_close_all_tabs:
3201  * @window: a #GeditWindow
3202  *
3203  * Closes all opened tabs.
3204  */
3205 void
gedit_window_close_all_tabs(GeditWindow * window)3206 gedit_window_close_all_tabs (GeditWindow *window)
3207 {
3208 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3209 	g_return_if_fail (!(window->priv->state & GEDIT_WINDOW_STATE_SAVING));
3210 
3211 	window->priv->removing_tabs = TRUE;
3212 
3213 	gedit_multi_notebook_close_all_tabs (window->priv->multi_notebook);
3214 
3215 	window->priv->removing_tabs = FALSE;
3216 }
3217 
3218 /**
3219  * gedit_window_close_tabs:
3220  * @window: a #GeditWindow
3221  * @tabs: (element-type Gedit.Tab): a list of #GeditTab
3222  *
3223  * Closes all tabs specified by @tabs.
3224  */
3225 void
gedit_window_close_tabs(GeditWindow * window,const GList * tabs)3226 gedit_window_close_tabs (GeditWindow *window,
3227 			 const GList *tabs)
3228 {
3229 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3230 	g_return_if_fail (!(window->priv->state & GEDIT_WINDOW_STATE_SAVING));
3231 
3232 	window->priv->removing_tabs = TRUE;
3233 
3234 	gedit_multi_notebook_close_tabs (window->priv->multi_notebook, tabs);
3235 
3236 	window->priv->removing_tabs = FALSE;
3237 }
3238 
3239 GeditWindow *
_gedit_window_move_tab_to_new_window(GeditWindow * window,GeditTab * tab)3240 _gedit_window_move_tab_to_new_window (GeditWindow *window,
3241 				      GeditTab    *tab)
3242 {
3243 	GeditWindow *new_window;
3244 	GeditNotebook *old_notebook;
3245 	GeditNotebook *new_notebook;
3246 
3247 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3248 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
3249 	g_return_val_if_fail (gedit_multi_notebook_get_n_notebooks (
3250 	                        window->priv->multi_notebook) > 1 ||
3251 	                      gedit_multi_notebook_get_n_tabs (
3252 	                        window->priv->multi_notebook) > 1,
3253 	                      NULL);
3254 
3255 	new_window = clone_window (window);
3256 
3257 	old_notebook = GEDIT_NOTEBOOK (gtk_widget_get_parent (GTK_WIDGET (tab)));
3258 	new_notebook = gedit_multi_notebook_get_active_notebook (new_window->priv->multi_notebook);
3259 
3260 	gedit_notebook_move_tab (old_notebook,
3261 				 new_notebook,
3262 				 tab,
3263 				 -1);
3264 
3265 	gtk_widget_show (GTK_WIDGET (new_window));
3266 
3267 	return new_window;
3268 }
3269 
3270 void
_gedit_window_move_tab_to_new_tab_group(GeditWindow * window,GeditTab * tab)3271 _gedit_window_move_tab_to_new_tab_group (GeditWindow *window,
3272                                          GeditTab    *tab)
3273 {
3274 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3275 	g_return_if_fail (GEDIT_IS_TAB (tab));
3276 
3277 	gedit_multi_notebook_add_new_notebook_with_tab (window->priv->multi_notebook,
3278 	                                                tab);
3279 }
3280 
3281 /**
3282  * gedit_window_set_active_tab:
3283  * @window: a #GeditWindow
3284  * @tab: a #GeditTab
3285  *
3286  * Switches to the tab that matches with @tab.
3287  */
3288 void
gedit_window_set_active_tab(GeditWindow * window,GeditTab * tab)3289 gedit_window_set_active_tab (GeditWindow *window,
3290 			     GeditTab    *tab)
3291 {
3292 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3293 
3294 	gedit_multi_notebook_set_active_tab (window->priv->multi_notebook,
3295 					     tab);
3296 }
3297 
3298 /**
3299  * gedit_window_get_group:
3300  * @window: a #GeditWindow
3301  *
3302  * Gets the #GtkWindowGroup in which @window resides.
3303  *
3304  * Returns: (transfer none): the #GtkWindowGroup
3305  */
3306 GtkWindowGroup *
gedit_window_get_group(GeditWindow * window)3307 gedit_window_get_group (GeditWindow *window)
3308 {
3309 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3310 
3311 	return window->priv->window_group;
3312 }
3313 
3314 gboolean
_gedit_window_is_removing_tabs(GeditWindow * window)3315 _gedit_window_is_removing_tabs (GeditWindow *window)
3316 {
3317 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), FALSE);
3318 
3319 	return window->priv->removing_tabs;
3320 }
3321 
3322 /**
3323  * gedit_window_get_side_panel:
3324  * @window: a #GeditWindow
3325  *
3326  * Gets the side panel of the @window.
3327  *
3328  * Returns: (transfer none): the side panel's #GtkStack.
3329  */
3330 GtkWidget *
gedit_window_get_side_panel(GeditWindow * window)3331 gedit_window_get_side_panel (GeditWindow *window)
3332 {
3333 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3334 
3335 	return window->priv->side_panel;
3336 }
3337 
3338 /**
3339  * gedit_window_get_bottom_panel:
3340  * @window: a #GeditWindow
3341  *
3342  * Gets the bottom panel of the @window.
3343  *
3344  * Returns: (transfer none): the bottom panel's #GtkStack.
3345  */
3346 GtkWidget *
gedit_window_get_bottom_panel(GeditWindow * window)3347 gedit_window_get_bottom_panel (GeditWindow *window)
3348 {
3349 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3350 
3351 	return window->priv->bottom_panel;
3352 }
3353 
3354 /**
3355  * gedit_window_get_statusbar:
3356  * @window: a #GeditWindow
3357  *
3358  * Gets the #GeditStatusbar of the @window.
3359  *
3360  * Returns: (transfer none): the #GeditStatusbar of the @window.
3361  */
3362 GtkWidget *
gedit_window_get_statusbar(GeditWindow * window)3363 gedit_window_get_statusbar (GeditWindow *window)
3364 {
3365 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), 0);
3366 
3367 	return window->priv->statusbar;
3368 }
3369 
3370 /**
3371  * gedit_window_get_state:
3372  * @window: a #GeditWindow
3373  *
3374  * Retrieves the state of the @window.
3375  *
3376  * Returns: the current #GeditWindowState of the @window.
3377  */
3378 GeditWindowState
gedit_window_get_state(GeditWindow * window)3379 gedit_window_get_state (GeditWindow *window)
3380 {
3381 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), GEDIT_WINDOW_STATE_NORMAL);
3382 
3383 	return window->priv->state;
3384 }
3385 
3386 const gchar *
_gedit_window_get_file_chooser_folder_uri(GeditWindow * window,GtkFileChooserAction action)3387 _gedit_window_get_file_chooser_folder_uri (GeditWindow          *window,
3388 					   GtkFileChooserAction  action)
3389 {
3390 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3391 	g_return_val_if_fail ((action == GTK_FILE_CHOOSER_ACTION_OPEN) ||
3392 			      (action == GTK_FILE_CHOOSER_ACTION_SAVE), NULL);
3393 
3394 	if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
3395 	{
3396 		GeditSettings *settings;
3397 		GSettings *file_chooser_state_settings;
3398 
3399 		settings = _gedit_settings_get_singleton ();
3400 		file_chooser_state_settings = _gedit_settings_peek_file_chooser_state_settings (settings);
3401 
3402 		if (g_settings_get_boolean (file_chooser_state_settings,
3403 					    GEDIT_SETTINGS_FILE_CHOOSER_OPEN_RECENT))
3404 		{
3405 			return NULL;
3406 		}
3407 	}
3408 
3409 	return window->priv->file_chooser_folder_uri;
3410 }
3411 
3412 void
_gedit_window_set_file_chooser_folder_uri(GeditWindow * window,GtkFileChooserAction action,const gchar * folder_uri)3413 _gedit_window_set_file_chooser_folder_uri (GeditWindow          *window,
3414 					   GtkFileChooserAction  action,
3415 					   const gchar          *folder_uri)
3416 {
3417 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3418 	g_return_if_fail ((action == GTK_FILE_CHOOSER_ACTION_OPEN) ||
3419 			  (action == GTK_FILE_CHOOSER_ACTION_SAVE));
3420 
3421 	if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
3422 	{
3423 		GeditSettings *settings;
3424 		GSettings *file_chooser_state_settings;
3425 		gboolean open_recent = folder_uri == NULL;
3426 
3427 		settings = _gedit_settings_get_singleton ();
3428 		file_chooser_state_settings = _gedit_settings_peek_file_chooser_state_settings (settings);
3429 
3430 		g_settings_set_boolean (file_chooser_state_settings,
3431 					GEDIT_SETTINGS_FILE_CHOOSER_OPEN_RECENT,
3432 					open_recent);
3433 
3434 		if (open_recent)
3435 		{
3436 			/* Do not set window->priv->file_chooser_folder_uri to
3437 			 * NULL, to not lose the folder for the Save action.
3438 			 */
3439 			return;
3440 		}
3441 	}
3442 
3443 	g_free (window->priv->file_chooser_folder_uri);
3444 	window->priv->file_chooser_folder_uri = g_strdup (folder_uri);
3445 }
3446 
3447 static void
add_unsaved_doc(GeditTab * tab,GList ** res)3448 add_unsaved_doc (GeditTab *tab,
3449 		 GList   **res)
3450 {
3451 	if (!_gedit_tab_get_can_close (tab))
3452 	{
3453 		GeditDocument *doc;
3454 
3455 		doc = gedit_tab_get_document (tab);
3456 		*res = g_list_prepend (*res, doc);
3457 	}
3458 }
3459 
3460 /**
3461  * gedit_window_get_unsaved_documents:
3462  * @window: a #GeditWindow
3463  *
3464  * Gets the list of documents that need to be saved before closing the window.
3465  *
3466  * Returns: (element-type Gedit.Document) (transfer container): a list of
3467  * #GeditDocument that need to be saved before closing the window
3468  */
3469 GList *
gedit_window_get_unsaved_documents(GeditWindow * window)3470 gedit_window_get_unsaved_documents (GeditWindow *window)
3471 {
3472 	GList *res = NULL;
3473 
3474 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3475 
3476 	gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
3477 					  (GtkCallback)add_unsaved_doc,
3478 					  &res);
3479 
3480 	return g_list_reverse (res);
3481 }
3482 
3483 GList *
_gedit_window_get_all_tabs(GeditWindow * window)3484 _gedit_window_get_all_tabs (GeditWindow *window)
3485 {
3486 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3487 
3488 	return gedit_multi_notebook_get_all_tabs (window->priv->multi_notebook);
3489 }
3490 
3491 void
_gedit_window_fullscreen(GeditWindow * window)3492 _gedit_window_fullscreen (GeditWindow *window)
3493 {
3494 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3495 
3496 	if (_gedit_window_is_fullscreen (window))
3497 		return;
3498 
3499 	sync_fullscreen_actions (window, TRUE);
3500 
3501 	/* Go to fullscreen mode and hide bars */
3502 	gtk_window_fullscreen (GTK_WINDOW (&window->window));
3503 }
3504 
3505 void
_gedit_window_unfullscreen(GeditWindow * window)3506 _gedit_window_unfullscreen (GeditWindow *window)
3507 {
3508 	g_return_if_fail (GEDIT_IS_WINDOW (window));
3509 
3510 	if (!_gedit_window_is_fullscreen (window))
3511 		return;
3512 
3513 	sync_fullscreen_actions (window, FALSE);
3514 
3515 	/* Unfullscreen and show bars */
3516 	gtk_window_unfullscreen (GTK_WINDOW (&window->window));
3517 }
3518 
3519 gboolean
_gedit_window_is_fullscreen(GeditWindow * window)3520 _gedit_window_is_fullscreen (GeditWindow *window)
3521 {
3522 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), FALSE);
3523 
3524 	return window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN;
3525 }
3526 
3527 /**
3528  * gedit_window_get_tab_from_location:
3529  * @window: a #GeditWindow
3530  * @location: a #GFile
3531  *
3532  * Gets the #GeditTab that matches with the given @location.
3533  *
3534  * Returns: (transfer none): the #GeditTab that matches with the given @location.
3535  */
3536 GeditTab *
gedit_window_get_tab_from_location(GeditWindow * window,GFile * location)3537 gedit_window_get_tab_from_location (GeditWindow *window,
3538 				    GFile       *location)
3539 {
3540 	GList *tabs;
3541 	GList *l;
3542 	GeditTab *ret = NULL;
3543 
3544 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3545 	g_return_val_if_fail (G_IS_FILE (location), NULL);
3546 
3547 	tabs = gedit_multi_notebook_get_all_tabs (window->priv->multi_notebook);
3548 
3549 	for (l = tabs; l != NULL; l = g_list_next (l))
3550 	{
3551 		GeditDocument *doc;
3552 		GtkSourceFile *file;
3553 		GeditTab *tab;
3554 		GFile *cur_location;
3555 
3556 		tab = GEDIT_TAB (l->data);
3557 		doc = gedit_tab_get_document (tab);
3558 		file = gedit_document_get_file (doc);
3559 		cur_location = gtk_source_file_get_location (file);
3560 
3561 		if (cur_location != NULL)
3562 		{
3563 			gboolean found = g_file_equal (location, cur_location);
3564 
3565 			if (found)
3566 			{
3567 				ret = tab;
3568 				break;
3569 			}
3570 		}
3571 	}
3572 
3573 	g_list_free (tabs);
3574 
3575 	return ret;
3576 }
3577 
3578 /**
3579  * gedit_window_get_message_bus:
3580  * @window: a #GeditWindow
3581  *
3582  * Gets the #GeditMessageBus associated with @window. The returned reference
3583  * is owned by the window and should not be unreffed.
3584  *
3585  * Return value: (transfer none): the #GeditMessageBus associated with @window
3586  */
3587 GeditMessageBus *
gedit_window_get_message_bus(GeditWindow * window)3588 gedit_window_get_message_bus (GeditWindow *window)
3589 {
3590 	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
3591 
3592 	return window->priv->message_bus;
3593 }
3594 
3595 /* ex:set ts=8 noet: */
3596