1 /*-
2  * Copyright (c) 2004-2007 os-cillation e.K.
3  *
4  * Written by Benedikt Meurer <benny@xfce.org>.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <libxfce4ui/libxfce4ui.h>
25 
26 #ifdef GDK_WINDOWING_X11
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #endif
30 
31 #include <terminal/terminal-util.h>
32 #include <terminal/terminal-enum-types.h>
33 #include <terminal/terminal-preferences-dialog.h>
34 #include <terminal/terminal-encoding-action.h>
35 #include <terminal/terminal-private.h>
36 
37 #include "terminal-preferences-ui.h"
38 
39 static void     terminal_preferences_dialog_finalize          (GObject                   *object);
40 static void     terminal_preferences_dialog_disc_bindings     (GtkWidget                 *widget,
41                                                                TerminalPreferencesDialog *dialog);
42 static void     terminal_preferences_dialog_died              (gpointer                   user_data,
43                                                                GObject                   *where_the_object_was);
44 static void     terminal_preferences_dialog_response          (GtkWidget                 *widget,
45                                                                gint                       response,
46                                                                TerminalPreferencesDialog *dialog);
47 static gboolean terminal_preferences_dialog_color_press_event (GtkWidget                 *widget,
48                                                                GdkEventButton            *event);
49 #ifdef GDK_WINDOWING_X11
50 static void     terminal_preferences_dialog_geometry_changed  (TerminalPreferencesDialog *dialog);
51 static void     terminal_preferences_dialog_geometry_columns  (GtkAdjustment             *adj,
52                                                                TerminalPreferencesDialog *dialog);
53 static void     terminal_preferences_dialog_geometry_rows     (GtkAdjustment             *adj,
54                                                                TerminalPreferencesDialog *dialog);
55 #endif
56 static void     terminal_preferences_dialog_palette_changed   (GtkWidget                 *button,
57                                                                TerminalPreferencesDialog *dialog);
58 static void     terminal_preferences_dialog_palette_notify    (TerminalPreferencesDialog *dialog);
59 static void     terminal_preferences_dialog_presets_load      (TerminalPreferencesDialog *dialog);
60 #if VTE_CHECK_VERSION (0, 51, 3)
61 static void     terminal_preferences_dialog_reset_cell_scale  (GtkWidget                 *button,
62                                                                TerminalPreferencesDialog *dialog);
63 #endif
64 static void     terminal_preferences_dialog_reset_compat      (GtkWidget                 *button,
65                                                                TerminalPreferencesDialog *dialog);
66 static void     terminal_preferences_dialog_reset_word_chars  (GtkWidget                 *button,
67                                                                TerminalPreferencesDialog *dialog);
68 static void     terminal_preferences_dialog_background_mode   (GtkWidget                 *combobox,
69                                                                TerminalPreferencesDialog *dialog);
70 static void     terminal_preferences_dialog_background_notify (GObject                   *object,
71                                                                GParamSpec                *pspec,
72                                                                GObject                   *widget);
73 static void     terminal_preferences_dialog_background_set    (GtkFileChooserButton      *widget,
74                                                                TerminalPreferencesDialog *dialog);
75 static void     terminal_preferences_dialog_encoding_changed  (GtkComboBox               *combobox,
76                                                                TerminalPreferencesDialog *dialog);
77 static gboolean monospace_filter                              (const PangoFontFamily     *family,
78                                                                const PangoFontFace       *face,
79                                                                gpointer                   data);
80 
81 
82 
83 struct _TerminalPreferencesDialogClass
84 {
85   GtkBuilderClass parent_class;
86 };
87 
88 struct _TerminalPreferencesDialog
89 {
90   GtkBuilder           parent_instance;
91 
92   TerminalPreferences *preferences;
93   GSList              *bindings;
94 
95   gulong               bg_image_signal_id;
96   gulong               palette_signal_id;
97   gulong               geometry_signal_id;
98 };
99 
100 enum
101 {
102   PRESET_COLUMN_TITLE,
103   PRESET_COLUMN_IS_SEPARATOR,
104   PRESET_COLUMN_PATH,
105   N_PRESET_COLUMNS
106 };
107 
108 
109 
G_DEFINE_TYPE(TerminalPreferencesDialog,terminal_preferences_dialog,GTK_TYPE_BUILDER)110 G_DEFINE_TYPE (TerminalPreferencesDialog, terminal_preferences_dialog, GTK_TYPE_BUILDER)
111 
112 
113 
114 static void
115 terminal_preferences_dialog_class_init (TerminalPreferencesDialogClass *klass)
116 {
117   GObjectClass *gobject_class;
118 
119   gobject_class = G_OBJECT_CLASS (klass);
120   gobject_class->finalize = terminal_preferences_dialog_finalize;
121 }
122 
123 
124 
125 #define BIND_PROPERTIES(name, property) \
126   G_STMT_START { \
127   object = gtk_builder_get_object (GTK_BUILDER (dialog), name); \
128   terminal_return_if_fail (G_IS_OBJECT (object)); \
129   binding = g_object_bind_property (G_OBJECT (dialog->preferences), name, \
130                                     G_OBJECT (object), property, \
131                                     G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); \
132   dialog->bindings = g_slist_prepend (dialog->bindings, binding); \
133   } G_STMT_END
134 
135 
136 
137 #define RESET_PROPERTIES(properties) \
138   G_STMT_START { \
139   guint i; \
140   for (i = 0; i < G_N_ELEMENTS (properties); i++) \
141     { \
142       GParamSpec *spec = g_object_class_find_property (G_OBJECT_GET_CLASS (dialog->preferences), properties[i]); \
143       if (G_LIKELY (spec != NULL)) \
144         { \
145           GValue value = { 0, }; \
146           g_value_init (&value, spec->value_type); \
147           g_param_value_set_default (spec, &value); \
148           g_object_set_property (G_OBJECT (dialog->preferences), properties[i], &value); \
149           g_value_unset (&value); \
150         } \
151     } \
152   } G_STMT_END
153 
154 
155 
156 static void
terminal_preferences_dialog_init(TerminalPreferencesDialog * dialog)157 terminal_preferences_dialog_init (TerminalPreferencesDialog *dialog)
158 {
159   GError           *error = NULL;
160   guint             i;
161   GObject          *object, *object2;
162   gchar             palette_name[16];
163   GtkFileFilter    *filter;
164   GBinding         *binding;
165   GtkTreeModel     *model;
166   gchar            *current;
167   GtkTreeIter       current_iter;
168   const gchar      *props_active[] = { "title-mode", "command-login-shell",
169                                        "command-update-records", "run-custom-command",
170                                        "use-default-working-dir", "scrolling-on-output",
171                                        "scrolling-on-keystroke", "scrolling-bar",
172                                        "scrolling-unlimited", "misc-cursor-shape",
173                                        "misc-cursor-blinks", "font-allow-bold",
174                                        "font-use-system", "text-blink-mode",
175                                        "misc-show-unsafe-paste-dialog", "misc-menubar-default",
176                                        "misc-toolbar-default", "misc-borders-default",
177                                        "misc-tab-close-middle-click", "misc-middle-click-opens-uri",
178                                        "misc-mouse-autohide", "misc-rewrap-on-resize",
179                                        "misc-copy-on-select", "misc-slim-tabs",
180                                        "misc-new-tab-adjacent", "misc-bell",
181                                        "misc-bell-urgent", "shortcuts-no-helpkey",
182                                        "shortcuts-no-mnemonics", "shortcuts-no-menukey",
183                                        "binding-backspace", "binding-delete",
184                                        "binding-ambiguous-width", "background-mode",
185                                        "background-image-style", "color-background-vary",
186                                        "color-bold-is-bright", "color-use-theme",
187                                        "dropdown-keep-open-default", "dropdown-keep-above",
188                                        "dropdown-toggle-focus", "dropdown-status-icon",
189                                        "dropdown-move-to-active", "dropdown-always-show-tabs",
190                                        "dropdown-show-borders"
191                                      };
192   const gchar      *props_color[] =  { "color-foreground", "color-background",
193                                        "tab-activity-color", "color-cursor-foreground",
194                                        "color-cursor", "color-selection",
195                                        "color-selection-background", "color-bold"
196                                      };
197   const gchar      *props_value[] =  { "dropdown-height", "dropdown-width",
198                                        "dropdown-position", "dropdown-position-vertical",
199                                        "dropdown-opacity", "dropdown-animation-time"
200                                      };
201 
202   dialog->preferences = terminal_preferences_get ();
203 
204   if (!gtk_builder_add_from_string (GTK_BUILDER (dialog), terminal_preferences_ui,
205                                     terminal_preferences_ui_length, &error)) {
206       g_critical ("Error loading UI: %s", error->message);
207       g_error_free (error);
208       return;
209   }
210 
211   /* connect response to dialog */
212   object = gtk_builder_get_object (GTK_BUILDER (dialog), "dialog");
213   terminal_return_if_fail (G_IS_OBJECT (object));
214   g_object_weak_ref (object, (GWeakNotify) terminal_preferences_dialog_died, dialog);
215   g_signal_connect (object, "destroy",
216       G_CALLBACK (terminal_preferences_dialog_disc_bindings), dialog);
217   g_signal_connect (object, "response",
218       G_CALLBACK (terminal_preferences_dialog_response), dialog);
219 
220   /* bind active properties */
221   for (i = 0; i < G_N_ELEMENTS (props_active); i++)
222     BIND_PROPERTIES (props_active[i], "active");
223 
224   /* bind color properties and click handler */
225   for (i = 0; i < G_N_ELEMENTS (props_color); i++)
226     {
227       BIND_PROPERTIES (props_color[i], "rgba");
228       g_signal_connect (object, "button-press-event",
229           G_CALLBACK (terminal_preferences_dialog_color_press_event), object);
230     }
231 
232   /* bind value properties */
233   for (i = 0; i < G_N_ELEMENTS (props_value); i++)
234     BIND_PROPERTIES (props_value[i], "value");
235 
236   /* bind color palette properties */
237   for (i = 1; i <= 16; i++)
238     {
239       g_snprintf (palette_name, sizeof (palette_name), "color-palette%d", i);
240       object = gtk_builder_get_object (GTK_BUILDER (dialog), palette_name);
241       terminal_return_if_fail (G_IS_OBJECT (object));
242       g_signal_connect (object, "color-set",
243           G_CALLBACK (terminal_preferences_dialog_palette_changed), dialog);
244 
245       /* don't show palette when editing colors */
246       g_object_set (object, "show-editor", TRUE, NULL);
247     }
248 
249   /* watch color changes in property */
250   dialog->palette_signal_id = g_signal_connect_swapped (G_OBJECT (dialog->preferences),
251       "notify::color-palette", G_CALLBACK (terminal_preferences_dialog_palette_notify), dialog);
252   terminal_preferences_dialog_palette_notify (dialog);
253 
254   /* color presets */
255   terminal_preferences_dialog_presets_load (dialog);
256 
257   /* other properties */
258   BIND_PROPERTIES ("font-name", "font-name");
259   BIND_PROPERTIES ("title-initial", "text");
260   BIND_PROPERTIES ("custom-command", "text");
261   BIND_PROPERTIES ("default-working-dir", "text");
262   BIND_PROPERTIES ("word-chars", "text");
263   BIND_PROPERTIES ("scrolling-lines", "value");
264   BIND_PROPERTIES ("tab-activity-timeout", "value");
265   BIND_PROPERTIES ("background-darkness", "value");
266   BIND_PROPERTIES ("background-image-shading", "value");
267 
268 #ifndef HAVE_LIBUTEMPTER
269   /* hide "Update utmp/wtmp records" if no support for that */
270   object = gtk_builder_get_object (GTK_BUILDER (dialog), "command-update-records");
271   terminal_return_if_fail (G_IS_OBJECT (object));
272   gtk_widget_hide (GTK_WIDGET (object));
273 #endif
274 
275 #if VTE_CHECK_VERSION (0, 51, 3)
276   /* bind cell width scale */
277   object = gtk_builder_get_object (GTK_BUILDER (dialog), "spin-cell-width-scale");
278   object2 = G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (object)));
279   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
280   binding = g_object_bind_property (G_OBJECT (dialog->preferences), "cell-width-scale",
281                                     G_OBJECT (object2), "value",
282                                     G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
283   dialog->bindings = g_slist_prepend (dialog->bindings, binding);
284 
285   /* bind cell height scale */
286   object = gtk_builder_get_object (GTK_BUILDER (dialog), "spin-cell-height-scale");
287   object2 = G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (object)));
288   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
289   binding = g_object_bind_property (G_OBJECT (dialog->preferences), "cell-height-scale",
290                                     G_OBJECT (object2), "value",
291                                     G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
292   dialog->bindings = g_slist_prepend (dialog->bindings, binding);
293 
294   /* cell scale "Reset" button */
295   object = gtk_builder_get_object (GTK_BUILDER (dialog), "reset-cell-scale");
296   terminal_return_if_fail (G_IS_OBJECT (object));
297   g_signal_connect (object, "clicked",
298                     G_CALLBACK (terminal_preferences_dialog_reset_cell_scale), dialog);
299 #else
300   /* hide "Text blinks" if vte doesn't support it */
301   object = gtk_builder_get_object (GTK_BUILDER (dialog), "box-text-blink");
302   terminal_return_if_fail (G_IS_OBJECT (object));
303   gtk_widget_hide (GTK_WIDGET (object));
304 
305   /* hide "Cell spacing" if vte doesn't support it */
306   object = gtk_builder_get_object (GTK_BUILDER (dialog), "cell-sp-box");
307   terminal_return_if_fail (G_IS_OBJECT (object));
308   gtk_widget_hide (GTK_WIDGET (object));
309 
310   /* hide "Bold is bright" if vte doesn't support it */
311   object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-bold-is-bright");
312   terminal_return_if_fail (G_IS_OBJECT (object));
313   gtk_widget_hide (GTK_WIDGET (object));
314 #endif
315 
316 #if VTE_CHECK_VERSION (0, 58, 0)
317   /* hide "Rewrap on resize" if vte's support for it has been dropped */
318   object = gtk_builder_get_object (GTK_BUILDER (dialog), "misc-rewrap-on-resize");
319   terminal_return_if_fail (G_IS_OBJECT (object));
320   gtk_widget_hide (GTK_WIDGET (object));
321 #endif
322 
323   /* run custom command button */
324   object = gtk_builder_get_object (GTK_BUILDER (dialog), "run-custom-command");
325   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "hbox3");
326   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
327   g_object_bind_property (object, "active",
328                           object2, "sensitive",
329                           G_BINDING_SYNC_CREATE);
330 
331   /* working directory button */
332   object = gtk_builder_get_object (GTK_BUILDER (dialog), "use-default-working-dir");
333   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "default-working-dir");
334   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
335   g_object_bind_property (object, "active",
336                           object2, "sensitive",
337                           G_BINDING_SYNC_CREATE);
338 
339   /* unlimited scrollback button */
340   object = gtk_builder_get_object (GTK_BUILDER (dialog), "scrolling-unlimited");
341   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "scrolling-lines");
342   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
343   g_object_bind_property (object, "active",
344                           object2, "sensitive",
345                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
346 
347   /* use system font button */
348   object = gtk_builder_get_object (GTK_BUILDER (dialog), "font-use-system");
349   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "font-name");
350   terminal_return_if_fail (G_IS_OBJECT (object) && G_IS_OBJECT (object2));
351   gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (object2), monospace_filter, NULL, NULL);
352   g_object_bind_property (object, "active",
353                           object2, "sensitive",
354                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
355 
356   /* reset comparibility button */
357   object = gtk_builder_get_object (GTK_BUILDER (dialog), "reset-compatibility");
358   terminal_return_if_fail (G_IS_OBJECT (object));
359   g_signal_connect (object, "clicked",
360       G_CALLBACK (terminal_preferences_dialog_reset_compat), dialog);
361 
362   /* reset word-chars button */
363   object = gtk_builder_get_object (GTK_BUILDER (dialog), "reset-word-chars");
364   terminal_return_if_fail (G_IS_OBJECT (object));
365   g_signal_connect (object, "clicked",
366       G_CALLBACK (terminal_preferences_dialog_reset_word_chars), dialog);
367 
368   /* position scale */
369   object = gtk_builder_get_object (GTK_BUILDER (dialog), "scale-position");
370   terminal_return_if_fail (G_IS_OBJECT (object));
371   for (i = 0; i <= 100; i += 25)
372     gtk_scale_add_mark (GTK_SCALE (object), i, GTK_POS_BOTTOM, NULL);
373 
374   /* inverted custom colors and set sensitivity */
375   object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-use-theme");
376   terminal_return_if_fail (G_IS_OBJECT (object));
377   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-foreground");
378   terminal_return_if_fail (G_IS_OBJECT (object2));
379   g_object_bind_property (object, "active",
380                           object2, "sensitive",
381                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
382   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-background");
383   terminal_return_if_fail (G_IS_OBJECT (object2));
384   g_object_bind_property (object, "active",
385                           object2, "sensitive",
386                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
387 
388   object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-cursor-custom");
389   terminal_return_if_fail (G_IS_OBJECT (object));
390   g_object_bind_property (G_OBJECT (dialog->preferences), "color-cursor-use-default",
391                           object, "active",
392                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
393   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-cursor-foreground");
394   terminal_return_if_fail (G_IS_OBJECT (object2));
395   g_object_bind_property (object, "active",
396                           object2, "sensitive",
397                           G_BINDING_SYNC_CREATE);
398   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-cursor");
399   terminal_return_if_fail (G_IS_OBJECT (object2));
400   g_object_bind_property (object, "active",
401                           object2, "sensitive",
402                           G_BINDING_SYNC_CREATE);
403 
404   object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-selection-custom");
405   terminal_return_if_fail (G_IS_OBJECT (object));
406   g_object_bind_property (G_OBJECT (dialog->preferences), "color-selection-use-default",
407                           object, "active",
408                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
409   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-selection");
410   terminal_return_if_fail (G_IS_OBJECT (object2));
411   g_object_bind_property (object, "active",
412                           object2, "sensitive",
413                           G_BINDING_SYNC_CREATE);
414   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-selection-background");
415   terminal_return_if_fail (G_IS_OBJECT (object2));
416   g_object_bind_property (object, "active",
417                           object2, "sensitive",
418                           G_BINDING_SYNC_CREATE);
419 
420   object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-bold-custom");
421   terminal_return_if_fail (G_IS_OBJECT (object));
422   g_object_bind_property (G_OBJECT (dialog->preferences), "color-bold-use-default",
423                           object, "active",
424                           G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
425   object2 = gtk_builder_get_object (GTK_BUILDER (dialog), "color-bold");
426   terminal_return_if_fail (G_IS_OBJECT (object2));
427   g_object_bind_property (object, "active",
428                           object2, "sensitive",
429                           G_BINDING_SYNC_CREATE);
430 
431 #ifdef GDK_WINDOWING_X11
432   terminal_preferences_dialog_geometry_changed (dialog);
433   dialog->geometry_signal_id = g_signal_connect_swapped (G_OBJECT (dialog->preferences),
434       "notify::misc-default-geometry",
435       G_CALLBACK (terminal_preferences_dialog_geometry_changed), dialog);
436 
437   /* geo changes */
438   object = gtk_builder_get_object (GTK_BUILDER (dialog), "geo-columns");
439   terminal_return_if_fail (G_IS_OBJECT (object));
440   g_signal_connect (object, "value-changed",
441       G_CALLBACK (terminal_preferences_dialog_geometry_columns), dialog);
442   object = gtk_builder_get_object (GTK_BUILDER (dialog), "geo-rows");
443   terminal_return_if_fail (G_IS_OBJECT (object));
444   g_signal_connect (object, "value-changed",
445       G_CALLBACK (terminal_preferences_dialog_geometry_rows), dialog);
446 #else
447   /* hide */
448   object = gtk_builder_get_object (GTK_BUILDER (dialog), "geo-box");
449   terminal_return_if_fail (G_IS_OBJECT (object));
450   gtk_widget_hide (GTK_WIDGET (object));
451 #endif
452 
453   /* background widgets visibility */
454   object = gtk_builder_get_object (GTK_BUILDER (dialog), "background-mode");
455   terminal_return_if_fail (G_IS_OBJECT (object));
456   g_signal_connect (object, "changed",
457       G_CALLBACK (terminal_preferences_dialog_background_mode), dialog);
458   terminal_preferences_dialog_background_mode (GTK_WIDGET (object), dialog);
459 
460   /* background image file */
461   object = gtk_builder_get_object (GTK_BUILDER (dialog), "background-image-file");
462   terminal_return_if_fail (G_IS_OBJECT (object));
463   dialog->bg_image_signal_id = g_signal_connect (G_OBJECT (dialog->preferences),
464       "notify::background-image-file", G_CALLBACK (terminal_preferences_dialog_background_notify), object);
465   terminal_preferences_dialog_background_notify (G_OBJECT (dialog->preferences), NULL, object);
466   g_signal_connect (object, "file-set",
467       G_CALLBACK (terminal_preferences_dialog_background_set), dialog);
468 
469   /* add file filters */
470   filter = gtk_file_filter_new ();
471   gtk_file_filter_set_name (filter, _("All Files"));
472   gtk_file_filter_add_pattern (filter, "*");
473   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (object), filter);
474 
475   /* add "Image Files" filter */
476   filter = gtk_file_filter_new ();
477   gtk_file_filter_set_name (filter, _("Image Files"));
478   gtk_file_filter_add_pixbuf_formats (filter);
479   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (object), filter);
480   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (object), filter);
481 
482   /* encoding combo */
483   object = gtk_builder_get_object (GTK_BUILDER (dialog), "encoding-combo");
484   g_object_get (dialog->preferences, "encoding", &current, NULL);
485   model = terminal_encoding_model_new (current, &current_iter);
486   gtk_combo_box_set_model (GTK_COMBO_BOX (object), model);
487   gtk_combo_box_set_active_iter (GTK_COMBO_BOX (object), &current_iter);
488   g_signal_connect (object, "changed",
489       G_CALLBACK (terminal_preferences_dialog_encoding_changed), dialog);
490   g_object_unref (G_OBJECT (model));
491   g_free (current);
492 }
493 
494 
495 
496 static void
terminal_preferences_dialog_finalize(GObject * object)497 terminal_preferences_dialog_finalize (GObject *object)
498 {
499   TerminalPreferencesDialog *dialog = TERMINAL_PREFERENCES_DIALOG (object);
500 
501   /* disconnect signals */
502   if (G_LIKELY (dialog->bg_image_signal_id != 0))
503     g_signal_handler_disconnect (dialog->preferences, dialog->bg_image_signal_id);
504   if (G_LIKELY (dialog->palette_signal_id != 0))
505     g_signal_handler_disconnect (dialog->preferences, dialog->palette_signal_id);
506   if (G_LIKELY (dialog->geometry_signal_id != 0))
507     g_signal_handler_disconnect (dialog->preferences, dialog->geometry_signal_id);
508 
509   /* release the preferences */
510   g_object_unref (G_OBJECT (dialog->preferences));
511 
512   (*G_OBJECT_CLASS (terminal_preferences_dialog_parent_class)->finalize) (object);
513 }
514 
515 
516 
517 static void
terminal_preferences_dialog_disc_bindings(GtkWidget * widget,TerminalPreferencesDialog * dialog)518 terminal_preferences_dialog_disc_bindings (GtkWidget                 *widget,
519                                            TerminalPreferencesDialog *dialog)
520 {
521   GSList *li;
522 
523   /* disconnect all the bindings */
524   for (li = dialog->bindings; li != NULL; li = li->next)
525     g_object_unref (G_OBJECT (li->data));
526   g_slist_free (dialog->bindings);
527 }
528 
529 
530 
531 static void
terminal_preferences_dialog_died(gpointer user_data,GObject * where_the_object_was)532 terminal_preferences_dialog_died (gpointer  user_data,
533                                   GObject  *where_the_object_was)
534 {
535   g_object_unref (G_OBJECT (user_data));
536 }
537 
538 
539 
540 static gboolean
terminal_preferences_dialog_color_press_event(GtkWidget * widget,GdkEventButton * event)541 terminal_preferences_dialog_color_press_event (GtkWidget      *widget,
542                                                GdkEventButton *event)
543 {
544   gboolean show_editor;
545 
546   if (event->type == GDK_BUTTON_PRESS && event->button == 1 && event->state == GDK_CONTROL_MASK)
547     {
548       /* use Ctrl+click to open color editor directly */
549       g_object_get (G_OBJECT (widget), "show-editor", &show_editor, NULL);
550       g_object_set (G_OBJECT (widget), "show-editor", TRUE, NULL);
551       gtk_button_clicked (GTK_BUTTON (widget));
552       g_object_set (G_OBJECT (widget), "show-editor", show_editor, NULL);
553       return TRUE;
554     }
555 
556   return FALSE;
557 }
558 
559 
560 
561 static void
terminal_preferences_dialog_response(GtkWidget * widget,gint response,TerminalPreferencesDialog * dialog)562 terminal_preferences_dialog_response (GtkWidget                 *widget,
563                                       gint                       response,
564                                       TerminalPreferencesDialog *dialog)
565 {
566   GObject     *object;
567   GObject     *notebook;
568   const gchar *section;
569 
570   /* check if we should open the user manual */
571   if (G_UNLIKELY (response == 1))
572     {
573       /* if the drop-down preferences are shown, we open that page in the wiki */
574       notebook = gtk_builder_get_object (GTK_BUILDER (dialog), "notebook");
575       terminal_return_if_fail (GTK_IS_NOTEBOOK (notebook));
576       object = gtk_builder_get_object (GTK_BUILDER (dialog), "dropdown-box");
577       terminal_return_if_fail (G_IS_OBJECT (object));
578       if (gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (object))
579           == gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)))
580         section = "dropdown";
581       else
582         section = "preferences";
583 
584       /* open the "Preferences" section of the user manual */
585       xfce_dialog_show_help (GTK_WINDOW (widget), "terminal",
586                              section, NULL);
587     }
588   else
589     {
590       /* close the preferences dialog */
591       gtk_widget_destroy (widget);
592     }
593 }
594 
595 
596 
597 #ifdef GDK_WINDOWING_X11
598 static void
terminal_preferences_dialog_geometry_changed(TerminalPreferencesDialog * dialog)599 terminal_preferences_dialog_geometry_changed (TerminalPreferencesDialog *dialog)
600 {
601   GObject *object;
602   gchar   *geo;
603   guint    w = 0, h = 0;
604   gint     x, y;
605 
606   g_object_get (G_OBJECT (dialog->preferences), "misc-default-geometry", &geo, NULL);
607   if (G_LIKELY (geo != NULL))
608     {
609       /* parse the string */
610       XParseGeometry (geo, &x, &y, &w, &h);
611       g_free (geo);
612     }
613 
614   /* set cols */
615   object = gtk_builder_get_object (GTK_BUILDER (dialog), "geo-columns");
616   terminal_return_if_fail (GTK_IS_ADJUSTMENT (object));
617   g_signal_handlers_block_by_func (object,
618       terminal_preferences_dialog_geometry_columns, dialog);
619   gtk_adjustment_set_value (GTK_ADJUSTMENT (object), w != 0 ? w : 80);
620   g_signal_handlers_unblock_by_func (object,
621       terminal_preferences_dialog_geometry_columns, dialog);
622 
623   /* set rows */
624   object = gtk_builder_get_object (GTK_BUILDER (dialog), "geo-rows");
625   terminal_return_if_fail (GTK_IS_ADJUSTMENT (object));
626   g_signal_handlers_block_by_func (object,
627       terminal_preferences_dialog_geometry_columns, dialog);
628   gtk_adjustment_set_value (GTK_ADJUSTMENT (object), h != 0 ? h : 24);
629   g_signal_handlers_unblock_by_func (object,
630       terminal_preferences_dialog_geometry_columns, dialog);
631 }
632 
633 
634 
635 static void
terminal_preferences_dialog_geometry(TerminalPreferencesDialog * dialog,gint columns,gint rows)636 terminal_preferences_dialog_geometry (TerminalPreferencesDialog *dialog,
637                                       gint                       columns,
638                                       gint                       rows)
639 {
640   gint     x, y;
641   guint    w = 0, h = 0;
642   gchar   *geo;
643   gint     mask = NoValue;
644 
645   g_object_get (G_OBJECT (dialog->preferences), "misc-default-geometry", &geo, NULL);
646   if (G_LIKELY (geo != NULL))
647     {
648       /* parse the string */
649       mask = XParseGeometry (geo, &x, &y, &w, &h);
650       g_free (geo);
651     }
652 
653   /* set new value */
654   if (columns > 0)
655     w = columns;
656   if (rows > 0)
657     h = rows;
658 
659   /* if there is an x or y value, preserve this */
660   if ((mask & XValue) != 0 || (mask & YValue) != 0)
661     geo = g_strdup_printf ("%ux%u%+d%+d", w, h, x, y);
662   else
663     geo = g_strdup_printf ("%ux%u", w, h);
664 
665   /* save */
666   g_signal_handler_block (G_OBJECT (dialog->preferences), dialog->geometry_signal_id);
667   g_object_set (G_OBJECT (dialog->preferences), "misc-default-geometry", geo, NULL);
668   g_signal_handler_unblock (G_OBJECT (dialog->preferences), dialog->geometry_signal_id);
669   g_free (geo);
670 }
671 
672 
673 
674 static void
terminal_preferences_dialog_geometry_columns(GtkAdjustment * adj,TerminalPreferencesDialog * dialog)675 terminal_preferences_dialog_geometry_columns (GtkAdjustment             *adj,
676                                               TerminalPreferencesDialog *dialog)
677 {
678   terminal_return_if_fail (GTK_IS_ADJUSTMENT (adj));
679   terminal_preferences_dialog_geometry (dialog, gtk_adjustment_get_value (adj), -1);
680 }
681 
682 
683 
684 static void
terminal_preferences_dialog_geometry_rows(GtkAdjustment * adj,TerminalPreferencesDialog * dialog)685 terminal_preferences_dialog_geometry_rows (GtkAdjustment             *adj,
686                                            TerminalPreferencesDialog *dialog)
687 {
688   terminal_return_if_fail (GTK_IS_ADJUSTMENT (adj));
689   terminal_preferences_dialog_geometry (dialog, -1, gtk_adjustment_get_value (adj));
690 }
691 #endif
692 
693 
694 
695 static void
terminal_preferences_dialog_palette_changed(GtkWidget * button,TerminalPreferencesDialog * dialog)696 terminal_preferences_dialog_palette_changed (GtkWidget                 *button,
697                                              TerminalPreferencesDialog *dialog)
698 {
699   gchar    name[16];
700   guint    i;
701   GObject *obj;
702   GdkRGBA  color;
703   gchar   *color_str;
704   GString *array;
705 
706   array = g_string_sized_new (225);
707 
708   for (i = 1; i <= 16; i++)
709     {
710       /* get color value from button */
711       g_snprintf (name, sizeof (name), "color-palette%d", i);
712       obj = gtk_builder_get_object (GTK_BUILDER (dialog), name);
713       terminal_return_if_fail (GTK_IS_COLOR_BUTTON (obj));
714       gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (obj), &color);
715 
716       /* append to string */
717       color_str = gdk_rgba_to_string (&color);
718       g_string_append (array, color_str);
719       g_free (color_str);
720 
721       if (i != 16)
722         g_string_append_c (array, ';');
723     }
724 
725   /* set property */
726   g_signal_handler_block (dialog->preferences, dialog->palette_signal_id);
727   g_object_set (dialog->preferences, "color-palette", array->str, NULL);
728   g_signal_handler_unblock (dialog->preferences, dialog->palette_signal_id);
729   g_string_free (array, TRUE);
730 }
731 
732 
733 
734 static void
terminal_preferences_dialog_palette_notify(TerminalPreferencesDialog * dialog)735 terminal_preferences_dialog_palette_notify (TerminalPreferencesDialog *dialog)
736 {
737   gchar   *color_str;
738   gchar  **colors;
739   guint    i;
740   gchar    name[16];
741   GObject *obj;
742   GdkRGBA  color;
743 
744   g_object_get (dialog->preferences, "color-palette", &color_str, NULL);
745   if (G_LIKELY (color_str != NULL))
746     {
747       /* make array */
748       colors = g_strsplit (color_str, ";", -1);
749       g_free (color_str);
750 
751       /* apply values to buttons */
752       if (colors != NULL)
753         for (i = 0; i < 16 && colors[i] != NULL; i++)
754           {
755             g_snprintf (name, sizeof (name), "color-palette%d", i + 1);
756             obj = gtk_builder_get_object (GTK_BUILDER (dialog), name);
757             terminal_return_if_fail (GTK_IS_COLOR_BUTTON (obj));
758 
759             if (gdk_rgba_parse (&color, colors[i]))
760               gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (obj), &color);
761           }
762 
763       g_strfreev (colors);
764     }
765 }
766 
767 
768 
769 static gboolean
terminal_preferences_dialog_presets_sepfunc(GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)770 terminal_preferences_dialog_presets_sepfunc (GtkTreeModel *model,
771                                              GtkTreeIter  *iter,
772                                              gpointer      user_data)
773 {
774   gboolean is_separator;
775   gtk_tree_model_get (model, iter, PRESET_COLUMN_IS_SEPARATOR, &is_separator, -1);
776   return is_separator;
777 }
778 
779 
780 
781 static void
terminal_preferences_dialog_presets_changed(GtkComboBox * combobox,TerminalPreferencesDialog * dialog)782 terminal_preferences_dialog_presets_changed (GtkComboBox               *combobox,
783                                              TerminalPreferencesDialog *dialog)
784 {
785   GtkTreeModel *model;
786   GtkTreeIter   iter;
787   gchar        *path;
788   XfceRc       *rc;
789   GParamSpec  **pspecs, *pspec;
790   guint         nspecs;
791   guint         n;
792   const gchar  *blurb;
793   const gchar  *name;
794   const gchar  *str;
795   GValue        src = { 0, };
796   GValue        dst = { 0, };
797 
798   if (!gtk_combo_box_get_active_iter (combobox, &iter))
799     return;
800 
801   model = gtk_combo_box_get_model (combobox);
802   gtk_tree_model_get (model, &iter, PRESET_COLUMN_PATH, &path, -1);
803   if (path == NULL)
804     return;
805 
806   /* load file */
807   rc = xfce_rc_simple_open (path, TRUE);
808   g_free (path);
809   if (G_UNLIKELY (rc == NULL))
810     return;
811 
812   xfce_rc_set_group (rc, "Scheme");
813 
814   g_value_init (&src, G_TYPE_STRING);
815 
816   /* walk all properties and look for items in the scheme */
817   pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (dialog->preferences), &nspecs);
818   for (n = 0; n < nspecs; ++n)
819     {
820       pspec = pspecs[n];
821 
822       /* get color keys */
823       blurb = g_param_spec_get_blurb (pspec);
824       if (strstr (blurb, "Color") == NULL)
825         continue;
826 
827       /* read value */
828       name = g_param_spec_get_name (pspec);
829       str = xfce_rc_read_entry_untranslated (rc, blurb, NULL);
830 
831       if (str == NULL || *str == '\0')
832         {
833           /* reset to the default value */
834           g_value_init (&dst, G_PARAM_SPEC_VALUE_TYPE (pspec));
835           g_param_value_set_default (pspec, &dst);
836           g_object_set_property (G_OBJECT (dialog->preferences), name, &dst);
837           g_value_unset (&dst);
838         }
839       else
840         {
841           g_value_set_static_string (&src, str);
842 
843           if (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING)
844             {
845               /* set the string property */
846               g_object_set_property (G_OBJECT (dialog->preferences), name, &src);
847             }
848           else
849             {
850               /* transform value */
851               g_value_init (&dst, G_PARAM_SPEC_VALUE_TYPE (pspec));
852               if (G_LIKELY (g_value_transform (&src, &dst)))
853                 g_object_set_property (G_OBJECT (dialog->preferences), name, &dst);
854               else
855                 g_warning ("Unable to convert scheme property \"%s\"", name);
856               g_value_unset (&dst);
857             }
858         }
859     }
860 
861   g_free (pspecs);
862   g_value_unset (&src);
863   xfce_rc_close (rc);
864 }
865 
866 
867 
868 static void
terminal_preferences_dialog_presets_load(TerminalPreferencesDialog * dialog)869 terminal_preferences_dialog_presets_load (TerminalPreferencesDialog *dialog)
870 {
871   gchar       **global, **user, **presets;
872   guint         n_global, n_user, n_presets = 0, n;
873   GObject      *object;
874   XfceRc       *rc;
875   GtkListStore *store;
876   GtkTreeIter   iter;
877   const gchar  *title;
878   gchar        *path;
879 
880   /* load schemes */
881   global = xfce_resource_match (XFCE_RESOURCE_DATA, "xfce4/terminal/colorschemes/*", TRUE);
882   user = xfce_resource_match (XFCE_RESOURCE_CONFIG, "xfce4/terminal/colorschemes/*", TRUE);
883   n_global = g_strv_length (global);
884   n_user = g_strv_length (user);
885   presets = g_new0 (gchar *, n_global + n_user);
886   if (G_LIKELY (presets != NULL))
887     {
888       /* copy pointers to global- and user-defined presets */
889       for (n = 0; n < n_global; n++)
890         presets[n] = global[n];
891       for (n = 0; n < n_user; n++)
892         presets[n_global + n] = user[n];
893 
894       /* create sorting store */
895       store = gtk_list_store_new (N_PRESET_COLUMNS, G_TYPE_STRING,
896                                   G_TYPE_BOOLEAN, G_TYPE_STRING);
897       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
898                                             PRESET_COLUMN_TITLE,
899                                             GTK_SORT_ASCENDING);
900 
901       /* append files */
902       for (n = 0; n < n_global + n_user && presets[n] != NULL; n++)
903         {
904           /* open the scheme */
905           path = xfce_resource_lookup (n < n_global ? XFCE_RESOURCE_DATA : XFCE_RESOURCE_CONFIG,
906                                        presets[n]);
907           if (G_UNLIKELY (path == NULL))
908             continue;
909 
910           rc = xfce_rc_simple_open (path, TRUE);
911           if (G_UNLIKELY (rc == NULL))
912             {
913               g_free (path);
914               continue;
915             }
916 
917           xfce_rc_set_group (rc, "Scheme");
918 
919           /* translated name */
920           title = xfce_rc_read_entry (rc, "Name", NULL);
921           if (G_LIKELY (title != NULL))
922             {
923               gtk_list_store_insert_with_values (store, NULL, n_presets++,
924                                                  PRESET_COLUMN_TITLE, title,
925                                                  PRESET_COLUMN_PATH, path,
926                                                  -1);
927             }
928 
929           xfce_rc_close (rc);
930           g_free (path);
931         }
932 
933       /* stop sorting */
934       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
935                                             GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
936                                             GTK_SORT_ASCENDING);
937 
938       /* default item + separator */
939       gtk_list_store_insert_with_values (store, &iter, 0,
940                                          PRESET_COLUMN_TITLE, _("Load Presets..."),
941                                          -1);
942       gtk_list_store_insert_with_values (store, NULL, 1,
943                                          PRESET_COLUMN_IS_SEPARATOR, TRUE,
944                                          -1);
945 
946       /* set model */
947       object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-presets");
948       terminal_return_if_fail (GTK_IS_COMBO_BOX (object));
949       gtk_combo_box_set_model (GTK_COMBO_BOX (object), GTK_TREE_MODEL (store));
950       gtk_combo_box_set_active_iter  (GTK_COMBO_BOX (object), &iter);
951       gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (object),
952           terminal_preferences_dialog_presets_sepfunc, NULL, NULL);
953       g_signal_connect (object, "changed",
954           G_CALLBACK (terminal_preferences_dialog_presets_changed), dialog);
955       g_object_unref (store);
956     }
957 
958   g_strfreev (global);
959   g_strfreev (user);
960   g_free (presets);
961 
962   if (n_presets == 0)
963     {
964       /* hide frame + combo */
965       object = gtk_builder_get_object (GTK_BUILDER (dialog), "color-presets-frame");
966       terminal_return_if_fail (GTK_IS_WIDGET (object));
967       gtk_widget_hide (GTK_WIDGET (object));
968     }
969 }
970 
971 
972 
973 #if VTE_CHECK_VERSION (0, 51, 3)
974 static void
terminal_preferences_dialog_reset_cell_scale(GtkWidget * button,TerminalPreferencesDialog * dialog)975 terminal_preferences_dialog_reset_cell_scale (GtkWidget                 *button,
976                                               TerminalPreferencesDialog *dialog)
977 {
978   const gchar *properties[] = { "cell-width-scale", "cell-height-scale" };
979   RESET_PROPERTIES (properties);
980 }
981 #endif
982 
983 
984 
985 static void
terminal_preferences_dialog_reset_compat(GtkWidget * button,TerminalPreferencesDialog * dialog)986 terminal_preferences_dialog_reset_compat (GtkWidget                 *button,
987                                           TerminalPreferencesDialog *dialog)
988 {
989   const gchar *properties[] = { "binding-backspace", "binding-delete", "binding-ambiguous-width" };
990   RESET_PROPERTIES (properties);
991 }
992 
993 
994 
995 static void
terminal_preferences_dialog_reset_word_chars(GtkWidget * button,TerminalPreferencesDialog * dialog)996 terminal_preferences_dialog_reset_word_chars (GtkWidget                 *button,
997                                               TerminalPreferencesDialog *dialog)
998 {
999   const gchar *properties[] = { "word-chars" };
1000   RESET_PROPERTIES (properties);
1001 }
1002 
1003 
1004 
1005 static void
terminal_preferences_dialog_background_mode(GtkWidget * combobox,TerminalPreferencesDialog * dialog)1006 terminal_preferences_dialog_background_mode (GtkWidget                 *combobox,
1007                                              TerminalPreferencesDialog *dialog)
1008 {
1009   GObject  *object;
1010   gint      active;
1011   gboolean  composited;
1012 
1013   terminal_return_if_fail (TERMINAL_IS_PREFERENCES_DIALOG (dialog));
1014   terminal_return_if_fail (GTK_IS_COMBO_BOX (combobox));
1015 
1016   active = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox));
1017   composited = gdk_screen_is_composited (gtk_widget_get_screen (combobox));
1018 
1019   object = gtk_builder_get_object (GTK_BUILDER (dialog), "box-file");
1020   terminal_return_if_fail (G_IS_OBJECT (object));
1021   g_object_set (object, "visible", active == 1, NULL);
1022 
1023   object = gtk_builder_get_object (GTK_BUILDER (dialog), "box-shading");
1024   terminal_return_if_fail (G_IS_OBJECT (object));
1025   g_object_set (object, "visible", active == 1, NULL);
1026 
1027   object = gtk_builder_get_object (GTK_BUILDER (dialog), "box-opacity");
1028   terminal_return_if_fail (G_IS_OBJECT (object));
1029   g_object_set (object, "visible", active > 1, NULL);
1030   g_object_set (object, "sensitive", active > 1 && composited, NULL);
1031 
1032   object = gtk_builder_get_object (GTK_BUILDER (dialog), "label-opacity-not-available");
1033   terminal_return_if_fail (G_IS_OBJECT (object));
1034   g_object_set (object, "visible", active > 1 && !composited, NULL);
1035 
1036 }
1037 
1038 
1039 
1040 static void
terminal_preferences_dialog_background_notify(GObject * object,GParamSpec * pspec,GObject * widget)1041 terminal_preferences_dialog_background_notify (GObject    *object,
1042                                                GParamSpec *pspec,
1043                                                GObject    *widget)
1044 {
1045   gchar *button_file, *prop_file;
1046 
1047   terminal_return_if_fail (TERMINAL_IS_PREFERENCES (object));
1048   terminal_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (widget));
1049 
1050   button_file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
1051   g_object_get (object, "background-image-file", &prop_file, NULL);
1052   if (g_strcmp0 (button_file, prop_file) != 0)
1053     gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), prop_file);
1054   g_free (button_file);
1055   g_free (prop_file);
1056 }
1057 
1058 
1059 
1060 static void
terminal_preferences_dialog_background_set(GtkFileChooserButton * widget,TerminalPreferencesDialog * dialog)1061 terminal_preferences_dialog_background_set (GtkFileChooserButton      *widget,
1062                                             TerminalPreferencesDialog *dialog)
1063 {
1064   gchar *filename;
1065 
1066   terminal_return_if_fail (TERMINAL_IS_PREFERENCES_DIALOG (dialog));
1067   terminal_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (widget));
1068 
1069   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
1070   g_object_set (G_OBJECT (dialog->preferences), "background-image-file", filename, NULL);
1071   g_free (filename);
1072 }
1073 
1074 
1075 
1076 static void
terminal_preferences_dialog_encoding_changed(GtkComboBox * combobox,TerminalPreferencesDialog * dialog)1077 terminal_preferences_dialog_encoding_changed (GtkComboBox               *combobox,
1078                                               TerminalPreferencesDialog *dialog)
1079 {
1080   GtkTreeIter   iter;
1081   gchar        *encoding;
1082   GtkTreeModel *model;
1083   gboolean      is_charset;
1084   GtkTreeIter   child_iter;
1085 
1086   if (gtk_combo_box_get_active_iter (combobox, &iter))
1087     {
1088       model = gtk_combo_box_get_model (combobox);
1089       gtk_tree_model_get (model, &iter,
1090                           ENCODING_COLUMN_IS_CHARSET, &is_charset,
1091                           ENCODING_COLUMN_VALUE, &encoding, -1);
1092 
1093       /* select the child if a menu header is clicked */
1094       if (encoding == NULL && !is_charset)
1095         {
1096           if (gtk_tree_model_iter_children (model, &child_iter, &iter))
1097             gtk_combo_box_set_active_iter (combobox, &child_iter);
1098           return;
1099         }
1100 
1101       /* save new default */
1102       g_object_set (dialog->preferences, "encoding", encoding, NULL);
1103       g_free (encoding);
1104     }
1105 }
1106 
1107 
1108 
1109 static gboolean
monospace_filter(const PangoFontFamily * family,const PangoFontFace * face,gpointer data)1110 monospace_filter (const PangoFontFamily *family,
1111                   const PangoFontFace   *face,
1112                   gpointer data)
1113 {
1114   return pango_font_family_is_monospace ((PangoFontFamily *) family);
1115 }
1116 
1117 
1118 
1119 /**
1120  * terminal_preferences_dialog_new:
1121  *
1122  * Return value :
1123  **/
1124 GtkWidget*
terminal_preferences_dialog_new(gboolean show_drop_down,gboolean drop_down_mode)1125 terminal_preferences_dialog_new (gboolean show_drop_down,
1126                                  gboolean drop_down_mode)
1127 {
1128   static GtkBuilder *builder = NULL;
1129 
1130   GObject *dialog;
1131   GObject *object;
1132   GObject *notebook;
1133 
1134   if (builder == NULL)
1135     {
1136       builder = g_object_new (TERMINAL_TYPE_PREFERENCES_DIALOG, NULL);
1137       g_object_add_weak_pointer (G_OBJECT (builder), (gpointer) &builder);
1138     }
1139 
1140   object = gtk_builder_get_object (builder, "dropdown-box");
1141   terminal_return_val_if_fail (GTK_IS_WIDGET (object), NULL);
1142   gtk_widget_set_visible (GTK_WIDGET (object), show_drop_down);
1143 
1144   /* focus the drop-down tab if in drop-down mode */
1145   if (show_drop_down && drop_down_mode)
1146     {
1147       notebook = gtk_builder_get_object (builder, "notebook");
1148       terminal_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
1149       gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook),
1150           gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (object)));
1151     }
1152 
1153   /* show warning and disable control if WM does not support compositing */
1154   if (show_drop_down && !gdk_screen_is_composited (gtk_widget_get_screen (GTK_WIDGET (object))))
1155     {
1156       object = gtk_builder_get_object (builder, "dropdown-opacity-not-available");
1157       terminal_return_val_if_fail (G_IS_OBJECT (object), NULL);
1158       gtk_widget_set_visible (GTK_WIDGET (object), TRUE);
1159       object = gtk_builder_get_object (builder, "scale-opacity");
1160       terminal_return_val_if_fail (G_IS_OBJECT (object), NULL);
1161       gtk_widget_set_sensitive (GTK_WIDGET (object), FALSE);
1162     }
1163 
1164   dialog = gtk_builder_get_object (builder, "dialog");
1165   terminal_return_val_if_fail (XFCE_IS_TITLED_DIALOG (dialog), NULL);
1166   gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
1167   return GTK_WIDGET (dialog);
1168 }
1169