1 #include <config.h>
2 #include <time.h>
3 #include <sys/types.h>
4 #include <string.h>
5 #include <glib/gi18n.h>
6 #include <gtk/gtk.h>
7 #include <libpeas/peas-extension-set.h>
8 
9 #include "xed-ui.h"
10 #include "xed-window.h"
11 #include "xed-window-private.h"
12 #include "xed-app.h"
13 #include "xed-notebook.h"
14 #include "xed-statusbar.h"
15 #include "xed-searchbar.h"
16 #include "xed-view-frame.h"
17 #include "xed-utils.h"
18 #include "xed-commands.h"
19 #include "xed-debug.h"
20 #include "xed-document.h"
21 #include "xed-document-private.h"
22 #include "xed-panel.h"
23 #include "xed-documents-panel.h"
24 #include "xed-plugins-engine.h"
25 #include "xed-window-activatable.h"
26 #include "xed-enum-types.h"
27 #include "xed-dirs.h"
28 #include "xed-status-menu-button.h"
29 #include "xed-highlight-mode-selector.h"
30 #include "xed-settings.h"
31 
32 #define LANGUAGE_NONE  (const gchar *)"LangNone"
33 #define TAB_WIDTH_DATA "XedWindowTabWidthData"
34 #define LANGUAGE_DATA  "XedWindowLanguageData"
35 
36 #define XED_WINDOW_DEFAULT_WIDTH  650
37 #define XED_WINDOW_DEFAULT_HEIGHT 500
38 
39 /* Signals */
40 enum
41 {
42     TAB_ADDED,
43     TAB_REMOVED,
44     TABS_REORDERED,
45     ACTIVE_TAB_CHANGED,
46     ACTIVE_TAB_STATE_CHANGED,
47     LAST_SIGNAL
48 };
49 
50 static guint signals[LAST_SIGNAL] = { 0 };
51 
52 enum
53 {
54     PROP_0,
55     PROP_STATE
56 };
57 
58 enum
59 {
60     TARGET_URI_LIST = 100
61 };
62 
63 G_DEFINE_TYPE_WITH_PRIVATE (XedWindow, xed_window, GTK_TYPE_APPLICATION_WINDOW)
64 
65 static void recent_manager_changed (GtkRecentManager *manager, XedWindow *window);
66 
67 static void
xed_window_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)68 xed_window_get_property (GObject    *object,
69                          guint       prop_id,
70                          GValue     *value,
71                          GParamSpec *pspec)
72 {
73     XedWindow *window = XED_WINDOW(object);
74 
75     switch (prop_id)
76     {
77         case PROP_STATE:
78             g_value_set_enum (value, xed_window_get_state (window));
79             break;
80         default:
81             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
82             break;
83     }
84 }
85 
86 static void
save_panes_state(XedWindow * window)87 save_panes_state (XedWindow *window)
88 {
89     gint panel_page;
90 
91     xed_debug (DEBUG_WINDOW);
92 
93     if (window->priv->side_panel_size > 0)
94     {
95         g_settings_set_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_SIZE, window->priv->side_panel_size);
96     }
97 
98     panel_page = _xed_panel_get_active_item_id (XED_PANEL (window->priv->side_panel));
99     if (panel_page != 0)
100     {
101         g_settings_set_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_ACTIVE_PAGE, panel_page);
102     }
103 
104     if (window->priv->bottom_panel_size > 0)
105     {
106         g_settings_set_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_SIZE, window->priv->bottom_panel_size);
107     }
108 
109     panel_page = _xed_panel_get_active_item_id (XED_PANEL(window->priv->bottom_panel));
110     if (panel_page != 0)
111     {
112         g_settings_set_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE, panel_page);
113     }
114 
115     g_settings_apply (window->priv->window_settings);
116 }
117 
118 static gboolean
on_key_pressed(GtkWidget * widget,GdkEventKey * event,XedWindow * window)119 on_key_pressed (GtkWidget *widget,
120                 GdkEventKey *event,
121                 XedWindow *window)
122 {
123     if (event->state & GDK_CONTROL_MASK &&
124          (event->keyval == GDK_KEY_KP_Tab ||
125           event->keyval == GDK_KEY_Tab ||
126           event->keyval == GDK_KEY_ISO_Left_Tab)) {
127         int current_page = gtk_notebook_get_current_page (window->priv->notebook);
128         int num_pages = gtk_notebook_get_n_pages (window->priv->notebook);
129         if (event->state & GDK_SHIFT_MASK)
130             gtk_notebook_set_current_page (window->priv->notebook, (current_page - 1) % num_pages);
131         else
132             gtk_notebook_set_current_page (window->priv->notebook, (current_page + 1) % num_pages);
133         return GDK_EVENT_STOP;
134     }
135     else if (event->keyval == GDK_KEY_Escape)
136     {
137         XedTab *tab;
138         XedViewFrame *frame;
139 
140         tab = xed_window_get_active_tab (window);
141 
142         if (tab != NULL)
143         {
144             frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
145 
146             if (xed_view_frame_get_search_popup_visible (frame))
147             {
148                 return GDK_EVENT_PROPAGATE;
149             }
150         }
151 
152         xed_searchbar_hide (XED_SEARCHBAR (window->priv->searchbar));
153         return GDK_EVENT_STOP;
154     }
155     else if (event->keyval == GDK_KEY_Alt_L)
156     {
157         if (gtk_widget_is_visible (window->priv->menubar)) {
158             if (!g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_MENUBAR_VISIBLE)) {
159                 gtk_widget_hide (window->priv->menubar);
160             }
161         }
162         else {
163             if (!_xed_window_is_fullscreen (window)) {
164                 gtk_widget_show (window->priv->menubar);
165             }
166         }
167 
168         return GDK_EVENT_STOP;
169     }
170 
171     return GDK_EVENT_PROPAGATE;
172 }
173 
174 static void
save_window_state(GtkWidget * widget)175 save_window_state (GtkWidget *widget)
176 {
177     XedWindow *window = XED_WINDOW (widget);
178 
179     if ((window->priv->window_state &
180         (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
181     {
182         GtkAllocation allocation;
183 
184         gtk_widget_get_allocation (widget, &allocation);
185 
186         window->priv->width = allocation.width;
187         window->priv->height = allocation.height;
188 
189         g_settings_set (window->priv->window_settings, XED_SETTINGS_WINDOW_SIZE,
190                         "(ii)", window->priv->width, window->priv->height);
191     }
192 }
193 
194 static void
xed_window_dispose(GObject * object)195 xed_window_dispose (GObject *object)
196 {
197     XedWindow *window;
198 
199     xed_debug (DEBUG_WINDOW);
200 
201     window = XED_WINDOW (object);
202 
203     /* Stop tracking removal of panes otherwise we always
204      * end up with thinking we had no pane active, since they
205      * should all be removed below */
206     if (window->priv->bottom_panel_item_removed_handler_id != 0)
207     {
208         g_signal_handler_disconnect (window->priv->bottom_panel, window->priv->bottom_panel_item_removed_handler_id);
209         window->priv->bottom_panel_item_removed_handler_id = 0;
210     }
211 
212     /* First of all, force collection so that plugins
213      * really drop some of the references.
214      */
215     peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default()));
216 
217     /* save the panes position and make sure to deactivate plugins
218      * for this window, but only once */
219     if (!window->priv->dispose_has_run)
220     {
221         save_window_state (GTK_WIDGET (window));
222         save_panes_state (window);
223 
224         /* Note that unreffing the extension will automatically remove
225            all extensions which in turn will deactivate the extension */
226         g_object_unref (window->priv->extensions);
227 
228         peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
229 
230         window->priv->dispose_has_run = TRUE;
231     }
232 
233     if (window->priv->recents_handler_id != 0)
234     {
235         GtkRecentManager *recent_manager;
236         recent_manager = gtk_recent_manager_get_default ();
237         g_signal_handler_disconnect (recent_manager, window->priv->recents_handler_id);
238         window->priv->recents_handler_id = 0;
239     }
240 
241     if (window->priv->favorites_handler_id != 0)
242     {
243         XAppFavorites *favorites;
244         favorites = xapp_favorites_get_default ();
245         g_signal_handler_disconnect (favorites, window->priv->favorites_handler_id);
246         window->priv->favorites_handler_id = 0;
247     }
248 
249     g_clear_object (&window->priv->manager);
250     g_clear_object (&window->priv->message_bus);
251     g_clear_object (&window->priv->window_group);
252     g_clear_object (&window->priv->default_location);
253 
254     /* We must free the settings after saving the panels */
255     g_clear_object (&window->priv->editor_settings);
256     g_clear_object (&window->priv->ui_settings);
257     g_clear_object (&window->priv->window_settings);
258 
259     /* Now that there have broken some reference loops, force collection again. */
260     peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
261 
262     G_OBJECT_CLASS (xed_window_parent_class)->dispose (object);
263 }
264 
265 static void
xed_window_finalize(GObject * object)266 xed_window_finalize (GObject *object)
267 {
268     xed_debug (DEBUG_WINDOW);
269 
270     G_OBJECT_CLASS (xed_window_parent_class)->finalize (object);
271 }
272 
273 static gboolean
xed_window_window_state_event(GtkWidget * widget,GdkEventWindowState * event)274 xed_window_window_state_event (GtkWidget           *widget,
275                                GdkEventWindowState *event)
276 {
277     XedWindow *window = XED_WINDOW (widget);
278 
279     window->priv->window_state = event->new_window_state;
280     g_settings_set_int (window->priv->window_settings, XED_SETTINGS_WINDOW_STATE, window->priv->window_state);
281 
282     return FALSE;
283 }
284 
285 static gboolean
xed_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)286 xed_window_configure_event (GtkWidget         *widget,
287                             GdkEventConfigure *event)
288 {
289     XedWindow *window = XED_WINDOW (widget);
290 
291     if (gtk_widget_get_realized (widget) &&
292         (window->priv->window_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
293     {
294         save_window_state (widget);
295     }
296 
297     return GTK_WIDGET_CLASS (xed_window_parent_class)->configure_event (widget, event);
298 }
299 
300 /*
301  * GtkWindow catches keybindings for the menu items _before_ passing them to
302  * the focused widget. This is unfortunate and means that pressing ctrl+V
303  * in an entry on a panel ends up pasting text in the TextView.
304  * Here we override GtkWindow's handler to do the same things that it
305  * does, but in the opposite order and then we chain up to the grand
306  * parent handler, skipping gtk_window_key_press_event.
307  */
308 static gboolean
xed_window_key_press_event(GtkWidget * widget,GdkEventKey * event)309 xed_window_key_press_event (GtkWidget *widget,
310                             GdkEventKey *event)
311 {
312     static gpointer grand_parent_class = NULL;
313     GtkWindow *window = GTK_WINDOW(widget);
314     gboolean handled = FALSE;
315 
316     if (grand_parent_class == NULL)
317     {
318         grand_parent_class = g_type_class_peek_parent (xed_window_parent_class);
319     }
320 
321     /* handle focus widget key events */
322     if (!handled)
323     {
324         handled = gtk_window_propagate_key_event (window, event);
325     }
326 
327     /* handle mnemonics and accelerators */
328     if (!handled)
329     {
330         handled = gtk_window_activate_key (window, event);
331     }
332 
333     /* Chain up, invokes binding set */
334     if (!handled)
335     {
336         handled = GTK_WIDGET_CLASS (grand_parent_class)->key_press_event (widget, event);
337     }
338 
339     return handled;
340 }
341 
342 static void
xed_window_tab_removed(XedWindow * window,XedTab * tab)343 xed_window_tab_removed (XedWindow *window,
344                         XedTab *tab)
345 {
346     peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
347 }
348 
349 static void
xed_window_class_init(XedWindowClass * klass)350 xed_window_class_init (XedWindowClass *klass)
351 {
352     GObjectClass *object_class = G_OBJECT_CLASS(klass);
353     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
354 
355     klass->tab_removed = xed_window_tab_removed;
356 
357     object_class->dispose = xed_window_dispose;
358     object_class->finalize = xed_window_finalize;
359     object_class->get_property = xed_window_get_property;
360 
361     widget_class->window_state_event = xed_window_window_state_event;
362     widget_class->configure_event = xed_window_configure_event;
363     widget_class->key_press_event = xed_window_key_press_event;
364 
365     signals[TAB_ADDED] = g_signal_new ("tab_added", G_OBJECT_CLASS_TYPE(object_class),
366                                     G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tab_added),
367                                     NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
368 
369     signals[TAB_REMOVED] = g_signal_new ("tab_removed", G_OBJECT_CLASS_TYPE(object_class),
370                                     G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tab_removed),
371                                     NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
372 
373     signals[TABS_REORDERED] = g_signal_new ("tabs_reordered", G_OBJECT_CLASS_TYPE(object_class),
374                                     G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tabs_reordered),
375                                     NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
376 
377     signals[ACTIVE_TAB_CHANGED] = g_signal_new ("active_tab_changed", G_OBJECT_CLASS_TYPE(object_class),
378                                     G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, active_tab_changed),
379                                     NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
380 
381     signals[ACTIVE_TAB_STATE_CHANGED] = g_signal_new ("active_tab_state_changed", G_OBJECT_CLASS_TYPE(object_class),
382                                     G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, active_tab_state_changed),
383                                     NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
384 
385     g_object_class_install_property (object_class, PROP_STATE, g_param_spec_flags ("state",
386                                                                     "State",
387                                                                     "The window's state",
388                                                                     XED_TYPE_WINDOW_STATE,
389                                                                     XED_WINDOW_STATE_NORMAL,
390                                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
391 }
392 
393 static void
menu_item_select_cb(GtkMenuItem * proxy,XedWindow * window)394 menu_item_select_cb (GtkMenuItem *proxy,
395                      XedWindow *window)
396 {
397     GtkAction *action;
398     char *message;
399 
400     action = gtk_activatable_get_related_action (GTK_ACTIVATABLE(proxy));
401     g_return_if_fail(action != NULL);
402 
403     g_object_get (G_OBJECT(action), "tooltip", &message, NULL);
404     if (message)
405     {
406         gtk_statusbar_push (GTK_STATUSBAR(window->priv->statusbar), window->priv->tip_message_cid, message);
407         g_free (message);
408     }
409 }
410 
411 static void
menu_item_deselect_cb(GtkMenuItem * proxy,XedWindow * window)412 menu_item_deselect_cb (GtkMenuItem *proxy,
413                        XedWindow *window)
414 {
415     gtk_statusbar_pop (GTK_STATUSBAR(window->priv->statusbar), window->priv->tip_message_cid);
416 }
417 
418 static void
connect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,XedWindow * window)419 connect_proxy_cb (GtkUIManager *manager,
420                   GtkAction *action,
421                   GtkWidget *proxy,
422                   XedWindow *window)
423 {
424     if (GTK_IS_MENU_ITEM(proxy))
425     {
426         g_signal_connect(proxy, "select", G_CALLBACK (menu_item_select_cb), window);
427         g_signal_connect(proxy, "deselect", G_CALLBACK (menu_item_deselect_cb), window);
428     }
429 }
430 
431 static void
disconnect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,XedWindow * window)432 disconnect_proxy_cb (GtkUIManager *manager,
433                      GtkAction *action,
434                      GtkWidget *proxy,
435                      XedWindow *window)
436 {
437     if (GTK_IS_MENU_ITEM(proxy))
438     {
439         g_signal_handlers_disconnect_by_func(proxy, G_CALLBACK (menu_item_select_cb), window);
440         g_signal_handlers_disconnect_by_func(proxy, G_CALLBACK (menu_item_deselect_cb), window);
441     }
442 }
443 
444 /* Returns TRUE if toolbar is visible */
445 static gboolean
set_toolbar_style(XedWindow * window,XedWindow * origin)446 set_toolbar_style (XedWindow *window,
447                    XedWindow *origin)
448 {
449     gboolean visible;
450     GtkAction *action;
451 
452     if (origin == NULL)
453     {
454         visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_TOOLBAR_VISIBLE);
455     }
456     else
457     {
458         visible = gtk_widget_get_visible (origin->priv->toolbar);
459     }
460 
461     /* Set visibility */
462     if (visible)
463     {
464         gtk_widget_show (window->priv->toolbar);
465     }
466     else
467     {
468         gtk_widget_hide (window->priv->toolbar);
469     }
470 
471     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
472 
473     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible)
474     {
475         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
476     }
477 
478     return visible;
479 }
480 
481 /* Returns TRUE if menu bar is visible */
482 static gboolean
set_menubar_style(XedWindow * window,XedWindow * origin)483 set_menubar_style (XedWindow *window,
484                      XedWindow *origin)
485 {
486     GtkAction *action;
487     gboolean visible;
488 
489     if (origin == NULL)
490     {
491         visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_MENUBAR_VISIBLE);
492     }
493     else
494     {
495         visible = gtk_widget_get_visible (origin->priv->menubar);
496     }
497 
498     if (visible)
499     {
500         gtk_widget_show (window->priv->menubar);
501     }
502     else
503     {
504         gtk_widget_hide (window->priv->menubar);
505     }
506 
507     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewMenubar");
508 
509     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
510     {
511         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
512     }
513 
514     return visible;
515 }
516 
517 static void
update_next_prev_doc_sensitivity(XedWindow * window,XedTab * tab)518 update_next_prev_doc_sensitivity (XedWindow *window,
519                                   XedTab *tab)
520 {
521     gint tab_number;
522     GtkNotebook *notebook;
523     GtkAction *action;
524 
525     xed_debug (DEBUG_WINDOW);
526 
527     notebook = GTK_NOTEBOOK(_xed_window_get_notebook (window));
528 
529     tab_number = gtk_notebook_page_num (notebook, GTK_WIDGET(tab));
530     g_return_if_fail(tab_number >= 0);
531 
532     action = gtk_action_group_get_action (window->priv->action_group, "DocumentsPreviousDocument");
533     gtk_action_set_sensitive (action, tab_number != 0);
534 
535     action = gtk_action_group_get_action (window->priv->action_group, "DocumentsNextDocument");
536     gtk_action_set_sensitive (action, tab_number < gtk_notebook_get_n_pages (notebook) - 1);
537 }
538 
539 static void
update_next_prev_doc_sensitivity_per_window(XedWindow * window)540 update_next_prev_doc_sensitivity_per_window (XedWindow *window)
541 {
542     XedTab *tab;
543     GtkAction *action;
544 
545     xed_debug (DEBUG_WINDOW);
546 
547     tab = xed_window_get_active_tab (window);
548     if (tab != NULL)
549     {
550         update_next_prev_doc_sensitivity (window, tab);
551         return;
552     }
553 
554     action = gtk_action_group_get_action (window->priv->action_group, "DocumentsPreviousDocument");
555     gtk_action_set_sensitive (action, FALSE);
556 
557     action = gtk_action_group_get_action (window->priv->action_group, "DocumentsNextDocument");
558     gtk_action_set_sensitive (action, FALSE);
559 
560 }
561 
562 static void
received_clipboard_contents(GtkClipboard * clipboard,GtkSelectionData * selection_data,XedWindow * window)563 received_clipboard_contents (GtkClipboard *clipboard,
564                              GtkSelectionData *selection_data,
565                              XedWindow *window)
566 {
567     gboolean sensitive;
568     GtkAction *action;
569 
570     /* getting clipboard contents is async, so we need to
571      * get the current tab and its state */
572 
573     if (window->priv->active_tab != NULL)
574     {
575         XedTabState state;
576         gboolean state_normal;
577 
578         state = xed_tab_get_state (window->priv->active_tab);
579         state_normal = (state == XED_TAB_STATE_NORMAL);
580         sensitive = state_normal && gtk_selection_data_targets_include_text (selection_data);
581     }
582     else
583     {
584         sensitive = FALSE;
585     }
586 
587     action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
588 
589     if (action != NULL)
590     {
591         gtk_action_set_sensitive (action, sensitive);
592     }
593 
594     g_object_unref (window);
595 }
596 
597 static void
set_paste_sensitivity_according_to_clipboard(XedWindow * window,GtkClipboard * clipboard)598 set_paste_sensitivity_according_to_clipboard (XedWindow *window,
599                                               GtkClipboard *clipboard)
600 {
601     GdkDisplay *display;
602 
603     display = gtk_clipboard_get_display (clipboard);
604     if (gdk_display_supports_selection_notification (display))
605     {
606         gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"),
607                                         (GtkClipboardReceivedFunc) received_clipboard_contents, g_object_ref (window));
608     }
609     else
610     {
611         GtkAction *action;
612         action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
613 
614         /* XFIXES extension not available, make
615          * Paste always sensitive */
616         gtk_action_set_sensitive (action, TRUE);
617     }
618 }
619 
620 static void
set_sensitivity_according_to_tab(XedWindow * window,XedTab * tab)621 set_sensitivity_according_to_tab (XedWindow *window,
622                                   XedTab    *tab)
623 {
624     XedDocument *doc;
625     XedView *view;
626     GtkAction *action;
627     gboolean b;
628     gboolean state_normal;
629     gboolean editable;
630     XedTabState state;
631     GtkClipboard *clipboard;
632     gboolean enable_syntax_hl;
633 
634     g_return_if_fail (XED_TAB (tab));
635 
636     xed_debug (DEBUG_WINDOW);
637 
638     enable_syntax_hl = g_settings_get_boolean (window->priv->editor_settings, XED_SETTINGS_SYNTAX_HIGHLIGHTING);
639 
640     state = xed_tab_get_state (tab);
641     state_normal = (state == XED_TAB_STATE_NORMAL);
642 
643     view = xed_tab_get_view (tab);
644     editable = gtk_text_view_get_editable (GTK_TEXT_VIEW(view));
645 
646     doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
647 
648     clipboard = gtk_widget_get_clipboard (GTK_WIDGET(window),
649     GDK_SELECTION_CLIPBOARD);
650 
651     action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
652     gtk_action_set_sensitive (
653                     action,
654                     (state_normal || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
655                     || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW))
656                     && !xed_document_get_readonly (doc));
657 
658     action = gtk_action_group_get_action (window->priv->action_group, "FileSaveAs");
659     gtk_action_set_sensitive (
660                     action,
661                     (state_normal || (state == XED_TAB_STATE_SAVING_ERROR)
662                     || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
663                     || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)));
664 
665     action = gtk_action_group_get_action (window->priv->action_group, "FileRevert");
666     gtk_action_set_sensitive (
667                     action,
668                     (state_normal || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION))
669                     && !xed_document_is_untitled (doc));
670 
671     action = gtk_action_group_get_action (window->priv->action_group, "FilePrintPreview");
672     gtk_action_set_sensitive (action, state_normal);
673 
674     action = gtk_action_group_get_action (window->priv->action_group, "FilePrint");
675     gtk_action_set_sensitive (action, (state_normal || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)));
676 
677     action = gtk_action_group_get_action (window->priv->close_action_group, "FileClose");
678 
679     gtk_action_set_sensitive (
680                     action,
681                     (state != XED_TAB_STATE_CLOSING) && (state != XED_TAB_STATE_SAVING)
682                     && (state != XED_TAB_STATE_SHOWING_PRINT_PREVIEW)
683                     && (state != XED_TAB_STATE_PRINTING) && (state != XED_TAB_STATE_PRINT_PREVIEWING)
684                     && (state != XED_TAB_STATE_SAVING_ERROR));
685 
686     action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
687     gtk_action_set_sensitive (action, state_normal && gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER(doc)));
688 
689     action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
690     gtk_action_set_sensitive (action, state_normal && gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER(doc)));
691 
692     action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
693     gtk_action_set_sensitive (action,
694                     state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
695 
696     action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
697     gtk_action_set_sensitive (action,
698                     (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
699                     && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
700 
701     action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
702     if (state_normal && editable)
703     {
704         set_paste_sensitivity_according_to_clipboard (window, clipboard);
705     }
706     else
707     {
708         gtk_action_set_sensitive (action, FALSE);
709     }
710 
711     action = gtk_action_group_get_action (window->priv->action_group, "EditDelete");
712     gtk_action_set_sensitive (action,
713                     state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
714 
715     action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
716     gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
717 
718     action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
719     gtk_action_set_sensitive (action, state_normal && editable);
720 
721     b = TRUE;
722     action = gtk_action_group_get_action (window->priv->action_group, "SearchFindNext");
723     gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
724 
725     action = gtk_action_group_get_action (window->priv->action_group, "SearchFindPrevious");
726     gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
727 
728     action = gtk_action_group_get_action (window->priv->action_group, "SearchGoToLine");
729     gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
730 
731     action = gtk_action_group_get_action (window->priv->action_group, "ViewHighlightMode");
732     gtk_action_set_sensitive (action, (state != XED_TAB_STATE_CLOSING) && enable_syntax_hl);
733 
734     update_next_prev_doc_sensitivity (window, tab);
735 
736     peas_extension_set_call (window->priv->extensions, "update_state");
737 }
738 
739 void
_xed_recent_add(XedWindow * window,GFile * location,const gchar * mime)740 _xed_recent_add (XedWindow   *window,
741                  GFile       *location,
742                  const gchar *mime)
743 {
744     GtkRecentManager *recent_manager;
745     GtkRecentData *recent_data;
746     gchar *uri;
747 
748     static gchar *groups[2] = { "xed", NULL };
749 
750     recent_manager = gtk_recent_manager_get_default ();
751 
752     recent_data = g_slice_new(GtkRecentData);
753 
754     recent_data->display_name = NULL;
755     recent_data->description = NULL;
756     recent_data->mime_type = (gchar *) mime;
757     recent_data->app_name = (gchar *) g_get_application_name ();
758     recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
759     recent_data->groups = groups;
760     recent_data->is_private = FALSE;
761 
762     uri = g_file_get_uri (location);
763 
764     gtk_recent_manager_add_full (recent_manager, uri, recent_data);
765 
766     g_free (uri);
767     g_free (recent_data->app_exec);
768 
769     g_slice_free(GtkRecentData, recent_data);
770 }
771 
772 void
_xed_recent_remove(XedWindow * window,GFile * location)773 _xed_recent_remove (XedWindow *window,
774                     GFile     *location)
775 {
776     GtkRecentManager *recent_manager;
777     gchar *uri;
778 
779     recent_manager = gtk_recent_manager_get_default ();
780 
781     uri = g_file_get_uri (location);
782     gtk_recent_manager_remove_item (recent_manager, uri, NULL);
783     g_free (uri);
784 }
785 
786 static void
open_recent_file(GFile * location,XedWindow * window)787 open_recent_file (GFile     *location,
788                   XedWindow *window)
789 {
790     GSList *locations = NULL;
791     GSList *loaded = NULL;
792 
793     locations = g_slist_prepend (locations, (gpointer) location);
794 
795     loaded = xed_commands_load_locations (window, locations, NULL, 0);
796 
797     if (!loaded || loaded->next) /* if it doesn't contain just 1 element */
798     {
799         _xed_recent_remove (window, location);
800     }
801 
802     g_slist_free (locations);
803     g_slist_free (loaded);
804 }
805 
806 static void
recents_menu_activate(GtkAction * action,XedWindow * window)807 recents_menu_activate (GtkAction *action,
808                        XedWindow *window)
809 {
810     GtkRecentInfo *info;
811     GFile *location;
812     const gchar *uri;
813 
814     info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
815     g_return_if_fail (info != NULL);
816 
817     uri = gtk_recent_info_get_uri (info);
818     location = g_file_new_for_uri (uri);
819 
820     if (location)
821     {
822         open_recent_file (location, window);
823         g_object_unref (location);
824     }
825 }
826 
827 static gint
sort_recents_mru(GtkRecentInfo * a,GtkRecentInfo * b)828 sort_recents_mru (GtkRecentInfo *a,
829                   GtkRecentInfo *b)
830 {
831     return (gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a));
832 }
833 
834 static void
835 update_recent_files_menu (XedWindow *window);
836 
837 static void
recent_manager_changed(GtkRecentManager * manager,XedWindow * window)838 recent_manager_changed (GtkRecentManager *manager,
839                         XedWindow *window)
840 {
841     /* regenerate the menu when the model changes */
842     update_recent_files_menu (window);
843 }
844 
845 /*
846  * Manually construct the inline recents list in the File menu.
847  * Hopefully gtk 2.12 will add support for it.
848  */
849 static void
update_recent_files_menu(XedWindow * window)850 update_recent_files_menu (XedWindow *window)
851 {
852     XedWindowPrivate *p = window->priv;
853     GtkRecentManager *recent_manager;
854     gint max_recents;
855     GList *actions, *l, *items;
856     GList *filtered_items = NULL;
857     guint i;
858 
859     xed_debug (DEBUG_WINDOW);
860 
861     max_recents = g_settings_get_uint (window->priv->ui_settings, XED_SETTINGS_MAX_RECENTS);
862 
863     g_return_if_fail(p->recents_action_group != NULL);
864 
865     if (p->recents_menu_ui_id != 0)
866     {
867         gtk_ui_manager_remove_ui (p->manager, p->recents_menu_ui_id);
868     }
869 
870     actions = gtk_action_group_list_actions (p->recents_action_group);
871     for (l = actions; l != NULL; l = l->next)
872     {
873         g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (recents_menu_activate), window);
874         gtk_action_group_remove_action (p->recents_action_group, GTK_ACTION(l->data));
875     }
876     g_list_free (actions);
877 
878     p->recents_menu_ui_id = gtk_ui_manager_new_merge_id (p->manager);
879 
880     recent_manager = gtk_recent_manager_get_default ();
881     items = gtk_recent_manager_get_items (recent_manager);
882 
883     /* filter */
884     for (l = items; l != NULL; l = l->next)
885     {
886         GtkRecentInfo *info = l->data;
887         if (!gtk_recent_info_has_group (info, "xed"))
888         {
889             continue;
890         }
891 
892         filtered_items = g_list_prepend (filtered_items, info);
893     }
894 
895     /* sort */
896     filtered_items = g_list_sort (filtered_items, (GCompareFunc) sort_recents_mru);
897 
898     i = 0;
899     for (l = filtered_items; l != NULL; l = l->next)
900     {
901         gchar *action_name;
902         const gchar *display_name;
903         gchar *escaped;
904         gchar *label;
905         gchar *uri;
906         gchar *ruri;
907         gchar *tip;
908         GtkAction *action;
909         GtkRecentInfo *info = l->data;
910         GFile *location;
911 
912         /* clamp */
913         if (i >= max_recents)
914         {
915             break;
916         }
917 
918         i++;
919 
920         action_name = g_strdup_printf ("recent-info-%d", i);
921 
922         display_name = gtk_recent_info_get_display_name (info);
923         escaped = xed_utils_escape_underscores (display_name, -1);
924         if (i >= 10)
925         {
926             label = g_strdup_printf ("%d.  %s", i, escaped);
927         }
928         else
929             label = g_strdup_printf ("_%d.  %s", i, escaped);
930         g_free (escaped);
931 
932         /* gtk_recent_info_get_uri_display (info) is buggy and
933          * works only for local files */
934         location = g_file_new_for_uri (gtk_recent_info_get_uri (info));
935         uri = g_file_get_parse_name (location);
936         g_object_unref (location);
937         ruri = xed_utils_replace_home_dir_with_tilde (uri);
938         g_free (uri);
939 
940         /* Translators: %s is a URI */
941         tip = g_strdup_printf (_("Open '%s'"), ruri);
942         g_free (ruri);
943 
944         action = gtk_action_new (action_name, label, tip, NULL);
945 
946         g_object_set_data_full (G_OBJECT(action), "gtk-recent-info", gtk_recent_info_ref (info),
947                                 (GDestroyNotify) gtk_recent_info_unref);
948 
949         g_signal_connect(action, "activate", G_CALLBACK (recents_menu_activate), window);
950 
951         gtk_action_group_add_action (p->recents_action_group, action);
952         g_object_unref (action);
953 
954         gtk_ui_manager_add_ui (p->manager, p->recents_menu_ui_id, "/MenuBar/FileMenu/FileRecentsMenu/FileRecentsPlaceholder",
955                                action_name, action_name, GTK_UI_MANAGER_MENUITEM, FALSE);
956 
957         g_free (action_name);
958         g_free (label);
959         g_free (tip);
960     }
961 
962     g_list_free (filtered_items);
963 
964     g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
965     g_list_free (items);
966 }
967 
968 static void
toolbar_visibility_changed(GtkWidget * toolbar,XedWindow * window)969 toolbar_visibility_changed (GtkWidget *toolbar,
970                             XedWindow *window)
971 {
972     gboolean visible;
973     GtkAction *action;
974 
975     visible = gtk_widget_get_visible (toolbar);
976 
977     g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_TOOLBAR_VISIBLE, visible);
978 
979     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
980 
981     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
982     {
983         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
984     }
985 }
986 
987 
988 
989 static void
favorite_activated(GtkAction * action,gpointer user_data)990 favorite_activated (GtkAction     *action,
991                     gpointer       user_data)
992 {
993     GFile *location;
994 
995     location = g_file_new_for_uri (gtk_action_get_name (action));
996     xed_commands_load_location (XED_WINDOW (user_data), location, NULL, 0);
997 
998     g_object_unref (location);
999 }
1000 
1001 static void
update_favorites_menu(XedWindow * window)1002 update_favorites_menu (XedWindow *window)
1003 {
1004     XedWindowPrivate *p = window->priv;
1005     XAppFavorites *favorites;
1006     GList *actions, *l;
1007     GList *items = NULL;
1008 
1009     xed_debug (DEBUG_WINDOW);
1010 
1011     g_return_if_fail (p->favorites_action_group != NULL);
1012 
1013     if (p->favorites_menu_ui_id != 0)
1014     {
1015         gtk_ui_manager_remove_ui (p->manager, p->favorites_menu_ui_id);
1016     }
1017 
1018     actions = gtk_action_group_list_actions (p->favorites_action_group);
1019     for (l = actions; l != NULL; l = l->next)
1020     {
1021         g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (favorite_activated), window);
1022         gtk_action_group_remove_action (p->favorites_action_group, GTK_ACTION(l->data));
1023     }
1024     g_list_free (actions);
1025 
1026     p->favorites_menu_ui_id = gtk_ui_manager_new_merge_id (p->manager);
1027 
1028     favorites = xapp_favorites_get_default ();
1029 
1030     const gchar *supported_mimetypes[2] = {
1031         "text/plain",
1032         NULL
1033     };
1034 
1035     items = xapp_favorites_create_actions (favorites, supported_mimetypes);
1036 
1037     for (l = items; l != NULL; l = l->next)
1038     {
1039         GtkAction *action = GTK_ACTION (l->data);
1040         const gchar *name = gtk_action_get_name (action);
1041 
1042         g_signal_connect (action, "activate", G_CALLBACK (favorite_activated), window);
1043 
1044         gtk_action_group_add_action (p->favorites_action_group, action);
1045 
1046         gtk_ui_manager_add_ui (p->manager, p->favorites_menu_ui_id, "/MenuBar/FileMenu/XAppFavoritesMenu/XAppFavorites",
1047                                name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
1048     }
1049 
1050     g_list_free_full (items, g_object_unref);
1051 }
1052 
1053 static GtkWidget *
create_toolbar_button(GtkAction * action)1054 create_toolbar_button (GtkAction *action)
1055 {
1056     GtkWidget *button;
1057     GtkWidget *image;
1058 
1059     button = gtk_button_new ();
1060     image = gtk_image_new ();
1061 
1062     gtk_button_set_image (GTK_BUTTON (button), image);
1063     gtk_style_context_add_class (gtk_widget_get_style_context (button), "flat");
1064     gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
1065     gtk_button_set_label (GTK_BUTTON (button), NULL);
1066     gtk_widget_set_tooltip_text (button, gtk_action_get_tooltip (action));
1067 
1068     return button;
1069 }
1070 
1071 static void
create_menu_bar_and_toolbar(XedWindow * window,GtkWidget * main_box)1072 create_menu_bar_and_toolbar (XedWindow *window,
1073                              GtkWidget *main_box)
1074 {
1075     GtkActionGroup *action_group;
1076     GtkAction *action;
1077     GtkUIManager *manager;
1078     GtkRecentManager *recent_manager;
1079     GError *error = NULL;
1080     GtkToolItem *tool_item;
1081     GtkWidget *tool_box;
1082     GtkWidget *box;
1083     GtkWidget *separator;
1084     GtkWidget *button;
1085     XAppFavorites *favorites;
1086 
1087     xed_debug (DEBUG_WINDOW);
1088 
1089     manager = gtk_ui_manager_new ();
1090     window->priv->manager = manager;
1091 
1092     gtk_window_add_accel_group (GTK_WINDOW(window), gtk_ui_manager_get_accel_group (manager));
1093 
1094     action_group = gtk_action_group_new ("XedWindowAlwaysSensitiveActions");
1095     gtk_action_group_set_translation_domain (action_group, NULL);
1096     gtk_action_group_add_actions (action_group, xed_always_sensitive_menu_entries,
1097                                   G_N_ELEMENTS(xed_always_sensitive_menu_entries), window);
1098     gtk_action_group_add_toggle_actions (action_group, xed_always_sensitive_toggle_menu_entries,
1099                                          G_N_ELEMENTS(xed_always_sensitive_toggle_menu_entries), window);
1100 
1101     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1102     g_object_unref (action_group);
1103     window->priv->always_sensitive_action_group = action_group;
1104 
1105     action_group = gtk_action_group_new ("XedWindowActions");
1106     gtk_action_group_set_translation_domain (action_group, NULL);
1107     gtk_action_group_add_actions (action_group, xed_menu_entries, G_N_ELEMENTS(xed_menu_entries), window);
1108     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1109     g_object_unref (action_group);
1110     window->priv->action_group = action_group;
1111 
1112     action_group = gtk_action_group_new ("XedQuitWindowActions");
1113     gtk_action_group_set_translation_domain (action_group, NULL);
1114     gtk_action_group_add_actions (action_group, xed_quit_menu_entries, G_N_ELEMENTS(xed_quit_menu_entries), window);
1115 
1116     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1117     g_object_unref (action_group);
1118     window->priv->quit_action_group = action_group;
1119 
1120     action_group = gtk_action_group_new ("XedCloseWindowActions");
1121     gtk_action_group_set_translation_domain (action_group, NULL);
1122     gtk_action_group_add_actions (action_group, xed_close_menu_entries, G_N_ELEMENTS(xed_close_menu_entries), window);
1123 
1124     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1125     g_object_unref (action_group);
1126     window->priv->close_action_group = action_group;
1127 
1128     action_group = gtk_action_group_new ("XedWindowPanesActions");
1129     gtk_action_group_set_translation_domain (action_group, NULL);
1130     gtk_action_group_add_toggle_actions (action_group, xed_panes_toggle_menu_entries,
1131                                          G_N_ELEMENTS(xed_panes_toggle_menu_entries), window);
1132 
1133     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1134     g_object_unref (action_group);
1135     window->priv->panes_action_group = action_group;
1136 
1137     gtk_ui_manager_add_ui_from_resource (manager, "/org/x/editor/ui/xed-ui.xml", &error);
1138     if (error != NULL)
1139     {
1140         g_warning ("Could not add ui definition: %s", error->message);
1141         g_error_free (error);
1142     }
1143 
1144     /* show tooltips in the statusbar */
1145     g_signal_connect(manager, "connect_proxy", G_CALLBACK (connect_proxy_cb), window);
1146     g_signal_connect(manager, "disconnect_proxy", G_CALLBACK (disconnect_proxy_cb), window);
1147 
1148     /* recent files menu */
1149     action_group = gtk_action_group_new ("RecentFilesActions");
1150     gtk_action_group_set_translation_domain (action_group, NULL);
1151     window->priv->recents_action_group = action_group;
1152     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1153     g_object_unref (action_group);
1154 
1155     recent_manager = gtk_recent_manager_get_default ();
1156     window->priv->recents_handler_id = g_signal_connect(recent_manager, "changed", G_CALLBACK (recent_manager_changed),
1157                                                         window);
1158     update_recent_files_menu (window);
1159 
1160     action_group = gtk_action_group_new ("FavoriteFilesActions");
1161     gtk_action_group_set_translation_domain (action_group, NULL);
1162     window->priv->favorites_action_group = action_group;
1163     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1164     g_object_unref (action_group);
1165 
1166     favorites = xapp_favorites_get_default ();
1167     window->priv->favorites_handler_id = g_signal_connect_swapped (favorites,
1168                                                                    "changed", G_CALLBACK (update_favorites_menu),
1169                                                                    window);
1170 
1171     update_favorites_menu (window);
1172 
1173     /* list of open documents menu */
1174     action_group = gtk_action_group_new ("DocumentsListActions");
1175     gtk_action_group_set_translation_domain (action_group, NULL);
1176     window->priv->documents_list_action_group = action_group;
1177     gtk_ui_manager_insert_action_group (manager, action_group, 0);
1178     g_object_unref (action_group);
1179 
1180     window->priv->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
1181     gtk_box_pack_start (GTK_BOX(main_box), window->priv->menubar, FALSE, FALSE, 0);
1182 
1183     window->priv->toolbar = gtk_toolbar_new ();
1184     gtk_style_context_add_class (gtk_widget_get_style_context (window->priv->toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
1185     gtk_box_pack_start (GTK_BOX(main_box), window->priv->toolbar, FALSE, FALSE, 0);
1186 
1187     tool_item = gtk_tool_item_new ();
1188     gtk_tool_item_set_expand ((tool_item), TRUE);
1189     gtk_toolbar_insert (GTK_TOOLBAR (window->priv->toolbar), (tool_item), 0);
1190 
1191     tool_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1192     gtk_container_add (GTK_CONTAINER (tool_item), tool_box);
1193 
1194     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1195     gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1196 
1197     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
1198     button = create_toolbar_button (action);
1199     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1200 
1201     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
1202     button = create_toolbar_button (action);
1203     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1204 
1205     action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
1206     button = create_toolbar_button (action);
1207     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1208 
1209     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1210     gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1211 
1212     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1213     gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1214 
1215     action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
1216     button = create_toolbar_button (action);
1217     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1218 
1219     action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
1220     button = create_toolbar_button (action);
1221     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1222 
1223     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1224     gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1225 
1226     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1227     gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1228 
1229     action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
1230     button = create_toolbar_button (action);
1231     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1232 
1233     action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
1234     button = create_toolbar_button (action);
1235     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1236 
1237     action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
1238     button = create_toolbar_button (action);
1239     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1240 
1241     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1242     gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1243 
1244     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1245     gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1246 
1247     action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
1248     button = create_toolbar_button (action);
1249     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1250 
1251     action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
1252     button = create_toolbar_button (action);
1253     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1254 
1255     gtk_widget_show_all (GTK_WIDGET (window->priv->toolbar));
1256 
1257     set_toolbar_style (window, NULL);
1258     set_menubar_style (window, NULL);
1259 
1260     g_signal_connect_after(G_OBJECT (window->priv->toolbar), "show", G_CALLBACK (toolbar_visibility_changed), window);
1261     g_signal_connect_after(G_OBJECT (window->priv->toolbar), "hide", G_CALLBACK (toolbar_visibility_changed), window);
1262 }
1263 
1264 static void
documents_list_menu_activate(GtkToggleAction * action,XedWindow * window)1265 documents_list_menu_activate (GtkToggleAction *action,
1266                               XedWindow *window)
1267 {
1268     gint n;
1269     if (gtk_toggle_action_get_active (action) == FALSE)
1270     {
1271         return;
1272     }
1273     n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION(action));
1274     gtk_notebook_set_current_page (GTK_NOTEBOOK(window->priv->notebook), n);
1275 }
1276 
1277 static gchar *
get_menu_tip_for_tab(XedTab * tab)1278 get_menu_tip_for_tab (XedTab *tab)
1279 {
1280     XedDocument *doc;
1281     gchar *uri;
1282     gchar *ruri;
1283     gchar *tip;
1284 
1285     doc = xed_tab_get_document (tab);
1286 
1287     uri = xed_document_get_uri_for_display (doc);
1288     ruri = xed_utils_replace_home_dir_with_tilde (uri);
1289     g_free (uri);
1290 
1291     /* Translators: %s is a URI */
1292     tip = g_strdup_printf (_("Activate '%s'"), ruri);
1293     g_free (ruri);
1294 
1295     return tip;
1296 }
1297 
1298 static void
update_documents_list_menu(XedWindow * window)1299 update_documents_list_menu (XedWindow *window)
1300 {
1301     XedWindowPrivate *p = window->priv;
1302     GList *actions, *l;
1303     gint n, i;
1304     guint id;
1305     GSList *group = NULL;
1306 
1307     xed_debug (DEBUG_WINDOW);
1308 
1309     g_return_if_fail(p->documents_list_action_group != NULL);
1310 
1311     if (p->documents_list_menu_ui_id != 0)
1312     {
1313         gtk_ui_manager_remove_ui (p->manager, p->documents_list_menu_ui_id);
1314     }
1315 
1316     actions = gtk_action_group_list_actions (p->documents_list_action_group);
1317     for (l = actions; l != NULL; l = l->next)
1318     {
1319         g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (documents_list_menu_activate), window);
1320         gtk_action_group_remove_action (p->documents_list_action_group, GTK_ACTION(l->data));
1321     }
1322     g_list_free (actions);
1323 
1324     n = gtk_notebook_get_n_pages (GTK_NOTEBOOK(p->notebook));
1325 
1326     id = (n > 0) ? gtk_ui_manager_new_merge_id (p->manager) : 0;
1327 
1328     for (i = 0; i < n; i++)
1329     {
1330         GtkWidget *tab;
1331         GtkRadioAction *action;
1332         gchar *action_name;
1333         gchar *tab_name;
1334         gchar *name;
1335         gchar *tip;
1336         gchar *accel;
1337 
1338         tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK(p->notebook), i);
1339 
1340         /* NOTE: the action is associated to the position of the tab in
1341          * the notebook not to the tab itself! This is needed to work
1342          * around the gtk+ bug #170727: gtk leaves around the accels
1343          * of the action. Since the accel depends on the tab position
1344          * the problem is worked around, action with the same name always
1345          * get the same accel.
1346          */
1347         action_name = g_strdup_printf ("Tab_%d", i);
1348         tab_name = _xed_tab_get_name (XED_TAB(tab));
1349         name = xed_utils_escape_underscores (tab_name, -1);
1350         tip = get_menu_tip_for_tab (XED_TAB(tab));
1351 
1352         /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
1353         accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
1354 
1355         action = gtk_radio_action_new (action_name, name, tip, NULL, i);
1356 
1357         if (group != NULL)
1358         {
1359             gtk_radio_action_set_group (action, group);
1360         }
1361 
1362         /* note that group changes each time we add an action, so it must be updated */
1363         group = gtk_radio_action_get_group (action);
1364 
1365         gtk_action_group_add_action_with_accel (p->documents_list_action_group, GTK_ACTION(action), accel);
1366 
1367         g_signal_connect(action, "activate", G_CALLBACK (documents_list_menu_activate), window);
1368 
1369         gtk_ui_manager_add_ui (p->manager, id, "/MenuBar/DocumentsMenu/DocumentsListPlaceholder", action_name,
1370                                action_name, GTK_UI_MANAGER_MENUITEM, FALSE);
1371 
1372         if (XED_TAB (tab) == p->active_tab)
1373         {
1374             gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), TRUE);
1375         }
1376 
1377         g_object_unref (action);
1378 
1379         g_free (action_name);
1380         g_free (tab_name);
1381         g_free (name);
1382         g_free (tip);
1383         g_free (accel);
1384     }
1385 
1386     p->documents_list_menu_ui_id = id;
1387 }
1388 
1389 /* Returns TRUE if status bar is visible */
1390 static gboolean
set_statusbar_style(XedWindow * window,XedWindow * origin)1391 set_statusbar_style (XedWindow *window,
1392                      XedWindow *origin)
1393 {
1394     GtkAction *action;
1395     gboolean visible;
1396 
1397     if (origin == NULL)
1398     {
1399         visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_STATUSBAR_VISIBLE);
1400     }
1401     else
1402     {
1403         visible = gtk_widget_get_visible (origin->priv->statusbar);
1404     }
1405 
1406     if (visible)
1407     {
1408         gtk_widget_show (window->priv->statusbar);
1409     }
1410     else
1411     {
1412         gtk_widget_hide (window->priv->statusbar);
1413     }
1414 
1415     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
1416 
1417     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
1418     {
1419         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
1420     }
1421 
1422     return visible;
1423 }
1424 
1425 static void
statusbar_visibility_changed(GtkWidget * statusbar,XedWindow * window)1426 statusbar_visibility_changed (GtkWidget *statusbar,
1427                               XedWindow *window)
1428 {
1429     gboolean visible;
1430     GtkAction *action;
1431 
1432     visible = gtk_widget_get_visible (statusbar);
1433 
1434     g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_STATUSBAR_VISIBLE, visible);
1435 
1436     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
1437 
1438     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
1439     {
1440         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
1441     }
1442 }
1443 
1444 static void
tab_width_button_clicked(GtkMenuItem * item,XedWindow * window)1445 tab_width_button_clicked (GtkMenuItem *item,
1446                          XedWindow *window)
1447 {
1448     XedView *view;
1449     guint width_data = 0;
1450 
1451     view = xed_window_get_active_view (window);
1452 
1453     if (!view)
1454     {
1455         return;
1456     }
1457 
1458     width_data = GPOINTER_TO_INT(g_object_get_data (G_OBJECT (item), TAB_WIDTH_DATA));
1459 
1460     if (width_data == 0)
1461     {
1462         return;
1463     }
1464 
1465     gtk_source_view_set_tab_width (GTK_SOURCE_VIEW(view), width_data);
1466 }
1467 
1468 static void
set_tab_spaces_label(XedView * view,XedWindow * window,gboolean use_spaces)1469 set_tab_spaces_label (XedView   *view,
1470                       XedWindow *window,
1471                       gboolean   use_spaces)
1472 {
1473     gchar *label;
1474     guint tab_width;
1475 
1476     tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (view));
1477 
1478     if (use_spaces)
1479     {
1480         label = g_strdup_printf (_("Spaces: %u"), tab_width);
1481     }
1482     else
1483     {
1484         label = g_strdup_printf (_("Tabs: %u"), tab_width);
1485     }
1486 
1487     xed_status_menu_button_set_label (XED_STATUS_MENU_BUTTON (window->priv->tab_width_button), label);
1488 
1489     g_free (label);
1490 }
1491 
1492 static void
use_spaces_toggled(GtkCheckMenuItem * item,XedWindow * window)1493 use_spaces_toggled (GtkCheckMenuItem *item,
1494                     XedWindow *window)
1495 {
1496     XedView *view;
1497     gboolean use_spaces;
1498 
1499     view = xed_window_get_active_view (window);
1500     use_spaces = gtk_check_menu_item_get_active (item);
1501 
1502     set_tab_spaces_label (view, window, use_spaces);
1503 
1504     g_signal_handler_block (view, window->priv->spaces_instead_of_tabs_id);
1505     gtk_source_view_set_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (view), use_spaces);
1506     g_signal_handler_unblock (view, window->priv->spaces_instead_of_tabs_id);
1507 }
1508 
1509 typedef struct
1510 {
1511     const gchar *label;
1512     guint width;
1513 } TabWidthDefinition;
1514 
1515 static void
tab_width_menu_popped_up(GtkMenu * menu,gpointer flipped_rect,gpointer final_rect,gboolean flipped_x,gboolean flipped_y,gpointer user_data)1516 tab_width_menu_popped_up (GtkMenu *menu,
1517                           gpointer flipped_rect,
1518                           gpointer final_rect,
1519                           gboolean flipped_x,
1520                           gboolean flipped_y,
1521                           gpointer user_data)
1522 {
1523     XedWindow *window = XED_WINDOW (user_data);
1524 
1525     gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (window->priv->tab_width_item));
1526 }
1527 
1528 static void
setup_tab_width_menu(XedWindow * window)1529 setup_tab_width_menu (XedWindow *window)
1530 {
1531     static TabWidthDefinition defs[] = { { "2", 2 }, { "4", 4 }, { "8", 8 }, { "", 0 }, /* custom size */
1532     { NULL, 0 } };
1533 
1534     guint i = 0;
1535     GtkWidget *item;
1536 
1537     window->priv->tab_width_menu = gtk_menu_new ();
1538 
1539     while (defs[i].label != NULL)
1540     {
1541         item = gtk_menu_item_new_with_label (defs[i].label);
1542         g_object_set_data (G_OBJECT(item), TAB_WIDTH_DATA, GINT_TO_POINTER (defs[i].width));
1543 
1544         gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1545 
1546         g_signal_connect(G_OBJECT (item), "activate",
1547                          G_CALLBACK (tab_width_button_clicked), window);
1548 
1549         if (defs[i].width != 0)
1550         {
1551             gtk_widget_show (item);
1552         }
1553 
1554         ++i;
1555     }
1556 
1557     item = gtk_separator_menu_item_new ();
1558     gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1559     gtk_widget_show (item);
1560 
1561     item = gtk_check_menu_item_new_with_label (_("Use Spaces"));
1562     gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1563     gtk_widget_show (item);
1564 
1565     g_signal_connect (item, "toggled", G_CALLBACK (use_spaces_toggled), window);
1566 
1567     g_signal_connect (window->priv->tab_width_menu, "popped-up", G_CALLBACK (tab_width_menu_popped_up), window);
1568 }
1569 
1570 static void
on_language_selector_shown(XedHighlightModeSelector * sel,XedWindow * window)1571 on_language_selector_shown (XedHighlightModeSelector *sel,
1572                             XedWindow                *window)
1573 {
1574     XedDocument *doc;
1575 
1576     doc = xed_window_get_active_document (window);
1577     if (doc)
1578     {
1579         xed_highlight_mode_selector_select_language (sel,
1580                                                      xed_document_get_language (doc));
1581     }
1582 }
1583 
1584 static void
on_language_selected(XedHighlightModeSelector * sel,GtkSourceLanguage * language,XedWindow * window)1585 on_language_selected (XedHighlightModeSelector *sel,
1586                       GtkSourceLanguage        *language,
1587                       XedWindow                *window)
1588 {
1589     XedDocument *doc;
1590 
1591     doc = xed_window_get_active_document (window);
1592     if (doc)
1593     {
1594         xed_document_set_language (doc, language);
1595     }
1596 
1597     gtk_widget_hide (GTK_WIDGET (window->priv->language_popover));
1598 }
1599 
1600 static void
create_statusbar(XedWindow * window,GtkWidget * main_box)1601 create_statusbar (XedWindow *window,
1602                   GtkWidget *main_box)
1603 {
1604     GtkWidget *image;
1605     GtkWidget *button_box;
1606     GtkAction *action;
1607     XedHighlightModeSelector *sel;
1608 
1609     xed_debug (DEBUG_WINDOW);
1610 
1611     window->priv->statusbar = xed_statusbar_new ();
1612     window->priv->searchbar = xed_searchbar_new (GTK_WINDOW (window));
1613 
1614     window->priv->generic_message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar),
1615                                                                       "generic_message");
1616     window->priv->tip_message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar),
1617                                                                   "tip_message");
1618 
1619     gtk_box_pack_end (GTK_BOX( main_box), window->priv->statusbar, FALSE, TRUE, 0);
1620 
1621     gtk_widget_set_margin_start (GTK_WIDGET (window->priv->statusbar), 0);
1622     gtk_widget_set_margin_end (GTK_WIDGET (window->priv->statusbar), 0);
1623 
1624     window->priv->tab_width_button = xed_status_menu_button_new ();
1625     gtk_widget_show (window->priv->tab_width_button);
1626     gtk_box_pack_end (GTK_BOX (window->priv->statusbar), window->priv->tab_width_button, FALSE, FALSE, 0);
1627     gtk_widget_set_margin_bottom (GTK_WIDGET (window->priv->tab_width_button), 2);
1628     gtk_widget_set_margin_top (GTK_WIDGET (window->priv->tab_width_button), 2);
1629 
1630     setup_tab_width_menu (window);
1631 
1632     gtk_menu_button_set_popup (GTK_MENU_BUTTON (window->priv->tab_width_button),
1633                                window->priv->tab_width_menu);
1634 
1635     window->priv->language_button = xed_status_menu_button_new ();
1636     gtk_widget_show (window->priv->language_button);
1637     gtk_widget_set_margin_bottom (GTK_WIDGET (window->priv->language_button), 2);
1638     gtk_widget_set_margin_top (GTK_WIDGET (window->priv->language_button), 2);
1639     gtk_box_pack_end (GTK_BOX(window->priv->statusbar), window->priv->language_button, FALSE, FALSE, 0);
1640 
1641     window->priv->language_popover = gtk_popover_new (window->priv->language_button);
1642     gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->language_button),
1643                                  window->priv->language_popover);
1644 
1645     sel = xed_highlight_mode_selector_new ();
1646     g_signal_connect (sel,
1647                       "show",
1648                       G_CALLBACK (on_language_selector_shown),
1649                       window);
1650     g_signal_connect (sel,
1651                       "language-selected",
1652                       G_CALLBACK (on_language_selected),
1653                       window);
1654 
1655     gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (sel));
1656     gtk_widget_show (GTK_WIDGET (sel));
1657 
1658     button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
1659     gtk_widget_set_margin_top (button_box, 4);
1660     gtk_widget_set_margin_bottom (button_box, 4);
1661     gtk_widget_set_margin_start (button_box, 6);
1662     gtk_box_pack_start (GTK_BOX (window->priv->statusbar), button_box, FALSE, FALSE, 0);
1663 
1664     window->priv->show_side_pane_button = gtk_toggle_button_new ();
1665     image = gtk_image_new_from_icon_name ("view-left-pane-symbolic", GTK_ICON_SIZE_INVALID);
1666     gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
1667     gtk_container_add (GTK_CONTAINER (window->priv->show_side_pane_button), image);
1668     gtk_box_pack_start (GTK_BOX (button_box), window->priv->show_side_pane_button, FALSE, FALSE, 0);
1669 
1670     action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewSidePane");
1671     gtk_activatable_set_related_action (GTK_ACTIVATABLE (window->priv->show_side_pane_button), action);
1672     gtk_widget_set_tooltip_text (window->priv->show_side_pane_button, gtk_action_get_tooltip (action));
1673 
1674     window->priv->bottom_pane_button_revealer = gtk_revealer_new ();
1675     gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->bottom_pane_button_revealer),
1676                                       GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT);
1677     gtk_box_pack_start (GTK_BOX (button_box), window->priv->bottom_pane_button_revealer, FALSE, FALSE, 0);
1678 
1679     window->priv->show_bottom_pane_button = gtk_toggle_button_new ();
1680     image = gtk_image_new_from_icon_name ("view-bottom-pane-symbolic", GTK_ICON_SIZE_INVALID);
1681     gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
1682     gtk_container_add (GTK_CONTAINER (window->priv->show_bottom_pane_button), image);
1683     gtk_container_add (GTK_CONTAINER (window->priv->bottom_pane_button_revealer), window->priv->show_bottom_pane_button);
1684 
1685     action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
1686     gtk_activatable_set_related_action (GTK_ACTIVATABLE (window->priv->show_bottom_pane_button), action);
1687     gtk_widget_set_tooltip_text (window->priv->show_bottom_pane_button, gtk_action_get_tooltip (action));
1688 
1689     gtk_widget_show_all (button_box);
1690 
1691     g_signal_connect_after(G_OBJECT (window->priv->statusbar), "show",
1692                            G_CALLBACK (statusbar_visibility_changed), window);
1693 
1694     g_signal_connect_after(G_OBJECT (window->priv->statusbar), "hide",
1695                            G_CALLBACK (statusbar_visibility_changed), window);
1696 
1697     set_statusbar_style (window, NULL);
1698 
1699     gtk_box_pack_end (GTK_BOX (main_box), window->priv->searchbar, FALSE, FALSE, 0);
1700 
1701     gtk_box_reorder_child (GTK_BOX (window->priv->statusbar), button_box, 0);
1702 }
1703 
1704 static XedWindow *
clone_window(XedWindow * origin)1705 clone_window (XedWindow *origin)
1706 {
1707     XedWindow *window;
1708     GdkScreen *screen;
1709     XedApp *app;
1710     gint panel_page;
1711 
1712     xed_debug (DEBUG_WINDOW);
1713 
1714     app = XED_APP (g_application_get_default ());
1715 
1716     screen = gtk_window_get_screen (GTK_WINDOW (origin));
1717     window = xed_app_create_window (app, screen);
1718 
1719     gtk_window_set_default_size (GTK_WINDOW (window), origin->priv->width, origin->priv->height);
1720 
1721     if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
1722     {
1723         gtk_window_maximize (GTK_WINDOW (window));
1724     }
1725     else
1726     {
1727         gtk_window_unmaximize (GTK_WINDOW (window));
1728     }
1729 
1730     if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY) != 0)
1731     {
1732         gtk_window_stick (GTK_WINDOW(window));
1733     }
1734     else
1735     {
1736         gtk_window_unstick (GTK_WINDOW(window));
1737     }
1738 
1739     /* set the panes size, the paned position will be set when
1740      * they are mapped */
1741     window->priv->side_panel_size = origin->priv->side_panel_size;
1742     window->priv->bottom_panel_size = origin->priv->bottom_panel_size;
1743 
1744     panel_page = _xed_panel_get_active_item_id (XED_PANEL(origin->priv->side_panel));
1745     _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->side_panel), panel_page);
1746 
1747     panel_page = _xed_panel_get_active_item_id (XED_PANEL(origin->priv->bottom_panel));
1748     _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->bottom_panel), panel_page);
1749 
1750     if (gtk_widget_get_visible (origin->priv->side_panel))
1751     {
1752         gtk_widget_show (window->priv->side_panel);
1753     }
1754     else
1755     {
1756         gtk_widget_hide (window->priv->side_panel);
1757     }
1758 
1759     if (gtk_widget_get_visible (origin->priv->bottom_panel))
1760     {
1761         gtk_widget_show (window->priv->bottom_panel);
1762     }
1763     else
1764     {
1765         gtk_widget_hide (window->priv->bottom_panel);
1766     }
1767 
1768     set_menubar_style (window, origin);
1769     set_statusbar_style (window, origin);
1770     set_toolbar_style (window, origin);
1771 
1772     return window;
1773 }
1774 
1775 static void
update_cursor_position_statusbar(GtkTextBuffer * buffer,XedWindow * window)1776 update_cursor_position_statusbar (GtkTextBuffer *buffer,
1777                                   XedWindow *window)
1778 {
1779     gint row, col;
1780     GtkTextIter iter;
1781     GtkTextIter start;
1782     guint tab_size;
1783     XedView *view;
1784 
1785     xed_debug (DEBUG_WINDOW);
1786 
1787     if (buffer != GTK_TEXT_BUFFER(xed_window_get_active_document (window)))
1788     {
1789         return;
1790     }
1791 
1792     view = xed_window_get_active_view (window);
1793 
1794     gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
1795 
1796     row = gtk_text_iter_get_line (&iter);
1797 
1798     start = iter;
1799     gtk_text_iter_set_line_offset (&start, 0);
1800     col = 0;
1801 
1802     tab_size = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW(view));
1803 
1804     while (!gtk_text_iter_equal (&start, &iter))
1805     {
1806         /* FIXME: Are we Unicode compliant here? */
1807         if (gtk_text_iter_get_char (&start) == '\t')
1808         {
1809             col += (tab_size - (col % tab_size));
1810         }
1811         else
1812         {
1813             ++col;
1814         }
1815         gtk_text_iter_forward_char (&start);
1816     }
1817 
1818     xed_statusbar_set_cursor_position (XED_STATUSBAR(window->priv->statusbar), row + 1, col + 1);
1819 }
1820 
1821 static void
update_overwrite_mode_statusbar(GtkTextView * view,XedWindow * window)1822 update_overwrite_mode_statusbar (GtkTextView *view,
1823                                  XedWindow *window)
1824 {
1825     if (view != GTK_TEXT_VIEW (xed_window_get_active_view (window)))
1826     {
1827         return;
1828     }
1829 
1830     /* Note that we have to use !gtk_text_view_get_overwrite since we
1831      are in the in the signal handler of "toggle overwrite" that is
1832      G_SIGNAL_RUN_LAST
1833      */
1834     xed_statusbar_set_overwrite (XED_STATUSBAR(window->priv->statusbar), !gtk_text_view_get_overwrite (view));
1835 }
1836 
1837 #define MAX_TITLE_LENGTH 100
1838 
1839 static void
set_title(XedWindow * window)1840 set_title (XedWindow *window)
1841 {
1842     XedDocument *doc = NULL;
1843     gchar *name;
1844     gchar *dirname = NULL;
1845     gchar *title = NULL;
1846     gint len;
1847 
1848     if (window->priv->active_tab == NULL)
1849     {
1850         xed_app_set_window_title (XED_APP (g_application_get_default ()), window, "Xed");
1851         return;
1852     }
1853 
1854     doc = xed_tab_get_document (window->priv->active_tab);
1855     g_return_if_fail(doc != NULL);
1856 
1857     name = xed_document_get_short_name_for_display (doc);
1858 
1859     len = g_utf8_strlen (name, -1);
1860 
1861     /* if the name is awfully long, truncate it and be done with it,
1862      * otherwise also show the directory (ellipsized if needed)
1863      */
1864     if (len > MAX_TITLE_LENGTH)
1865     {
1866         gchar *tmp;
1867         tmp = xed_utils_str_middle_truncate (name, MAX_TITLE_LENGTH);
1868         g_free (name);
1869         name = tmp;
1870     }
1871     else
1872     {
1873         GtkSourceFile *file = xed_document_get_file (doc);
1874         GFile *location = gtk_source_file_get_location (file);
1875 
1876         if (location != NULL)
1877         {
1878             gchar *str = xed_utils_location_get_dirname_for_display (location);
1879 
1880             /* use the remaining space for the dir, but use a min of 20 chars
1881              * so that we do not end up with a dirname like "(a...b)".
1882              * This means that in the worst case when the filename is long 99
1883              * we have a title long 99 + 20, but I think it's a rare enough
1884              * case to be acceptable. It's justa darn title afterall :)
1885              */
1886             dirname = xed_utils_str_middle_truncate (str, MAX(20, MAX_TITLE_LENGTH - len));
1887             g_free (str);
1888         }
1889     }
1890 
1891     if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc)))
1892     {
1893         gchar *tmp_name;
1894         tmp_name = g_strdup_printf ("*%s", name);
1895         g_free (name);
1896         name = tmp_name;
1897     }
1898 
1899     if (xed_document_get_readonly (doc))
1900     {
1901         if (dirname != NULL)
1902         {
1903             title = g_strdup_printf ("%s [%s] (%s)", name, _("Read-Only"), dirname);
1904         }
1905         else
1906         {
1907             title = g_strdup_printf ("%s [%s]", name, _("Read-Only"));
1908         }
1909     }
1910     else
1911     {
1912         if (dirname != NULL)
1913         {
1914             title = g_strdup_printf ("%s (%s)", name, dirname);
1915         }
1916         else
1917         {
1918             title = g_strdup_printf ("%s", name);
1919         }
1920     }
1921 
1922     xed_app_set_window_title (XED_APP (g_application_get_default ()), window, title);
1923 
1924     g_free (dirname);
1925     g_free (name);
1926     g_free (title);
1927 }
1928 
1929 #undef MAX_TITLE_LENGTH
1930 
1931 static void
spaces_instead_of_tabs_changed(GObject * object,GParamSpec * pspec,XedWindow * window)1932 spaces_instead_of_tabs_changed (GObject *object,
1933                                 GParamSpec *pspec,
1934                                 XedWindow *window)
1935 {
1936     XedView *view = XED_VIEW(object);
1937     gboolean active = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW(view));
1938     GList *children = gtk_container_get_children (GTK_CONTAINER (window->priv->tab_width_menu));
1939     GtkCheckMenuItem *item;
1940     item = GTK_CHECK_MENU_ITEM(g_list_last (children)->data);
1941     gtk_check_menu_item_set_active (item, active);
1942     g_list_free (children);
1943 }
1944 
1945 static void
tab_width_changed(GObject * object,GParamSpec * pspec,XedWindow * window)1946 tab_width_changed (GObject *object,
1947                    GParamSpec *pspec,
1948                    XedWindow *window)
1949 {
1950     GList *items;
1951     GList *item;
1952     guint new_tab_width;
1953     gboolean use_spaces;
1954     gboolean found = FALSE;
1955 
1956     items = gtk_container_get_children (GTK_CONTAINER (window->priv->tab_width_menu));
1957 
1958     new_tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (object));
1959     use_spaces = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (object));
1960 
1961     for (item = items; item; item = item->next)
1962     {
1963         guint tab_width = GPOINTER_TO_INT(g_object_get_data (G_OBJECT (item->data), TAB_WIDTH_DATA));
1964 
1965         if (tab_width == new_tab_width)
1966         {
1967             window->priv->tab_width_item = item->data;
1968             if (gtk_widget_get_realized (window->priv->tab_width_menu))
1969             {
1970                 gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (item->data));
1971             }
1972             found = TRUE;
1973         }
1974 
1975         if (GTK_IS_SEPARATOR_MENU_ITEM(item->next->data))
1976         {
1977             if (!found)
1978             {
1979                 /* Set for the last item the custom thing */
1980                 gchar *text;
1981 
1982                 text = g_strdup_printf ("%u", new_tab_width);
1983                 gtk_menu_item_set_label (GTK_MENU_ITEM(item->data), text);
1984 
1985                 window->priv->tab_width_item = item->data;
1986                 if (gtk_widget_get_realized (window->priv->tab_width_menu))
1987                 {
1988                     gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (item->data));
1989                 }
1990                 gtk_widget_show (GTK_WIDGET(item->data));
1991             }
1992             else
1993             {
1994                 gtk_widget_hide (GTK_WIDGET(item->data));
1995             }
1996 
1997             break;
1998         }
1999     }
2000 
2001     set_tab_spaces_label (XED_VIEW (object), window, use_spaces);
2002 
2003     g_list_free (items);
2004 }
2005 
2006 static void
language_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2007 language_changed (GObject *object,
2008                   GParamSpec *pspec,
2009                   XedWindow *window)
2010 {
2011     GtkSourceLanguage *new_language;
2012     const gchar *label;
2013     GtkAction *action;
2014 
2015     new_language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (object));
2016 
2017     if (new_language)
2018     {
2019         label = gtk_source_language_get_name (new_language);
2020 
2021         action = gtk_action_group_get_action (window->priv->action_group, "EditToggleComment");
2022         gtk_action_set_sensitive (action,
2023                                   gtk_source_language_get_metadata (new_language, "line-comment-start") != NULL);
2024 
2025         action = gtk_action_group_get_action (window->priv->action_group, "EditToggleCommentBlock");
2026         gtk_action_set_sensitive (action,
2027                                   (gtk_source_language_get_metadata (new_language, "block-comment-start") != NULL
2028                                   && gtk_source_language_get_metadata (new_language, "block-comment-end") != NULL));
2029     }
2030     else
2031     {
2032         label = _("Plain Text");
2033 
2034         action = gtk_action_group_get_action (window->priv->action_group, "EditToggleComment");
2035         gtk_action_set_sensitive (action, FALSE);
2036 
2037         action = gtk_action_group_get_action (window->priv->action_group, "EditToggleCommentBlock");
2038         gtk_action_set_sensitive (action, FALSE);
2039     }
2040 
2041     xed_status_menu_button_set_label (XED_STATUS_MENU_BUTTON (window->priv->language_button), label);
2042 }
2043 
2044 static void
word_wrap_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2045 word_wrap_changed (GObject *object,
2046                    GParamSpec *pspec,
2047                    XedWindow *window)
2048 {
2049     XedView *view;
2050     GtkWrapMode wrap_mode;
2051     GtkAction *action;
2052     gboolean wrap_enabled;
2053 
2054     view = XED_VIEW (object);
2055     wrap_mode = gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view));
2056     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewWordWrap");
2057 
2058     if (wrap_mode == GTK_WRAP_NONE)
2059     {
2060         wrap_enabled = FALSE;
2061     }
2062     else
2063     {
2064         wrap_enabled = TRUE;
2065     }
2066 
2067     g_signal_handlers_block_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_word_wrap), window);
2068     gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), wrap_enabled);
2069     g_signal_handlers_unblock_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_word_wrap), window);
2070 }
2071 
2072 static void
show_overview_map_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2073 show_overview_map_changed (GObject    *object,
2074                            GParamSpec *pspec,
2075                            XedWindow  *window)
2076 {
2077     GtkFrame *map_frame;
2078     GtkAction *action;
2079     gboolean overveiw_map_visible = FALSE;
2080 
2081     map_frame = GTK_FRAME (object);
2082     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap");
2083 
2084     if (gtk_widget_get_visible (GTK_WIDGET (map_frame)))
2085     {
2086         overveiw_map_visible = TRUE;
2087     }
2088 
2089     g_signal_handlers_block_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_overview_map), window);
2090     gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), overveiw_map_visible);
2091     g_signal_handlers_unblock_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_overview_map), window);
2092 }
2093 
2094 static void
notebook_switch_page(GtkNotebook * book,GtkWidget * pg,gint page_num,XedWindow * window)2095 notebook_switch_page (GtkNotebook *book,
2096                       GtkWidget *pg,
2097                       gint page_num,
2098                       XedWindow *window)
2099 {
2100     XedView *view;
2101     GtkFrame *map_frame;
2102     XedTab *tab;
2103     GtkAction *action;
2104     gchar *action_name;
2105 
2106     /* CHECK: I don't know why but it seems notebook_switch_page is called
2107      two times every time the user change the active tab */
2108 
2109     tab = XED_TAB (gtk_notebook_get_nth_page (book, page_num));
2110     if (tab == window->priv->active_tab)
2111     {
2112         return;
2113     }
2114 
2115     if (window->priv->active_tab)
2116     {
2117         if (window->priv->tab_width_id)
2118         {
2119             g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->tab_width_id);
2120             window->priv->tab_width_id = 0;
2121         }
2122 
2123         if (window->priv->spaces_instead_of_tabs_id)
2124         {
2125             g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->spaces_instead_of_tabs_id);
2126             window->priv->spaces_instead_of_tabs_id = 0;
2127         }
2128 
2129         if (window->priv->use_word_wrap_id)
2130         {
2131             g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->use_word_wrap_id);
2132             window->priv->use_word_wrap_id = 0;
2133         }
2134 
2135         if (window->priv->show_overview_map_id)
2136         {
2137             g_signal_handler_disconnect (xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (window->priv->active_tab))), window->priv->show_overview_map_id);
2138             window->priv->show_overview_map_id = 0;
2139         }
2140     }
2141 
2142     /* set the active tab */
2143     window->priv->active_tab = tab;
2144 
2145     set_title (window);
2146     set_sensitivity_according_to_tab (window, tab);
2147 
2148     /* activate the right item in the documents menu */
2149     action_name = g_strdup_printf ("Tab_%d", page_num);
2150     action = gtk_action_group_get_action (window->priv->documents_list_action_group, action_name);
2151 
2152     /* sometimes the action doesn't exist yet, and the proper action
2153      * is set active during the documents list menu creation
2154      * CHECK: would it be nicer if active_tab was a property and we monitored the notify signal?
2155      */
2156     if (action != NULL)
2157     {
2158         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2159     }
2160 
2161     g_free (action_name);
2162 
2163     view = xed_tab_get_view (tab);
2164     map_frame = xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (tab)));
2165 
2166     /* sync the statusbar */
2167     update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window);
2168     xed_statusbar_set_overwrite (XED_STATUSBAR (window->priv->statusbar),
2169                                  gtk_text_view_get_overwrite (GTK_TEXT_VIEW(view)));
2170 
2171     gtk_widget_show (window->priv->tab_width_button);
2172     gtk_widget_show (window->priv->language_button);
2173 
2174     window->priv->tab_width_id = g_signal_connect(view, "notify::tab-width", G_CALLBACK (tab_width_changed), window);
2175 
2176     window->priv->spaces_instead_of_tabs_id = g_signal_connect(view, "notify::insert-spaces-instead-of-tabs",
2177                                                                G_CALLBACK (spaces_instead_of_tabs_changed), window);
2178 
2179     window->priv->language_changed_id = g_signal_connect(xed_tab_get_document (tab), "notify::language",
2180                                                          G_CALLBACK (language_changed), window);
2181 
2182     window->priv->use_word_wrap_id = g_signal_connect (view, "notify::wrap-mode",
2183                                                        G_CALLBACK (word_wrap_changed), window);
2184 
2185     window->priv->show_overview_map_id = g_signal_connect (map_frame, "notify::visible",
2186                                                            G_CALLBACK (show_overview_map_changed), window);
2187 
2188     /* call it for the first time */
2189     tab_width_changed (G_OBJECT (view), NULL, window);
2190     spaces_instead_of_tabs_changed (G_OBJECT (view), NULL, window);
2191     language_changed (G_OBJECT (xed_tab_get_document (tab)), NULL, window);
2192     word_wrap_changed (G_OBJECT (view), NULL, window);
2193     show_overview_map_changed (G_OBJECT (map_frame), NULL, window);
2194 
2195     g_signal_emit (G_OBJECT (window), signals[ACTIVE_TAB_CHANGED], 0, window->priv->active_tab);
2196 }
2197 
2198 static void
set_sensitivity_according_to_window_state(XedWindow * window)2199 set_sensitivity_according_to_window_state (XedWindow *window)
2200 {
2201     GtkAction *action;
2202 
2203     /* We disable File->Quit/SaveAll/CloseAll while printing to avoid to have two
2204      operations (save and print/print preview) that uses the message area at
2205      the same time (may be we can remove this limitation in the future) */
2206     /* We disable File->Quit/CloseAll if state is saving since saving cannot be
2207      cancelled (may be we can remove this limitation in the future) */
2208     gtk_action_group_set_sensitive (
2209                     window->priv->quit_action_group,
2210                     !(window->priv->state & XED_WINDOW_STATE_SAVING)
2211                     && !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2212 
2213     action = gtk_action_group_get_action (window->priv->action_group, "FileCloseAll");
2214     gtk_action_set_sensitive (
2215                     action,
2216                     !(window->priv->state & XED_WINDOW_STATE_SAVING)
2217                     && !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2218 
2219     action = gtk_action_group_get_action (window->priv->action_group, "FileSaveAll");
2220     gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2221 
2222     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
2223     gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2224 
2225     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
2226     gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2227 
2228     gtk_action_group_set_sensitive (window->priv->recents_action_group,
2229                                     !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2230 
2231     xed_notebook_set_close_buttons_sensitive (XED_NOTEBOOK(window->priv->notebook),
2232                                               !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2233 
2234     xed_notebook_set_tab_drag_and_drop_enabled (XED_NOTEBOOK(window->priv->notebook),
2235                                                 !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2236 
2237     if ((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) != 0)
2238     {
2239         /* TODO: If we really care, Find could be active
2240          * when in SAVING_SESSION state */
2241         if (gtk_action_group_get_sensitive (window->priv->action_group))
2242         {
2243             gtk_action_group_set_sensitive (window->priv->action_group, FALSE);
2244         }
2245         if (gtk_action_group_get_sensitive (window->priv->quit_action_group))
2246         {
2247             gtk_action_group_set_sensitive (window->priv->quit_action_group, FALSE);
2248         }
2249         if (gtk_action_group_get_sensitive (window->priv->close_action_group))
2250         {
2251             gtk_action_group_set_sensitive (window->priv->close_action_group, FALSE);
2252         }
2253     }
2254     else
2255     {
2256         if (!gtk_action_group_get_sensitive (window->priv->action_group))
2257         {
2258             gtk_action_group_set_sensitive (window->priv->action_group, window->priv->num_tabs > 0);
2259         }
2260         if (!gtk_action_group_get_sensitive (window->priv->quit_action_group))
2261         {
2262             gtk_action_group_set_sensitive (window->priv->quit_action_group, window->priv->num_tabs > 0);
2263         }
2264         if (!gtk_action_group_get_sensitive (window->priv->close_action_group))
2265         {
2266             gtk_action_group_set_sensitive (window->priv->close_action_group, window->priv->num_tabs > 0);
2267         }
2268     }
2269 }
2270 
2271 static void
analyze_tab_state(XedTab * tab,XedWindow * window)2272 analyze_tab_state (XedTab *tab,
2273                    XedWindow *window)
2274 {
2275     XedTabState ts;
2276 
2277     ts = xed_tab_get_state (tab);
2278 
2279     switch (ts)
2280     {
2281         case XED_TAB_STATE_LOADING:
2282         case XED_TAB_STATE_REVERTING:
2283             window->priv->state |= XED_WINDOW_STATE_LOADING;
2284             break;
2285         case XED_TAB_STATE_SAVING:
2286             window->priv->state |= XED_WINDOW_STATE_SAVING;
2287             break;
2288         case XED_TAB_STATE_PRINTING:
2289         case XED_TAB_STATE_PRINT_PREVIEWING:
2290             window->priv->state |= XED_WINDOW_STATE_PRINTING;
2291             break;
2292         case XED_TAB_STATE_LOADING_ERROR:
2293         case XED_TAB_STATE_REVERTING_ERROR:
2294         case XED_TAB_STATE_SAVING_ERROR:
2295         case XED_TAB_STATE_GENERIC_ERROR:
2296             window->priv->state |= XED_WINDOW_STATE_ERROR;
2297             ++window->priv->num_tabs_with_error;
2298             break;
2299         default:
2300             /* NOP */
2301             break;
2302     }
2303 }
2304 
2305 static void
update_window_state(XedWindow * window)2306 update_window_state (XedWindow *window)
2307 {
2308     XedWindowState old_ws;
2309     gint old_num_of_errors;
2310 
2311     xed_debug_message (DEBUG_WINDOW, "Old state: %x", window->priv->state);
2312 
2313     old_ws = window->priv->state;
2314     old_num_of_errors = window->priv->num_tabs_with_error;
2315 
2316     window->priv->state = old_ws & XED_WINDOW_STATE_SAVING_SESSION;
2317 
2318     window->priv->num_tabs_with_error = 0;
2319 
2320     gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) analyze_tab_state, window);
2321 
2322     xed_debug_message (DEBUG_WINDOW, "New state: %x", window->priv->state);
2323 
2324     if (old_ws != window->priv->state)
2325     {
2326         set_sensitivity_according_to_window_state (window);
2327         xed_statusbar_set_window_state (XED_STATUSBAR(window->priv->statusbar), window->priv->state,
2328                                         window->priv->num_tabs_with_error);
2329         g_object_notify (G_OBJECT(window), "state");
2330     }
2331     else if (old_num_of_errors != window->priv->num_tabs_with_error)
2332     {
2333         xed_statusbar_set_window_state (XED_STATUSBAR(window->priv->statusbar), window->priv->state,
2334                                         window->priv->num_tabs_with_error);
2335     }
2336 }
2337 
2338 static void
update_can_close(XedWindow * window)2339 update_can_close (XedWindow *window)
2340 {
2341     XedWindowPrivate *priv = window->priv;
2342     GList *tabs;
2343     GList *l;
2344     gboolean can_close = TRUE;
2345 
2346     tabs = xed_notebook_get_all_tabs (XED_NOTEBOOK (priv->notebook));
2347 
2348     for (l = tabs; l != NULL; l = g_list_next (l))
2349     {
2350         XedTab *tab = l->data;
2351 
2352         if (!_xed_tab_get_can_close (tab))
2353         {
2354             can_close = FALSE;
2355             break;
2356         }
2357     }
2358 
2359     if (can_close && (priv->inhibition_cookie != 0))
2360     {
2361         gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ()), priv->inhibition_cookie);
2362         priv->inhibition_cookie = 0;
2363     }
2364     else if (!can_close && (priv->inhibition_cookie == 0))
2365     {
2366         priv->inhibition_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
2367                                                            GTK_WINDOW (window),
2368                                                            GTK_APPLICATION_INHIBIT_LOGOUT,
2369                                                            _("There are unsaved documents"));
2370     }
2371 
2372     g_list_free (tabs);
2373 }
2374 
2375 static void
sync_state(XedTab * tab,GParamSpec * pspec,XedWindow * window)2376 sync_state (XedTab *tab,
2377             GParamSpec *pspec,
2378             XedWindow *window)
2379 {
2380     xed_debug (DEBUG_WINDOW);
2381     update_window_state (window);
2382     if (tab != window->priv->active_tab)
2383     {
2384         return;
2385     }
2386     set_sensitivity_according_to_tab (window, tab);
2387     g_signal_emit (G_OBJECT(window), signals[ACTIVE_TAB_STATE_CHANGED], 0);
2388 }
2389 
2390 static void
sync_name(XedTab * tab,GParamSpec * pspec,XedWindow * window)2391 sync_name (XedTab *tab,
2392            GParamSpec *pspec,
2393            XedWindow *window)
2394 {
2395     GtkAction *action;
2396     gchar *action_name;
2397     gchar *tab_name;
2398     gchar *escaped_name;
2399     gchar *tip;
2400     gint n;
2401     XedDocument *doc;
2402 
2403     if (tab == window->priv->active_tab)
2404     {
2405         set_title (window);
2406         doc = xed_tab_get_document (tab);
2407         action = gtk_action_group_get_action (window->priv->action_group, "FileRevert");
2408         gtk_action_set_sensitive (action, !xed_document_is_untitled (doc));
2409     }
2410 
2411     /* sync the item in the documents list menu */
2412     n = gtk_notebook_page_num (GTK_NOTEBOOK(window->priv->notebook), GTK_WIDGET(tab));
2413     action_name = g_strdup_printf ("Tab_%d", n);
2414     action = gtk_action_group_get_action (window->priv->documents_list_action_group, action_name);
2415     g_free (action_name);
2416     g_return_if_fail(action != NULL);
2417 
2418     tab_name = _xed_tab_get_name (tab);
2419     escaped_name = xed_utils_escape_underscores (tab_name, -1);
2420     tip = get_menu_tip_for_tab (tab);
2421 
2422     g_object_set (action, "label", escaped_name, NULL);
2423     g_object_set (action, "tooltip", tip, NULL);
2424 
2425     g_free (tab_name);
2426     g_free (escaped_name);
2427     g_free (tip);
2428 
2429     peas_extension_set_call (window->priv->extensions, "update_state");
2430 }
2431 
2432 static void
sync_can_close(XedTab * tab,GParamSpec * pspec,XedWindow * window)2433 sync_can_close (XedTab     *tab,
2434                 GParamSpec *pspec,
2435                 XedWindow  *window)
2436 {
2437     update_can_close (window);
2438 }
2439 
2440 static XedWindow *
get_drop_window(GtkWidget * widget)2441 get_drop_window (GtkWidget *widget)
2442 {
2443     GtkWidget *target_window;
2444     target_window = gtk_widget_get_toplevel (widget);
2445     g_return_val_if_fail(XED_IS_WINDOW (target_window), NULL);
2446 
2447     if ((XED_WINDOW(target_window)->priv->state & XED_WINDOW_STATE_SAVING_SESSION) != 0)
2448     {
2449         return NULL;
2450     }
2451 
2452     return XED_WINDOW(target_window);
2453 }
2454 
2455 static void
load_uris_from_drop(XedWindow * window,gchar ** uri_list)2456 load_uris_from_drop (XedWindow *window,
2457                      gchar    **uri_list)
2458 {
2459     GSList *locations = NULL;
2460     gint i;
2461     GSList *loaded;
2462 
2463     if (uri_list == NULL)
2464     {
2465         return;
2466     }
2467 
2468     for (i = 0; uri_list[i] != NULL; ++i)
2469     {
2470         locations = g_slist_prepend (locations, g_file_new_for_uri (uri_list[i]));
2471     }
2472 
2473     locations = g_slist_reverse (locations);
2474     loaded = xed_commands_load_locations (window, locations, NULL, 0);
2475 
2476     g_slist_free (loaded);
2477 
2478     g_slist_foreach (locations, (GFunc) g_object_unref, NULL);
2479     g_slist_free (locations);
2480 }
2481 
2482 /* Handle drops on the XedWindow */
2483 static void
drag_data_received_cb(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint timestamp,gpointer data)2484 drag_data_received_cb (GtkWidget *widget,
2485                        GdkDragContext *context,
2486                        gint x,
2487                        gint y,
2488                        GtkSelectionData *selection_data,
2489                        guint info,
2490                        guint timestamp,
2491                        gpointer data)
2492 {
2493     XedWindow *window;
2494     gchar **uri_list;
2495 
2496     window = get_drop_window (widget);
2497     if (window == NULL)
2498     {
2499         return;
2500     }
2501 
2502     if (info == TARGET_URI_LIST)
2503     {
2504         uri_list = xed_utils_drop_get_uris (selection_data);
2505         load_uris_from_drop (window, uri_list);
2506         g_strfreev (uri_list);
2507     }
2508 }
2509 
2510 /* Handle drops on the XedView */
2511 static void
drop_uris_cb(GtkWidget * widget,gchar ** uri_list)2512 drop_uris_cb (GtkWidget *widget,
2513               gchar **uri_list)
2514 {
2515     XedWindow *window;
2516     window = get_drop_window (widget);
2517     if (window == NULL)
2518     {
2519         return;
2520     }
2521     load_uris_from_drop (window, uri_list);
2522 }
2523 
2524 static gboolean
on_fullscreen_controls_enter_notify_event(GtkWidget * widget,GdkEventCrossing * event,XedWindow * window)2525 on_fullscreen_controls_enter_notify_event (GtkWidget        *widget,
2526                                            GdkEventCrossing *event,
2527                                            XedWindow        *window)
2528 {
2529     gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
2530 
2531     return FALSE;
2532 }
2533 
2534 static gboolean
on_fullscreen_controls_leave_notify_event(GtkWidget * widget,GdkEventCrossing * event,XedWindow * window)2535 on_fullscreen_controls_leave_notify_event (GtkWidget        *widget,
2536                                            GdkEventCrossing *event,
2537                                            XedWindow        *window)
2538 {
2539     GdkWindow *gdk_window;
2540     GdkDevice *device;
2541     GdkSeat *seat;
2542     gint x, y;
2543 
2544     seat = gdk_display_get_default_seat (gdk_display_get_default ());
2545     device = gdk_seat_get_pointer (seat);
2546     gdk_window = gtk_widget_get_parent_window (widget);
2547 
2548     gdk_window_get_device_position (gdk_window, device, &x, &y, NULL);
2549 
2550     // sometimes the leave event is erroneously triggered when y = 0
2551     if (y != 0)
2552     {
2553         gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
2554     }
2555 
2556     return FALSE;
2557 }
2558 
2559 static void
fullscreen_controls_build(XedWindow * window)2560 fullscreen_controls_build (XedWindow *window)
2561 {
2562     XedWindowPrivate *priv = window->priv;
2563     GtkAction *action;
2564     GtkWidget *box;
2565     GtkWidget *toolbar;
2566     GtkToolItem *toolitem;
2567     GtkWidget *toolbox;
2568     GtkWidget *fullscreen_btn;
2569     GtkWidget *separator;
2570     GtkWidget *button;
2571 
2572     if (priv->fullscreen_controls != NULL)
2573     {
2574         return;
2575     }
2576 
2577     priv->fullscreen_controls = gtk_revealer_new ();
2578     gtk_widget_set_valign (priv->fullscreen_controls, GTK_ALIGN_START);
2579     gtk_container_add (GTK_CONTAINER (priv->fullscreen_eventbox), priv->fullscreen_controls);
2580 
2581     toolbar = gtk_toolbar_new ();
2582     toolitem = gtk_tool_item_new ();
2583     gtk_tool_item_set_expand (toolitem, TRUE);
2584     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0);
2585 
2586     toolbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2587     gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "primary-toolbar");
2588     gtk_container_add (GTK_CONTAINER (toolitem), toolbox);
2589     gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), toolbar);
2590 
2591     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2592     gtk_widget_set_vexpand (box, FALSE);
2593     gtk_box_pack_start (GTK_BOX (toolbox), box, FALSE, FALSE, 0);
2594 
2595     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
2596     button = create_toolbar_button (action);
2597     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2598 
2599     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
2600     button = create_toolbar_button (action);
2601     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2602 
2603     action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
2604     button = create_toolbar_button (action);
2605     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2606 
2607     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2608     gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2609 
2610     action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
2611     button = create_toolbar_button (action);
2612     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2613 
2614     action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
2615     button = create_toolbar_button (action);
2616     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2617 
2618     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2619     gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2620 
2621     action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
2622     button = create_toolbar_button (action);
2623     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2624 
2625     action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
2626     button = create_toolbar_button (action);
2627     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2628 
2629     action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
2630     button = create_toolbar_button (action);
2631     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2632 
2633     separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2634     gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2635 
2636     action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
2637     button = create_toolbar_button (action);
2638     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2639 
2640     action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
2641     button = create_toolbar_button (action);
2642     gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2643 
2644     action = gtk_action_group_get_action (priv->always_sensitive_action_group, "LeaveFullscreen");
2645     g_object_set (action, "is-important", TRUE, NULL);
2646     fullscreen_btn = create_toolbar_button (action);
2647     gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0);
2648 
2649     gtk_widget_show_all (toolbox);
2650 
2651     g_signal_connect (priv->fullscreen_eventbox, "enter-notify-event",
2652                       G_CALLBACK (on_fullscreen_controls_enter_notify_event), window);
2653 
2654     g_signal_connect (priv->fullscreen_eventbox, "leave-notify-event",
2655                       G_CALLBACK (on_fullscreen_controls_leave_notify_event), window);
2656 
2657     gtk_widget_set_size_request (priv->fullscreen_eventbox, -1, 1);
2658 }
2659 
2660 static void
search_text_notify_cb(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2661 search_text_notify_cb (XedDocument *doc,
2662                        GParamSpec  *pspec,
2663                        XedWindow   *window)
2664 {
2665     gboolean sensitive;
2666     GtkAction *action;
2667 
2668     if (doc != xed_window_get_active_document (window))
2669     {
2670         return;
2671     }
2672 
2673     sensitive = TRUE;
2674 
2675     action = gtk_action_group_get_action (window->priv->action_group, "SearchFindNext");
2676     gtk_action_set_sensitive (action, sensitive);
2677 
2678     action = gtk_action_group_get_action (window->priv->action_group, "SearchFindPrevious");
2679     gtk_action_set_sensitive (action, sensitive);
2680 }
2681 
2682 static void
can_undo(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2683 can_undo (XedDocument *doc,
2684           GParamSpec *pspec,
2685           XedWindow *window)
2686 {
2687     GtkAction *action;
2688     gboolean sensitive;
2689 
2690     sensitive = gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER(doc));
2691 
2692     if (doc != xed_window_get_active_document (window))
2693     {
2694         return;
2695     }
2696 
2697     action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
2698     gtk_action_set_sensitive (action, sensitive);
2699 }
2700 
2701 static void
can_redo(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2702 can_redo (XedDocument *doc,
2703           GParamSpec *pspec,
2704           XedWindow *window)
2705 {
2706     GtkAction *action;
2707     gboolean sensitive;
2708 
2709     sensitive = gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER(doc));
2710 
2711     if (doc != xed_window_get_active_document (window))
2712     {
2713         return;
2714     }
2715 
2716     action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
2717     gtk_action_set_sensitive (action, sensitive);
2718 }
2719 
2720 static void
selection_changed(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2721 selection_changed (XedDocument *doc,
2722                    GParamSpec *pspec,
2723                    XedWindow *window)
2724 {
2725     XedTab *tab;
2726     XedView *view;
2727     GtkAction *action;
2728     XedTabState state;
2729     gboolean state_normal;
2730     gboolean editable;
2731 
2732     xed_debug (DEBUG_WINDOW);
2733 
2734     if (doc != xed_window_get_active_document (window))
2735     {
2736         return;
2737     }
2738 
2739     tab = xed_tab_get_from_document (doc);
2740     state = xed_tab_get_state (tab);
2741     state_normal = (state == XED_TAB_STATE_NORMAL);
2742 
2743     view = xed_tab_get_view (tab);
2744     editable = gtk_text_view_get_editable (GTK_TEXT_VIEW(view));
2745 
2746     action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
2747     gtk_action_set_sensitive (action,
2748                     state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2749 
2750     action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
2751     gtk_action_set_sensitive (action,
2752                     (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2753                     && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2754 
2755     action = gtk_action_group_get_action (window->priv->action_group, "EditDelete");
2756     gtk_action_set_sensitive (action,
2757                     state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2758 
2759     peas_extension_set_call (window->priv->extensions, "update_state");
2760 }
2761 
2762 static void
sync_languages_menu(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2763 sync_languages_menu (XedDocument *doc,
2764                      GParamSpec *pspec,
2765                      XedWindow *window)
2766 {
2767     peas_extension_set_call (window->priv->extensions, "update_state");
2768 }
2769 
2770 static void
readonly_changed(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2771 readonly_changed (XedDocument *doc,
2772                   GParamSpec *pspec,
2773                   XedWindow *window)
2774 {
2775     set_sensitivity_according_to_tab (window, window->priv->active_tab);
2776     sync_name (window->priv->active_tab, NULL, window);
2777     peas_extension_set_call (window->priv->extensions, "update_state");
2778 }
2779 
2780 static void
editable_changed(XedView * view,GParamSpec * arg1,XedWindow * window)2781 editable_changed (XedView *view,
2782                   GParamSpec *arg1,
2783                   XedWindow *window)
2784 {
2785     peas_extension_set_call (window->priv->extensions, "update_state");
2786 }
2787 
2788 static void
update_sensitivity_according_to_open_tabs(XedWindow * window)2789 update_sensitivity_according_to_open_tabs (XedWindow *window)
2790 {
2791     GtkAction *action;
2792 
2793     /* Set sensitivity */
2794     gtk_action_group_set_sensitive (window->priv->action_group, window->priv->num_tabs != 0);
2795 
2796     action = gtk_action_group_get_action (window->priv->action_group, "DocumentsMoveToNewWindow");
2797     gtk_action_set_sensitive (action, window->priv->num_tabs > 1);
2798     gtk_action_group_set_sensitive (window->priv->close_action_group, window->priv->num_tabs != 0);
2799 }
2800 
2801 static void
notebook_tab_added(XedNotebook * notebook,XedTab * tab,XedWindow * window)2802 notebook_tab_added (XedNotebook *notebook,
2803                     XedTab *tab,
2804                     XedWindow *window)
2805 {
2806     XedView *view;
2807     XedDocument *doc;
2808 
2809     xed_debug (DEBUG_WINDOW);
2810 
2811     g_return_if_fail((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) == 0);
2812 
2813     ++window->priv->num_tabs;
2814 
2815     update_sensitivity_according_to_open_tabs (window);
2816 
2817     view = xed_tab_get_view (tab);
2818     doc = xed_tab_get_document (tab);
2819 
2820     /* IMPORTANT: remember to disconnect the signal in notebook_tab_removed
2821      * if a new signal is connected here */
2822 
2823     g_signal_connect (tab, "notify::name", G_CALLBACK (sync_name), window);
2824     g_signal_connect (tab, "notify::state", G_CALLBACK (sync_state), window);
2825     g_signal_connect (tab, "notify::can-close", G_CALLBACK (sync_can_close), window);
2826 
2827     g_signal_connect (doc, "cursor-moved", G_CALLBACK (update_cursor_position_statusbar), window);
2828     g_signal_connect (doc, "notify::search-text", G_CALLBACK (search_text_notify_cb), window);
2829     g_signal_connect (doc, "notify::can-undo", G_CALLBACK (can_undo), window);
2830     g_signal_connect (doc, "notify::can-redo", G_CALLBACK (can_redo), window);
2831     g_signal_connect (doc, "notify::has-selection", G_CALLBACK (selection_changed), window);
2832     g_signal_connect (doc, "notify::language", G_CALLBACK (sync_languages_menu), window);
2833     g_signal_connect (doc, "notify::read-only", G_CALLBACK (readonly_changed), window);
2834     g_signal_connect (view, "toggle_overwrite", G_CALLBACK (update_overwrite_mode_statusbar), window);
2835     g_signal_connect (view, "notify::editable", G_CALLBACK (editable_changed), window);
2836 
2837     update_documents_list_menu (window);
2838 
2839     g_signal_connect(view, "drop_uris", G_CALLBACK (drop_uris_cb), NULL);
2840 
2841     update_window_state (window);
2842     update_can_close (window);
2843 
2844     g_signal_emit (G_OBJECT(window), signals[TAB_ADDED], 0, tab);
2845 }
2846 
2847 static void
notebook_tab_removed(XedNotebook * notebook,XedTab * tab,XedWindow * window)2848 notebook_tab_removed (XedNotebook *notebook,
2849                       XedTab *tab,
2850                       XedWindow *window)
2851 {
2852     XedView *view;
2853     XedViewFrame *frame;
2854     XedDocument *doc;
2855 
2856     xed_debug (DEBUG_WINDOW);
2857 
2858     g_return_if_fail((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) == 0);
2859 
2860     --window->priv->num_tabs;
2861 
2862     view = xed_tab_get_view (tab);
2863     frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
2864     doc = xed_tab_get_document (tab);
2865 
2866     g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window);
2867     g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_state), window);
2868     g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_can_close), window);
2869     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (update_cursor_position_statusbar), window);
2870     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (search_text_notify_cb), window);
2871     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (can_undo), window);
2872     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (can_redo), window);
2873     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (selection_changed), window);
2874     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (sync_languages_menu), window);
2875     g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (readonly_changed), window);
2876     g_signal_handlers_disconnect_by_func (view, G_CALLBACK (update_overwrite_mode_statusbar), window);
2877     g_signal_handlers_disconnect_by_func (view, G_CALLBACK (editable_changed), window);
2878     g_signal_handlers_disconnect_by_func (view, G_CALLBACK (drop_uris_cb), NULL);
2879 
2880     if (window->priv->tab_width_id && tab == xed_window_get_active_tab (window))
2881     {
2882         g_signal_handler_disconnect (view, window->priv->tab_width_id);
2883         window->priv->tab_width_id = 0;
2884     }
2885 
2886     if (window->priv->spaces_instead_of_tabs_id && tab == xed_window_get_active_tab (window))
2887     {
2888         g_signal_handler_disconnect (view, window->priv->spaces_instead_of_tabs_id);
2889         window->priv->spaces_instead_of_tabs_id = 0;
2890     }
2891 
2892     if (window->priv->language_changed_id && tab == xed_window_get_active_tab (window))
2893     {
2894         g_signal_handler_disconnect (doc, window->priv->language_changed_id);
2895         window->priv->language_changed_id = 0;
2896     }
2897 
2898     if (window->priv->use_word_wrap_id && tab == xed_window_get_active_tab (window))
2899     {
2900         g_signal_handler_disconnect (view, window->priv->use_word_wrap_id);
2901         window->priv->use_word_wrap_id = 0;
2902     }
2903 
2904     if (window->priv->show_overview_map_id && tab == xed_window_get_active_tab (window))
2905     {
2906         g_signal_handler_disconnect (xed_view_frame_get_map_frame (frame), window->priv->show_overview_map_id);
2907         window->priv->show_overview_map_id = 0;
2908     }
2909 
2910     g_return_if_fail(window->priv->num_tabs >= 0);
2911     if (window->priv->num_tabs == 0)
2912     {
2913         window->priv->active_tab = NULL;
2914         set_title (window);
2915 
2916         /* Remove line and col info */
2917         xed_statusbar_set_cursor_position (XED_STATUSBAR(window->priv->statusbar), -1, -1);
2918 
2919         xed_statusbar_clear_overwrite (XED_STATUSBAR(window->priv->statusbar));
2920 
2921         /* hide the combos */
2922         gtk_widget_hide (window->priv->tab_width_button);
2923         gtk_widget_hide (window->priv->language_button);
2924     }
2925 
2926     if (!window->priv->removing_tabs || window->priv->num_tabs == 0)
2927     {
2928         update_documents_list_menu (window);
2929         update_next_prev_doc_sensitivity_per_window (window);
2930     }
2931 
2932     update_sensitivity_according_to_open_tabs (window);
2933 
2934     if (window->priv->num_tabs == 0)
2935     {
2936         peas_extension_set_call (window->priv->extensions, "update_state");
2937     }
2938 
2939     update_window_state (window);
2940     update_can_close (window);
2941 
2942     g_signal_emit (G_OBJECT(window), signals[TAB_REMOVED], 0, tab);
2943 }
2944 
2945 static void
notebook_tabs_reordered(XedNotebook * notebook,XedWindow * window)2946 notebook_tabs_reordered (XedNotebook *notebook,
2947                          XedWindow *window)
2948 {
2949     update_documents_list_menu (window);
2950     update_next_prev_doc_sensitivity_per_window (window);
2951     g_signal_emit (G_OBJECT(window), signals[TABS_REORDERED], 0);
2952 }
2953 
2954 static void
notebook_tab_detached(XedNotebook * notebook,XedTab * tab,XedWindow * window)2955 notebook_tab_detached (XedNotebook *notebook,
2956                        XedTab *tab,
2957                        XedWindow *window)
2958 {
2959     XedWindow *new_window;
2960 
2961     new_window = clone_window (window);
2962 
2963     xed_notebook_move_tab (notebook, XED_NOTEBOOK(_xed_window_get_notebook (new_window)), tab, 0);
2964 
2965     gtk_window_set_position (GTK_WINDOW(new_window), GTK_WIN_POS_MOUSE);
2966 
2967     gtk_widget_show (GTK_WIDGET(new_window));
2968 }
2969 
2970 static void
notebook_tab_close_request(XedNotebook * notebook,XedTab * tab,GtkWindow * window)2971 notebook_tab_close_request (XedNotebook *notebook,
2972                             XedTab *tab,
2973                             GtkWindow *window)
2974 {
2975     /* Note: we are destroying the tab before the default handler
2976      * seems to be ok, but we need to keep an eye on this. */
2977     _xed_cmd_file_close_tab (tab, XED_WINDOW(window));
2978 }
2979 
2980 static gboolean
show_notebook_popup_menu(GtkNotebook * notebook,XedWindow * window,GdkEventButton * event)2981 show_notebook_popup_menu (GtkNotebook *notebook,
2982                           XedWindow *window,
2983                           GdkEventButton *event)
2984 {
2985     GtkWidget *menu;
2986 //  GtkAction *action;
2987 
2988     menu = gtk_ui_manager_get_widget (window->priv->manager, "/NotebookPopup");
2989     g_return_val_if_fail(menu != NULL, FALSE);
2990 
2991 // CHECK do we need this?
2992 #if 0
2993     /* allow extensions to sync when showing the popup */
2994     action = gtk_action_group_get_action (window->priv->action_group,
2995                     "NotebookPopupAction");
2996     g_return_val_if_fail (action != NULL, FALSE);
2997     gtk_action_activate (action);
2998 #endif
2999     if (event != NULL)
3000     {
3001         gtk_menu_popup_at_pointer (GTK_MENU(menu), (GdkEvent *) event);
3002 
3003     }
3004     else
3005     {
3006         GtkWidget *tab;
3007         GtkWidget *tab_label;
3008 
3009         tab = GTK_WIDGET (xed_window_get_active_tab (window));
3010         g_return_val_if_fail (tab != NULL, FALSE);
3011 
3012         tab_label = gtk_notebook_get_tab_label (notebook, tab);
3013 
3014         gtk_menu_popup_at_widget (GTK_MENU (menu), tab_label, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
3015 
3016         gtk_menu_shell_select_first (GTK_MENU_SHELL(menu), FALSE);
3017     }
3018 
3019     return TRUE;
3020 }
3021 
3022 static gboolean
notebook_button_press_event(GtkNotebook * notebook,GdkEventButton * event,XedWindow * window)3023 notebook_button_press_event (GtkNotebook *notebook,
3024                              GdkEventButton *event,
3025                              XedWindow *window)
3026 {
3027     if (GDK_BUTTON_PRESS == event->type && 3 == event->button)
3028     {
3029         return show_notebook_popup_menu (notebook, window, event);
3030     }
3031     else if (GDK_BUTTON_PRESS == event->type && 2 == event->button)
3032     {
3033         XedTab *tab;
3034         tab = xed_window_get_active_tab (window);
3035         notebook_tab_close_request (XED_NOTEBOOK(notebook), tab, GTK_WINDOW(window));
3036         return FALSE;
3037     }
3038     return FALSE;
3039 }
3040 
3041 static gboolean
notebook_popup_menu(GtkNotebook * notebook,XedWindow * window)3042 notebook_popup_menu (GtkNotebook *notebook,
3043                      XedWindow *window)
3044 {
3045     /* Only respond if the notebook is the actual focus */
3046     if (XED_IS_NOTEBOOK(gtk_window_get_focus (GTK_WINDOW (window))))
3047     {
3048         return show_notebook_popup_menu (notebook, window, NULL);
3049     }
3050     return FALSE;
3051 }
3052 
3053 static void
side_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,XedWindow * window)3054 side_panel_size_allocate (GtkWidget *widget,
3055                           GtkAllocation *allocation,
3056                           XedWindow *window)
3057 {
3058     if (!xed_paned_get_is_animating (XED_PANED (window->priv->hpaned)))
3059     {
3060         window->priv->side_panel_size = allocation->width;
3061     }
3062 }
3063 
3064 static void
bottom_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,XedWindow * window)3065 bottom_panel_size_allocate (GtkWidget *widget,
3066                             GtkAllocation *allocation,
3067                             XedWindow *window)
3068 {
3069     if (!xed_paned_get_is_animating (XED_PANED (window->priv->vpaned)))
3070     {
3071         window->priv->bottom_panel_size = allocation->height;
3072     }
3073 }
3074 
3075 static void
hpaned_restore_position(GtkWidget * widget,XedWindow * window)3076 hpaned_restore_position (GtkWidget *widget,
3077                          XedWindow *window)
3078 {
3079     gint pos;
3080     xed_debug_message (DEBUG_WINDOW, "Restoring hpaned position: side panel size %d", window->priv->side_panel_size);
3081 
3082     pos = MAX(100, window->priv->side_panel_size);
3083     gtk_paned_set_position (GTK_PANED(window->priv->hpaned), pos);
3084 
3085     /* start monitoring the size */
3086     g_signal_connect(window->priv->side_panel, "size-allocate", G_CALLBACK (side_panel_size_allocate), window);
3087 
3088     /* run this only once */
3089     g_signal_handlers_disconnect_by_func(widget, hpaned_restore_position, window);
3090 }
3091 
3092 static void
vpaned_restore_position(GtkWidget * widget,XedWindow * window)3093 vpaned_restore_position (GtkWidget *widget,
3094                          XedWindow *window)
3095 {
3096     GtkAllocation allocation;
3097     gint pos;
3098 
3099     gtk_widget_get_allocation (widget, &allocation);
3100 
3101     xed_debug_message (DEBUG_WINDOW, "Restoring vpaned position: bottom panel size %d",
3102                        window->priv->bottom_panel_size);
3103 
3104     pos = allocation.height - MAX(50, window->priv->bottom_panel_size);
3105     gtk_paned_set_position (GTK_PANED(window->priv->vpaned), pos);
3106 
3107     /* start monitoring the size */
3108     g_signal_connect(window->priv->bottom_panel, "size-allocate", G_CALLBACK (bottom_panel_size_allocate), window);
3109 
3110     /* run this only once */
3111     g_signal_handlers_disconnect_by_func(widget, vpaned_restore_position, window);
3112 }
3113 
3114 static void
side_panel_visibility_changed(GtkWidget * side_panel,XedWindow * window)3115 side_panel_visibility_changed (GtkWidget *side_panel,
3116                                XedWindow *window)
3117 {
3118     gboolean visible;
3119     GtkAction *action;
3120 
3121     visible = gtk_widget_get_visible (side_panel);
3122 
3123     g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_SIDE_PANEL_VISIBLE, visible);
3124 
3125     action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewSidePane");
3126 
3127     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
3128     {
3129         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
3130     }
3131 
3132     /* focus the document */
3133     if (!visible && window->priv->active_tab != NULL)
3134     {
3135         gtk_widget_grab_focus (GTK_WIDGET(xed_tab_get_view (XED_TAB (window->priv->active_tab))));
3136     }
3137 }
3138 
3139 static void
create_side_panel(XedWindow * window)3140 create_side_panel (XedWindow *window)
3141 {
3142     GtkWidget *documents_panel;
3143     xed_debug (DEBUG_WINDOW);
3144 
3145     window->priv->side_panel = xed_panel_new (GTK_ORIENTATION_VERTICAL);
3146 
3147     gtk_paned_pack1 (GTK_PANED (window->priv->hpaned), window->priv->side_panel, FALSE, TRUE);
3148 
3149     g_signal_connect_after (window->priv->side_panel, "show", G_CALLBACK (side_panel_visibility_changed), window);
3150     g_signal_connect_after (window->priv->side_panel, "hide", G_CALLBACK (side_panel_visibility_changed), window);
3151 
3152     documents_panel = xed_documents_panel_new (window);
3153     xed_panel_add_item (XED_PANEL (window->priv->side_panel), documents_panel, _("Documents"), "text-x-generic");
3154 }
3155 
3156 static void
bottom_panel_visibility_changed(XedPanel * bottom_panel,XedWindow * window)3157 bottom_panel_visibility_changed (XedPanel *bottom_panel,
3158                                  XedWindow *window)
3159 {
3160     gboolean visible;
3161     GtkAction *action;
3162 
3163     visible = gtk_widget_get_visible (GTK_WIDGET (bottom_panel));
3164 
3165     g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_BOTTOM_PANEL_VISIBLE, visible);
3166 
3167     action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3168 
3169     if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
3170     {
3171         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
3172     }
3173 
3174     /* focus the document */
3175     if (!visible && window->priv->active_tab != NULL)
3176     {
3177         gtk_widget_grab_focus (GTK_WIDGET(xed_tab_get_view (XED_TAB (window->priv->active_tab))));
3178     }
3179 }
3180 
3181 static void
bottom_panel_item_removed(XedPanel * panel,GtkWidget * item,XedWindow * window)3182 bottom_panel_item_removed (XedPanel  *panel,
3183                            GtkWidget *item,
3184                            XedWindow *window)
3185 {
3186     if (xed_panel_get_n_items (panel) == 0)
3187     {
3188         GtkAction *action;
3189 
3190         xed_paned_close (XED_PANED (window->priv->vpaned), 2);
3191         gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
3192         action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3193         gtk_action_set_sensitive (action, FALSE);
3194     }
3195 }
3196 
3197 static void
bottom_panel_item_added(XedPanel * panel,GtkWidget * item,XedWindow * window)3198 bottom_panel_item_added (XedPanel  *panel,
3199                          GtkWidget *item,
3200                          XedWindow *window)
3201 {
3202     /* if it's the first item added, set the menu item
3203      * sensitive and if needed show the panel */
3204     if (xed_panel_get_n_items (panel) == 1)
3205     {
3206         GtkAction *action;
3207         gboolean show;
3208 
3209         gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), TRUE);
3210 
3211         action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3212         gtk_action_set_sensitive (action, TRUE);
3213         show = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3214         if (show)
3215         {
3216             gtk_widget_show (GTK_WIDGET(panel));
3217         }
3218     }
3219 }
3220 
3221 static void
create_bottom_panel(XedWindow * window)3222 create_bottom_panel (XedWindow *window)
3223 {
3224     xed_debug (DEBUG_WINDOW);
3225     window->priv->bottom_panel = xed_panel_new (GTK_ORIENTATION_HORIZONTAL);
3226     gtk_paned_pack2 (GTK_PANED (window->priv->vpaned), window->priv->bottom_panel, FALSE, TRUE);
3227     g_signal_connect_after(window->priv->bottom_panel, "show", G_CALLBACK (bottom_panel_visibility_changed), window);
3228     g_signal_connect_after(window->priv->bottom_panel, "hide", G_CALLBACK (bottom_panel_visibility_changed), window);
3229 }
3230 
3231 static void
init_panels_visibility(XedWindow * window)3232 init_panels_visibility (XedWindow *window)
3233 {
3234     gint active_page;
3235     gboolean side_panel_visible;
3236     gboolean bottom_panel_visible;
3237 
3238     xed_debug (DEBUG_WINDOW);
3239 
3240     /* side pane */
3241     active_page = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_ACTIVE_PAGE);
3242     _xed_panel_set_active_item_by_id (XED_PANEL (window->priv->side_panel), active_page);
3243 
3244     side_panel_visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_SIDE_PANEL_VISIBLE);
3245     bottom_panel_visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_BOTTOM_PANEL_VISIBLE);
3246 
3247     if (side_panel_visible)
3248     {
3249         gtk_widget_show (window->priv->side_panel);
3250     }
3251 
3252     /* bottom pane, it can be empty */
3253     if (xed_panel_get_n_items (XED_PANEL (window->priv->bottom_panel)) > 0)
3254     {
3255         active_page = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE);
3256         _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->bottom_panel), active_page);
3257 
3258         if (bottom_panel_visible)
3259         {
3260             gtk_widget_show (window->priv->bottom_panel);
3261         }
3262 
3263         gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), TRUE);
3264     }
3265     else
3266     {
3267         GtkAction *action;
3268 
3269         action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3270         gtk_action_set_sensitive (action, FALSE);
3271         gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
3272     }
3273 
3274     /* start track sensitivity after the initial state is set */
3275     window->priv->bottom_panel_item_removed_handler_id =
3276         g_signal_connect (window->priv->bottom_panel, "item_removed",
3277         G_CALLBACK (bottom_panel_item_removed), window);
3278 
3279     g_signal_connect(window->priv->bottom_panel, "item_added", G_CALLBACK (bottom_panel_item_added), window);
3280 }
3281 
3282 static void
clipboard_owner_change(GtkClipboard * clipboard,GdkEventOwnerChange * event,XedWindow * window)3283 clipboard_owner_change (GtkClipboard *clipboard,
3284                         GdkEventOwnerChange *event,
3285                         XedWindow *window)
3286 {
3287     set_paste_sensitivity_according_to_clipboard (window, clipboard);
3288 }
3289 
3290 static void
window_realized(GtkWidget * window,gpointer * data)3291 window_realized (GtkWidget *window,
3292                  gpointer *data)
3293 {
3294     GtkClipboard *clipboard;
3295     clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD);
3296     g_signal_connect(clipboard, "owner_change", G_CALLBACK (clipboard_owner_change), window);
3297 }
3298 
3299 static void
window_unrealized(GtkWidget * window,gpointer * data)3300 window_unrealized (GtkWidget *window,
3301                    gpointer *data)
3302 {
3303     GtkClipboard *clipboard;
3304     clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD);
3305     g_signal_handlers_disconnect_by_func(clipboard, G_CALLBACK (clipboard_owner_change), window);
3306 }
3307 
3308 static void
check_window_is_active(XedWindow * window,GParamSpec * property,gpointer useless)3309 check_window_is_active (XedWindow *window,
3310                         GParamSpec *property,
3311                         gpointer useless)
3312 {
3313     if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
3314     {
3315         gtk_widget_set_visible (window->priv->fullscreen_eventbox, gtk_window_is_active (GTK_WINDOW (window)));
3316     }
3317 }
3318 
3319 static void
connect_notebook_signals(XedWindow * window,GtkWidget * notebook)3320 connect_notebook_signals (XedWindow *window,
3321                           GtkWidget *notebook)
3322 {
3323     g_signal_connect(notebook, "switch-page", G_CALLBACK (notebook_switch_page), window);
3324     g_signal_connect(notebook, "tab-added", G_CALLBACK (notebook_tab_added), window);
3325     g_signal_connect(notebook, "tab-removed", G_CALLBACK (notebook_tab_removed), window);
3326     g_signal_connect(notebook, "tabs-reordered", G_CALLBACK (notebook_tabs_reordered), window);
3327     g_signal_connect(notebook, "tab-detached", G_CALLBACK (notebook_tab_detached), window);
3328     g_signal_connect(notebook, "tab-close-request", G_CALLBACK (notebook_tab_close_request), window);
3329     g_signal_connect(notebook, "button-press-event", G_CALLBACK (notebook_button_press_event), window);
3330     g_signal_connect(notebook, "popup-menu", G_CALLBACK (notebook_popup_menu), window);
3331 }
3332 
3333 static void
add_notebook(XedWindow * window,GtkWidget * notebook)3334 add_notebook (XedWindow *window,
3335               GtkWidget *notebook)
3336 {
3337     gtk_paned_pack1 (GTK_PANED(window->priv->vpaned), notebook, TRUE, TRUE);
3338     gtk_widget_show (notebook);
3339 
3340     // xed_notebook_set_tab_scrolling_enabled (XED_NOTEBOOK (notebook), xed_prefs_manager_get_enable_tab_scrolling ());
3341 
3342     connect_notebook_signals (window, notebook);
3343 }
3344 
3345  static void
extension_added(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,XedWindow * window)3346 extension_added (PeasExtensionSet *extensions,
3347                  PeasPluginInfo   *info,
3348                  PeasExtension    *exten,
3349                  XedWindow        *window)
3350 {
3351     peas_extension_call (exten, "activate");
3352 }
3353 
3354 static void
extension_removed(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,XedWindow * window)3355 extension_removed (PeasExtensionSet *extensions,
3356                    PeasPluginInfo   *info,
3357                    PeasExtension    *exten,
3358                    XedWindow        *window)
3359 {
3360     peas_extension_call (exten, "deactivate");
3361 
3362     /* Ensure update of the ui manager, because we suspect it does something with expected static strings in the
3363      * type module (when unloaded the strings don't exist anymore, and the ui manager update in a idle func) */
3364     gtk_ui_manager_ensure_update (window->priv->manager);
3365 }
3366 
3367 static void
xed_window_init(XedWindow * window)3368 xed_window_init (XedWindow *window)
3369 {
3370     GtkWidget *main_box;
3371     GtkTargetList *tl;
3372 
3373     xed_debug (DEBUG_WINDOW);
3374 
3375     window->priv = xed_window_get_instance_private (window);
3376     window->priv->active_tab = NULL;
3377     window->priv->num_tabs = 0;
3378     window->priv->removing_tabs = FALSE;
3379     window->priv->state = XED_WINDOW_STATE_NORMAL;
3380     window->priv->inhibition_cookie = 0;
3381     window->priv->dispose_has_run = FALSE;
3382     window->priv->fullscreen_controls = NULL;
3383     window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor");
3384     window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui");
3385 
3386     /* Window settings are applied only once the window is closed. We do not want
3387        to keep writing to disk when the window is dragged around */
3388     window->priv->window_settings = g_settings_new ("org.x.editor.state.window");
3389     g_settings_delay (window->priv->window_settings);
3390 
3391     window->priv->message_bus = xed_message_bus_new ();
3392 
3393     window->priv->window_group = gtk_window_group_new ();
3394     gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
3395 
3396     gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window");
3397 
3398     main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3399     window->priv->fullscreen_overlay = gtk_overlay_new ();
3400     gtk_container_add (GTK_CONTAINER (window->priv->fullscreen_overlay), main_box);
3401     gtk_container_add (GTK_CONTAINER (window), window->priv->fullscreen_overlay);
3402     gtk_widget_show (window->priv->fullscreen_overlay);
3403     gtk_widget_show (main_box);
3404 
3405     window->priv->fullscreen_eventbox = gtk_event_box_new ();
3406     gtk_widget_set_valign (window->priv->fullscreen_eventbox, GTK_ALIGN_START);
3407     gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fullscreen_overlay), window->priv->fullscreen_eventbox);
3408 
3409     /* Add menu bar and toolbar bar */
3410     create_menu_bar_and_toolbar (window, main_box);
3411 
3412     /* If we're running as root, add and infobar to warn about elevated privileges */
3413     if (geteuid () == 0)
3414     {
3415         GtkWidget *root_bar = gtk_info_bar_new ();
3416         gtk_info_bar_set_message_type (GTK_INFO_BAR (root_bar), GTK_MESSAGE_ERROR);
3417         GtkWidget *content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (root_bar));
3418         GtkWidget *label = gtk_label_new (_("Elevated Privileges"));
3419         gtk_widget_show (label);
3420         gtk_container_add (GTK_CONTAINER (content_area), label);
3421         gtk_box_pack_start (GTK_BOX (main_box), root_bar, FALSE, FALSE, 0);
3422         gtk_widget_set_visible (root_bar, TRUE);
3423     }
3424 
3425     /* Add status bar */
3426     create_statusbar (window, main_box);
3427 
3428     /* Add the main area */
3429     xed_debug_message (DEBUG_WINDOW, "Add main area");
3430     window->priv->hpaned = xed_paned_new (GTK_ORIENTATION_HORIZONTAL);
3431     gtk_box_pack_start (GTK_BOX (main_box), window->priv->hpaned, TRUE, TRUE, 0);
3432 
3433     window->priv->vpaned = xed_paned_new (GTK_ORIENTATION_VERTICAL);
3434     gtk_paned_pack2 (GTK_PANED (window->priv->hpaned), window->priv->vpaned, TRUE, FALSE);
3435 
3436     xed_debug_message (DEBUG_WINDOW, "Create xed notebook");
3437     window->priv->notebook = xed_notebook_new ();
3438     add_notebook (window, window->priv->notebook);
3439 
3440     /* side and bottom panels */
3441     create_side_panel (window);
3442     create_bottom_panel (window);
3443 
3444     /* panes' state must be restored after panels have been mapped,
3445      * since the bottom pane position depends on the size of the vpaned. */
3446     window->priv->side_panel_size = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_SIZE);
3447     window->priv->bottom_panel_size = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_SIZE);
3448 
3449     g_signal_connect_after(window->priv->hpaned, "map", G_CALLBACK (hpaned_restore_position), window);
3450     g_signal_connect_after(window->priv->vpaned, "map", G_CALLBACK (vpaned_restore_position), window);
3451 
3452     gtk_widget_show (window->priv->hpaned);
3453     gtk_widget_show (window->priv->vpaned);
3454 
3455     /* Drag and drop support, set targets to NULL because we add the
3456      default uri_targets below */
3457     gtk_drag_dest_set (GTK_WIDGET(window), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
3458                        NULL, 0, GDK_ACTION_COPY);
3459 
3460     /* Add uri targets */
3461     tl = gtk_drag_dest_get_target_list (GTK_WIDGET (window));
3462 
3463     if (tl == NULL)
3464     {
3465         tl = gtk_target_list_new (NULL, 0);
3466         gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
3467         gtk_target_list_unref (tl);
3468     }
3469 
3470     gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
3471 
3472     /* connect instead of override, so that we can share the cb code with the view */
3473     g_signal_connect (window, "drag_data_received", G_CALLBACK (drag_data_received_cb), NULL);
3474 
3475     /* we can get the clipboard only after the widget is realized */
3476     g_signal_connect (window, "realize", G_CALLBACK (window_realized), NULL);
3477     g_signal_connect (window, "unrealize", G_CALLBACK (window_unrealized), NULL);
3478 
3479     /* Check if the window is active for fullscreen */
3480     g_signal_connect (window, "notify::is-active", G_CALLBACK (check_window_is_active), NULL);
3481 
3482     g_signal_connect (GTK_WIDGET (window), "key-press-event", G_CALLBACK (on_key_pressed), window);
3483 
3484     xed_debug_message (DEBUG_WINDOW, "Update plugins ui");
3485 
3486     window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (xed_plugins_engine_get_default ()),
3487                                                        XED_TYPE_WINDOW_ACTIVATABLE, "window", window, NULL);
3488 
3489     g_signal_connect (window->priv->extensions, "extension-added", G_CALLBACK (extension_added), window);
3490     g_signal_connect (window->priv->extensions, "extension-removed", G_CALLBACK (extension_removed), window);
3491 
3492     peas_extension_set_call (window->priv->extensions, "activate");
3493 
3494     /* set visibility of panes.
3495      * This needs to be done after plugins activatation */
3496     init_panels_visibility (window);
3497 
3498     update_sensitivity_according_to_open_tabs (window);
3499 
3500     xed_debug_message (DEBUG_WINDOW, "END");
3501 }
3502 
3503 /**
3504  * xed_window_get_active_view:
3505  * @window: a #XedWindow
3506  *
3507  * Gets the active #XedView.
3508  *
3509  * Returns: (transfer none): the active #XedView
3510  */
3511 XedView *
xed_window_get_active_view(XedWindow * window)3512 xed_window_get_active_view (XedWindow *window)
3513 {
3514     XedView *view;
3515 
3516     if (window == NULL)
3517     {
3518         return NULL;
3519     }
3520 
3521     if (window->priv->active_tab == NULL)
3522     {
3523         return NULL;
3524     }
3525 
3526     view = xed_tab_get_view (XED_TAB (window->priv->active_tab));
3527 
3528     return view;
3529 }
3530 
3531 /**
3532  * xed_window_get_active_document:
3533  * @window: a #XedWindow
3534  *
3535  * Gets the active #XedDocument.
3536  *
3537  * Returns: (transfer none): the active #XedDocument
3538  */
3539 XedDocument *
xed_window_get_active_document(XedWindow * window)3540 xed_window_get_active_document (XedWindow *window)
3541 {
3542     XedView *view;
3543 
3544     if (window == NULL)
3545     {
3546         return NULL;
3547     }
3548 
3549     view = xed_window_get_active_view (window);
3550     if (view == NULL)
3551     {
3552         return NULL;
3553     }
3554 
3555     return XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
3556 }
3557 
3558 GtkWidget *
_xed_window_get_notebook(XedWindow * window)3559 _xed_window_get_notebook (XedWindow *window)
3560 {
3561     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3562 
3563     return window->priv->notebook;
3564 }
3565 
3566 /**
3567  * xed_window_create_tab:
3568  * @window: a #XedWindow
3569  * @jump_to: %TRUE to set the new #XedTab as active
3570  *
3571  * Creates a new #XedTab and adds the new tab to the #XedNotebook.
3572  * In case @jump_to is %TRUE the #XedNotebook switches to that new #XedTab.
3573  *
3574  * Returns: (transfer none): a new #XedTab
3575  */
3576 XedTab *
xed_window_create_tab(XedWindow * window,gboolean jump_to)3577 xed_window_create_tab (XedWindow *window,
3578                        gboolean jump_to)
3579 {
3580     XedTab *tab;
3581 
3582     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3583 
3584     tab = XED_TAB(_xed_tab_new ());
3585     gtk_widget_show (GTK_WIDGET (tab));
3586 
3587     xed_notebook_add_tab (XED_NOTEBOOK (window->priv->notebook), tab, -1, jump_to);
3588 
3589     if (!gtk_widget_get_visible (GTK_WIDGET (window)))
3590     {
3591         gtk_window_present (GTK_WINDOW (window));
3592     }
3593 
3594     return tab;
3595 }
3596 
3597 static XedTab *
process_create_tab(XedWindow * window,XedTab * tab,gboolean jump_to)3598 process_create_tab (XedWindow *window,
3599                     XedTab    *tab,
3600                     gboolean   jump_to)
3601 {
3602     if (tab == NULL)
3603     {
3604         return NULL;
3605     }
3606 
3607     gtk_widget_show (GTK_WIDGET (tab));
3608 
3609     xed_notebook_add_tab (XED_NOTEBOOK (window->priv->notebook), tab, -1, jump_to);
3610 
3611     if (!gtk_widget_get_visible (GTK_WIDGET (window)))
3612     {
3613         gtk_window_present (GTK_WINDOW (window));
3614     }
3615 
3616     return tab;
3617 }
3618 
3619 /**
3620  * xed_window_create_tab_from_location:
3621  * @window: a #XedWindow
3622  * @location: the location of the document
3623  * @encoding: (allow-none): a #GtkSourceEncoding
3624  * @line_pos: the line position to visualize
3625  * @create: %TRUE to create a new document in case @uri does exist
3626  * @jump_to: %TRUE to set the new #XedTab as active
3627  *
3628  * Creates a new #XedTab loading the document specified by @uri.
3629  * In case @jump_to is %TRUE the #XedNotebook swithes to that new #XedTab.
3630  * Whether @create is %TRUE, creates a new empty document if location does
3631  * not refer to an existing file
3632  *
3633  * Returns: (transfer none): a new #XedTab
3634  */
3635 XedTab *
xed_window_create_tab_from_location(XedWindow * window,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gboolean create,gboolean jump_to)3636 xed_window_create_tab_from_location (XedWindow               *window,
3637                                      GFile                   *location,
3638                                      const GtkSourceEncoding *encoding,
3639                                      gint                     line_pos,
3640                                      gboolean                 create,
3641                                      gboolean                 jump_to)
3642 {
3643     GtkWidget *tab;
3644 
3645     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3646     g_return_val_if_fail(G_IS_FILE (location), NULL);
3647 
3648     tab = _xed_tab_new_from_location (location, encoding, line_pos, create);
3649 
3650     return process_create_tab (window, XED_TAB (tab), jump_to);
3651 }
3652 
3653 /**
3654  * xed_window_create_tab_from_stream:
3655  * @window: a #XedWindow
3656  * @stream: the #GInputStream
3657  * @encoding: the encoding to use in the stream
3658  * @line_pos: the position
3659  * @jump_to: whether to jump to the new tab
3660  *
3661  * Returns: (transfer none): the active #XedTab in the @window.
3662  */
3663 XedTab *
xed_window_create_tab_from_stream(XedWindow * window,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gboolean jump_to)3664 xed_window_create_tab_from_stream (XedWindow               *window,
3665                                    GInputStream            *stream,
3666                                    const GtkSourceEncoding *encoding,
3667                                    gint                     line_pos,
3668                                    gboolean                 jump_to)
3669 {
3670     GtkWidget *tab;
3671 
3672     g_return_val_if_fail (XED_IS_WINDOW (window), NULL);
3673     g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
3674 
3675     tab = _xed_tab_new_from_stream (stream, encoding, line_pos);
3676 
3677     return process_create_tab (window, XED_TAB (tab), jump_to);
3678 }
3679 
3680 /**
3681  * xed_window_get_active_tab:
3682  * @window: a XedWindow
3683  *
3684  * Gets the active #XedTab in the @window.
3685  *
3686  * Returns: (transfer none): the active #XedTab in the @window.
3687  */
3688 XedTab *
xed_window_get_active_tab(XedWindow * window)3689 xed_window_get_active_tab (XedWindow *window)
3690 {
3691     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3692 
3693     if (window->priv->active_tab == NULL)
3694     {
3695         return NULL;
3696     }
3697     else
3698     {
3699         return XED_TAB(window->priv->active_tab);
3700     }
3701 }
3702 
3703 static void
add_document(XedTab * tab,GList ** res)3704 add_document (XedTab *tab,
3705               GList **res)
3706 {
3707     XedDocument *doc;
3708 
3709     doc = xed_tab_get_document (tab);
3710 
3711     *res = g_list_prepend (*res, doc);
3712 }
3713 
3714 /**
3715  * xed_window_get_documents:
3716  * @window: a #XedWindow
3717  *
3718  * Gets a newly allocated list with all the documents in the window.
3719  * This list must be freed.
3720  *
3721  * Returns: (element-type Xed.Document) (transfer container): a newly
3722  * allocated list with all the documents in the window
3723  */
3724 GList *
xed_window_get_documents(XedWindow * window)3725 xed_window_get_documents (XedWindow *window)
3726 {
3727     GList *res = NULL;
3728     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3729     gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) add_document, &res);
3730     res = g_list_reverse (res);
3731     return res;
3732 }
3733 
3734 static void
add_view(XedTab * tab,GList ** res)3735 add_view (XedTab *tab,
3736           GList **res)
3737 {
3738     XedView *view;
3739     view = xed_tab_get_view (tab);
3740     *res = g_list_prepend (*res, view);
3741 }
3742 
3743 /**
3744  * xed_window_get_views:
3745  * @window: a #XedWindow
3746  *
3747  * Gets a list with all the views in the window. This list must be freed.
3748  *
3749  * Returns: (element-type Xed.View) (transfer container): a newly allocated
3750  * list with all the views in the window
3751  */
3752 GList *
xed_window_get_views(XedWindow * window)3753 xed_window_get_views (XedWindow *window)
3754 {
3755     GList *res = NULL;
3756     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3757     gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) add_view, &res);
3758     res = g_list_reverse (res);
3759     return res;
3760 }
3761 
3762 /**
3763  * xed_window_close_tab:
3764  * @window: a #XedWindow
3765  * @tab: the #XedTab to close
3766  *
3767  * Closes the @tab.
3768  */
3769 void
xed_window_close_tab(XedWindow * window,XedTab * tab)3770 xed_window_close_tab (XedWindow *window,
3771                       XedTab *tab)
3772 {
3773     g_return_if_fail (XED_IS_WINDOW (window));
3774     g_return_if_fail (XED_IS_TAB (tab));
3775     g_return_if_fail ((xed_tab_get_state (tab) != XED_TAB_STATE_SAVING)
3776                         && (xed_tab_get_state (tab) != XED_TAB_STATE_SHOWING_PRINT_PREVIEW));
3777 
3778     xed_notebook_remove_tab (XED_NOTEBOOK (window->priv->notebook), tab);
3779 }
3780 
3781 /**
3782  * xed_window_close_all_tabs:
3783  * @window: a #XedWindow
3784  *
3785  * Closes all opened tabs.
3786  */
3787 void
xed_window_close_all_tabs(XedWindow * window)3788 xed_window_close_all_tabs (XedWindow *window)
3789 {
3790     g_return_if_fail(XED_IS_WINDOW (window));
3791     g_return_if_fail(!(window->priv->state & XED_WINDOW_STATE_SAVING)
3792                         && !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
3793 
3794     window->priv->removing_tabs = TRUE;
3795     xed_notebook_remove_all_tabs (XED_NOTEBOOK(window->priv->notebook));
3796     window->priv->removing_tabs = FALSE;
3797 }
3798 
3799 /**
3800  * xed_window_close_tabs:
3801  * @window: a #XedWindow
3802  * @tabs: (element-type Xed.Tab): a list of #XedTab
3803  *
3804  * Closes all tabs specified by @tabs.
3805  */
3806 void
xed_window_close_tabs(XedWindow * window,const GList * tabs)3807 xed_window_close_tabs (XedWindow *window,
3808                        const GList *tabs)
3809 {
3810     g_return_if_fail(XED_IS_WINDOW (window));
3811     g_return_if_fail(!(window->priv->state & XED_WINDOW_STATE_SAVING)
3812                         && !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
3813 
3814     if (tabs == NULL)
3815     {
3816         return;
3817     }
3818 
3819     window->priv->removing_tabs = TRUE;
3820 
3821     while (tabs != NULL)
3822     {
3823         if (tabs->next == NULL)
3824         {
3825             window->priv->removing_tabs = FALSE;
3826         }
3827 
3828         xed_notebook_remove_tab (XED_NOTEBOOK(window->priv->notebook), XED_TAB(tabs->data));
3829         tabs = g_list_next(tabs);
3830     }
3831 
3832     g_return_if_fail(window->priv->removing_tabs == FALSE);
3833 }
3834 
3835 XedWindow *
_xed_window_move_tab_to_new_window(XedWindow * window,XedTab * tab)3836 _xed_window_move_tab_to_new_window (XedWindow *window,
3837                                     XedTab *tab)
3838 {
3839     XedWindow *new_window;
3840 
3841     g_return_val_if_fail (XED_IS_WINDOW (window), NULL);
3842     g_return_val_if_fail (XED_IS_TAB (tab), NULL);
3843     g_return_val_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) > 1, NULL);
3844 
3845     new_window = clone_window (window);
3846     xed_notebook_move_tab (XED_NOTEBOOK (window->priv->notebook), XED_NOTEBOOK (new_window->priv->notebook), tab, -1);
3847     gtk_widget_show (GTK_WIDGET (new_window));
3848 
3849     return new_window;
3850 }
3851 
3852 /**
3853  * xed_window_set_active_tab:
3854  * @window: a #XedWindow
3855  * @tab: a #XedTab
3856  *
3857  * Switches to the tab that matches with @tab.
3858  */
3859 void
xed_window_set_active_tab(XedWindow * window,XedTab * tab)3860 xed_window_set_active_tab (XedWindow *window,
3861                            XedTab *tab)
3862 {
3863     gint page_num;
3864 
3865     g_return_if_fail(XED_IS_WINDOW (window));
3866     g_return_if_fail(XED_IS_TAB (tab));
3867 
3868     page_num = gtk_notebook_page_num (GTK_NOTEBOOK(window->priv->notebook), GTK_WIDGET(tab));
3869     g_return_if_fail(page_num != -1);
3870     gtk_notebook_set_current_page (GTK_NOTEBOOK(window->priv->notebook), page_num);
3871 
3872     /* Make sure to grab focus if the page didn't change */
3873     gtk_widget_grab_focus (GTK_WIDGET (xed_tab_get_view (tab)));
3874 }
3875 
3876 /**
3877  * xed_window_get_group:
3878  * @window: a #XedWindow
3879  *
3880  * Gets the #GtkWindowGroup in which @window resides.
3881  *
3882  * Returns: (transfer none): the #GtkWindowGroup
3883  */
3884 GtkWindowGroup *
xed_window_get_group(XedWindow * window)3885 xed_window_get_group (XedWindow *window)
3886 {
3887     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3888     return window->priv->window_group;
3889 }
3890 
3891 gboolean
_xed_window_is_removing_tabs(XedWindow * window)3892 _xed_window_is_removing_tabs (XedWindow *window)
3893 {
3894     g_return_val_if_fail(XED_IS_WINDOW (window), FALSE);
3895     return window->priv->removing_tabs;
3896 }
3897 
3898 /**
3899  * xed_window_get_ui_manager:
3900  * @window: a #XedWindow
3901  *
3902  * Gets the #GtkUIManager associated with the @window.
3903  *
3904  * Returns: (transfer none): the #GtkUIManager of the @window.
3905  */
3906 GtkUIManager *
xed_window_get_ui_manager(XedWindow * window)3907 xed_window_get_ui_manager (XedWindow *window)
3908 {
3909     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3910     return window->priv->manager;
3911 }
3912 
3913 /**
3914  * xed_window_get_side_panel:
3915  * @window: a #XedWindow
3916  *
3917  * Gets the side #XedPanel of the @window.
3918  *
3919  * Returns: (transfer none): the side #XedPanel.
3920  */
3921 XedPanel *
xed_window_get_side_panel(XedWindow * window)3922 xed_window_get_side_panel (XedWindow *window)
3923 {
3924     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3925     return XED_PANEL(window->priv->side_panel);
3926 }
3927 
3928 /**
3929  * xed_window_get_bottom_panel:
3930  * @window: a #XedWindow
3931  *
3932  * Gets the bottom #XedPanel of the @window.
3933  *
3934  * Returns: (transfer none): the bottom #XedPanel.
3935  */
3936 XedPanel *
xed_window_get_bottom_panel(XedWindow * window)3937 xed_window_get_bottom_panel (XedWindow *window)
3938 {
3939     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3940     return XED_PANEL(window->priv->bottom_panel);
3941 }
3942 
3943 /**
3944  * xed_window_get_statusbar:
3945  * @window: a #XedWindow
3946  *
3947  * Gets the #XedStatusbar of the @window.
3948  *
3949  * Returns: (transfer none): the #XedStatusbar of the @window.
3950  */
3951 GtkWidget *
xed_window_get_statusbar(XedWindow * window)3952 xed_window_get_statusbar (XedWindow *window)
3953 {
3954     g_return_val_if_fail(XED_IS_WINDOW (window), 0);
3955     return window->priv->statusbar;
3956 }
3957 
3958 /**
3959  * xed_window_get_searchbar:
3960  * @window: a #XedWindow
3961  *
3962  * Gets the #XedSearchbar of the @window.
3963  *
3964  * Returns: (transfer none): the #XedSearchbar of the @window.
3965  */
3966 GtkWidget *
xed_window_get_searchbar(XedWindow * window)3967 xed_window_get_searchbar (XedWindow *window)
3968 {
3969     g_return_val_if_fail(XED_IS_WINDOW (window), 0);
3970     return window->priv->searchbar;
3971 }
3972 
3973 /**
3974  * xed_window_get_state:
3975  * @window: a #XedWindow
3976  *
3977  * Retrieves the state of the @window.
3978  *
3979  * Returns: the current #XedWindowState of the @window.
3980  */
3981 XedWindowState
xed_window_get_state(XedWindow * window)3982 xed_window_get_state (XedWindow *window)
3983 {
3984     g_return_val_if_fail(XED_IS_WINDOW (window), XED_WINDOW_STATE_NORMAL);
3985     return window->priv->state;
3986 }
3987 
3988 GFile *
_xed_window_get_default_location(XedWindow * window)3989 _xed_window_get_default_location (XedWindow *window)
3990 {
3991     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3992     if (window->priv->default_location != NULL)
3993     {
3994         return g_object_ref (window->priv->default_location);
3995     }
3996     else
3997     {
3998         return NULL;
3999     }
4000 }
4001 
4002 void
_xed_window_set_default_location(XedWindow * window,GFile * location)4003 _xed_window_set_default_location (XedWindow *window,
4004                                   GFile *location)
4005 {
4006     GFile *dir;
4007 
4008     g_return_if_fail(XED_IS_WINDOW (window));
4009     g_return_if_fail(G_IS_FILE (location));
4010 
4011     dir = g_file_get_parent (location);
4012     g_return_if_fail(dir != NULL);
4013 
4014     if (window->priv->default_location != NULL)
4015     {
4016         g_object_unref (window->priv->default_location);
4017     }
4018 
4019     window->priv->default_location = dir;
4020 }
4021 
4022 /**
4023  * xed_window_get_unsaved_documents:
4024  * @window: a #XedWindow
4025  *
4026  * Gets the list of documents that need to be saved before closing the window.
4027  *
4028  * Returns: (element-type Xed.Document) (transfer container): a list of
4029  * #XedDocument that need to be saved before closing the window
4030  */
4031 GList *
xed_window_get_unsaved_documents(XedWindow * window)4032 xed_window_get_unsaved_documents (XedWindow *window)
4033 {
4034     GList *unsaved_docs = NULL;
4035     GList *tabs;
4036     GList *l;
4037 
4038     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4039 
4040     tabs = gtk_container_get_children (GTK_CONTAINER(window->priv->notebook));
4041 
4042     l = tabs;
4043     while (l != NULL)
4044     {
4045         XedTab *tab;
4046         tab = XED_TAB(l->data);
4047         if (!_xed_tab_get_can_close (tab))
4048         {
4049             XedDocument *doc;
4050             doc = xed_tab_get_document (tab);
4051             unsaved_docs = g_list_prepend (unsaved_docs, doc);
4052         }
4053         l = g_list_next(l);
4054     }
4055 
4056     g_list_free (tabs);
4057 
4058     return g_list_reverse (unsaved_docs);
4059 }
4060 
4061 void
_xed_window_set_saving_session_state(XedWindow * window,gboolean saving_session)4062 _xed_window_set_saving_session_state (XedWindow *window,
4063                                       gboolean saving_session)
4064 {
4065     XedWindowState old_state;
4066 
4067     g_return_if_fail(XED_IS_WINDOW (window));
4068 
4069     old_state = window->priv->state;
4070 
4071     if (saving_session)
4072     {
4073         window->priv->state |= XED_WINDOW_STATE_SAVING_SESSION;
4074     }
4075     else
4076     {
4077         window->priv->state &= ~XED_WINDOW_STATE_SAVING_SESSION;
4078     }
4079 
4080     if (old_state != window->priv->state)
4081     {
4082         set_sensitivity_according_to_window_state (window);
4083         g_object_notify (G_OBJECT(window), "state");
4084     }
4085 }
4086 
4087 static void
hide_notebook_tabs_on_fullscreen(GtkNotebook * notebook,GParamSpec * pspec,XedWindow * window)4088 hide_notebook_tabs_on_fullscreen (GtkNotebook *notebook,
4089                                   GParamSpec *pspec,
4090                                   XedWindow *window)
4091 {
4092     gtk_notebook_set_show_tabs (notebook, FALSE);
4093 }
4094 
4095 void
_xed_window_fullscreen(XedWindow * window)4096 _xed_window_fullscreen (XedWindow *window)
4097 {
4098     g_return_if_fail (XED_IS_WINDOW (window));
4099 
4100     if (_xed_window_is_fullscreen (window))
4101     {
4102         return;
4103     }
4104 
4105     /* Go to fullscreen mode and hide bars */
4106     gtk_window_fullscreen (GTK_WINDOW (&window->window));
4107 
4108     gtk_widget_hide (window->priv->menubar);
4109 
4110     g_signal_handlers_block_by_func (window->priv->toolbar, toolbar_visibility_changed, window);
4111     gtk_widget_hide (window->priv->toolbar);
4112 
4113     g_signal_handlers_block_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
4114     gtk_widget_hide (window->priv->statusbar);
4115 
4116     fullscreen_controls_build (window);
4117 
4118     gtk_widget_show_all (window->priv->fullscreen_eventbox);
4119 }
4120 
4121 void
_xed_window_unfullscreen(XedWindow * window)4122 _xed_window_unfullscreen (XedWindow *window)
4123 {
4124     gboolean visible;
4125     GtkAction *action;
4126 
4127     g_return_if_fail (XED_IS_WINDOW (window));
4128 
4129     if (!_xed_window_is_fullscreen (window))
4130     {
4131         return;
4132     }
4133 
4134     /* Unfullscreen and show bars */
4135     gtk_window_unfullscreen (GTK_WINDOW (&window->window));
4136     g_signal_handlers_disconnect_by_func (window->priv->notebook, hide_notebook_tabs_on_fullscreen, window);
4137 
4138     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
4139     visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4140     if (visible)
4141     {
4142         gtk_widget_show (window->priv->toolbar);
4143     }
4144     g_signal_handlers_unblock_by_func (window->priv->toolbar, toolbar_visibility_changed, window);
4145 
4146     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewMenubar");
4147     visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4148     if (visible)
4149     {
4150         gtk_widget_show (window->priv->menubar);
4151     }
4152 
4153     action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
4154     visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4155     if (visible)
4156     {
4157         gtk_widget_show (window->priv->statusbar);
4158     }
4159     g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
4160 
4161     gtk_widget_hide (window->priv->fullscreen_eventbox);
4162 }
4163 
4164 gboolean
_xed_window_is_fullscreen(XedWindow * window)4165 _xed_window_is_fullscreen (XedWindow *window)
4166 {
4167     g_return_val_if_fail(XED_IS_WINDOW (window), FALSE);
4168     return window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN;
4169 }
4170 
4171 /**
4172  * xed_window_get_tab_from_location:
4173  * @window: a #XedWindow
4174  * @location: a #GFile
4175  *
4176  * Gets the #XedTab that matches with the given @location.
4177  *
4178  * Returns: (transfer none): the #XedTab that matches with the given @location.
4179  */
4180 XedTab *
xed_window_get_tab_from_location(XedWindow * window,GFile * location)4181 xed_window_get_tab_from_location (XedWindow *window,
4182                                   GFile *location)
4183 {
4184     GList *tabs;
4185     GList *l;
4186     XedTab *ret = NULL;
4187 
4188     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4189     g_return_val_if_fail(G_IS_FILE (location), NULL);
4190 
4191     tabs = gtk_container_get_children (GTK_CONTAINER(window->priv->notebook));
4192 
4193     for (l = tabs; l != NULL; l = g_list_next(l))
4194     {
4195         XedDocument *doc;
4196         GtkSourceFile *file;
4197         XedTab *tab;
4198         GFile *cur_location;
4199 
4200         tab = XED_TAB (l->data);
4201         doc = xed_tab_get_document (tab);
4202         file = xed_document_get_file (doc);
4203         cur_location = gtk_source_file_get_location (file);
4204 
4205         if (cur_location != NULL)
4206         {
4207             gboolean found = g_file_equal (location, cur_location);
4208 
4209             if (found)
4210             {
4211                 ret = tab;
4212                 break;
4213             }
4214         }
4215     }
4216 
4217     g_list_free (tabs);
4218 
4219     return ret;
4220 }
4221 
4222 /**
4223  * xed_window_get_message_bus:
4224  * @window: a #XedWindow
4225  *
4226  * Gets the #XedMessageBus associated with @window. The returned reference
4227  * is owned by the window and should not be unreffed.
4228  *
4229  * Return value: (transfer none): the #XedMessageBus associated with @window
4230  */
4231 XedMessageBus *
xed_window_get_message_bus(XedWindow * window)4232 xed_window_get_message_bus (XedWindow *window)
4233 {
4234     g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4235     return window->priv->message_bus;
4236 }
4237 
4238 void
_xed_window_get_default_size(gint * width,gint * height)4239 _xed_window_get_default_size (gint *width,
4240                               gint *height)
4241 {
4242     g_return_if_fail (width != NULL && height != NULL);
4243 
4244     *width = XED_WINDOW_DEFAULT_WIDTH;
4245     *height = XED_WINDOW_DEFAULT_HEIGHT;
4246 }
4247 
4248 XedPaned *
_xed_window_get_hpaned(XedWindow * window)4249 _xed_window_get_hpaned (XedWindow *window)
4250 {
4251     return XED_PANED (window->priv->hpaned);
4252 }
4253 
4254 XedPaned *
_xed_window_get_vpaned(XedWindow * window)4255 _xed_window_get_vpaned (XedWindow *window)
4256 {
4257     return XED_PANED (window->priv->vpaned);
4258 }
4259 
4260 gint
_xed_window_get_side_panel_size(XedWindow * window)4261 _xed_window_get_side_panel_size (XedWindow *window)
4262 {
4263     return window->priv->side_panel_size;
4264 }
4265 
4266 gint
_xed_window_get_bottom_panel_size(XedWindow * window)4267 _xed_window_get_bottom_panel_size (XedWindow *window)
4268 {
4269     return window->priv->bottom_panel_size;
4270 }
4271