f31e797e6f59ec361a187fd8cf838e43a251bf12
[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  * Set the scrollbar position of the given TildaTerminal to
283  * the value in self->scrollbar_position.
284  */
285 static void
286 tilda_terminal_set_scrollbar_position (TildaTerminal *self)
287 {
288         enum scrollbar_positions { DISABLED, LEFT, RIGHT };
289         switch (self->scrollbar_position)
290         {
291                 case LEFT:
292                         gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 0);
293                         gtk_widget_show (self->scrollbar);
294                         break;
295
296                 case RIGHT:
297                         gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 1);
298                         gtk_widget_show (self->scrollbar);
299                         break;
300
301                 case DISABLED:
302                 default:
303                         gtk_widget_hide (self->scrollbar);
304                         break;
305         }
306 }
307
308 /*******************************************************************************
309  * All GObject stuff is below. You probably don't need to change this...
310  ******************************************************************************/
311
312 static GObjectClass *parent_class = NULL;
313
314 enum tilda_terminal_properties {
315         TILDA_TERMINAL_NUMBER = 1,
316         TILDA_TERMINAL_WINDOW_NUMBER,
317         TILDA_TERMINAL_TW,
318
319         /* All non-constructor-only properties */
320         TILDA_TERMINAL_BACKGROUND_IMAGE,
321         TILDA_TERMINAL_SHELL,
322         TILDA_TERMINAL_FONT,
323         TILDA_TERMINAL_TITLE,
324         TILDA_TERMINAL_WORKING_DIRECTORY,
325         TILDA_TERMINAL_WEB_BROWSER,
326
327         TILDA_TERMINAL_SCROLLBACK_LINES,
328         TILDA_TERMINAL_TRANSPARENCY_PERCENT,
329
330         TILDA_TERMINAL_BACKSPACE_BINDING,
331         TILDA_TERMINAL_DELETE_BINDING,
332         TILDA_TERMINAL_DYNAMIC_TITLE,
333         TILDA_TERMINAL_EXIT_ACTION,
334         TILDA_TERMINAL_SCROLLBAR_POSITION,
335
336         TILDA_TERMINAL_SCROLL_BACKGROUND,
337         TILDA_TERMINAL_SCROLL_ON_OUTPUT,
338         TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
339         TILDA_TERMINAL_ANTIALIASED,
340         TILDA_TERMINAL_ALLOW_BOLD_TEXT,
341         TILDA_TERMINAL_CURSOR_BLINKS,
342         TILDA_TERMINAL_AUDIBLE_BELL,
343         TILDA_TERMINAL_VISIBLE_BELL,
344         TILDA_TERMINAL_DOUBLE_BUFFERED,
345         TILDA_TERMINAL_MOUSE_AUTOHIDE,
346 };
347
348 static void
349 tilda_terminal_instance_init (GTypeInstance *instance,
350                                                           gpointer       g_class)
351 {
352         TildaTerminal *self = (TildaTerminal *) instance;
353
354         /* Initialize instance members and allocate any necessary memory here.
355          * NOTE: any constructor-time values will be set later. */
356         self->dispose_has_run = FALSE;
357         self->number = 0;
358
359         self->vte_term = vte_terminal_new ();
360         self->scrollbar = gtk_vscrollbar_new (VTE_TERMINAL(self->vte_term)->adjustment);
361         self->hbox = gtk_hbox_new (FALSE, 0);
362 }
363
364 static void
365 tilda_terminal_set_property (GObject      *object,
366                                                          guint         property_id,
367                                                          const GValue *value,
368                                                          GParamSpec   *pspec)
369 {
370         TildaTerminal *self = (TildaTerminal *) object;
371
372         switch (property_id) {
373
374                 case TILDA_TERMINAL_NUMBER:
375                         self->number = g_value_get_int (value);
376                         g_print ("terminal number: %d\n", self->number);
377                         break;
378
379                 case TILDA_TERMINAL_WINDOW_NUMBER:
380                         self->window_number = g_value_get_int (value);
381                         g_print ("terminal parent window number: %d\n", self->window_number);
382                         break;
383
384                 case TILDA_TERMINAL_TW:
385                         self->parent_window = g_value_get_pointer (value);
386                         g_print ("terminal parent window: 0x%x\n", self->parent_window);
387                         g_print ("terminal parent window number (direct): %d\n", TILDA_WINDOW(self->parent_window)->number);
388                         break;
389
390                 case TILDA_TERMINAL_BACKGROUND_IMAGE:
391                         g_free (self->background_image);
392                         self->background_image = g_value_dup_string (value);
393                         vte_terminal_set_background_image_file (VTE_TERMINAL(self->vte_term), self->background_image);
394                         g_print ("terminal back img: %s\n", self->background_image);
395                         break;
396
397                 case TILDA_TERMINAL_SHELL:
398                         g_free (self->shell);
399                         self->shell = g_value_dup_string (value);
400                         tilda_terminal_start_shell (self);
401                         g_print ("terminal shell: %s\n", self->shell);
402                         break;
403
404                 case TILDA_TERMINAL_FONT:
405                         g_free (self->font);
406                         self->font = g_value_dup_string (value);
407                         vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
408                                                                                                         self->font,
409                                                                                                         self->antialiased);
410                         g_print ("terminal font: %s\n", self->font);
411                         break;
412
413                 case TILDA_TERMINAL_TITLE:
414                         g_free (self->title);
415                         self->title = g_value_dup_string (value);
416                         g_print ("terminal title: %s\n", self->title);
417                         break;
418
419                 case TILDA_TERMINAL_WORKING_DIRECTORY:
420                         g_free (self->working_directory);
421                         self->working_directory = g_value_dup_string (value);
422                         g_print ("terminal wrk dir: %s\n", self->working_directory);
423                         break;
424
425                 case TILDA_TERMINAL_WEB_BROWSER:
426                         g_free (self->web_browser);
427                         self->web_browser = g_value_dup_string (value);
428                         g_print ("terminal web browser: %s\n", self->web_browser);
429                         break;
430
431                 case TILDA_TERMINAL_SCROLLBACK_LINES:
432                         self->scrollback_lines = g_value_get_int (value);
433                         vte_terminal_set_scrollback_lines (VTE_TERMINAL(self->vte_term), self->scrollback_lines);
434                         g_print ("terminal scrollback lines: %d\n", self->scrollback_lines);
435                         break;
436
437                 case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
438                         self->transparency_percent = g_value_get_int (value);
439                         tilda_terminal_set_transparent (self);
440                         g_print ("terminal transp percent: %d\n", self->transparency_percent);
441                         break;
442
443                 case TILDA_TERMINAL_BACKSPACE_BINDING:
444                         self->backspace_binding = g_value_get_int (value);
445                         vte_terminal_set_backspace_binding (VTE_TERMINAL(self->vte_term), self->backspace_binding);
446                         g_print ("terminal backspace key: %d\n", self->backspace_binding);
447                         break;
448
449                 case TILDA_TERMINAL_DELETE_BINDING:
450                         self->delete_binding = g_value_get_int (value);
451                         vte_terminal_set_delete_binding (VTE_TERMINAL(self->vte_term), self->delete_binding);
452                         g_print ("terminal delete key: %d\n", self->delete_binding);
453                         break;
454
455                 case TILDA_TERMINAL_DYNAMIC_TITLE:
456                         self->dynamic_title = g_value_get_int (value);
457                         g_print ("terminal dynamic title: %d\n", self->dynamic_title);
458                         break;
459
460                 case TILDA_TERMINAL_EXIT_ACTION:
461                         self->exit_action = g_value_get_int (value);
462                         g_print ("terminal exit action: %d\n", self->exit_action);
463                         break;
464
465                 case TILDA_TERMINAL_SCROLLBAR_POSITION:
466                         self->scrollbar_position = g_value_get_int (value);
467                         tilda_terminal_set_scrollbar_position (self);
468                         g_print ("terminal scrollbar position: %d\n", self->scrollbar_position);
469                         break;
470
471                 case TILDA_TERMINAL_SCROLL_BACKGROUND:
472                         self->scroll_background = g_value_get_boolean (value);
473                         vte_terminal_set_scroll_background (VTE_TERMINAL(self->vte_term), self->scroll_background);
474                         g_print ("terminal scroll background: %d\n", self->scroll_background);
475                         break;
476
477                 case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
478                         self->scroll_on_output = g_value_get_boolean (value);
479                         vte_terminal_set_scroll_on_output (VTE_TERMINAL(self->vte_term), self->scroll_on_output);
480                         g_print ("terminal scroll on output: %d\n", self->scroll_on_output);
481                         break;
482
483                 case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
484                         self->scroll_on_keystroke = g_value_get_boolean (value);
485                         vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL(self->vte_term), self->scroll_on_keystroke);
486                         g_print ("terminal scroll on keystroke: %d\n", self->scroll_on_keystroke);
487                         break;
488
489                 case TILDA_TERMINAL_ANTIALIASED:
490                         self->antialiased = g_value_get_boolean (value);
491                         vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
492                                                                                                         self->font,
493                                                                                                         self->antialiased);
494                         g_print ("terminal antialiased: %d\n", self->antialiased);
495                         break;
496
497                 case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
498                         self->allow_bold_text = g_value_get_boolean (value);
499                         vte_terminal_set_allow_bold (VTE_TERMINAL(self->vte_term), self->allow_bold_text);
500                         g_print ("terminal allow bold text: %d\n", self->allow_bold_text);
501                         break;
502
503                 case TILDA_TERMINAL_CURSOR_BLINKS:
504                         self->cursor_blinks = g_value_get_boolean (value);
505                         vte_terminal_set_cursor_blinks (VTE_TERMINAL(self->vte_term), self->cursor_blinks);
506                         g_print ("terminal cursor blinks: %d\n", self->cursor_blinks);
507                         break;
508
509                 case TILDA_TERMINAL_AUDIBLE_BELL:
510                         self->audible_bell = g_value_get_boolean (value);
511                         vte_terminal_set_audible_bell (VTE_TERMINAL(self->vte_term), self->audible_bell);
512                         g_print ("terminal audible bell: %d\n", self->audible_bell);
513                         break;
514
515                 case TILDA_TERMINAL_VISIBLE_BELL:
516                         self->visible_bell = g_value_get_boolean (value);
517                         vte_terminal_set_visible_bell (VTE_TERMINAL(self->vte_term), self->visible_bell);
518                         g_print ("terminal visible bell: %d\n", self->visible_bell);
519                         break;
520
521                 case TILDA_TERMINAL_DOUBLE_BUFFERED:
522                         self->double_buffered = g_value_get_boolean (value);
523                         gtk_widget_set_double_buffered (GTK_WIDGET(self->vte_term), self->double_buffered);
524                         g_print ("terminal double buffered: %d\n", self->double_buffered);
525                         break;
526
527                 case TILDA_TERMINAL_MOUSE_AUTOHIDE:
528                         self->mouse_autohide = g_value_get_boolean (value);
529                         vte_terminal_set_mouse_autohide (VTE_TERMINAL(self->vte_term), self->mouse_autohide);
530                         g_print ("terminal mouse autohide: %d\n", self->mouse_autohide);
531                         break;
532
533                 default:
534                         /* We don't have this property... */
535                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
536                         break;
537         }
538 }
539
540 static void
541 tilda_terminal_get_property (GObject    *object,
542                                                          guint       property_id,
543                                                          GValue     *value,
544                                                          GParamSpec *pspec)
545 {
546         TildaTerminal *self = (TildaTerminal *) object;
547
548         switch (property_id) {
549
550                 case TILDA_TERMINAL_NUMBER:
551                         g_value_set_int (value, self->number);
552                         break;
553
554                 case TILDA_TERMINAL_WINDOW_NUMBER:
555                         g_value_set_int (value, self->window_number);
556                         break;
557
558                 case TILDA_TERMINAL_TW:
559                         g_value_set_pointer (value, self->parent_window);
560                         break;
561
562                 case TILDA_TERMINAL_BACKGROUND_IMAGE:
563                         g_value_set_string (value, self->background_image);
564                         break;
565
566                 case TILDA_TERMINAL_SHELL:
567                         g_value_set_string (value, self->shell);
568                         break;
569
570                 case TILDA_TERMINAL_FONT:
571                         g_value_set_string (value, self->font);
572                         break;
573
574                 case TILDA_TERMINAL_TITLE:
575                         g_value_set_string (value, self->title);
576                         break;
577
578                 case TILDA_TERMINAL_WORKING_DIRECTORY:
579                         g_value_set_string (value, self->working_directory);
580                         break;
581
582                 case TILDA_TERMINAL_WEB_BROWSER:
583                         g_value_set_string (value, self->web_browser);
584                         break;
585
586                 case TILDA_TERMINAL_SCROLLBACK_LINES:
587                         g_value_set_int (value, self->scrollback_lines);
588                         break;
589
590                 case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
591                         g_value_set_int (value, self->transparency_percent);
592                         break;
593
594                 case TILDA_TERMINAL_BACKSPACE_BINDING:
595                         g_value_set_int (value, self->backspace_binding);
596                         break;
597
598                 case TILDA_TERMINAL_DELETE_BINDING:
599                         g_value_set_int (value, self->delete_binding);
600                         break;
601
602                 case TILDA_TERMINAL_DYNAMIC_TITLE:
603                         g_value_set_int (value, self->dynamic_title);
604                         break;
605
606                 case TILDA_TERMINAL_EXIT_ACTION:
607                         g_value_set_int (value, self->exit_action);
608                         break;
609
610                 case TILDA_TERMINAL_SCROLLBAR_POSITION:
611                         g_value_set_int (value, self->scrollbar_position);
612                         break;
613
614                 case TILDA_TERMINAL_SCROLL_BACKGROUND:
615                         g_value_set_boolean (value, self->scroll_background);
616                         break;
617
618                 case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
619                         g_value_set_boolean (value, self->scroll_on_output);
620                         break;
621
622                 case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
623                         g_value_set_boolean (value, self->scroll_on_keystroke);
624                         break;
625
626                 case TILDA_TERMINAL_ANTIALIASED:
627                         g_value_set_boolean (value, self->antialiased);
628                         break;
629
630                 case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
631                         g_value_set_boolean (value, self->allow_bold_text);
632                         break;
633
634                 case TILDA_TERMINAL_CURSOR_BLINKS:
635                         g_value_set_boolean (value, self->cursor_blinks);
636                         break;
637
638                 case TILDA_TERMINAL_AUDIBLE_BELL:
639                         g_value_set_boolean (value, self->audible_bell);
640                         break;
641
642                 case TILDA_TERMINAL_VISIBLE_BELL:
643                         g_value_set_boolean (value, self->visible_bell);
644                         break;
645
646                 case TILDA_TERMINAL_DOUBLE_BUFFERED:
647                         g_value_set_boolean (value, self->double_buffered);
648                         break;
649
650                 case TILDA_TERMINAL_MOUSE_AUTOHIDE:
651                         g_value_set_boolean (value, self->mouse_autohide);
652
653                 default:
654                         /* We don't have this property... */
655                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
656                         break;
657         }
658 }
659
660 static GObject *
661 tilda_terminal_constructor (GType                  type,
662                                                         guint                  n_construct_properties,
663                                                         GObjectConstructParam *construct_properties)
664 {
665         GObject *obj;
666         TildaTerminal *self;
667         gint ret;
668
669         /* Invoke parent constructor */
670         TildaTerminalClass *klass;
671         klass = TILDA_TERMINAL_CLASS (g_type_class_peek (TILDA_TYPE_TERMINAL));
672         obj = parent_class->constructor (type,
673                                                                          n_construct_properties,
674                                                                          construct_properties);
675
676         /* Do other stuff here. The object is ready to go now, and all
677          * ctor properties have been set.
678          *
679          * TODO: This is the place to do DBus-init */
680         self = TILDA_TERMINAL(obj);
681
682         /* Pack into the hbox */
683         gtk_box_pack_end (GTK_BOX(self->hbox), self->scrollbar, FALSE, FALSE, 0);
684         gtk_box_pack_end (GTK_BOX(self->hbox), self->vte_term, TRUE, TRUE, 0);
685         gtk_widget_show (self->scrollbar);
686         gtk_widget_show (self->vte_term);
687         gtk_widget_show (self->hbox);
688
689         /* Match URL's, etc */
690         ret = vte_terminal_match_add (VTE_TERMINAL(self->vte_term), DINGUS1);
691         vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
692         ret = vte_terminal_match_add(VTE_TERMINAL(self->vte_term), DINGUS2);
693         vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
694
695         /* Connect Signals */
696         g_signal_connect (G_OBJECT(self->vte_term), "child-exited",
697                                           G_CALLBACK(tilda_terminal_child_exited_cb), self);
698         g_signal_connect (G_OBJECT(self->vte_term), "eof",
699                                           G_CALLBACK(tilda_terminal_child_exited_cb), self);
700         g_signal_connect (G_OBJECT(self->vte_term), "window-title-changed",
701                                           G_CALLBACK(tilda_terminal_window_title_changed_cb), self);
702         g_signal_connect (G_OBJECT(self->vte_term), "button-press-event",
703                                           G_CALLBACK(tilda_terminal_button_press_cb), self);
704
705         tilda_terminal_start_shell (self);
706         tilda_terminal_dbus_register_object (self);
707
708         return obj;
709 }
710
711 static void
712 tilda_terminal_dispose (GObject *obj)
713 {
714         TildaTerminal *self = (TildaTerminal *) obj;
715
716         /* We don't want to run dispose twice, so just return immediately */
717         if (self->dispose_has_run)
718                 return;
719
720         self->dispose_has_run = TRUE;
721
722         /*
723          * In dispose, you are supposed to free all types referenced from this
724          * object which might themselves hold a reference to self. Generally,
725          * the most simple solution is to unref all members on which you own a
726          * reference.
727          */
728
729         /* Chain up to the parent class */
730         G_OBJECT_CLASS (parent_class)->dispose (obj);
731 }
732
733 static void
734 tilda_terminal_finalize (GObject *obj)
735 {
736         TildaTerminal *self = (TildaTerminal *) obj;
737
738         /*
739          * Here, complete object destruction.
740          * You might not need to do much...
741          */
742
743         // TODO: g_free() any primitives here
744         g_free (self->background_image);
745         g_free (self->shell);
746         g_free (self->font);
747         g_free (self->title);
748         g_free (self->working_directory);
749
750
751         /* Chain up to the parent class */
752         G_OBJECT_CLASS (parent_class)->finalize (obj);
753 }
754
755 static void
756 tilda_terminal_class_init (gpointer g_class,
757                                                    gpointer g_class_data)
758 {
759         GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
760         TildaTerminalClass *klass = TILDA_TERMINAL_CLASS (g_class);
761         GParamSpec *pspec;
762
763         /* Hook our functions to this type */
764         gobject_class->set_property = tilda_terminal_set_property;
765         gobject_class->get_property = tilda_terminal_get_property;
766         gobject_class->dispose = tilda_terminal_dispose;
767         gobject_class->finalize = tilda_terminal_finalize;
768         gobject_class->constructor = tilda_terminal_constructor;
769
770         parent_class = g_type_class_peek_parent (klass);
771
772         /* Hook the TildaTerminal type into DBus */
773         dbus_g_object_type_install_info (tilda_terminal_get_type(), &dbus_glib_tilda_terminal_object_info);
774
775         /* Install all of the properties */
776         pspec = g_param_spec_int ("number",
777                                                           "Terminal number",
778                                                           "Set terminal's number",
779                                                           0,            // min value
780                                                           INT_MAX,      // max value
781                                                           0,            // def value
782                                                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
783
784         g_object_class_install_property (gobject_class,
785                                                                          TILDA_TERMINAL_NUMBER,
786                                                                          pspec);
787
788         pspec = g_param_spec_int ("window-number",
789                                                           "Number of the window to which this terminal belongs",
790                                                           "Set the number of the parent window",
791                                                           0,
792                                                           INT_MAX,
793                                                           0x0000beef,
794                                                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
795
796         g_object_class_install_property (gobject_class,
797                                                                          TILDA_TERMINAL_WINDOW_NUMBER,
798                                                                          pspec);
799
800         pspec = g_param_spec_pointer ("parent-window",
801                                                                   "Pointer to terminal's parent TildaWindow",
802                                                                   "Set the pointer to the terminal's parent TildaWindow",
803                                                                   G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
804
805         g_object_class_install_property (gobject_class,
806                                                                          TILDA_TERMINAL_TW,
807                                                                          pspec);
808
809         pspec = g_param_spec_string ("background-image",
810                                                                  "Terminal's background image",
811                                                                  "Get/Set terminal's background image",
812                                                                  NULL,
813                                                                  G_PARAM_READWRITE);
814
815         g_object_class_install_property (gobject_class,
816                                                                          TILDA_TERMINAL_BACKGROUND_IMAGE,
817                                                                          pspec);
818
819         pspec = g_param_spec_string ("shell",
820                                                                  "Terminal's shell",
821                                                                  "Get/Set terminal's shell",
822                                                                  NULL,
823                                                                  G_PARAM_READWRITE);
824
825         g_object_class_install_property (gobject_class,
826                                                                          TILDA_TERMINAL_SHELL,
827                                                                          pspec);
828
829         pspec = g_param_spec_string ("font",
830                                                                  "Terminal's font",
831                                                                  "Get/Set terminal's font",
832                                                                  NULL,
833                                                                  G_PARAM_READWRITE);
834
835         g_object_class_install_property (gobject_class,
836                                                                          TILDA_TERMINAL_FONT,
837                                                                          pspec);
838
839         pspec = g_param_spec_string ("title",
840                                                                  "Terminal's title",
841                                                                  "Get/Set terminal's title",
842                                                                  NULL,
843                                                                  G_PARAM_READWRITE);
844
845         g_object_class_install_property (gobject_class,
846                                                                          TILDA_TERMINAL_TITLE,
847                                                                          pspec);
848
849         pspec = g_param_spec_string ("working-directory",
850                                                                  "Terminal's initial working directory",
851                                                                  "Get/Set terminal's initial working directory",
852                                                                  NULL,
853                                                                  G_PARAM_READWRITE);
854
855         g_object_class_install_property (gobject_class,
856                                                                          TILDA_TERMINAL_WORKING_DIRECTORY,
857                                                                          pspec);
858
859         pspec = g_param_spec_string ("web-browser",
860                                                                  "Terminal's web browser command",
861                                                                  NULL,
862                                                                  NULL,
863                                                                  G_PARAM_READWRITE);
864
865         g_object_class_install_property (gobject_class,
866                                                                          TILDA_TERMINAL_WEB_BROWSER,
867                                                                          pspec);
868
869         pspec = g_param_spec_int ("scrollback-lines",
870                                                           "Terminal's scrollback amount (lines)",
871                                                           "Get/Set terminal's scrollback amount",
872                                                           0,
873                                                           INT_MAX, // TODO: artificially limit this?
874                                                           1000,
875                                                           G_PARAM_READWRITE);
876
877         g_object_class_install_property (gobject_class,
878                                                                          TILDA_TERMINAL_SCROLLBACK_LINES,
879                                                                          pspec);
880
881         pspec = g_param_spec_int ("transparency-percent",
882                                                           "Terminal's transparency (percent)",
883                                                           "Get/Set terminal's transparency",
884                                                           0,
885                                                           100,
886                                                           0,
887                                                           G_PARAM_READWRITE);
888
889         g_object_class_install_property (gobject_class,
890                                                                          TILDA_TERMINAL_TRANSPARENCY_PERCENT,
891                                                                          pspec);
892
893         pspec = g_param_spec_int ("backspace-binding",
894                                                           "Terminal's backspace binding",
895                                                           "Get/Set terminal's backspace key binding",
896                                                           VTE_ERASE_AUTO,
897                                                           VTE_ERASE_DELETE_SEQUENCE,
898                                                           VTE_ERASE_AUTO,
899                                                           G_PARAM_READWRITE);
900
901         g_object_class_install_property (gobject_class,
902                                                                          TILDA_TERMINAL_BACKSPACE_BINDING,
903                                                                          pspec);
904
905         pspec = g_param_spec_int ("delete-binding",
906                                                           "Terminal's delete binding",
907                                                           "Get/Set terminal's delete key binding",
908                                                           VTE_ERASE_AUTO,
909                                                           VTE_ERASE_DELETE_SEQUENCE,
910                                                           VTE_ERASE_AUTO,
911                                                           G_PARAM_READWRITE);
912
913         g_object_class_install_property (gobject_class,
914                                                                          TILDA_TERMINAL_DELETE_BINDING,
915                                                                          pspec);
916
917         pspec = g_param_spec_int ("dynamic-title",
918                                                           "Terminal's dynamic title generation method",
919                                                           "Get/Set terminal's dynamic title generation method",
920                                                           0,
921                                                           INT_MAX,
922                                                           0,
923                                                           G_PARAM_READWRITE);
924
925         g_object_class_install_property (gobject_class,
926                                                                          TILDA_TERMINAL_DYNAMIC_TITLE,
927                                                                          pspec);
928
929         pspec = g_param_spec_int ("exit-action",
930                                                           "Terminal's action upon child exit",
931                                                           "Get/Set terminal's action upon child exit",
932                                                           0,
933                                                           INT_MAX,
934                                                           0,
935                                                           G_PARAM_READWRITE);
936
937         g_object_class_install_property (gobject_class,
938                                                                          TILDA_TERMINAL_EXIT_ACTION,
939                                                                          pspec);
940
941         pspec = g_param_spec_int ("scrollbar-position",
942                                                           "Terminal's scrollbar position",
943                                                           NULL,
944                                                           0,
945                                                           INT_MAX,
946                                                           0,
947                                                           G_PARAM_READWRITE);
948
949         g_object_class_install_property (gobject_class,
950                                                                          TILDA_TERMINAL_SCROLLBAR_POSITION,
951                                                                          pspec);
952
953         pspec = g_param_spec_boolean ("scroll-background",
954                                                                   "Controls terminal's scrolling behavior",
955                                                                   "Get/Set terminal's scrolling behavior",
956                                                                   FALSE,
957                                                                   G_PARAM_READWRITE);
958
959         g_object_class_install_property (gobject_class,
960                                                                          TILDA_TERMINAL_SCROLL_BACKGROUND,
961                                                                          pspec);
962
963         pspec = g_param_spec_boolean ("scroll-on-output",
964                                                                   "Controls terminal's scrolling behavior on output",
965                                                                   "Get/Set terminal's scrolling behavior on output",
966                                                                   FALSE,
967                                                                   G_PARAM_READWRITE);
968
969         g_object_class_install_property (gobject_class,
970                                                                          TILDA_TERMINAL_SCROLL_ON_OUTPUT,
971                                                                          pspec);
972
973         pspec = g_param_spec_boolean ("scroll-on-keystroke",
974                                                                   "Controls the terminal's scrolling behavior on keystroke",
975                                                                   NULL, FALSE, G_PARAM_READWRITE);
976
977         g_object_class_install_property (gobject_class,
978                                                                          TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
979                                                                          pspec);
980
981         pspec = g_param_spec_boolean ("antialiased",
982                                                                   "Attempt to antialias fonts",
983                                                                   NULL, FALSE, G_PARAM_READWRITE);
984
985         g_object_class_install_property (gobject_class,
986                                                                          TILDA_TERMINAL_ANTIALIASED,
987                                                                          pspec);
988
989         pspec = g_param_spec_boolean ("allow-bold-text",
990                                                                   "Allow bold text",
991                                                                   NULL, FALSE, G_PARAM_READWRITE);
992
993         g_object_class_install_property (gobject_class,
994                                                                          TILDA_TERMINAL_ALLOW_BOLD_TEXT,
995                                                                          pspec);
996
997         pspec = g_param_spec_boolean ("cursor-blinks",
998                                                                   NULL, NULL, FALSE, G_PARAM_READWRITE);
999
1000         g_object_class_install_property (gobject_class,
1001                                                                          TILDA_TERMINAL_CURSOR_BLINKS,
1002                                                                          pspec);
1003
1004         pspec = g_param_spec_boolean ("audible-bell",
1005                                                                   NULL, NULL, FALSE, G_PARAM_READWRITE);
1006
1007         g_object_class_install_property (gobject_class,
1008                                                                          TILDA_TERMINAL_AUDIBLE_BELL,
1009                                                                          pspec);
1010
1011         pspec = g_param_spec_boolean ("visible-bell",
1012                                                                   NULL, NULL, FALSE, G_PARAM_READWRITE);
1013
1014         g_object_class_install_property (gobject_class,
1015                                                                          TILDA_TERMINAL_VISIBLE_BELL,
1016                                                                          pspec);
1017
1018         pspec = g_param_spec_boolean ("double-buffered",
1019                                                                   NULL, NULL, FALSE, G_PARAM_READWRITE);
1020
1021         g_object_class_install_property (gobject_class,
1022                                                                          TILDA_TERMINAL_DOUBLE_BUFFERED,
1023                                                                          pspec);
1024
1025         pspec = g_param_spec_boolean ("mouse-autohide",
1026                                                                   NULL, NULL, FALSE, G_PARAM_READWRITE);
1027
1028         g_object_class_install_property (gobject_class,
1029                                                                          TILDA_TERMINAL_MOUSE_AUTOHIDE,
1030                                                                          pspec);
1031 }
1032
1033 GType
1034 tilda_terminal_get_type (void)
1035 {
1036         static GType type = 0;
1037
1038         if (type == 0)
1039         {
1040                 static const GTypeInfo info = {
1041                         sizeof (TildaTerminalClass),
1042                         NULL,   /* base_init */
1043                         NULL,   /* base_finalize */
1044                         tilda_terminal_class_init,      /* class_init */
1045                         NULL,   /* class_finalize */
1046                         NULL,   /* class_data */
1047                         sizeof (TildaTerminal),
1048                         0,              /* n_preallocs */
1049                         tilda_terminal_instance_init,   /* instance_init */
1050                 };
1051
1052                 type = g_type_register_static (G_TYPE_OBJECT,
1053                                                                            "TildaTerminalType",
1054                                                                            &info,
1055                                                                            0);
1056         }
1057
1058         return type;
1059 }
1060
1061 #if 0
1062
1063 int main (int argc, char *argv[])
1064 {
1065         GObject *tt;
1066         gint test_number = INT_MIN;
1067         gchar *test_string = NULL;
1068
1069         /* Initialize the GObject type system */
1070         g_type_init ();
1071         gtk_init (&argc, &argv);
1072
1073         tt = g_object_new (TILDA_TYPE_TERMINAL, "number", 10, NULL);
1074         g_object_get (G_OBJECT (tt), "number", &test_number, NULL);
1075         g_assert (test_number == 10);
1076
1077         g_object_unref (G_OBJECT (tt));
1078
1079         tt = g_object_new (TILDA_TYPE_TERMINAL, "number", 22, NULL);
1080         g_object_get (G_OBJECT (tt), "number", &test_number, NULL);
1081         g_assert (test_number == 22);
1082
1083         g_object_set (G_OBJECT (tt), "font", "hello I'm a font");
1084         g_object_set (G_OBJECT (tt), "font", "Bitstream Vera Sans Mono 13");
1085
1086         g_object_get (G_OBJECT (tt), "font", &test_string, NULL);
1087         g_print ("Read Font: %s\n", test_string);
1088         // NOTE: you MUST free the string!!!!
1089         g_free (test_string);
1090
1091         g_object_set (G_OBJECT (tt), "transparency-percent", 50);
1092
1093         g_object_unref (G_OBJECT (tt));
1094
1095         return 0;
1096 }
1097
1098 #endif
1099
1100 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */