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