[gnome-commander/vte] Added support for embedded terminal



commit 393f30610a093dec88c0c9a78a7a313e536c7a09
Author: Andras Varga <avarga71 gmail com>
Date:   Thu Jun 3 20:08:40 2010 +0200

    Added support for embedded terminal

 configure.in                   |    7 ++
 src/Makefile.am                |    6 +-
 src/gcmd-helper.cc             |   50 ++++++++++
 src/gnome-cmd-cmdline.cc       |   78 +++++++++++++++-
 src/gnome-cmd-data.cc          |    1 +
 src/gnome-cmd-data.h           |    1 +
 src/gnome-cmd-file-selector.cc |    5 +
 src/gnome-cmd-main-menu.cc     |   17 +++-
 src/gnome-cmd-main-win.cc      |  209 +++++++++++++++++++++++++++++++++++++++-
 src/gnome-cmd-main-win.h       |   25 +++++
 src/gnome-cmd-user-actions.cc  |    7 ++
 src/gnome-cmd-user-actions.h   |    1 +
 12 files changed, 398 insertions(+), 9 deletions(-)
---
diff --git a/configure.in b/configure.in
index 5842355..bee8957 100644
--- a/configure.in
+++ b/configure.in
@@ -48,6 +48,7 @@ GNOME_REQ=2.0.0
 GNOMEUI_REQ=2.4.0
 GNOMEVFS_REQ=2.0.0
 UNIQUE_REQ=0.9.3
+VTE_REQ=0.11
 PYTHON_REQ=2.5
 EXIV2_REQ=0.14
 TAGLIB_REQ=1.4
@@ -60,6 +61,7 @@ AC_SUBST(GNOME_REQ)
 AC_SUBST(GNOMEUI_REQ)
 AC_SUBST(GNOMEVFS_REQ)
 AC_SUBST(UNIQUE_REQ)
+AC_SUBST(VTE_REQ)
 AC_SUBST(PYTHON_REQ)
 AC_SUBST(EXIV2_REQ)
 AC_SUBST(TAGLIB_REQ)
@@ -197,6 +199,10 @@ dnl Check for libUnique
 PKG_CHECK_MODULES(UNIQUE, [ unique-1.0 >= ${UNIQUE_REQ} ])
 
 
+dnl Check for vte support
+PKG_CHECK_MODULES(VTE, vte >= $VTE_REQ)
+
+
 dnl Check for exiv2 support
 AC_ARG_WITH(libexiv2, [  --without-exiv2         disable EXIF and IPTC support])
 have_exiv2=no
@@ -443,6 +449,7 @@ echo "  gtk+     : ${GTK_VERSION}	in ${GTK_PREFIX}"
 echo "  gnome    : ${GNOME_VERSION}	in ${GNOME_PREFIX}"
 echo "  gnomeui  : ${GNOMEUI_VERSION}	in ${GNOMEUI_PREFIX}"
 echo "  gnome-vfs: ${GNOMEVFS_VERSION}	in ${GNOMEVFS_PREFIX}"
+echo "  vte      : ${VTE_REQ}	in ${GLIB_PREFIX}"
 if test "x$have_python" = "xyes"; then
 echo "  python   : ${PYTHON_VERSION}	in ${PY_EXEC_PREFIX}"
 fi
diff --git a/src/Makefile.am b/src/Makefile.am
index d3c5276..6fa64de 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,11 +8,12 @@ AM_CPPFLAGS = \
 	$(GNOMEUI_CFLAGS) \
 	$(GNOMEVFS_CFLAGS) \
 	$(UNIQUE_CFLAGS) \
+	$(VTE_CFLAGS) \
 	$(PYTHON_CFLAGS) \
 	-DDATADIR=\""$(datadir)"\"\
 	-DPLUGIN_DIR=\""$(libdir)/$(PACKAGE)/plugins"\"
 
-bin_PROGRAMS = gnome-commander gcmd-block
+bin_PROGRAMS = gnome-commander gcmd-block gcmd-helper
 
 gnome_commander_SOURCES = \
 	cap.cc cap.h \
@@ -106,6 +107,7 @@ gnome_commander_LDADD = \
 	$(GNOMEUI_LIBS) \
 	$(GNOMEVFS_LIBS) \
 	$(UNIQUE_LIBS) \
+	$(VTE_LIBS) \
 	$(EXIV2_LIBS) \
 	$(TAGLIB_LIBS) \
 	$(CHM_LIBS) \
@@ -115,3 +117,5 @@ gnome_commander_LDADD = \
 	$(PYTHON_EXTRA_LIBS)
 
 gcmd_block_SOURCES = block.cc
+
+gcmd_helper_SOURCES = gcmd-helper.cc
diff --git a/src/gcmd-helper.cc b/src/gcmd-helper.cc
new file mode 100644
index 0000000..c64c872
--- /dev/null
+++ b/src/gcmd-helper.cc
@@ -0,0 +1,50 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+const char *progname;
+
+void
+error(const char *msg, const char *arg="")
+{
+    fprintf(stderr, "%s: %s%s%s\n", progname, msg, (*arg ? ": " : ""), arg);
+    exit(1);
+}
+
+void
+writestring(const char *s, FILE *f)
+{
+    size_t size = strlen(s)+1;
+    if (fwrite(s, 1, size, f) != size)
+        error("Cannot write output file, disk full?");
+}
+
+int
+main(int argc, char **argv)
+{
+    progname = argv[0];
+    if (argc != 2)
+        error("One command line argument expected");
+
+    const char *fname = argv[1];
+    FILE *f = fopen(fname, "w");
+    if (f==NULL)
+        error(fname, strerror(errno));
+
+    const size_t bufsize = 4096;
+    char cwd[bufsize];
+    if (getcwd(cwd, bufsize)==NULL)
+        error("Cannot get current directory");
+
+    writestring(cwd, f);
+
+    for (char **pvar = environ; *pvar!=NULL; pvar++)
+        writestring(*pvar, f);
+
+    fclose(f);
+
+    return 0;
+}
+
diff --git a/src/gnome-cmd-cmdline.cc b/src/gnome-cmd-cmdline.cc
index 671fc0c..c1330b4 100644
--- a/src/gnome-cmd-cmdline.cc
+++ b/src/gnome-cmd-cmdline.cc
@@ -19,6 +19,7 @@
 */
 
 #include <config.h>
+#include <libgnome/libgnome.h>
 #include "gnome-cmd-includes.h"
 #include "gnome-cmd-cmdline.h"
 #include "gnome-cmd-combo.h"
@@ -69,6 +70,78 @@ inline void add_to_history (GnomeCmdCmdline *cmdline, const gchar *command)
     update_history_combo (cmdline);
 }
 
+char *g_tempfile = NULL;
+char **g_env = NULL;
+bool g_command_running = FALSE;
+
+static void run_in_terminal (GnomeCmdMainWin *mw, const gchar *command, const gchar *dir)
+{
+    if (strspn(command, " \t") == strlen(command))     // command empty or all whitespace
+        return;
+
+    if (g_command_running)
+    {
+        gnome_cmd_show_message (*mw, _("There was a problem with the command"), _("The previous command is still running in the terminal."));
+
+        return;
+    }
+
+    VteTerminal *terminal = mw->get_terminal();
+
+    vte_terminal_feed (terminal, "\r\n", 2);
+    vte_terminal_feed (terminal, dir, strlen(dir));
+    vte_terminal_feed (terminal, "$ ", 2);                  // "$" -> 'g_env["PS1"]'
+    vte_terminal_feed (terminal, command, strlen(command)); // XXX strlen OK utf8-wise?
+    vte_terminal_feed (terminal, "\r\n", 2);
+
+    if (g_tempfile == NULL)
+    {
+        const char *tmp_dir = getenv("TMP");
+        if (tmp_dir == NULL || tmp_dir[0] == 0)
+            tmp_dir = getenv("TEMP");
+        if (tmp_dir == NULL || tmp_dir[0] == 0)
+            tmp_dir = "/tmp";
+        g_tempfile = g_strdup_printf ("%s/gcmd-%d-XXXXXXXX", tmp_dir, (int) getpid());
+        mktemp(g_tempfile); // cannot use mkstemp() because helper prog will need to write this file
+    }
+
+    // PROBLEM WITH VTE_TERMINAL: when it receives SIGCHILD, it stops reading the pipe, so it loses the rest of the output!
+    // Workaround used here: append "; sleep 1" to the end of the command to give the terminal more time (i.e. delay SIGCHILD)
+    // Another possible workaround: steal SIGCHILD handler from VTE so it doesn't get notified...?
+
+    // if the command contains "&", bash reports "illegal token"; workaround is to put the command in parens
+    // HOWEVER, still these processes will immediately die as the shell exists; how to make them orphaned so that they survive...?
+    bool paren = command[strlen(command)-1] == '&';
+
+    // gcmd-helper will save cwd and env[] into the temp file, which we'll read afterwards
+    // gchar *full_command = g_strdup_printf ("%s%s%s; %s/bin/gcmd-helper %s; sleep 1", (paren?"(":""), command, (paren?")":""), PREFIX, g_tempfile);
+    gchar *full_command = g_strdup_printf ("%s%s%s; /home/andras/gcmd-devel/gcmd-1-3/src/gcmd-helper %s; sleep 1", (paren?"(":""), command, (paren?")":""), g_tempfile); //XXX debug
+    unlink(g_tempfile);
+
+    DEBUG('g', "running: %s\nin dir: %s\n", full_command, dir);
+
+    // from gnome-exec.c:
+    char *user_shell = gnome_util_user_shell ();
+    char *argv[4];
+    argv[0] = user_shell;
+    argv[1] = "-c";
+    argv[2] = (char *) full_command;
+    argv[3] = NULL;
+
+    pid_t command_pid = vte_terminal_fork_command (terminal, argv[0], argv, g_env, dir, TRUE, TRUE, TRUE);
+    g_free (full_command);
+
+    DEBUG('g', " pid: %d\n", (int) command_pid);
+
+    if (command_pid == -1)
+        return;  // launch failed
+
+    mw->hide_panels();
+    mw->focus_terminal(); // we'll get it back the focus when terminal emits "child-exited" signal
+
+    g_command_running = TRUE;
+}
+
 
 static void on_exec (GnomeCmdCmdline *cmdline, gboolean term)
 {
@@ -105,7 +178,8 @@ static void on_exec (GnomeCmdCmdline *cmdline, gboolean term)
             {
                 gchar *fpath = gnome_cmd_file_get_real_path (GNOME_CMD_FILE (fs->get_directory()));
 
-                run_command_indir (cmdline_text, fpath, term);
+                // run_command_indir (cmdline_text, fpath, term);
+                run_in_terminal (main_win, cmdline_text, fpath);
                 g_free (fpath);
             }
 
@@ -131,7 +205,7 @@ static gboolean on_key_pressed (GtkWidget *entry, GdkEventKey *event, GnomeCmdCm
             break;
     }
 
-    return gnome_cmd_cmdline_keypressed (cmdline, event) || main_win->key_pressed(event);
+    return gnome_cmd_cmdline_keypressed (cmdline, event) || !gnome_cmd_data.terminal_visibility && main_win->key_pressed(event);
 }
 
 
diff --git a/src/gnome-cmd-data.cc b/src/gnome-cmd-data.cc
index 115a527..33d78c1 100644
--- a/src/gnome-cmd-data.cc
+++ b/src/gnome-cmd-data.cc
@@ -930,6 +930,7 @@ GnomeCmdData::GnomeCmdData()
     concombo_visibility = TRUE;
     cmdline_visibility = TRUE;
     buttonbar_visibility = TRUE;
+    terminal_visibility = FALSE;
 
     use_ls_colors = FALSE;
 
diff --git a/src/gnome-cmd-data.h b/src/gnome-cmd-data.h
index f980bf9..ebf9d31 100644
--- a/src/gnome-cmd-data.h
+++ b/src/gnome-cmd-data.h
@@ -212,6 +212,7 @@ struct GnomeCmdData
     gboolean                     concombo_visibility;
     gboolean                     cmdline_visibility;
     gboolean                     buttonbar_visibility;
+    gboolean                     terminal_visibility;
 
     gboolean                     use_ls_colors;
 
diff --git a/src/gnome-cmd-file-selector.cc b/src/gnome-cmd-file-selector.cc
index 559f486..eb651c1 100644
--- a/src/gnome-cmd-file-selector.cc
+++ b/src/gnome-cmd-file-selector.cc
@@ -1705,6 +1705,11 @@ gboolean GnomeCmdFileSelector::key_pressed(GdkEventKey *event)
     {
         switch (event->keyval)
         {
+            case GDK_O:
+            case GDK_o:
+                view_terminal();
+                return TRUE;
+
             case GDK_V:
             case GDK_v:
                 gnome_cmd_file_selector_cap_paste (this);
diff --git a/src/gnome-cmd-main-menu.cc b/src/gnome-cmd-main-menu.cc
index b8442d0..59e2104 100644
--- a/src/gnome-cmd-main-menu.cc
+++ b/src/gnome-cmd-main-menu.cc
@@ -113,6 +113,7 @@ struct GnomeCmdMainMenuPrivate
     GtkWidget *menu_view_concombo;
     GtkWidget *menu_view_buttonbar;
     GtkWidget *menu_view_cmdline;
+    GtkWidget *menu_view_terminal;
     GtkWidget *menu_view_hidden_files;
     GtkWidget *menu_view_backup_files;
     GtkWidget *menu_view_back;
@@ -657,6 +658,12 @@ static void init (GnomeCmdMainMenu *main_menu)
             NULL
         },
         {
+            MENU_TYPE_TOGGLEITEM, _("Show Terminal"), "", NULL,
+            (gpointer) view_terminal, NULL,
+            GNOME_APP_PIXMAP_NONE, NULL,
+            NULL
+        },
+        {
             MENU_TYPE_TOGGLEITEM, _("Show Buttonbar"), "", NULL,
             (gpointer) view_buttonbar, NULL,
             GNOME_APP_PIXMAP_NONE, NULL,
@@ -847,9 +854,10 @@ static void init (GnomeCmdMainMenu *main_menu)
     main_menu->priv->menu_view_conbuttons = view_menu_uiinfo[8].widget;
     main_menu->priv->menu_view_concombo = view_menu_uiinfo[9].widget;
     main_menu->priv->menu_view_cmdline = view_menu_uiinfo[10].widget;
-    main_menu->priv->menu_view_buttonbar = view_menu_uiinfo[11].widget;
-    main_menu->priv->menu_view_hidden_files = view_menu_uiinfo[13].widget;
-    main_menu->priv->menu_view_backup_files = view_menu_uiinfo[14].widget;
+    main_menu->priv->menu_view_terminal = view_menu_uiinfo[11].widget;
+    main_menu->priv->menu_view_buttonbar = view_menu_uiinfo[12].widget;
+    main_menu->priv->menu_view_hidden_files = view_menu_uiinfo[14].widget;
+    main_menu->priv->menu_view_backup_files = view_menu_uiinfo[15].widget;
     main_menu->priv->menu_view_back = view_menu_uiinfo[0].widget;
     main_menu->priv->menu_view_forward = view_menu_uiinfo[1].widget;
 
@@ -869,6 +877,9 @@ static void init (GnomeCmdMainMenu *main_menu)
         GTK_CHECK_MENU_ITEM (main_menu->priv->menu_view_cmdline),
         gnome_cmd_data.cmdline_visibility);
     gtk_check_menu_item_set_active (
+        GTK_CHECK_MENU_ITEM (main_menu->priv->menu_view_terminal),
+        gnome_cmd_data.terminal_visibility);
+    gtk_check_menu_item_set_active (
         GTK_CHECK_MENU_ITEM (main_menu->priv->menu_view_hidden_files),
         !gnome_cmd_data.filter_settings.hidden);
     gtk_check_menu_item_set_active (
diff --git a/src/gnome-cmd-main-win.cc b/src/gnome-cmd-main-win.cc
index 062b58a..e12b8d9 100644
--- a/src/gnome-cmd-main-win.cc
+++ b/src/gnome-cmd-main-win.cc
@@ -22,6 +22,7 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <glib/gstdio.h>
 #include <libgnomeui/gnome-stock-icons.h>
 
 #include "gnome-cmd-includes.h"
@@ -110,6 +111,7 @@ struct GnomeCmdMainWin::Private
     GtkWidget *cmdline_sep;
     GtkWidget *buttonbar;
     GtkWidget *buttonbar_sep;
+    GtkWidget *terminal;
 
     GtkWidget *tb_first_btn;
     GtkWidget *tb_back_btn;
@@ -696,6 +698,157 @@ static gboolean on_window_state_event (GtkWidget *mw, GdkEventWindowState *event
 }
 
 
+static char *read_file (const char *filename, size_t maxsize, size_t &size)
+{
+    struct stat statbuf;
+    if (g_stat (filename, &statbuf) != 0)
+        return NULL;
+
+    FILE *f = fopen(filename, "r");
+    if (f == NULL)
+        return NULL;
+
+    size = statbuf.st_size;
+    size = min(size, maxsize); // impose some sensible limit on file size
+
+    char *buf = (char *) g_malloc (size+1);
+    size = fread(buf, 1, size, f);
+    fclose(f);
+
+    buf[size] = 0; // just to be safe
+
+    return buf;
+}
+
+
+// the following variables are defined and used in gnome_cmd_cmdline.cc
+extern char *g_tempfile;
+extern char **g_env;
+extern bool g_command_running;
+
+
+static void on_terminal_child_exited (GtkWidget *vte, GnomeCmdMainWin *mw)
+{
+    DEBUG('g', "done\n");
+    g_command_running = FALSE;
+
+    if (!gnome_cmd_data.terminal_visibility)
+        mw->show_panels();
+
+    mw->focus_cmdline();
+
+    // read the temp file, created by gcmd_helper
+    size_t size = 0;
+    char *buf = read_file (g_tempfile, 1024*1024, size);
+    if (buf != NULL)
+    {
+        // first string is the working directory when the shell exited
+        const char *working_dir = buf;
+        char *envstrings = buf + strlen(buf) + 1;
+
+        mw->fs(ACTIVE)->goto_directory(working_dir);
+
+        // then environment variables set in the shell, in NAME=VALUE form
+        if (g_env != NULL)
+        {
+            for (char **p = g_env; *p; ++p)
+                g_free (*p);
+            g_free (g_env);
+            g_env = NULL;
+        }
+
+        // count strings
+        int n = 0;
+        for (char *s = envstrings; s < buf+size; s += strlen(s) + 1)
+            ++n;
+
+        // build new g_env[]
+        g_env = g_new (char *, n+1);
+        char *s = envstrings;
+        for (int i=0; i<n; ++i)
+        {
+            DEBUG('g', "  env[%d] @%d: '%s'\n", i, s-envstrings, s);
+            g_env[i] = g_strdup (s);
+            s += strlen(s) + 1;
+        }
+        g_env[n] = NULL;
+
+        g_free (buf);
+    }
+}
+
+
+static void on_terminal_popup_menu__copy (GtkMenuItem *menuitem, GtkWidget *vte)
+{
+    vte_terminal_copy_clipboard (VTE_TERMINAL (vte));
+}
+
+
+inline void terminal_popup_menu (GtkWidget *vte, GnomeCmdMainWin *mw, GdkEventButton *event=NULL)
+{
+    GtkWidget *menu = gtk_menu_new ();
+    GtkWidget *menuitem;
+
+    menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
+
+    if (vte_terminal_get_has_selection (VTE_TERMINAL (vte)))
+        g_signal_connect (menuitem, "activate", G_CALLBACK (on_terminal_popup_menu__copy), vte);
+    else
+        gtk_widget_set_sensitive (menuitem, FALSE);
+
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
+
+    menuitem = gtk_menu_item_new_with_label (_("Hide terminal"));
+    g_signal_connect (menuitem, "activate", G_CALLBACK (view_terminal), NULL);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
+    gtk_widget_show_all (menu);
+    gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+                    (event != NULL) ? event->button : 0, gdk_event_get_time ((GdkEvent*) event));
+}
+
+
+static gboolean on_terminal_popup_menu (GtkWidget *vte, GnomeCmdMainWin *mw)
+{
+    terminal_popup_menu (vte, mw);
+
+    return TRUE;
+}
+
+
+static gboolean on_terminal_button_pressed (GtkWidget *vte, GdkEventButton *event, GnomeCmdMainWin *mw)
+{
+    if (event->type==GDK_BUTTON_PRESS && event->button==3)
+    {
+        terminal_popup_menu (vte, mw, event);
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+static gboolean on_terminal_key_pressed (GtkWidget *vte, GdkEventKey *event, GnomeCmdMainWin *mw)
+{
+    if (state_is_ctrl (event->state))
+        switch (event->keyval)
+        {
+            case GDK_O:
+            case GDK_o:
+                view_terminal();
+                return TRUE;
+
+            default:
+                return FALSE;
+        }
+
+    return FALSE;
+}
+
+
 /*******************************
  * Gtk class implementation
  *******************************/
@@ -814,9 +967,20 @@ static void init (GnomeCmdMainWin *mw)
     gtk_widget_show (mw->priv->file_selector[RIGHT]);
     gtk_paned_pack2 (GTK_PANED (mw->priv->paned), mw->priv->file_selector[RIGHT], TRUE, TRUE);
 
+    // GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+    // gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    // gtk_box_pack_start (GTK_BOX (mw->priv->vbox), scrolled_window, TRUE, TRUE, 0);
+
+    GtkWidget *terminal = mw->priv->terminal = vte_terminal_new ();
+    gtk_widget_ref (terminal);
+    gtk_object_set_data_full (*mw, "vbox", terminal, (GtkDestroyNotify) gtk_widget_unref);
+    // gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (terminal));
+    gtk_box_pack_start (GTK_BOX (mw->priv->vbox), terminal, TRUE, TRUE, 0);
+
     mw->update_toolbar_visibility();
     mw->update_cmdline_visibility();
     mw->update_buttonbar_visibility();
+    mw->update_panels_visibility();
 
     g_signal_connect (mw, "realize", G_CALLBACK (on_main_win_realize), mw);
     g_signal_connect (mw->fs(LEFT), "dir-changed", G_CALLBACK (on_fs_dir_change), mw);
@@ -831,6 +995,11 @@ static void init (GnomeCmdMainWin *mw)
     g_signal_connect (mw->priv->paned, "button-press-event", G_CALLBACK (on_slide_button_press), mw);
     g_signal_connect (mw, "window-state-event", G_CALLBACK (on_window_state_event), NULL);
 
+    g_signal_connect (terminal, "child-exited", G_CALLBACK (on_terminal_child_exited), mw);
+    g_signal_connect (terminal, "key-press-event", G_CALLBACK (on_terminal_key_pressed), mw);
+    g_signal_connect (terminal, "button-press-event", G_CALLBACK (on_terminal_button_pressed), mw);
+    g_signal_connect (terminal, "popup-menu", G_CALLBACK (on_terminal_popup_menu), mw);
+
     mw->fs(LEFT)->update_connections();
     mw->fs(RIGHT)->update_connections();
 
@@ -932,6 +1101,20 @@ void GnomeCmdMainWin::focus_file_lists()
 }
 
 
+void GnomeCmdMainWin::focus_cmdline()
+{
+    gtk_widget_grab_focus (priv->cmdline);
+    priv->focused_widget = priv->cmdline;
+}
+
+
+void GnomeCmdMainWin::focus_terminal()
+{
+    gtk_widget_grab_focus (priv->terminal);
+    priv->focused_widget = priv->terminal;
+}
+
+
 void GnomeCmdMainWin::refocus()
 {
     if (priv->focused_widget)
@@ -939,6 +1122,20 @@ void GnomeCmdMainWin::refocus()
 }
 
 
+void GnomeCmdMainWin::hide_panels()
+{
+    gtk_widget_hide (priv->paned);
+    gtk_widget_show (priv->terminal);
+}
+
+
+void GnomeCmdMainWin::show_panels()
+{
+    gtk_widget_show (priv->paned);
+    gtk_widget_hide (priv->terminal);
+}
+
+
 gboolean GnomeCmdMainWin::key_pressed(GdkEventKey *event)
 {
     if (state_is_alt (event->state))
@@ -1134,6 +1331,12 @@ GnomeCmdCmdline *GnomeCmdMainWin::get_cmdline()
 }
 
 
+VteTerminal *GnomeCmdMainWin::get_terminal()
+{
+    return VTE_TERMINAL (priv->terminal);
+}
+
+
 void GnomeCmdMainWin::update_bookmarks()
 {
     gnome_cmd_main_menu_update_bookmarks (GNOME_CMD_MAIN_MENU (priv->menubar));
@@ -1222,8 +1425,8 @@ void GnomeCmdMainWin::update_cmdline_visibility()
             pos += 2;
         gtk_box_pack_start (GTK_BOX (priv->vbox), priv->cmdline_sep, FALSE, TRUE, 0);
         gtk_box_pack_start (GTK_BOX (priv->vbox), priv->cmdline, FALSE, TRUE, 1);
-        gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->cmdline_sep, pos);
-        gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->cmdline, pos+1);
+        gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->cmdline_sep, pos+1);
+        gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->cmdline, pos+2);
     }
     else
     {
@@ -1296,7 +1499,7 @@ GnomeCmdState *GnomeCmdMainWin::get_state()
 }
 
 
-void GnomeCmdMainWin::set_cap_state (gboolean state)
+void GnomeCmdMainWin::set_cap_state(gboolean state)
 {
     gtk_widget_set_sensitive (priv->tb_cap_paste_btn, state);
 }
diff --git a/src/gnome-cmd-main-win.h b/src/gnome-cmd-main-win.h
index 92e97ca..7d42383 100644
--- a/src/gnome-cmd-main-win.h
+++ b/src/gnome-cmd-main-win.h
@@ -21,6 +21,8 @@
 #ifndef __GNOME_CMD_MAIN_WIN_H__
 #define __GNOME_CMD_MAIN_WIN_H__
 
+#include <vte/vte.h>
+
 #include "gnome-cmd-file-selector.h"
 #include "gnome-cmd-advrename-dialog.h"
 #include "gnome-cmd-cmdline.h"
@@ -67,13 +69,21 @@ struct GnomeCmdMainWin
     void set_cap_state(gboolean state);
 
     GnomeCmdCmdline *get_cmdline();
+    VteTerminal *get_terminal();
 
     void focus_file_lists();
+    void focus_cmdline();
+    void focus_terminal();
     void refocus();
 
+    void hide_panels();
+    void show_panels();
+
     void update_style();
     void update_bookmarks();
     void update_toolbar_visibility();
+    void update_panels_visibility();
+    void toggle_terminal_visibility();
     void update_cmdline_visibility();
     void update_buttonbar_visibility();
     void update_list_orientation();
@@ -82,6 +92,21 @@ struct GnomeCmdMainWin
 };
 
 
+inline void GnomeCmdMainWin::update_panels_visibility ()
+{
+    if (gnome_cmd_data.terminal_visibility)
+        hide_panels();
+    else
+        show_panels();
+}
+
+inline void GnomeCmdMainWin::toggle_terminal_visibility ()
+{
+    gnome_cmd_data.terminal_visibility = !gnome_cmd_data.terminal_visibility;
+    update_panels_visibility();
+}
+
+
 GtkWidget *gnome_cmd_main_win_new ();
 
 
diff --git a/src/gnome-cmd-user-actions.cc b/src/gnome-cmd-user-actions.cc
index 06f160c..8fa404b 100644
--- a/src/gnome-cmd-user-actions.cc
+++ b/src/gnome-cmd-user-actions.cc
@@ -1454,6 +1454,13 @@ void view_close_tab (GtkMenuItem *menuitem, gpointer not_used)
 }
 
 
+void view_terminal (GtkMenuItem *menuitem, gpointer not_used)
+{
+    if (GTK_WIDGET_REALIZED (main_win))
+        main_win->toggle_terminal_visibility();
+}
+
+
 /************** Options Menu **************/
 void options_edit (GtkMenuItem *menuitem, gpointer not_used)
 {
diff --git a/src/gnome-cmd-user-actions.h b/src/gnome-cmd-user-actions.h
index 0a0325c..6836016 100644
--- a/src/gnome-cmd-user-actions.h
+++ b/src/gnome-cmd-user-actions.h
@@ -296,6 +296,7 @@ GNOME_CMD_USER_ACTION(view_home);
 GNOME_CMD_USER_ACTION(view_root);
 GNOME_CMD_USER_ACTION(view_new_tab);
 GNOME_CMD_USER_ACTION(view_close_tab);
+GNOME_CMD_USER_ACTION(view_terminal);
 
 /************** Bookmarks Menu **************/
 GNOME_CMD_USER_ACTION(bookmarks_add_current);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]