+static void
+tilda_terminal_dbus_register_object (TildaTerminal *tt)
+{
+ debug_enter ();
+ debug_assert (TILDA_IS_TERMINAL(tt));
+
+ TildaWindow *parent_window = TILDA_WINDOW(tt->parent_window);
+ gchar *object_path;
+
+ // Register this object with DBus
+ object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d/Terminal%d",
+ parent_window->number, tt->number);
+ dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(tt));
+ g_free (object_path);
+}
+
+gboolean
+tilda_terminal_run_command (TildaTerminal *self, gchar *command, GError **error)
+{
+ debug_enter ();
+ debug_assert (TILDA_IS_TERMINAL(self));
+
+ vte_terminal_feed_child (VTE_TERMINAL(self->vte_term), command, -1);
+ vte_terminal_feed_child (VTE_TERMINAL(self->vte_term), "\n", -1);
+
+ return TRUE;
+}
+
+gboolean
+tilda_terminal_close (TildaTerminal *self, GError **error)
+{
+ debug_enter ();
+ debug_assert (TILDA_IS_TERMINAL(self));
+
+ TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
+
+ tilda_window_remove_terminal (parent_window, self->number);
+
+ return TRUE;
+}
+
+/**
+ * Start the current tt->shell in the given TildaTerminal
+ * NOTE: this will kill whatever is running in the terminal,
+ * NOTE: and run the current tt->shell instead :)
+ * Return: TRUE if ok, FALSE otherwise
+ */
+static gboolean
+tilda_terminal_start_shell (TildaTerminal *tt)
+{
+ debug_enter ();
+ debug_assert (TILDA_IS_TERMINAL(tt));
+
+ gint ret;
+ gint argc;
+ gchar **argv;
+ GError *error = NULL;
+
+ /* Launch a custom command if tt->shell is set (not NULL) */
+ if (tt->shell)
+ {
+ /* Try to parse the user's custom command */
+ ret = g_shell_parse_argv (tt->shell, &argc, &argv, &error);
+
+ if (ret == FALSE)
+ {
+ g_printerr (_("Problem parsing custom command: %s\n"), error->message);
+ g_printerr (_("Launching default shell instead\n"));
+
+ g_error_free (error);
+ goto launch_default_shell;
+ }
+
+ /* Try to start the user's custom command */
+ ret = vte_terminal_fork_command (VTE_TERMINAL(tt->vte_term),
+ argv[0], /* Command */
+ argv, /* Arg Vector */
+ NULL, /* Env Vector */
+ tt->working_directory, /* Start directory */
+ TRUE, /* Add to lastlog */
+ TRUE, /* Add to utmp */
+ TRUE); /* Add to wtmp */
+
+ g_strfreev (argv);
+
+ /* Check for error */
+ if (ret == -1)
+ {
+ g_printerr (_("Unable to launch custom command: %s\n"), tt->shell);
+ g_printerr (_("Launching default shell instead\n"));
+
+ goto launch_default_shell;
+ }
+
+ return TRUE; /* SUCCESS: the early way out */
+ }
+
+launch_default_shell:
+
+ ret = vte_terminal_fork_command (VTE_TERMINAL(tt->vte_term),
+ NULL, /* Command -- VTE will figure it out */
+ NULL, /* Arg Vector */
+ NULL, /* Env Vector */
+ tt->working_directory, /* Start Directory */
+ TRUE, /* Add to lastlog */
+ TRUE, /* Add to utmp */
+ TRUE);/* Add to wtmp */
+
+ if (ret == -1)
+ {
+ g_printerr (_("Unable to launch default shell\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Called when the child process running in the VteTerminal exits.
+ */
+static void
+tilda_terminal_child_exited_cb (GtkWidget *widget, gpointer data)
+{
+ debug_enter ();
+ debug_assert (GTK_IS_WIDGET(widget));
+ debug_assert (TILDA_IS_TERMINAL(data));
+
+ TildaTerminal *self = TILDA_TERMINAL(data);
+
+ /* Check the user's preference for what to do when the child terminal
+ * is closed. Take the appropriate action */
+ switch (self->exit_action)
+ {
+ case TILDA_CHILD_EXIT_ACTION_EXIT:
+ tilda_window_remove_terminal (TILDA_WINDOW(self->parent_window), self->number);
+ break;
+ case TILDA_CHILD_EXIT_ACTION_RESTART:
+ vte_terminal_feed (VTE_TERMINAL(self->vte_term), "\r\n\r\n", 4);
+ tilda_terminal_start_shell (self);
+ break;
+ case TILDA_CHILD_EXIT_ACTION_HOLD_OPEN:
+ break;
+ default:
+ g_warning ("Bad value in self->exit_action\n");
+ break;
+ }
+}
+
+/**
+ * Called when the child window title changes. Determines if a new
+ * title needs to be put into the notebook's tab label.
+ */
+static void
+tilda_terminal_window_title_changed_cb (GtkWidget *widget, gpointer data)
+{
+ debug_enter ();
+ debug_assert (GTK_IS_WIDGET(widget));
+ debug_assert (TILDA_IS_TERMINAL(data));
+
+ TildaTerminal *self = TILDA_TERMINAL(data);
+ TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
+ GtkWidget *label;
+ const gchar *vte_title = NULL;
+ gchar *new_title = NULL;
+
+ vte_title = vte_terminal_get_window_title (VTE_TERMINAL (widget));
+ label = gtk_notebook_get_tab_label (GTK_NOTEBOOK(parent_window->notebook), self->hbox);
+
+ switch (self->dynamic_title)
+ {
+ case TILDA_DYNAMIC_TITLE_DISABLED:
+ new_title = g_strdup (self->title);
+ break;
+
+ case TILDA_DYNAMIC_TITLE_AFTER_INITIAL:
+ new_title = g_strdup_printf ("%s - %s", self->title, vte_title);
+ break;
+
+ case TILDA_DYNAMIC_TITLE_BEFORE_INITIAL:
+ new_title = g_strdup_printf ("%s - %s", vte_title, self->title);
+ break;
+
+ case TILDA_DYNAMIC_TITLE_REPLACE_INITIAL:
+ new_title = g_strdup (self->title);
+ break;
+
+ default:
+ g_warning ("Bad value in self->dynamic-title\n");
+ break;
+ }
+
+ gtk_label_set_text (GTK_LABEL(label), new_title);
+ g_free (new_title);
+}
+
+/**
+ * Gets called whenever there is a button-press event in the VteTerminal. It
+ * is used to open the user's web browser, for example.
+ */
+static gint
+tilda_terminal_button_press_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ debug_enter ();
+ debug_assert (GTK_IS_WIDGET(widget));
+ debug_assert (TILDA_IS_TERMINAL(data));
+ debug_printf ("event->button = %d\n", event->button);
+
+ GError *error = NULL;
+ TildaTerminal *self = TILDA_TERMINAL(data);
+ VteTerminal *terminal = VTE_TERMINAL(self->vte_term);
+ gint tag, xpad, ypad;
+ gchar *match, *cmd, *web_browser_cmd;
+ gboolean ret = FALSE;
+
+ switch (event->button)
+ {
+ case 3: /* Right Click */
+ // FIXME: need to add this
+ //popup_menu (tt->tw, tt);
+ g_print ("FIXME: popup_menu() here\n");
+ break;
+
+ case 2: /* Middle Click */
+ break;
+
+ case 1: /* Left Click */
+ vte_terminal_get_padding (terminal, &xpad, &ypad);
+ match = vte_terminal_match_check (terminal,
+ (event->x - ypad) / terminal->char_width,
+ (event->y - ypad) / terminal->char_height,
+ &tag);
+
+ /* Check if we can launch a web browser, and do so if possible */
+ if ((event->state & GDK_CONTROL_MASK) && match != NULL)
+ {
+ web_browser_cmd = g_strescape (self->web_browser, NULL);
+ cmd = g_strdup_printf ("%s %s", web_browser_cmd, match);
+
+ debug_printf ("Got a Ctrl+Left-Click -- match: '%s' tag: %d\n", match, tag);
+ debug_printf ("Launching command: '%s'\n", cmd);
+
+ ret = g_spawn_command_line_async(cmd, &error);
+
+ /* Check that the command launched */
+ if (!ret)
+ {
+ g_printerr (_("Failed to launch web browser command: `%s'\n"), cmd);
+ g_printerr (_("Error message: %s\n"), error->message);
+ }
+
+ /* Free allocated memory */
+ g_free (web_browser_cmd);
+ g_free (cmd);
+ }
+
+ /* Always free match if it is non NULL */
+ g_free (match);
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Set the given TildaTerminal to the appropriate transparency level
+ * based on the self->transparency_percent member. */
+static void
+tilda_terminal_set_transparent (TildaTerminal *self)
+{
+ debug_enter ();
+ debug_assert (TILDA_IS_TERMINAL(self));
+
+ TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
+ gdouble temp;
+
+ /* Convert the transparency to VTE's format */
+ temp = ((gdouble) self->transparency_percent) / 100.0;
+
+ if (self->transparency_percent > 0)
+ {
+ vte_terminal_set_background_saturation (VTE_TERMINAL(self->vte_term), temp);
+ vte_terminal_set_opacity (VTE_TERMINAL(self->vte_term), (1.0 - temp) * 0xffff);
+
+ /* Use fake transparency if necessary */
+ vte_terminal_set_background_transparent (VTE_TERMINAL(self->vte_term),
+ !parent_window->have_real_transparency);
+ return;
+ }
+
+ /* Turn off transparency */
+ vte_terminal_set_background_saturation (VTE_TERMINAL(self->vte_term), 0);
+ vte_terminal_set_opacity (VTE_TERMINAL(self->vte_term), 0xffff);
+ vte_terminal_set_background_transparent (VTE_TERMINAL(self->vte_term), FALSE);
+}
+
+/**
+ * Set the scrollbar position of the given TildaTerminal to
+ * the value in self->scrollbar_position.