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