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