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