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