Add debugging macros + use them
[tilda-gobject.git] / tilda-terminal.c
index 06a712b..38a353f 100644 (file)
+#include "tilda.h"
 #include "tilda-terminal.h"
+#include "tilda-terminal-dbus-glue.h"
 
-static GObjectClass *parent_class = NULL;
+// FIXME: temporary helpers for gettext
+// TODO:  remove these
+#define _(X) X
+#define N_(X) X
 
-/* API */
+#define DINGUS1 "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?"
+#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_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\) ,\\\"]"
 
-/*
- * All GObject stuff is below. You probably don't need to change this...
+
+static void
+tilda_terminal_dbus_register_object (TildaTerminal *tt)
+{
+       debug_enter  ();
+       debug_assert (TILDA_IS_TERMINAL(tt));
+
+       gchar *object_path;
+
+       // Register this object with DBus
+       object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d/Terminal%d",
+                                                                  tt->window_number, tt->number);
+       dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(tt));
+       g_free (object_path);
+}
+
+/**
+ * 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);
+
+       /* These can stay here. They don't need to go into a header because
+        * they are only used at this point in the code. */
+       enum exit_actions { HOLD_TERMINAL_OPEN, RESTART_COMMAND, EXIT_TERMINAL };
+
+       /* Check the user's preference for what to do when the child terminal
+        * is closed. Take the appropriate action */
+       switch (self->exit_action)
+       {
+               case EXIT_TERMINAL:
+                       tilda_window_remove_term (TILDA_WINDOW(self->parent_window), self->number);
+                       break;
+               case RESTART_COMMAND:
+                       vte_terminal_feed (VTE_TERMINAL(self->vte_term), "\r\n\r\n", 4);
+                       tilda_terminal_start_shell (self);
+                       break;
+               case HOLD_TERMINAL_OPEN:
+                       break;
+               default:
+                       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;
+       gchar *new_title;
+
+       enum dynamic_titles { NOT_DISPLAYED, AFTER_INITIAL, BEFORE_INITIAL, REPLACE_INITIAL };
+       label = gtk_notebook_get_tab_label (GTK_NOTEBOOK(parent_window->notebook), self->hbox);
+
+       /* If we aren't using a dynamic title -- NOT_DISPLAYED -- then just
+        * set it to the static title and exit */
+       if (!self->dynamic_title)
+       {
+               gtk_label_set_text (GTK_LABEL(label), self->title);
+               return;
+       }
+
+       /* Get the title from VTE */
+       vte_title = vte_terminal_get_window_title (VTE_TERMINAL (widget));
+
+       /* Take the appropriate action */
+       switch (self->dynamic_title)
+       {
+               case REPLACE_INITIAL:
+                       new_title = g_strdup (vte_title);
+                       break;
+
+               case BEFORE_INITIAL:
+                       new_title = g_strdup_printf ("%s - %s", vte_title, self->title);
+                       break;
+
+               case AFTER_INITIAL:
+                       new_title = g_strdup_printf ("%s - %s", self->title, vte_title);
+                       break;
+
+               default:
+                       debug_printf ("ERROR: Bad value of self->dynamic_title\n");
+               case NOT_DISPLAYED:
+                       new_title = g_strdup(self->title);
+                       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.
  */
+static void
+tilda_terminal_set_scrollbar_position (TildaTerminal *self)
+{
+       debug_enter  ();
+       debug_assert (TILDA_IS_TERMINAL(self));
+
+       enum scrollbar_positions { DISABLED, LEFT, RIGHT };
+       switch (self->scrollbar_position)
+       {
+               case LEFT:
+                       gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 0);
+                       gtk_widget_show (self->scrollbar);
+                       break;
+
+               case RIGHT:
+                       gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 1);
+                       gtk_widget_show (self->scrollbar);
+                       break;
+
+               default:
+                       debug_printf ("ERROR: Bad scrollbar position\n");
+               case DISABLED:
+                       gtk_widget_hide (self->scrollbar);
+                       break;
+       }
+}
+
+/*******************************************************************************
+ * All GObject stuff is below. You probably don't need to change this...
+ ******************************************************************************/
+
+static GObjectClass *parent_class = NULL;
 
 enum tilda_terminal_properties {
        TILDA_TERMINAL_NUMBER = 1,
-       // TODO: All properties
+       TILDA_TERMINAL_WINDOW_NUMBER,
+       TILDA_TERMINAL_TW,
+
+       /* All non-constructor-only properties */
+       TILDA_TERMINAL_BACKGROUND_IMAGE,
+       TILDA_TERMINAL_SHELL,
+       TILDA_TERMINAL_FONT,
+       TILDA_TERMINAL_TITLE,
+       TILDA_TERMINAL_WORKING_DIRECTORY,
+       TILDA_TERMINAL_WEB_BROWSER,
+
+       TILDA_TERMINAL_SCROLLBACK_LINES,
+       TILDA_TERMINAL_TRANSPARENCY_PERCENT,
+
+       TILDA_TERMINAL_BACKSPACE_BINDING,
+       TILDA_TERMINAL_DELETE_BINDING,
+       TILDA_TERMINAL_DYNAMIC_TITLE,
+       TILDA_TERMINAL_EXIT_ACTION,
+       TILDA_TERMINAL_SCROLLBAR_POSITION,
+
+       TILDA_TERMINAL_SCROLL_BACKGROUND,
+       TILDA_TERMINAL_SCROLL_ON_OUTPUT,
+       TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
+       TILDA_TERMINAL_ANTIALIASED,
+       TILDA_TERMINAL_ALLOW_BOLD_TEXT,
+       TILDA_TERMINAL_CURSOR_BLINKS,
+       TILDA_TERMINAL_AUDIBLE_BELL,
+       TILDA_TERMINAL_VISIBLE_BELL,
+       TILDA_TERMINAL_DOUBLE_BUFFERED,
+       TILDA_TERMINAL_MOUSE_AUTOHIDE,
 };
 
 static void
 tilda_terminal_instance_init (GTypeInstance *instance,
                                                          gpointer       g_class)
 {
+       debug_enter ();
+
        TildaTerminal *self = (TildaTerminal *) instance;
 
        /* Initialize instance members and allocate any necessary memory here.
         * NOTE: any constructor-time values will be set later. */
        self->dispose_has_run = FALSE;
        self->number = 0;
+
+       self->vte_term = vte_terminal_new ();
+       self->scrollbar = gtk_vscrollbar_new (VTE_TERMINAL(self->vte_term)->adjustment);
+       self->hbox = gtk_hbox_new (FALSE, 0);
 }
 
 static void
@@ -37,7 +399,160 @@ tilda_terminal_set_property (GObject      *object,
 
                case TILDA_TERMINAL_NUMBER:
                        self->number = g_value_get_int (value);
-                       g_print ("terminal number: %d\n", self->number);
+                       debug_printf ("terminal number: %d\n", self->number);
+                       break;
+
+               case TILDA_TERMINAL_WINDOW_NUMBER:
+                       self->window_number = g_value_get_int (value);
+                       debug_printf ("terminal parent window number: %d\n", self->window_number);
+                       break;
+
+               case TILDA_TERMINAL_TW:
+                       self->parent_window = g_value_get_pointer (value);
+                       debug_printf ("terminal parent window: 0x%x\n", self->parent_window);
+                       break;
+
+               case TILDA_TERMINAL_BACKGROUND_IMAGE:
+                       g_free (self->background_image);
+                       self->background_image = g_value_dup_string (value);
+                       vte_terminal_set_background_image_file (VTE_TERMINAL(self->vte_term), self->background_image);
+                       debug_printf ("terminal back img: %s\n", self->background_image);
+                       break;
+
+               case TILDA_TERMINAL_SHELL:
+                       g_free (self->shell);
+                       self->shell = g_value_dup_string (value);
+                       tilda_terminal_start_shell (self);
+                       debug_printf ("terminal shell: %s\n", self->shell);
+                       break;
+
+               case TILDA_TERMINAL_FONT:
+                       g_free (self->font);
+                       self->font = g_value_dup_string (value);
+                       vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
+                                                                                                       self->font,
+                                                                                                       self->antialiased);
+                       debug_printf ("terminal font: %s\n", self->font);
+                       break;
+
+               case TILDA_TERMINAL_TITLE:
+                       g_free (self->title);
+                       self->title = g_value_dup_string (value);
+                       debug_printf ("terminal title: %s\n", self->title);
+                       break;
+
+               case TILDA_TERMINAL_WORKING_DIRECTORY:
+                       g_free (self->working_directory);
+                       self->working_directory = g_value_dup_string (value);
+                       debug_printf ("terminal wrk dir: %s\n", self->working_directory);
+                       break;
+
+               case TILDA_TERMINAL_WEB_BROWSER:
+                       g_free (self->web_browser);
+                       self->web_browser = g_value_dup_string (value);
+                       debug_printf ("terminal web browser: %s\n", self->web_browser);
+                       break;
+
+               case TILDA_TERMINAL_SCROLLBACK_LINES:
+                       self->scrollback_lines = g_value_get_int (value);
+                       vte_terminal_set_scrollback_lines (VTE_TERMINAL(self->vte_term), self->scrollback_lines);
+                       debug_printf ("terminal scrollback lines: %d\n", self->scrollback_lines);
+                       break;
+
+               case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
+                       self->transparency_percent = g_value_get_int (value);
+                       tilda_terminal_set_transparent (self);
+                       debug_printf ("terminal transp percent: %d\n", self->transparency_percent);
+                       break;
+
+               case TILDA_TERMINAL_BACKSPACE_BINDING:
+                       self->backspace_binding = g_value_get_int (value);
+                       vte_terminal_set_backspace_binding (VTE_TERMINAL(self->vte_term), self->backspace_binding);
+                       debug_printf ("terminal backspace key: %d\n", self->backspace_binding);
+                       break;
+
+               case TILDA_TERMINAL_DELETE_BINDING:
+                       self->delete_binding = g_value_get_int (value);
+                       vte_terminal_set_delete_binding (VTE_TERMINAL(self->vte_term), self->delete_binding);
+                       debug_printf ("terminal delete key: %d\n", self->delete_binding);
+                       break;
+
+               case TILDA_TERMINAL_DYNAMIC_TITLE:
+                       self->dynamic_title = g_value_get_int (value);
+                       debug_printf ("terminal dynamic title: %d\n", self->dynamic_title);
+                       break;
+
+               case TILDA_TERMINAL_EXIT_ACTION:
+                       self->exit_action = g_value_get_int (value);
+                       debug_printf ("terminal exit action: %d\n", self->exit_action);
+                       break;
+
+               case TILDA_TERMINAL_SCROLLBAR_POSITION:
+                       self->scrollbar_position = g_value_get_int (value);
+                       tilda_terminal_set_scrollbar_position (self);
+                       debug_printf ("terminal scrollbar position: %d\n", self->scrollbar_position);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_BACKGROUND:
+                       self->scroll_background = g_value_get_boolean (value);
+                       vte_terminal_set_scroll_background (VTE_TERMINAL(self->vte_term), self->scroll_background);
+                       debug_printf ("terminal scroll background: %d\n", self->scroll_background);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
+                       self->scroll_on_output = g_value_get_boolean (value);
+                       vte_terminal_set_scroll_on_output (VTE_TERMINAL(self->vte_term), self->scroll_on_output);
+                       debug_printf ("terminal scroll on output: %d\n", self->scroll_on_output);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
+                       self->scroll_on_keystroke = g_value_get_boolean (value);
+                       vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL(self->vte_term), self->scroll_on_keystroke);
+                       debug_printf ("terminal scroll on keystroke: %d\n", self->scroll_on_keystroke);
+                       break;
+
+               case TILDA_TERMINAL_ANTIALIASED:
+                       self->antialiased = g_value_get_boolean (value);
+                       vte_terminal_set_font_from_string_full (VTE_TERMINAL(self->vte_term),
+                                                                                                       self->font,
+                                                                                                       self->antialiased);
+                       debug_printf ("terminal antialiased: %d\n", self->antialiased);
+                       break;
+
+               case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
+                       self->allow_bold_text = g_value_get_boolean (value);
+                       vte_terminal_set_allow_bold (VTE_TERMINAL(self->vte_term), self->allow_bold_text);
+                       debug_printf ("terminal allow bold text: %d\n", self->allow_bold_text);
+                       break;
+
+               case TILDA_TERMINAL_CURSOR_BLINKS:
+                       self->cursor_blinks = g_value_get_boolean (value);
+                       vte_terminal_set_cursor_blinks (VTE_TERMINAL(self->vte_term), self->cursor_blinks);
+                       debug_printf ("terminal cursor blinks: %d\n", self->cursor_blinks);
+                       break;
+
+               case TILDA_TERMINAL_AUDIBLE_BELL:
+                       self->audible_bell = g_value_get_boolean (value);
+                       vte_terminal_set_audible_bell (VTE_TERMINAL(self->vte_term), self->audible_bell);
+                       debug_printf ("terminal audible bell: %d\n", self->audible_bell);
+                       break;
+
+               case TILDA_TERMINAL_VISIBLE_BELL:
+                       self->visible_bell = g_value_get_boolean (value);
+                       vte_terminal_set_visible_bell (VTE_TERMINAL(self->vte_term), self->visible_bell);
+                       debug_printf ("terminal visible bell: %d\n", self->visible_bell);
+                       break;
+
+               case TILDA_TERMINAL_DOUBLE_BUFFERED:
+                       self->double_buffered = g_value_get_boolean (value);
+                       gtk_widget_set_double_buffered (GTK_WIDGET(self->vte_term), self->double_buffered);
+                       debug_printf ("terminal double buffered: %d\n", self->double_buffered);
+                       break;
+
+               case TILDA_TERMINAL_MOUSE_AUTOHIDE:
+                       self->mouse_autohide = g_value_get_boolean (value);
+                       vte_terminal_set_mouse_autohide (VTE_TERMINAL(self->vte_term), self->mouse_autohide);
+                       debug_printf ("terminal mouse autohide: %d\n", self->mouse_autohide);
                        break;
 
                default:
@@ -61,6 +576,105 @@ tilda_terminal_get_property (GObject    *object,
                        g_value_set_int (value, self->number);
                        break;
 
+               case TILDA_TERMINAL_WINDOW_NUMBER:
+                       g_value_set_int (value, self->window_number);
+                       break;
+
+               case TILDA_TERMINAL_TW:
+                       g_value_set_pointer (value, self->parent_window);
+                       break;
+
+               case TILDA_TERMINAL_BACKGROUND_IMAGE:
+                       g_value_set_string (value, self->background_image);
+                       break;
+
+               case TILDA_TERMINAL_SHELL:
+                       g_value_set_string (value, self->shell);
+                       break;
+
+               case TILDA_TERMINAL_FONT:
+                       g_value_set_string (value, self->font);
+                       break;
+
+               case TILDA_TERMINAL_TITLE:
+                       g_value_set_string (value, self->title);
+                       break;
+
+               case TILDA_TERMINAL_WORKING_DIRECTORY:
+                       g_value_set_string (value, self->working_directory);
+                       break;
+
+               case TILDA_TERMINAL_WEB_BROWSER:
+                       g_value_set_string (value, self->web_browser);
+                       break;
+
+               case TILDA_TERMINAL_SCROLLBACK_LINES:
+                       g_value_set_int (value, self->scrollback_lines);
+                       break;
+
+               case TILDA_TERMINAL_TRANSPARENCY_PERCENT:
+                       g_value_set_int (value, self->transparency_percent);
+                       break;
+
+               case TILDA_TERMINAL_BACKSPACE_BINDING:
+                       g_value_set_int (value, self->backspace_binding);
+                       break;
+
+               case TILDA_TERMINAL_DELETE_BINDING:
+                       g_value_set_int (value, self->delete_binding);
+                       break;
+
+               case TILDA_TERMINAL_DYNAMIC_TITLE:
+                       g_value_set_int (value, self->dynamic_title);
+                       break;
+
+               case TILDA_TERMINAL_EXIT_ACTION:
+                       g_value_set_int (value, self->exit_action);
+                       break;
+
+               case TILDA_TERMINAL_SCROLLBAR_POSITION:
+                       g_value_set_int (value, self->scrollbar_position);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_BACKGROUND:
+                       g_value_set_boolean (value, self->scroll_background);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_ON_OUTPUT:
+                       g_value_set_boolean (value, self->scroll_on_output);
+                       break;
+
+               case TILDA_TERMINAL_SCROLL_ON_KEYSTROKE:
+                       g_value_set_boolean (value, self->scroll_on_keystroke);
+                       break;
+
+               case TILDA_TERMINAL_ANTIALIASED:
+                       g_value_set_boolean (value, self->antialiased);
+                       break;
+
+               case TILDA_TERMINAL_ALLOW_BOLD_TEXT:
+                       g_value_set_boolean (value, self->allow_bold_text);
+                       break;
+
+               case TILDA_TERMINAL_CURSOR_BLINKS:
+                       g_value_set_boolean (value, self->cursor_blinks);
+                       break;
+
+               case TILDA_TERMINAL_AUDIBLE_BELL:
+                       g_value_set_boolean (value, self->audible_bell);
+                       break;
+
+               case TILDA_TERMINAL_VISIBLE_BELL:
+                       g_value_set_boolean (value, self->visible_bell);
+                       break;
+
+               case TILDA_TERMINAL_DOUBLE_BUFFERED:
+                       g_value_set_boolean (value, self->double_buffered);
+                       break;
+
+               case TILDA_TERMINAL_MOUSE_AUTOHIDE:
+                       g_value_set_boolean (value, self->mouse_autohide);
+
                default:
                        /* We don't have this property... */
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -73,7 +687,11 @@ tilda_terminal_constructor (GType                  type,
                                                        guint                  n_construct_properties,
                                                        GObjectConstructParam *construct_properties)
 {
+       debug_enter ();
+
        GObject *obj;
+       TildaTerminal *self;
+       gint ret;
 
        /* Invoke parent constructor */
        TildaTerminalClass *klass;
@@ -86,7 +704,33 @@ tilda_terminal_constructor (GType                  type,
         * ctor properties have been set.
         *
         * TODO: This is the place to do DBus-init */
+       self = TILDA_TERMINAL(obj);
+
+       /* Pack into the hbox */
+       gtk_box_pack_end (GTK_BOX(self->hbox), self->scrollbar, FALSE, FALSE, 0);
+       gtk_box_pack_end (GTK_BOX(self->hbox), self->vte_term, TRUE, TRUE, 0);
+       gtk_widget_show (self->scrollbar);
+       gtk_widget_show (self->vte_term);
+       gtk_widget_show (self->hbox);
+
+       /* Match URL's, etc */
+       ret = vte_terminal_match_add (VTE_TERMINAL(self->vte_term), DINGUS1);
+       vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
+       ret = vte_terminal_match_add(VTE_TERMINAL(self->vte_term), DINGUS2);
+       vte_terminal_match_set_cursor_type (VTE_TERMINAL(self->vte_term), ret, GDK_HAND2);
+
+       /* Connect Signals */
+       g_signal_connect (G_OBJECT(self->vte_term), "child-exited",
+                                         G_CALLBACK(tilda_terminal_child_exited_cb), self);
+       g_signal_connect (G_OBJECT(self->vte_term), "eof",
+                                         G_CALLBACK(tilda_terminal_child_exited_cb), self);
+       g_signal_connect (G_OBJECT(self->vte_term), "window-title-changed",
+                                         G_CALLBACK(tilda_terminal_window_title_changed_cb), self);
+       g_signal_connect (G_OBJECT(self->vte_term), "button-press-event",
+                                         G_CALLBACK(tilda_terminal_button_press_cb), self);
 
+       tilda_terminal_start_shell (self);
+       tilda_terminal_dbus_register_object (self);
 
        return obj;
 }
@@ -94,6 +738,8 @@ tilda_terminal_constructor (GType                  type,
 static void
 tilda_terminal_dispose (GObject *obj)
 {
+       debug_enter ();
+
        TildaTerminal *self = (TildaTerminal *) obj;
 
        /* We don't want to run dispose twice, so just return immediately */
@@ -116,6 +762,8 @@ tilda_terminal_dispose (GObject *obj)
 static void
 tilda_terminal_finalize (GObject *obj)
 {
+       debug_enter ();
+
        TildaTerminal *self = (TildaTerminal *) obj;
 
        /*
@@ -124,6 +772,11 @@ tilda_terminal_finalize (GObject *obj)
         */
 
        // TODO: g_free() any primitives here
+       g_free (self->background_image);
+       g_free (self->shell);
+       g_free (self->font);
+       g_free (self->title);
+       g_free (self->working_directory);
 
 
        /* Chain up to the parent class */
@@ -134,6 +787,8 @@ static void
 tilda_terminal_class_init (gpointer g_class,
                                                   gpointer g_class_data)
 {
+       debug_enter ();
+
        GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
        TildaTerminalClass *klass = TILDA_TERMINAL_CLASS (g_class);
        GParamSpec *pspec;
@@ -147,6 +802,9 @@ tilda_terminal_class_init (gpointer g_class,
 
        parent_class = g_type_class_peek_parent (klass);
 
+       /* Hook the TildaTerminal type into DBus */
+       dbus_g_object_type_install_info (tilda_terminal_get_type(), &dbus_glib_tilda_terminal_object_info);
+
        /* Install all of the properties */
        pspec = g_param_spec_int ("number",
                                                          "Terminal number",
@@ -159,6 +817,250 @@ tilda_terminal_class_init (gpointer g_class,
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_NUMBER,
                                                                         pspec);
+
+       pspec = g_param_spec_int ("window-number",
+                                                         "Number of the window to which this terminal belongs",
+                                                         "Set the number of the parent window",
+                                                         0,
+                                                         INT_MAX,
+                                                         0x0000beef,
+                                                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_WINDOW_NUMBER,
+                                                                        pspec);
+
+       pspec = g_param_spec_pointer ("parent-window",
+                                                                 "Pointer to terminal's parent TildaWindow",
+                                                                 "Set the pointer to the terminal's parent TildaWindow",
+                                                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_TW,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("background-image",
+                                                                "Terminal's background image",
+                                                                "Get/Set terminal's background image",
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_BACKGROUND_IMAGE,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("shell",
+                                                                "Terminal's shell",
+                                                                "Get/Set terminal's shell",
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SHELL,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("font",
+                                                                "Terminal's font",
+                                                                "Get/Set terminal's font",
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_FONT,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("title",
+                                                                "Terminal's title",
+                                                                "Get/Set terminal's title",
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_TITLE,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("working-directory",
+                                                                "Terminal's initial working directory",
+                                                                "Get/Set terminal's initial working directory",
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_WORKING_DIRECTORY,
+                                                                        pspec);
+
+       pspec = g_param_spec_string ("web-browser",
+                                                                "Terminal's web browser command",
+                                                                NULL,
+                                                                NULL,
+                                                                G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_WEB_BROWSER,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("scrollback-lines",
+                                                         "Terminal's scrollback amount (lines)",
+                                                         "Get/Set terminal's scrollback amount",
+                                                         0,
+                                                         INT_MAX, // TODO: artificially limit this?
+                                                         1000,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SCROLLBACK_LINES,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("transparency-percent",
+                                                         "Terminal's transparency (percent)",
+                                                         "Get/Set terminal's transparency",
+                                                         0,
+                                                         100,
+                                                         0,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_TRANSPARENCY_PERCENT,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("backspace-binding",
+                                                         "Terminal's backspace binding",
+                                                         "Get/Set terminal's backspace key binding",
+                                                         VTE_ERASE_AUTO,
+                                                         VTE_ERASE_DELETE_SEQUENCE,
+                                                         VTE_ERASE_AUTO,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_BACKSPACE_BINDING,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("delete-binding",
+                                                         "Terminal's delete binding",
+                                                         "Get/Set terminal's delete key binding",
+                                                         VTE_ERASE_AUTO,
+                                                         VTE_ERASE_DELETE_SEQUENCE,
+                                                         VTE_ERASE_AUTO,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_DELETE_BINDING,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("dynamic-title",
+                                                         "Terminal's dynamic title generation method",
+                                                         "Get/Set terminal's dynamic title generation method",
+                                                         0,
+                                                         INT_MAX,
+                                                         0,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_DYNAMIC_TITLE,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("exit-action",
+                                                         "Terminal's action upon child exit",
+                                                         "Get/Set terminal's action upon child exit",
+                                                         0,
+                                                         INT_MAX,
+                                                         0,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_EXIT_ACTION,
+                                                                        pspec);
+
+       pspec = g_param_spec_int ("scrollbar-position",
+                                                         "Terminal's scrollbar position",
+                                                         NULL,
+                                                         0,
+                                                         INT_MAX,
+                                                         0,
+                                                         G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SCROLLBAR_POSITION,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("scroll-background",
+                                                                 "Controls terminal's scrolling behavior",
+                                                                 "Get/Set terminal's scrolling behavior",
+                                                                 FALSE,
+                                                                 G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SCROLL_BACKGROUND,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("scroll-on-output",
+                                                                 "Controls terminal's scrolling behavior on output",
+                                                                 "Get/Set terminal's scrolling behavior on output",
+                                                                 FALSE,
+                                                                 G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SCROLL_ON_OUTPUT,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("scroll-on-keystroke",
+                                                                 "Controls the terminal's scrolling behavior on keystroke",
+                                                                 NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_SCROLL_ON_KEYSTROKE,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("antialiased",
+                                                                 "Attempt to antialias fonts",
+                                                                 NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_ANTIALIASED,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("allow-bold-text",
+                                                                 "Allow bold text",
+                                                                 NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_ALLOW_BOLD_TEXT,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("cursor-blinks",
+                                                                 NULL, NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_CURSOR_BLINKS,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("audible-bell",
+                                                                 NULL, NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_AUDIBLE_BELL,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("visible-bell",
+                                                                 NULL, NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_VISIBLE_BELL,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("double-buffered",
+                                                                 NULL, NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_DOUBLE_BUFFERED,
+                                                                        pspec);
+
+       pspec = g_param_spec_boolean ("mouse-autohide",
+                                                                 NULL, NULL, FALSE, G_PARAM_READWRITE);
+
+       g_object_class_install_property (gobject_class,
+                                                                        TILDA_TERMINAL_MOUSE_AUTOHIDE,
+                                                                        pspec);
 }
 
 GType
@@ -189,13 +1091,17 @@ tilda_terminal_get_type (void)
        return type;
 }
 
+#if 0
+
 int main (int argc, char *argv[])
 {
        GObject *tt;
        gint test_number = INT_MIN;
+       gchar *test_string = NULL;
 
        /* Initialize the GObject type system */
        g_type_init ();
+       gtk_init (&argc, &argv);
 
        tt = g_object_new (TILDA_TYPE_TERMINAL, "number", 10, NULL);
        g_object_get (G_OBJECT (tt), "number", &test_number, NULL);
@@ -207,10 +1113,21 @@ int main (int argc, char *argv[])
        g_object_get (G_OBJECT (tt), "number", &test_number, NULL);
        g_assert (test_number == 22);
 
+       g_object_set (G_OBJECT (tt), "font", "hello I'm a font");
+       g_object_set (G_OBJECT (tt), "font", "Bitstream Vera Sans Mono 13");
+
+       g_object_get (G_OBJECT (tt), "font", &test_string, NULL);
+       g_print ("Read Font: %s\n", test_string);
+       // NOTE: you MUST free the string!!!!
+       g_free (test_string);
+
+       g_object_set (G_OBJECT (tt), "transparency-percent", 50);
+
        g_object_unref (G_OBJECT (tt));
 
        return 0;
 }
 
-/* vim: set ts=4 sts=4 sw=4 noet tw=112: */
+#endif
 
+/* vim: set ts=4 sts=4 sw=4 noet tw=112: */