Add README
[tilda-gobject.git] / tilda-terminal.c
1 #include "tilda.h"
2 #include "tilda-terminal.h"
3 #include "tilda-config.h"
4 #include "tilda-terminal-dbus-glue.h"
5
6 #include <stdlib.h>
7
8 #define DINGUS1 "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?"
9 #define DINGUS2 "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\) ,\\\"]"
10
11 /*******************************************************************************
12  * All popup-menu code is below
13  ******************************************************************************/
14
15 static void
16 menu_add_term_cb (GtkWidget *widget, gpointer data)
17 {
18         debug_enter  ();
19         debug_assert (TILDA_IS_TERMINAL(data));
20
21         TildaTerminal *self = TILDA_TERMINAL(data);
22         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
23
24         tilda_window_add_terminal (parent_window);
25 }
26
27 static void
28 menu_remove_term_cb (GtkWidget *widget, gpointer data)
29 {
30         debug_enter  ();
31         debug_assert (TILDA_IS_TERMINAL(data));
32
33         TildaTerminal *self = TILDA_TERMINAL(data);
34         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
35
36         tilda_window_remove_terminal (parent_window, self->number);
37 }
38
39 static void
40 menu_copy_cb (GtkWidget *widget, gpointer data)
41 {
42         debug_enter  ();
43         debug_assert (TILDA_IS_TERMINAL(data));
44
45         TildaTerminal *self = TILDA_TERMINAL(data);
46
47         vte_terminal_copy_clipboard (VTE_TERMINAL(self->vte_term));
48 }
49
50 static void
51 menu_paste_cb (GtkWidget *widget, gpointer data)
52 {
53         debug_enter  ();
54         debug_assert (TILDA_IS_TERMINAL(data));
55
56         TildaTerminal *self = TILDA_TERMINAL(data);
57
58         vte_terminal_paste_clipboard (VTE_TERMINAL(self->vte_term));
59 }
60
61 static void
62 menu_preferences_cb (GtkWidget *widget, gpointer data)
63 {
64         debug_enter  ();
65         debug_assert (TILDA_IS_TERMINAL(data));
66
67         TildaTerminal *self = TILDA_TERMINAL(data);
68         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
69
70         /* TODO:
71          *
72          * Note that this lends interesting possibilities for the tilda-wizard
73          * command line interface. Maybe a --window --terminal option, which will
74          * auto-set the preferences to a current window and term :) Neat.
75          */
76
77         g_print ("FIXME: show wizard here\n");
78 }
79
80 static void
81 menu_quit_cb (GtkWidget *widget, gpointer data)
82 {
83         debug_enter  ();
84         debug_assert (TILDA_IS_TERMINAL(data));
85
86         TildaTerminal *self = TILDA_TERMINAL(data);
87         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
88         TildaController *controller = TILDA_CONTROLLER(parent_window->controller);
89
90         tilda_controller_remove_window (controller, parent_window->number);
91 }
92
93 static void
94 tilda_terminal_popup_menu (TildaTerminal *self)
95 {
96         debug_enter  ();
97         debug_assert (TILDA_IS_TERMINAL(self));
98
99         GtkAction *action;
100         GtkActionGroup *action_group;
101         GtkUIManager *ui_manager;
102         GError *error = NULL;
103         GtkWidget *menu;
104
105         /* Just use a static string here to initialize the GtkUIManager,
106          * rather than installing and reading from a file all the time. */
107         static const gchar menu_str[] =
108                 "<ui>"
109                         "<popup name=\"popup-menu\">"
110                                 "<menuitem action=\"add-term\" />"
111                                 "<menuitem action=\"remove-term\" />"
112                                 "<separator />"
113                                 "<menuitem action=\"copy\" />"
114                                 "<menuitem action=\"paste\" />"
115                                 "<separator />"
116                                 "<menuitem action=\"preferences\" />"
117                                 "<separator />"
118                                 "<menuitem action=\"quit\" />"
119                         "</popup>"
120                 "</ui>";
121
122         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
123
124         /* Create the action group */
125         action_group = gtk_action_group_new ("popup-menu-action-group");
126
127         /* Add Actions and connect callbacks */
128         action = gtk_action_new ("add-term", _("_Add Terminal"), NULL, GTK_STOCK_ADD);
129         gtk_action_group_add_action_with_accel (action_group, action, parent_window->accel_add_term);
130         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_add_term_cb), self);
131
132         action = gtk_action_new ("remove-term", _("_Remove Terminal"), NULL, GTK_STOCK_CLOSE);
133         gtk_action_group_add_action_with_accel (action_group, action, parent_window->accel_remove_term);
134         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_remove_term_cb), self);
135
136         action = gtk_action_new ("copy", NULL, NULL, GTK_STOCK_COPY);
137         gtk_action_group_add_action_with_accel (action_group, action, parent_window->accel_copy);
138         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_copy_cb), self);
139
140         action = gtk_action_new ("paste", NULL, NULL, GTK_STOCK_PASTE);
141         gtk_action_group_add_action_with_accel (action_group, action, parent_window->accel_paste);
142         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_paste_cb), self);
143
144         action = gtk_action_new ("preferences", NULL, NULL, GTK_STOCK_PREFERENCES);
145         gtk_action_group_add_action (action_group, action);
146         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_preferences_cb), self);
147
148         action = gtk_action_new ("quit", NULL, NULL, GTK_STOCK_QUIT);
149         gtk_action_group_add_action_with_accel (action_group, action, parent_window->accel_quit);
150         g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_quit_cb), self);
151
152         /* Create and add actions to the GtkUIManager */
153         ui_manager = gtk_ui_manager_new ();
154         gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
155         gtk_ui_manager_add_ui_from_string (ui_manager, menu_str, -1, &error);
156
157         /* Check for an error (REALLY REALLY unlikely, unless the developers screwed up */
158         if (error)
159         {
160                 g_critical ("GtkUIManager problem: %s\n", error->message);
161                 g_error_free (error);
162         }
163
164         /* Get the popup menu out of the GtkUIManager */
165         menu = gtk_ui_manager_get_widget (ui_manager, "/ui/popup-menu");
166
167         /* Display the menu */
168         gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
169         gtk_widget_show_all(menu);
170 }
171
172 /*******************************************************************************
173  * All TildaTerminal functions below
174  ******************************************************************************/
175
176 static void
177 tilda_terminal_dbus_register_object (TildaTerminal *tt)
178 {
179         debug_enter  ();
180         debug_assert (TILDA_IS_TERMINAL(tt));
181
182         TildaWindow *parent_window = TILDA_WINDOW(tt->parent_window);
183         gchar *object_path;
184
185         /* If DBus is not running, leave */
186         if (!dbus_connection)
187                 return;
188
189         /* Register this object with DBus */
190         object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d/Terminal%d",
191                                                                    parent_window->number, tt->number);
192         dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(tt));
193         g_free (object_path);
194 }
195
196 gboolean
197 tilda_terminal_run_command (TildaTerminal *self, gchar *command, GError **error)
198 {
199         debug_enter  ();
200         debug_assert (TILDA_IS_TERMINAL(self));
201
202         vte_terminal_feed_child (VTE_TERMINAL(self->vte_term), command, -1);
203         vte_terminal_feed_child (VTE_TERMINAL(self->vte_term), "\n", -1);
204
205         return TRUE;
206 }
207
208 gboolean
209 tilda_terminal_close (TildaTerminal *self, GError **error)
210 {
211         debug_enter  ();
212         debug_assert (TILDA_IS_TERMINAL(self));
213
214         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
215
216         tilda_window_remove_terminal (parent_window, self->number);
217
218         return TRUE;
219 }
220
221 /**
222  * Start the current tt->shell in the given TildaTerminal
223  * NOTE: this will kill whatever is running in the terminal,
224  * NOTE: and run the current tt->shell instead :)
225  * Return: TRUE if ok, FALSE otherwise
226  */
227 static gboolean
228 tilda_terminal_start_shell (TildaTerminal *tt)
229 {
230         debug_enter  ();
231         debug_assert (TILDA_IS_TERMINAL(tt));
232
233         gint ret;
234         gint argc;
235         gchar **argv;
236         GError *error = NULL;
237
238         /* Launch a custom command if tt->shell is set (not NULL) */
239         if (tt->shell)
240         {
241                 /* Try to parse the user's custom command */
242                 ret = g_shell_parse_argv (tt->shell, &argc, &argv, &error);
243
244                 if (ret == FALSE)
245                 {
246                         g_printerr (_("Problem parsing custom command: %s\n"), error->message);
247                         g_printerr (_("Launching default shell instead\n"));
248
249                         g_error_free (error);
250                         goto launch_default_shell;
251                 }
252
253                 /* Try to start the user's custom command */
254                 ret = vte_terminal_fork_command (VTE_TERMINAL(tt->vte_term),
255                                                                                  argv[0], /* Command */
256                                                                                  argv,    /* Arg Vector */
257                                                                                  NULL,    /* Env Vector */
258                                                                                  tt->working_directory, /* Start directory */
259                                                                                  TRUE,    /* Add to lastlog */
260                                                                                  TRUE,    /* Add to utmp */
261                                                                                  TRUE);   /* Add to wtmp */
262
263                 g_strfreev (argv);
264
265                 /* Check for error */
266                 if (ret == -1)
267                 {
268                         g_printerr (_("Unable to launch custom command: %s\n"), tt->shell);
269                         g_printerr (_("Launching default shell instead\n"));
270
271                         goto launch_default_shell;
272                 }
273
274                 return TRUE; /* SUCCESS: the early way out */
275         }
276
277 launch_default_shell:
278
279     ret = vte_terminal_fork_command (VTE_TERMINAL(tt->vte_term),
280                                                                          NULL, /* Command -- VTE will figure it out */
281                                                                          NULL, /* Arg Vector */
282                                                                          NULL, /* Env Vector */
283                                                                          tt->working_directory, /* Start Directory */
284                                                                          TRUE, /* Add to lastlog */
285                                                                          TRUE, /* Add to utmp */
286                                                                          TRUE);/* Add to wtmp */
287
288         if (ret == -1)
289         {
290                 g_printerr (_("Unable to launch default shell\n"));
291                 return FALSE;
292         }
293
294         return TRUE;
295 }
296
297 /**
298  * Called when the child process running in the VteTerminal exits.
299  */
300 static void
301 tilda_terminal_child_exited_cb (GtkWidget *widget, gpointer data)
302 {
303         debug_enter  ();
304         debug_assert (GTK_IS_WIDGET(widget));
305         debug_assert (TILDA_IS_TERMINAL(data));
306
307         TildaTerminal *self = TILDA_TERMINAL(data);
308
309         /* Check the user's preference for what to do when the child terminal
310          * is closed. Take the appropriate action */
311         switch (self->exit_action)
312         {
313                 case TILDA_CHILD_EXIT_ACTION_EXIT:
314                         tilda_window_remove_terminal (TILDA_WINDOW(self->parent_window), self->number);
315                         break;
316                 case TILDA_CHILD_EXIT_ACTION_RESTART:
317                         vte_terminal_feed (VTE_TERMINAL(self->vte_term), "\r\n\r\n", 4);
318                         tilda_terminal_start_shell (self);
319                         break;
320                 case TILDA_CHILD_EXIT_ACTION_HOLD_OPEN:
321                         break;
322                 default:
323                         g_warning ("Bad value in self->exit_action\n");
324                         break;
325         }
326 }
327
328 /**
329  * Called when the child window title changes. Determines if a new
330  * title needs to be put into the notebook's tab label.
331  */
332 static void
333 tilda_terminal_window_title_changed_cb (GtkWidget *widget, gpointer data)
334 {
335         debug_enter  ();
336         debug_assert (GTK_IS_WIDGET(widget));
337         debug_assert (TILDA_IS_TERMINAL(data));
338
339         TildaTerminal *self = TILDA_TERMINAL(data);
340         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
341         GtkWidget *label;
342         const gchar *vte_title = NULL;
343         gchar *new_title = NULL;
344
345         vte_title = vte_terminal_get_window_title (VTE_TERMINAL (widget));
346         label = gtk_notebook_get_tab_label (GTK_NOTEBOOK(parent_window->notebook), self->hbox);
347
348         switch (self->dynamic_title)
349         {
350                 case TILDA_DYNAMIC_TITLE_DISABLED:
351                         new_title = g_strdup (self->title);
352                         break;
353
354                 case TILDA_DYNAMIC_TITLE_AFTER_INITIAL:
355                         new_title = g_strdup_printf ("%s - %s", self->title, vte_title);
356                         break;
357
358                 case TILDA_DYNAMIC_TITLE_BEFORE_INITIAL:
359                         new_title = g_strdup_printf ("%s - %s", vte_title, self->title);
360                         break;
361
362                 case TILDA_DYNAMIC_TITLE_REPLACE_INITIAL:
363                         new_title = g_strdup (self->title);
364                         break;
365
366                 default:
367                         g_warning ("Bad value in self->dynamic-title\n");
368                         break;
369         }
370
371         gtk_label_set_text (GTK_LABEL(label), new_title);
372         g_free (new_title);
373 }
374
375 /**
376  * Gets called whenever there is a button-press event in the VteTerminal. It
377  * is used to open the user's web browser, for example.
378  */
379 static gint
380 tilda_terminal_button_press_cb (GtkWidget      *widget,
381                                                                 GdkEventButton *event,
382                                                                 gpointer        data)
383 {
384         debug_enter  ();
385         debug_assert (GTK_IS_WIDGET(widget));
386         debug_assert (TILDA_IS_TERMINAL(data));
387         debug_printf ("event->button = %d\n", event->button);
388
389         GError *error = NULL;
390         TildaTerminal *self = TILDA_TERMINAL(data);
391         VteTerminal *terminal = VTE_TERMINAL(self->vte_term);
392         gint tag, xpad, ypad;
393         gchar *match, *cmd, *web_browser_cmd;
394         gboolean ret = FALSE;
395
396         switch (event->button)
397         {
398                 case 3: /* Right Click */
399                         tilda_terminal_popup_menu (self);
400                         break;
401
402                 case 2: /* Middle Click */
403                         break;
404
405                 case 1: /* Left Click */
406                         vte_terminal_get_padding (terminal, &xpad, &ypad);
407                         match = vte_terminal_match_check (terminal,
408                                         (event->x - ypad) / terminal->char_width,
409                                         (event->y - ypad) / terminal->char_height,
410                                         &tag);
411
412                         /* Check if we can launch a web browser, and do so if possible */
413                         if ((event->state & GDK_CONTROL_MASK) && match != NULL)
414                         {
415                                 web_browser_cmd = g_strescape (self->web_browser, NULL);
416                                 cmd = g_strdup_printf ("%s %s", web_browser_cmd, match);
417
418                                 debug_printf ("Got a Ctrl+Left-Click -- match: '%s' tag: %d\n", match, tag);
419                                 debug_printf ("Launching command: '%s'\n", cmd);
420
421                                 ret = g_spawn_command_line_async(cmd, &error);
422
423                                 /* Check that the command launched */
424                                 if (!ret)
425                                 {
426                                         g_printerr (_("Failed to launch web browser command: `%s'\n"), cmd);
427                                         g_printerr (_("Error message: %s\n"), error->message);
428                                 }
429
430                                 /* Free allocated memory */
431                                 g_free (web_browser_cmd);
432                                 g_free (cmd);
433                         }
434
435                         /* Always free match if it is non NULL */
436                         g_free (match);
437                         break;
438
439                 default:
440                         break;
441         }
442
443         return FALSE;
444 }
445
446 /**
447  * Set the given TildaTerminal to the appropriate transparency level
448  * based on the self->transparency_percent member. */
449 static void
450 tilda_terminal_set_transparent (TildaTerminal *self)
451 {
452         debug_enter  ();
453         debug_assert (TILDA_IS_TERMINAL(self));
454
455         TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
456         gdouble temp;
457
458         /* Convert the transparency to VTE's format */
459         temp = ((gdouble) self->transparency_percent) / 100.0;
460
461         if (self->transparency_percent > 0)
462         {
463                 vte_terminal_set_background_saturation (VTE_TERMINAL(self->vte_term), temp);
464                 vte_terminal_set_opacity (VTE_TERMINAL(self->vte_term), (1.0 - temp) * 0xffff);
465
466                 /* Use fake transparency if necessary */
467                 vte_terminal_set_background_transparent (VTE_TERMINAL(self->vte_term),
468                                                                                                  !parent_window->have_real_transparency);
469                 return;
470         }
471
472         /* Turn off transparency */
473         vte_terminal_set_background_saturation (VTE_TERMINAL(self->vte_term), 0);
474         vte_terminal_set_opacity (VTE_TERMINAL(self->vte_term), 0xffff);
475         vte_terminal_set_background_transparent (VTE_TERMINAL(self->vte_term), FALSE);
476 }
477
478 /**
479  * Set the scrollbar position of the given TildaTerminal to
480  * the value in self->scrollbar_position.
481  */
482 static void
483 tilda_terminal_set_scrollbar_position (TildaTerminal *self)
484 {
485         debug_enter  ();
486         debug_assert (TILDA_IS_TERMINAL(self));
487
488         switch (self->scrollbar_position)
489         {
490                 case TILDA_SCROLLBAR_RIGHT:
491                         gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 0);
492                         gtk_widget_show (self->scrollbar);
493                         break;
494
495                 case TILDA_SCROLLBAR_LEFT:
496                         gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 1);
497                         gtk_widget_show (self->scrollbar);
498                         break;
499
500                 case TILDA_SCROLLBAR_DISABLED:
501                         gtk_widget_hide (self->scrollbar);
502                         break;
503
504                 default:
505                         g_warning ("Bad value in self->scrollbar_position\n");
506                         break;
507         }
508 }
509
510 /*******************************************************************************
511  * All GObject stuff is below. You probably don't need to change this...
512  ******************************************************************************/
513
514 static GObjectClass *parent_class = NULL;
515
516 enum tilda_terminal_properties {
517         TILDA_TERMINAL_NUMBER = 1,
518         TILDA_TERMINAL_PARENT_WINDOW,
519
520         /* All non-constructor-only properties */
521         TILDA_TERMINAL_BACKGROUND_IMAGE,
522         TILDA_TERMINAL_SHELL,
523         TILDA_TERMINAL_FONT,
524         TILDA_TERMINAL_TITLE,
525         TILDA_TERMINAL_WORKING_DIRECTORY,
526         TILDA_TERMINAL_WEB_BROWSER,
527
528         TILDA_TERMINAL_SCROLLBACK_LINES,
529         TILDA_TERMINAL_TRANSPARENCY_PERCENT,
530
531         TILDA_TERMINAL_BACKSPACE_BINDING,
532         TILDA_TERMINAL_DELETE_BINDING,
533         TILDA_TERMINAL_DYNAMIC_TITLE,
534         TILDA_TERMINAL_EXIT_ACTION,
535         TILDA_TERMINAL_SCROLLBAR_POSITION,
536
537         TILDA_TERMINAL_SCROLL_BACKGROUND,
538         TILDA_TERMINAL_SCROLL_ON_OUTPUT,
539         TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
540         TILDA_TERMINAL_ANTIALIASED,
541         TILDA_TERMINAL_ALLOW_BOLD_TEXT,
542         TILDA_TERMINAL_CURSOR_BLINKS,
543         TILDA_TERMINAL_AUDIBLE_BELL,
544         TILDA_TERMINAL_VISIBLE_BELL,
545         TILDA_TERMINAL_DOUBLE_BUFFERED,
546         TILDA_TERMINAL_MOUSE_AUTOHIDE,
547 };
548
549 static void
550 tilda_terminal_instance_init (GTypeInstance *instance,
551                                                           gpointer       g_class)
552 {
553         debug_enter ();
554
555         TildaTerminal *self = (TildaTerminal *) instance;
556
557         /* Initialize instance members and allocate any necessary memory here.
558          * NOTE: any constructor-time values will be set later. */
559         self->dispose_has_run = FALSE;
560         self->number = 0;
561
562         self->vte_term = vte_terminal_new ();
563         self->scrollbar = gtk_vscrollbar_new (VTE_TERMINAL(self->vte_term)->adjustment);
564         self->hbox = gtk_hbox_new (FALSE, 0);
565 }
566
567 static void
568 tilda_terminal_set_property (GObject      *object,
569                                                          guint         property_id,
570                                                          const GValue *value,
571                                                          GParamSpec   *pspec)
572 {
573         TildaTerminal *self = (TildaTerminal *) object;
574
575         switch (property_id) {
576
577                 case TILDA_TERMINAL_NUMBER:
578                         self->number = g_value_get_int (value);
579                         debug_printf ("terminal number: %d\n", self->number);
580                         break;
581
582                 case TILDA_TERMINAL_PARENT_WINDOW:
583                         self->parent_window = g_value_get_pointer (value);
584                         debug_printf ("terminal parent window: 0x%x\n", self->parent_window);
585                         break;
586
587                 case TILDA_TERMINAL_BACKGROUND_IMAGE:
588                         g_free (self->background_image);
589                         self->background_image = g_value_dup_string (value);
590                         vte_terminal_set_background_image_file (VTE_TERMINAL(self->vte_term), self->background_image);
591                         debug_printf ("terminal back img: %s\n", self->background_image);
592                         break;
593
594                 case TILDA_TERMINAL_SHELL:
595                         g_free (self->shell);
596                         self->shell = g_value_dup_string (value);
597                         tilda_terminal_start_shell (self);
598                         debug_printf ("terminal shell: %s\n", self->shell);
599                         break;
600
601                 case TILDA_TERMINAL_FONT:
602                         g_free (self->font);
603                         self->font = g_value_dup_string (value);
604                         vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
605                                                                                                         self->font,
606                                                                                                         self->antialiased);
607                         debug_printf ("terminal font: %s\n", self->font);
608                         break;
609
610                 case TILDA_TERMINAL_TITLE:
611                         g_free (self->title);
612                         self->title = g_value_dup_string (value);
613                         debug_printf ("terminal title: %s\n", self->title);
614                         break;
615
616                 case TILDA_TERMINAL_WORKING_DIRECTORY:
617                         g_free (self->working_directory);
618                         self->working_directory = g_value_dup_string (value);
619                         debug_printf ("terminal wrk dir: %s\n", self->working_directory);
620                         break;
621
622                 case TILDA_TERMINAL_WEB_BROWSER:
623                         g_free (self->web_browser);
624                         self->web_browser = g_value_dup_string (value);
625                         debug_printf ("terminal web browser: %s\n", self->web_browser);
626                         break;
627
628                 case TILDA_TERMINAL_SCROLLBACK_LINES:
629                         self->scrollback_lines = g_value_get_int (value);
630                         vte_terminal_set_scrollback_lines (VTE_TERMINAL(self->vte_term), self->scrollback_lines);
631                         debug_printf ("terminal scrollback lines: %d\n", self->scrollback_lines);
632                         break;
633
634                 case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
635                         self->transparency_percent = g_value_get_int (value);
636                         tilda_terminal_set_transparent (self);
637                         debug_printf ("terminal transp percent: %d\n", self->transparency_percent);
638                         break;
639
640                 case TILDA_TERMINAL_BACKSPACE_BINDING:
641                         self->backspace_binding = g_value_get_enum (value);
642                         vte_terminal_set_backspace_binding (VTE_TERMINAL(self->vte_term), self->backspace_binding);
643                         debug_printf ("terminal backspace key: %d\n", self->backspace_binding);
644                         break;
645
646                 case TILDA_TERMINAL_DELETE_BINDING:
647                         self->delete_binding = g_value_get_enum (value);
648                         vte_terminal_set_delete_binding (VTE_TERMINAL(self->vte_term), self->delete_binding);
649                         debug_printf ("terminal delete key: %d\n", self->delete_binding);
650                         break;
651
652                 case TILDA_TERMINAL_DYNAMIC_TITLE:
653                         self->dynamic_title = g_value_get_enum (value);
654                         debug_printf ("terminal dynamic title: %d\n", self->dynamic_title);
655                         break;
656
657                 case TILDA_TERMINAL_EXIT_ACTION:
658                         self->exit_action = g_value_get_enum (value);
659                         debug_printf ("terminal exit action: %d\n", self->exit_action);
660                         break;
661
662                 case TILDA_TERMINAL_SCROLLBAR_POSITION:
663                         self->scrollbar_position = g_value_get_enum (value);
664                         tilda_terminal_set_scrollbar_position (self);
665                         debug_printf ("terminal scrollbar position: %d\n", self->scrollbar_position);
666                         break;
667
668                 case TILDA_TERMINAL_SCROLL_BACKGROUND:
669                         self->scroll_background = g_value_get_boolean (value);
670                         vte_terminal_set_scroll_background (VTE_TERMINAL(self->vte_term), self->scroll_background);
671                         debug_printf ("terminal scroll background: %d\n", self->scroll_background);
672                         break;
673
674                 case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
675                         self->scroll_on_output = g_value_get_boolean (value);
676                         vte_terminal_set_scroll_on_output (VTE_TERMINAL(self->vte_term), self->scroll_on_output);
677                         debug_printf ("terminal scroll on output: %d\n", self->scroll_on_output);
678                         break;
679
680                 case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
681                         self->scroll_on_keystroke = g_value_get_boolean (value);
682                         vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL(self->vte_term), self->scroll_on_keystroke);
683                         debug_printf ("terminal scroll on keystroke: %d\n", self->scroll_on_keystroke);
684                         break;
685
686                 case TILDA_TERMINAL_ANTIALIASED:
687                         self->antialiased = g_value_get_boolean (value);
688                         vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
689                                                                                                         self->font,
690                                                                                                         self->antialiased);
691                         debug_printf ("terminal antialiased: %d\n", self->antialiased);
692                         break;
693
694                 case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
695                         self->allow_bold_text = g_value_get_boolean (value);
696                         vte_terminal_set_allow_bold (VTE_TERMINAL(self->vte_term), self->allow_bold_text);
697                         debug_printf ("terminal allow bold text: %d\n", self->allow_bold_text);
698                         break;
699
700                 case TILDA_TERMINAL_CURSOR_BLINKS:
701                         self->cursor_blinks = g_value_get_boolean (value);
702                         vte_terminal_set_cursor_blinks (VTE_TERMINAL(self->vte_term), self->cursor_blinks);
703                         debug_printf ("terminal cursor blinks: %d\n", self->cursor_blinks);
704                         break;
705
706                 case TILDA_TERMINAL_AUDIBLE_BELL:
707                         self->audible_bell = g_value_get_boolean (value);
708                         vte_terminal_set_audible_bell (VTE_TERMINAL(self->vte_term), self->audible_bell);
709                         debug_printf ("terminal audible bell: %d\n", self->audible_bell);
710                         break;
711
712                 case TILDA_TERMINAL_VISIBLE_BELL:
713                         self->visible_bell = g_value_get_boolean (value);
714                         vte_terminal_set_visible_bell (VTE_TERMINAL(self->vte_term), self->visible_bell);
715                         debug_printf ("terminal visible bell: %d\n", self->visible_bell);
716                         break;
717
718                 case TILDA_TERMINAL_DOUBLE_BUFFERED:
719                         self->double_buffered = g_value_get_boolean (value);
720                         gtk_widget_set_double_buffered (GTK_WIDGET(self->vte_term), self->double_buffered);
721                         debug_printf ("terminal double buffered: %d\n", self->double_buffered);
722                         break;
723
724                 case TILDA_TERMINAL_MOUSE_AUTOHIDE:
725                         self->mouse_autohide = g_value_get_boolean (value);
726                         vte_terminal_set_mouse_autohide (VTE_TERMINAL(self->vte_term), self->mouse_autohide);
727                         debug_printf ("terminal mouse autohide: %d\n", self->mouse_autohide);
728                         break;
729
730                 default:
731                         /* We don't have this property... */
732                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
733                         break;
734         }
735 }
736
737 static void
738 tilda_terminal_get_property (GObject    *object,
739                                                          guint       property_id,
740                                                          GValue     *value,
741                                                          GParamSpec *pspec)
742 {
743         TildaTerminal *self = (TildaTerminal *) object;
744
745         switch (property_id) {
746
747                 case TILDA_TERMINAL_NUMBER:
748                         g_value_set_int (value, self->number);
749                         break;
750
751                 case TILDA_TERMINAL_PARENT_WINDOW:
752                         g_value_set_pointer (value, self->parent_window);
753                         break;
754
755                 case TILDA_TERMINAL_BACKGROUND_IMAGE:
756                         g_value_set_string (value, self->background_image);
757                         break;
758
759                 case TILDA_TERMINAL_SHELL:
760                         g_value_set_string (value, self->shell);
761                         break;
762
763                 case TILDA_TERMINAL_FONT:
764                         g_value_set_string (value, self->font);
765                         break;
766
767                 case TILDA_TERMINAL_TITLE:
768                         g_value_set_string (value, self->title);
769                         break;
770
771                 case TILDA_TERMINAL_WORKING_DIRECTORY:
772                         g_value_set_string (value, self->working_directory);
773                         break;
774
775                 case TILDA_TERMINAL_WEB_BROWSER:
776                         g_value_set_string (value, self->web_browser);
777                         break;
778
779                 case TILDA_TERMINAL_SCROLLBACK_LINES:
780                         g_value_set_int (value, self->scrollback_lines);
781                         break;
782
783                 case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
784                         g_value_set_int (value, self->transparency_percent);
785                         break;
786
787                 case TILDA_TERMINAL_BACKSPACE_BINDING:
788                         g_value_set_enum (value, self->backspace_binding);
789                         break;
790
791                 case TILDA_TERMINAL_DELETE_BINDING:
792                         g_value_set_enum (value, self->delete_binding);
793                         break;
794
795                 case TILDA_TERMINAL_DYNAMIC_TITLE:
796                         g_value_set_enum (value, self->dynamic_title);
797                         break;
798
799                 case TILDA_TERMINAL_EXIT_ACTION:
800                         g_value_set_enum (value, self->exit_action);
801                         break;
802
803                 case TILDA_TERMINAL_SCROLLBAR_POSITION:
804                         g_value_set_enum (value, self->scrollbar_position);
805                         break;
806
807                 case TILDA_TERMINAL_SCROLL_BACKGROUND:
808                         g_value_set_boolean (value, self->scroll_background);
809                         break;
810
811                 case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
812                         g_value_set_boolean (value, self->scroll_on_output);
813                         break;
814
815                 case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
816                         g_value_set_boolean (value, self->scroll_on_keystroke);
817                         break;
818
819                 case TILDA_TERMINAL_ANTIALIASED:
820                         g_value_set_boolean (value, self->antialiased);
821                         break;
822
823                 case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
824                         g_value_set_boolean (value, self->allow_bold_text);
825                         break;
826
827                 case TILDA_TERMINAL_CURSOR_BLINKS:
828                         g_value_set_boolean (value, self->cursor_blinks);
829                         break;
830
831                 case TILDA_TERMINAL_AUDIBLE_BELL:
832                         g_value_set_boolean (value, self->audible_bell);
833                         break;
834
835                 case TILDA_TERMINAL_VISIBLE_BELL:
836                         g_value_set_boolean (value, self->visible_bell);
837                         break;
838
839                 case TILDA_TERMINAL_DOUBLE_BUFFERED:
840                         g_value_set_boolean (value, self->double_buffered);
841                         break;
842
843                 case TILDA_TERMINAL_MOUSE_AUTOHIDE:
844                         g_value_set_boolean (value, self->mouse_autohide);
845
846                 default:
847                         /* We don't have this property... */
848                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
849                         break;
850         }
851 }
852
853 static GObject *
854 tilda_terminal_constructor (GType                  type,
855                                                         guint                  n_construct_properties,
856                                                         GObjectConstructParam *construct_properties)
857 {
858         debug_enter ();
859
860         GObject *obj;
861         TildaTerminal *self;
862         gint ret;
863
864         /* Invoke parent constructor */
865         TildaTerminalClass *klass;
866         klass = TILDA_TERMINAL_CLASS (g_type_class_peek (TILDA_TYPE_TERMINAL));
867         obj = parent_class->constructor (type,
868                                                                          n_construct_properties,
869                                                                          construct_properties);
870
871         /* Do other stuff here. The object is ready to go now, and all
872          * ctor properties have been set. */
873         self = TILDA_TERMINAL(obj);
874
875         /* Pack into the hbox */
876         gtk_box_pack_end (GTK_BOX(self->hbox), self->scrollbar, FALSE, FALSE, 0);
877         gtk_box_pack_end (GTK_BOX(self->hbox), self->vte_term, TRUE, TRUE, 0);
878         gtk_widget_show (self->scrollbar);
879         gtk_widget_show (self->vte_term);
880         gtk_widget_show (self->hbox);
881
882         /* Match URL's, etc */
883         ret = vte_terminal_match_add (VTE_TERMINAL(self->vte_term), DINGUS1);
884         vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
885         ret = vte_terminal_match_add(VTE_TERMINAL(self->vte_term), DINGUS2);
886         vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
887
888         /* Connect Signals */
889         g_signal_connect (G_OBJECT(self->vte_term), "child-exited",
890                                           G_CALLBACK(tilda_terminal_child_exited_cb), self);
891         g_signal_connect (G_OBJECT(self->vte_term), "eof",
892                                           G_CALLBACK(tilda_terminal_child_exited_cb), self);
893         g_signal_connect (G_OBJECT(self->vte_term), "window-title-changed",
894                                           G_CALLBACK(tilda_terminal_window_title_changed_cb), self);
895         g_signal_connect (G_OBJECT(self->vte_term), "button-press-event",
896                                           G_CALLBACK(tilda_terminal_button_press_cb), self);
897
898         /* Setup all of the defaults from the config file */
899         tilda_terminal_set_property_from_config (self, "background-image");
900         tilda_terminal_set_property_from_config (self, "shell");
901         tilda_terminal_set_property_from_config (self, "font");
902         tilda_terminal_set_property_from_config (self, "title");
903         tilda_terminal_set_property_from_config (self, "working-directory");
904         tilda_terminal_set_property_from_config (self, "web-browser");
905
906         tilda_terminal_set_property_from_config (self, "scrollback-lines");
907         tilda_terminal_set_property_from_config (self, "transparency-percent");
908
909         tilda_terminal_set_property_from_config (self, "backspace-binding");
910         tilda_terminal_set_property_from_config (self, "delete-binding");
911         tilda_terminal_set_property_from_config (self, "dynamic-title");
912         tilda_terminal_set_property_from_config (self, "exit-action");
913         tilda_terminal_set_property_from_config (self, "scrollbar-position");
914
915         tilda_terminal_set_property_from_config (self, "scroll-background");
916         tilda_terminal_set_property_from_config (self, "scroll-on-output");
917         tilda_terminal_set_property_from_config (self, "scroll-on-keystroke");
918         tilda_terminal_set_property_from_config (self, "antialiased");
919         tilda_terminal_set_property_from_config (self, "allow-bold-text");
920         tilda_terminal_set_property_from_config (self, "cursor-blinks");
921         tilda_terminal_set_property_from_config (self, "audible-bell");
922         tilda_terminal_set_property_from_config (self, "visible-bell");
923         tilda_terminal_set_property_from_config (self, "double-buffered");
924         tilda_terminal_set_property_from_config (self, "mouse-autohide");
925
926         /* All right! We're all ready to go, so register with DBus, and lets start! */
927         tilda_terminal_dbus_register_object (self);
928
929         return obj;
930 }
931
932 static void
933 tilda_terminal_dispose (GObject *obj)
934 {
935         debug_enter ();
936
937         TildaTerminal *self = (TildaTerminal *) obj;
938
939         /* We don't want to run dispose twice, so just return immediately */
940         if (self->dispose_has_run)
941                 return;
942
943         self->dispose_has_run = TRUE;
944
945         /*
946          * In dispose, you are supposed to free all types referenced from this
947          * object which might themselves hold a reference to self. Generally,
948          * the most simple solution is to unref all members on which you own a
949          * reference.
950          */
951
952         /* Chain up to the parent class */
953         G_OBJECT_CLASS (parent_class)->dispose (obj);
954 }
955
956 static void
957 tilda_terminal_finalize (GObject *obj)
958 {
959         debug_enter ();
960
961         TildaTerminal *self = (TildaTerminal *) obj;
962
963         /*
964          * Here, complete object destruction.
965          * You might not need to do much...
966          */
967         g_free (self->background_image);
968         g_free (self->shell);
969         g_free (self->font);
970         g_free (self->title);
971         g_free (self->working_directory);
972
973
974         /* Chain up to the parent class */
975         G_OBJECT_CLASS (parent_class)->finalize (obj);
976 }
977
978 static void
979 tilda_terminal_class_init (gpointer g_class,
980                                                    gpointer g_class_data)
981 {
982         debug_enter ();
983
984         GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
985         TildaTerminalClass *klass = TILDA_TERMINAL_CLASS (g_class);
986         GParamSpec *pspec;
987
988         /* Hook our functions to this type */
989         gobject_class->set_property = tilda_terminal_set_property;
990         gobject_class->get_property = tilda_terminal_get_property;
991         gobject_class->dispose = tilda_terminal_dispose;
992         gobject_class->finalize = tilda_terminal_finalize;
993         gobject_class->constructor = tilda_terminal_constructor;
994
995         parent_class = g_type_class_peek_parent (klass);
996
997         /* Hook the TildaTerminal type into DBus */
998         dbus_g_object_type_install_info (tilda_terminal_get_type(), &dbus_glib_tilda_terminal_object_info);
999
1000         /* Install all of the properties */
1001         pspec = g_param_spec_int ("number",
1002                                                           _("Terminal number"),
1003                                                           NULL,
1004                                                           0,            // min value
1005                                                           INT_MAX,      // max value
1006                                                           0,            // def value
1007                                                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1008
1009         g_object_class_install_property (gobject_class,
1010                                                                          TILDA_TERMINAL_NUMBER,
1011                                                                          pspec);
1012
1013         pspec = g_param_spec_pointer ("parent-window",
1014                                                                   _("Pointer to terminal's parent TildaWindow"),
1015                                                                   NULL,
1016                                                                   G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1017
1018         g_object_class_install_property (gobject_class,
1019                                                                          TILDA_TERMINAL_PARENT_WINDOW,
1020                                                                          pspec);
1021
1022         pspec = g_param_spec_string ("background-image",
1023                                                                  _("Terminal's background image"),
1024                                                                  NULL,
1025                                                                  NULL,
1026                                                                  G_PARAM_READWRITE);
1027
1028         g_object_class_install_property (gobject_class,
1029                                                                          TILDA_TERMINAL_BACKGROUND_IMAGE,
1030                                                                          pspec);
1031
1032         pspec = g_param_spec_string ("shell",
1033                                                                  _("Terminal's shell"),
1034                                                                  NULL,
1035                                                                  NULL,
1036                                                                  G_PARAM_READWRITE);
1037
1038         g_object_class_install_property (gobject_class,
1039                                                                          TILDA_TERMINAL_SHELL,
1040                                                                          pspec);
1041
1042         pspec = g_param_spec_string ("font",
1043                                                                  _("Terminal's font"),
1044                                                                  NULL,
1045                                                                  NULL,
1046                                                                  G_PARAM_READWRITE);
1047
1048         g_object_class_install_property (gobject_class,
1049                                                                          TILDA_TERMINAL_FONT,
1050                                                                          pspec);
1051
1052         pspec = g_param_spec_string ("title",
1053                                                                  _("Terminal's title"),
1054                                                                  NULL,
1055                                                                  NULL,
1056                                                                  G_PARAM_READWRITE);
1057
1058         g_object_class_install_property (gobject_class,
1059                                                                          TILDA_TERMINAL_TITLE,
1060                                                                          pspec);
1061
1062         pspec = g_param_spec_string ("working-directory",
1063                                                                  _("Terminal's initial working directory"),
1064                                                                  NULL,
1065                                                                  NULL,
1066                                                                  G_PARAM_READWRITE);
1067
1068         g_object_class_install_property (gobject_class,
1069                                                                          TILDA_TERMINAL_WORKING_DIRECTORY,
1070                                                                          pspec);
1071
1072         pspec = g_param_spec_string ("web-browser",
1073                                                                  _("Terminal's web browser command"),
1074                                                                  NULL,
1075                                                                  NULL,
1076                                                                  G_PARAM_READWRITE);
1077
1078         g_object_class_install_property (gobject_class,
1079                                                                          TILDA_TERMINAL_WEB_BROWSER,
1080                                                                          pspec);
1081
1082         pspec = g_param_spec_int ("scrollback-lines",
1083                                                           _("Terminal's scrollback amount (lines)"),
1084                                                           NULL,
1085                                                           0,
1086                                                           INT_MAX, // TODO: artificially limit this?
1087                                                           1000,
1088                                                           G_PARAM_READWRITE);
1089
1090         g_object_class_install_property (gobject_class,
1091                                                                          TILDA_TERMINAL_SCROLLBACK_LINES,
1092                                                                          pspec);
1093
1094         pspec = g_param_spec_int ("transparency-percent",
1095                                                           _("Terminal's transparency (percent)"),
1096                                                           NULL,
1097                                                           0,
1098                                                           100,
1099                                                           0,
1100                                                           G_PARAM_READWRITE);
1101
1102         g_object_class_install_property (gobject_class,
1103                                                                          TILDA_TERMINAL_TRANSPARENCY_PERCENT,
1104                                                                          pspec);
1105
1106         pspec = g_param_spec_enum ("backspace-binding",
1107                                                            _("Terminal's backspace binding"),
1108                                                            NULL,
1109                                                            vte_terminal_erase_binding_get_type(),
1110                                                            VTE_ERASE_AUTO,
1111                                                            G_PARAM_READWRITE);
1112
1113         g_object_class_install_property (gobject_class,
1114                                                                          TILDA_TERMINAL_BACKSPACE_BINDING,
1115                                                                          pspec);
1116
1117         pspec = g_param_spec_enum ("delete-binding",
1118                                                            _("Terminal's delete binding"),
1119                                                            NULL,
1120                                                            vte_terminal_erase_binding_get_type(),
1121                                                            VTE_ERASE_AUTO,
1122                                                            G_PARAM_READWRITE);
1123
1124         g_object_class_install_property (gobject_class,
1125                                                                          TILDA_TERMINAL_DELETE_BINDING,
1126                                                                          pspec);
1127
1128         pspec = g_param_spec_enum ("dynamic-title",
1129                                                            _("Terminal's dynamic title generation method"),
1130                                                            NULL,
1131                                                            tilda_dynamic_title_get_type(),
1132                                                            TILDA_DYNAMIC_TITLE_DISABLED,
1133                                                            G_PARAM_READWRITE);
1134
1135         g_object_class_install_property (gobject_class,
1136                                                                          TILDA_TERMINAL_DYNAMIC_TITLE,
1137                                                                          pspec);
1138
1139         pspec = g_param_spec_enum ("exit-action",
1140                                                            _("Terminal's action upon child exit"),
1141                                                            NULL,
1142                                                            tilda_child_exit_action_get_type(),
1143                                                            TILDA_CHILD_EXIT_ACTION_EXIT,
1144                                                            G_PARAM_READWRITE);
1145
1146         g_object_class_install_property (gobject_class,
1147                                                                          TILDA_TERMINAL_EXIT_ACTION,
1148                                                                          pspec);
1149
1150         pspec = g_param_spec_enum ("scrollbar-position",
1151                                                            _("Terminal's scrollbar position"),
1152                                                            NULL,
1153                                                            tilda_scrollbar_position_get_type(),
1154                                                            TILDA_SCROLLBAR_RIGHT,
1155                                                            G_PARAM_READWRITE);
1156
1157         g_object_class_install_property (gobject_class,
1158                                                                          TILDA_TERMINAL_SCROLLBAR_POSITION,
1159                                                                          pspec);
1160
1161         pspec = g_param_spec_boolean ("scroll-background",
1162                                                                   _("Controls terminal's scrolling behavior"),
1163                                                                   NULL,
1164                                                                   FALSE,
1165                                                                   G_PARAM_READWRITE);
1166
1167         g_object_class_install_property (gobject_class,
1168                                                                          TILDA_TERMINAL_SCROLL_BACKGROUND,
1169                                                                          pspec);
1170
1171         pspec = g_param_spec_boolean ("scroll-on-output",
1172                                                                   _("Controls terminal's scrolling behavior on output"),
1173                                                                   NULL,
1174                                                                   FALSE,
1175                                                                   G_PARAM_READWRITE);
1176
1177         g_object_class_install_property (gobject_class,
1178                                                                          TILDA_TERMINAL_SCROLL_ON_OUTPUT,
1179                                                                          pspec);
1180
1181         pspec = g_param_spec_boolean ("scroll-on-keystroke",
1182                                                                   _("Controls the terminal's scrolling behavior on keystroke"),
1183                                                                   NULL, FALSE, G_PARAM_READWRITE);
1184
1185         g_object_class_install_property (gobject_class,
1186                                                                          TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
1187                                                                          pspec);
1188
1189         pspec = g_param_spec_boolean ("antialiased",
1190                                                                   _("Attempt to antialias fonts"),
1191                                                                   NULL, FALSE, G_PARAM_READWRITE);
1192
1193         g_object_class_install_property (gobject_class,
1194                                                                          TILDA_TERMINAL_ANTIALIASED,
1195                                                                          pspec);
1196
1197         pspec = g_param_spec_boolean ("allow-bold-text",
1198                                                                   _("Allow bold text"),
1199                                                                   NULL, FALSE, G_PARAM_READWRITE);
1200
1201         g_object_class_install_property (gobject_class,
1202                                                                          TILDA_TERMINAL_ALLOW_BOLD_TEXT,
1203                                                                          pspec);
1204
1205         pspec = g_param_spec_boolean ("cursor-blinks",
1206                                                                   _("Enable cursor blinking"),
1207                                                                   NULL, FALSE, G_PARAM_READWRITE);
1208
1209         g_object_class_install_property (gobject_class,
1210                                                                          TILDA_TERMINAL_CURSOR_BLINKS,
1211                                                                          pspec);
1212
1213         pspec = g_param_spec_boolean ("audible-bell",
1214                                                                   _("Enable the audible bell"),
1215                                                                   NULL, FALSE, G_PARAM_READWRITE);
1216
1217         g_object_class_install_property (gobject_class,
1218                                                                          TILDA_TERMINAL_AUDIBLE_BELL,
1219                                                                          pspec);
1220
1221         pspec = g_param_spec_boolean ("visible-bell",
1222                                                                   _("Enable the visible bell"),
1223                                                                   NULL, FALSE, G_PARAM_READWRITE);
1224
1225         g_object_class_install_property (gobject_class,
1226                                                                          TILDA_TERMINAL_VISIBLE_BELL,
1227                                                                          pspec);
1228
1229         pspec = g_param_spec_boolean ("double-buffered",
1230                                                                   _("Double buffer the terminal"),
1231                                                                   NULL, FALSE, G_PARAM_READWRITE);
1232
1233         g_object_class_install_property (gobject_class,
1234                                                                          TILDA_TERMINAL_DOUBLE_BUFFERED,
1235                                                                          pspec);
1236
1237         pspec = g_param_spec_boolean ("mouse-autohide",
1238                                                                   _("Hide the mouse cursor while typing"),
1239                                                                   NULL, FALSE, G_PARAM_READWRITE);
1240
1241         g_object_class_install_property (gobject_class,
1242                                                                          TILDA_TERMINAL_MOUSE_AUTOHIDE,
1243                                                                          pspec);
1244 }
1245
1246 GType
1247 tilda_terminal_get_type (void)
1248 {
1249         static GType type = 0;
1250
1251         if (type == 0)
1252         {
1253                 static const GTypeInfo info = {
1254                         sizeof (TildaTerminalClass),
1255                         NULL,   /* base_init */
1256                         NULL,   /* base_finalize */
1257                         tilda_terminal_class_init,      /* class_init */
1258                         NULL,   /* class_finalize */
1259                         NULL,   /* class_data */
1260                         sizeof (TildaTerminal),
1261                         0,              /* n_preallocs */
1262                         tilda_terminal_instance_init,   /* instance_init */
1263                 };
1264
1265                 type = g_type_register_static (G_TYPE_OBJECT,
1266                                                                            "TildaTerminalType",
1267                                                                            &info,
1268                                                                            0);
1269         }
1270
1271         return type;
1272 }
1273
1274 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */