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