gnome-terminal r3220 - trunk/src



Author: chpe
Date: Sat Nov 29 19:49:14 2008
New Revision: 3220
URL: http://svn.gnome.org/viewvc/gnome-terminal?rev=3220&view=rev

Log:
Implement saving and loading state to/from keyfile, and use that for
session support instead of building a 'restart-command' command line
that may exceed command line limits. Bug #328391.

Modified:
   trunk/src/terminal-app.c
   trunk/src/terminal-app.h
   trunk/src/terminal-options.c
   trunk/src/terminal-options.h
   trunk/src/terminal-screen.c
   trunk/src/terminal-screen.h
   trunk/src/terminal-util.c
   trunk/src/terminal-util.h
   trunk/src/terminal-window.c
   trunk/src/terminal-window.h
   trunk/src/terminal.c

Modified: trunk/src/terminal-app.c
==============================================================================
--- trunk/src/terminal-app.c	(original)
+++ trunk/src/terminal-app.c	Sat Nov 29 19:49:14 2008
@@ -46,8 +46,6 @@
 
 #define FALLBACK_PROFILE_ID "Default"
 
-#define EPSILON (1.0e-6)
-
 /* Settings storage works as follows:
  *   /apps/gnome-terminal/global/
  *   /apps/gnome-terminal/profiles/Foo/
@@ -866,8 +864,9 @@
   if (val != NULL &&
       val->type == GCONF_VALUE_STRING)
     name = gconf_value_get_string (val);
-  if (!name)
+  if (!name || !name[0])
     name = FALLBACK_PROFILE_ID;
+  g_assert (name != NULL);
 
   g_free (app->default_profile_id);
   app->default_profile_id = g_strdup (name);
@@ -1341,166 +1340,14 @@
   gtk_window_present (GTK_WINDOW (app->manage_profiles_dialog));
 }
 
-static void
-terminal_app_get_clone_command (TerminalApp *app,
-                                int         *argcp,
-                                char      ***argvp)
-{
-  GList *lw;
-  GPtrArray* args;
-
-  args = g_ptr_array_new ();
-
-   g_ptr_array_add (args, g_strdup (EXECUTABLE_NAME));
-
-  if (!app->use_factory)
-    g_ptr_array_add (args, g_strdup ("--disable-factory"));
-
-  for (lw = app->windows; lw != NULL; lw = lw->next)
-    {
-      GList *tabs;
-      GList *lt;
-      TerminalWindow *window = lw->data;
-      TerminalScreen *active_screen;
-
-      active_screen = terminal_window_get_active (window);
-
-      tabs = terminal_window_list_screen_containers (window);
-
-      for (lt = tabs; lt != NULL; lt = lt->next)
-        {
-          TerminalScreen *screen;
-          const char *profile_id;
-          const char **override_command;
-          const char *title;
-          double zoom;
-
-          screen = terminal_screen_container_get_screen (GTK_WIDGET (lt->data));
-          profile_id = terminal_profile_get_property_string (terminal_screen_get_profile (screen),
-                                                             TERMINAL_PROFILE_NAME);
-
-          if (lt == tabs)
-            {
-              GdkWindowState state;
-
-              g_ptr_array_add (args, g_strdup_printf ("--window-with-profile-internal-id=%s",
-                                                     profile_id));
-              if (terminal_window_get_menubar_visible (window))
-                 g_ptr_array_add (args, g_strdup ("--show-menubar"));
-              else
-                 g_ptr_array_add (args, g_strdup ("--hide-menubar"));
-
-               g_ptr_array_add (args, g_strdup_printf ("--role=%s",
-                                                       gtk_window_get_role (GTK_WINDOW (window))));
-
-               state = gdk_window_get_state (GTK_WIDGET (window)->window);
-               if (state & GDK_WINDOW_STATE_MAXIMIZED)
-                 g_ptr_array_add (args, g_strdup ("--maximize"));
-               if (state & GDK_WINDOW_STATE_FULLSCREEN)
-                 g_ptr_array_add (args, g_strdup ("--full-screen"));
-            }
-          else
-            {
-               g_ptr_array_add (args, g_strdup_printf ("--tab-with-profile-internal-id=%s",
-                                                     profile_id));
-            }
-
-          if (screen == active_screen)
-            {
-              int w, h, x, y;
-
-              /* FIXME saving the geometry is not great :-/ */
-               g_ptr_array_add (args, g_strdup ("--active"));
-
-               g_ptr_array_add (args, g_strdup ("--geometry"));
-
-              terminal_screen_get_size (screen, &w, &h);
-              gtk_window_get_position (GTK_WINDOW (window), &x, &y);
-              g_ptr_array_add (args, g_strdup_printf ("%dx%d+%d+%d", w, h, x, y));
-            }
-
-          override_command = terminal_screen_get_override_command (screen);
-          if (override_command)
-            {
-              char *flattened;
-
-               g_ptr_array_add (args, g_strdup ("--command"));
-
-              flattened = g_strjoinv (" ", (char**) override_command);
-               g_ptr_array_add (args, flattened);
-            }
-
-          title = terminal_screen_get_dynamic_title (screen);
-          if (title)
-            {
-               g_ptr_array_add (args, g_strdup ("--title"));
-               g_ptr_array_add (args, g_strdup (title));
-            }
-
-          {
-            const char *dir;
-
-            dir = terminal_screen_get_working_dir (screen);
-
-            if (dir != NULL && *dir != '\0') /* should always be TRUE anyhow */
-              {
-                 g_ptr_array_add (args, g_strdup ("--working-directory"));
-                g_ptr_array_add (args, g_strdup (dir));
-              }
-          }
-
-          zoom = terminal_screen_get_font_scale (screen);
-          if (zoom < (1.0 - EPSILON) || (zoom > 1.0 + EPSILON)) /* if not 1.0 */
-            {
-              char buf[G_ASCII_DTOSTR_BUF_SIZE];
-
-              g_ascii_dtostr (buf, sizeof (buf), zoom);
-
-              g_ptr_array_add (args, g_strdup ("--zoom"));
-              g_ptr_array_add (args, g_strdup (buf));
-            }
-        }
-
-      g_list_free (tabs);
-    }
-
-  /* final NULL */
-  g_ptr_array_add (args, NULL);
-
-  *argcp = args->len - 1;
-  *argvp = (char**) g_ptr_array_free (args, FALSE);
-}
-
 #ifdef WITH_SMCLIENT
 
-static gboolean
+static void
 terminal_app_save_state_cb (EggSMClient *client,
-                            GKeyFile *keyfile,
+                            GKeyFile *key_file,
                             TerminalApp *app)
 {
-  char **clone_command;
-  int argc;
-#ifdef GNOME_ENABLE_DEBUG
-  int i;
-#endif
-
-  terminal_app_get_clone_command (app, &argc, &clone_command);
-
-  /* GnomeClient builds the clone command from the restart command */
-  egg_sm_client_set_restart_command (client, argc, (const char **) clone_command);
-
-#ifdef GNOME_ENABLE_DEBUG
-  /* Debug spew */
-  g_print ("Saving session: ");
-  for (i = 0; i < argc; ++i)
-    g_print ("%s ", clone_command[i]);
-  g_print ("\n");
-#endif
-
-  g_strfreev (clone_command);
-
-  /* success */
-  return TRUE;
+  terminal_app_save_config (app, key_file);
 }
 
 static void
@@ -1796,9 +1643,10 @@
   return global_app;
 }
 
-void
+gboolean
 terminal_app_handle_options (TerminalApp *app,
-                             TerminalOptions *options)
+                             TerminalOptions *options,
+                             GError **error)
 {
   GList *lw;
   GdkScreen *screen;
@@ -1806,6 +1654,25 @@
   screen = terminal_app_get_screen_by_display_name (options->display_name,
                                                     options->screen_number);
 
+  if (options->save_config)
+    return terminal_app_save_config_file (app, options->config_file, error);
+
+  if (options->load_config)
+    {
+      GKeyFile *key_file;
+      gboolean result;
+
+      key_file = g_key_file_new ();
+      result = g_key_file_load_from_file (key_file, options->config_file, 0, error) &&
+               terminal_options_merge_config (options, key_file, error);
+      g_key_file_free (key_file);
+
+      if (!result)
+        return FALSE;
+
+      /* fall-through on success */
+    }
+
   for (lw = options->initial_windows;  lw != NULL; lw = lw->next)
     {
       InitialWindow *iw = lw->data;
@@ -1885,6 +1752,8 @@
 
       gtk_window_present (GTK_WINDOW (window));
     }
+
+  return TRUE;
 }
 
 TerminalWindow *
@@ -1919,26 +1788,9 @@
 
   g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
   g_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
-  g_return_val_if_fail (TERMINAL_IS_PROFILE (profile), NULL);
-
-  screen = terminal_screen_new ();
-
-  terminal_screen_set_profile (screen, profile);
-
-  if (title)
-    terminal_screen_set_override_title (screen, title);
-
-  if (working_dir)
-    terminal_screen_set_working_dir (screen, working_dir);
 
-  if (override_command)
-    terminal_screen_set_override_command (screen, override_command);
-
-  if (child_env)
-    terminal_screen_set_initial_environment (screen, child_env);
-
-  terminal_screen_set_font_scale (screen, zoom);
-  terminal_screen_set_font (screen);
+  screen = terminal_screen_new (profile, override_command, title,
+                                working_dir, child_env, zoom);
 
   terminal_window_add_screen (window, screen, -1);
   terminal_window_switch_screen (window, screen);
@@ -2079,3 +1931,61 @@
 
   return g_slist_sort (list, (GCompareFunc) compare_encodings);
 }
+
+void
+terminal_app_save_config (TerminalApp *app,
+                          GKeyFile *key_file)
+{
+  GList *lw;
+  guint n = 0;
+  GPtrArray *window_names_array;
+  char **window_names;
+  gsize len;
+
+  g_key_file_set_comment (key_file, NULL, NULL, "Written by " PACKAGE_STRING, NULL);
+
+  g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_VERSION, TERMINAL_CONFIG_VERSION);
+  g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_COMPAT_VERSION, TERMINAL_CONFIG_COMPAT_VERSION);
+
+  /* FIXMEchpe this seems useless */
+  g_key_file_set_boolean (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_FACTORY, app->use_factory);
+
+  window_names_array = g_ptr_array_sized_new (g_list_length (app->windows) + 1);
+
+  for (lw = app->windows; lw != NULL; lw = lw->next)
+    {
+      TerminalWindow *window = TERMINAL_WINDOW (lw->data);
+      char *group;
+
+      group = g_strdup_printf ("Window%u", n++);
+      g_ptr_array_add (window_names_array, group);
+
+      terminal_window_save_state (window, key_file, group);
+    }
+
+  g_ptr_array_add (window_names_array, NULL);
+  len = window_names_array->len;
+  window_names = (char **) g_ptr_array_free (window_names_array, FALSE);
+  g_key_file_set_string_list (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_WINDOWS, (const char * const *) window_names, len);
+  g_strfreev (window_names);
+}
+
+gboolean
+terminal_app_save_config_file (TerminalApp *app,
+                               const char *file_name,
+                               GError **error)
+{
+  GKeyFile *key_file;
+  char *data;
+  gsize len;
+  gboolean result;
+
+  key_file = g_key_file_new ();
+  terminal_app_save_config (app, key_file);
+
+  data = g_key_file_to_data (key_file, &len, NULL);
+  result = g_file_set_contents (file_name, data, len, error);
+  g_free (data);
+
+  return result;
+}

Modified: trunk/src/terminal-app.h
==============================================================================
--- trunk/src/terminal-app.h	(original)
+++ trunk/src/terminal-app.h	Sat Nov 29 19:49:14 2008
@@ -28,6 +28,35 @@
 
 G_BEGIN_DECLS
 
+/* Terminal conf files */
+
+#define TERMINAL_CONFIG_VERSION             (1) /* Bump this for any changes */
+#define TERMINAL_CONFIG_COMPAT_VERSION      (1) /* Bump this for incompatible changes */
+
+#define TERMINAL_CONFIG_GROUP               "GNOME Terminal Configuration"
+#define TERMINAL_CONFIG_PROP_FACTORY        "FactoryEnabled"
+#define TERMINAL_CONFIG_PROP_VERSION        "Version"
+#define TERMINAL_CONFIG_PROP_COMPAT_VERSION "CompatVersion"
+#define TERMINAL_CONFIG_PROP_WINDOWS        "Windows"
+
+#define TERMINAL_CONFIG_WINDOW_PROP_ACTIVE_TAB       "ActiveTerminal"
+#define TERMINAL_CONFIG_WINDOW_PROP_FULLSCREEN       "Fullscreen"
+#define TERMINAL_CONFIG_WINDOW_PROP_GEOMETRY         "Geometry"
+#define TERMINAL_CONFIG_WINDOW_PROP_MAXIMIZED        "Maximized"
+#define TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE  "MenubarVisible"
+#define TERMINAL_CONFIG_WINDOW_PROP_ROLE             "Role"
+#define TERMINAL_CONFIG_WINDOW_PROP_TABS             "Terminals"
+
+#define TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT             "Height"
+#define TERMINAL_CONFIG_TERMINAL_PROP_COMMAND            "Command"
+#define TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID         "ProfileID"
+#define TERMINAL_CONFIG_TERMINAL_PROP_TITLE              "Title"
+#define TERMINAL_CONFIG_TERMINAL_PROP_WIDTH              "Width"
+#define TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY  "WorkingDirectory"
+#define TERMINAL_CONFIG_TERMINAL_PROP_ZOOM               "Zoom"
+
+/* Configuration */
+
 #define CONF_PREFIX           "/apps/gnome-terminal"
 #define CONF_GLOBAL_PREFIX    CONF_PREFIX "/global"
 #define CONF_PROFILES_PREFIX  CONF_PREFIX "/profiles"
@@ -40,6 +69,8 @@
 #define TERMINAL_APP_ENABLE_MNEMONICS       "enable-mnemonics"
 #define TERMINAL_APP_SYSTEM_FONT            "system-font"
 
+#define EPSILON (1.0e-6)
+
 /* TerminalApp */
 
 #define TERMINAL_TYPE_APP              (terminal_app_get_type ())
@@ -60,8 +91,9 @@
 
 TerminalApp* terminal_app_get (void);
 
-void terminal_app_handle_options (TerminalApp *app,
-                                  TerminalOptions *options);
+gboolean terminal_app_handle_options (TerminalApp *app,
+                                      TerminalOptions *options,
+                                      GError **error);
 
 void terminal_app_edit_profile (TerminalApp     *app,
                                 TerminalProfile *profile,
@@ -114,6 +146,13 @@
 
 GSList* terminal_app_get_active_encodings (TerminalApp *app);
 
+void terminal_app_save_config (TerminalApp *app,
+                               GKeyFile *key_file);
+
+gboolean terminal_app_save_config_file (TerminalApp *app,
+                                        const char *file_name,
+                                        GError **error);
+
 G_END_DECLS
 
 #endif /* !TERMINAL_APP_H */

Modified: trunk/src/terminal-options.c
==============================================================================
--- trunk/src/terminal-options.c	(original)
+++ trunk/src/terminal-options.c	Sat Nov 29 19:49:14 2008
@@ -29,7 +29,9 @@
 
 #include "terminal-options.h"
 #include "terminal-screen.h"
+#include "terminal-app.h"
 #include "terminal-intl.h"
+#include "terminal-util.h"
 
 static GOptionContext *get_goption_context (TerminalOptions *options);
 
@@ -64,20 +66,11 @@
 }
 
 static InitialWindow*
-initial_window_new (const char *profile,
-                    gboolean    is_id)
+initial_window_new (void)
 {
   InitialWindow *iw;
 
-  iw = g_slice_new (InitialWindow);
-
-  iw->tabs = g_list_prepend (NULL, initial_tab_new (profile, is_id));
-  iw->force_menubar_state = FALSE;
-  iw->menubar_state = FALSE;
-  iw->start_fullscreen = FALSE;
-  iw->start_maximized = FALSE;
-  iw->geometry = NULL;
-  iw->role = NULL;
+  iw = g_slice_new0 (InitialWindow);
 
   return iw;
 }
@@ -124,11 +117,11 @@
 
   if (options->initial_windows == NULL)
     {
-      iw = initial_window_new (NULL, FALSE);
+      iw = initial_window_new ();
+      iw->tabs = g_list_append (NULL, initial_tab_new (NULL, FALSE));
       apply_defaults (options, iw);
 
-      options->initial_windows = g_list_append (options->initial_windows,
-                                                iw);
+      options->initial_windows = g_list_append (options->initial_windows, iw);
     }
   else
     {
@@ -162,8 +155,8 @@
 {
   InitialWindow *iw;
 
-  iw = initial_window_new (profile, is_id);
-
+  iw = initial_window_new ();
+  iw->tabs = g_list_prepend (NULL, initial_tab_new (profile, is_id));
   apply_defaults (options, iw);
 
   options->initial_windows = g_list_append (options->initial_windows, iw);
@@ -494,6 +487,27 @@
 }
 
 static gboolean
+option_load_save_config_cb (const gchar *option_name,
+                            const gchar *value,
+                            gpointer     data,
+                            GError     **error)
+{
+  TerminalOptions *options = data;
+
+  if (options->config_file)
+    {
+      g_set_error (error, 0, 0, "X"); /* FIXME */
+      return FALSE;
+    }
+
+  options->config_file = g_strdup (value);
+  options->load_config = strcmp (option_name, "--load-config") == 0;
+  options->save_config = strcmp (option_name, "--save-config") == 0;
+
+  return TRUE;
+}
+
+static gboolean
 option_title_callback (const gchar *option_name,
                        const gchar *value,
                        gpointer     data,
@@ -743,6 +757,110 @@
   return NULL;
 }
 
+gboolean
+terminal_options_merge_config (TerminalOptions *options,
+                               GKeyFile *key_file,
+                               GError **error)
+{
+  int version, compat_version;
+  char **groups;
+  guint i;
+  gboolean have_error = FALSE;
+  GList *initial_windows = NULL;
+
+  if (!g_key_file_has_group (key_file, TERMINAL_CONFIG_GROUP))
+    {
+      g_set_error_literal (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
+                           _("Not a valid terminal config file."));
+      return FALSE;
+    }
+  
+  version = g_key_file_get_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_VERSION, NULL);
+  compat_version = g_key_file_get_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_COMPAT_VERSION, NULL);
+
+  if (version <= 0 ||
+      compat_version <= 0 ||
+      compat_version > TERMINAL_CONFIG_COMPAT_VERSION)
+    {
+      g_set_error_literal (error, 0 /* FIXME */, 0,
+                           _("Incompatible terminal config file version."));
+      return FALSE;
+    }
+
+  groups = g_key_file_get_string_list (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_WINDOWS, NULL, error);
+  if (!groups)
+    return FALSE;
+
+  for (i = 0; groups[i]; ++i)
+    {
+      const char *window_group = groups[i];
+      char **tab_groups;
+      InitialWindow *iw;
+      guint j;
+
+      tab_groups = g_key_file_get_string_list (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_TABS, NULL, error);
+      if (!tab_groups)
+        continue; /* no tabs in this window, skip it */
+
+      iw = initial_window_new ();
+      initial_windows = g_list_append (initial_windows, iw);
+      apply_defaults (options, iw);
+
+      iw->role = g_key_file_get_string (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_ROLE, NULL);
+      iw->geometry = g_key_file_get_string (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_GEOMETRY, NULL);
+      iw->start_fullscreen = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_FULLSCREEN, NULL);
+      iw->start_maximized = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MAXIMIZED, NULL);
+      if (g_key_file_has_key (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE, NULL))
+        {
+          iw->force_menubar_state = TRUE;
+          iw->menubar_state = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE, NULL);
+        }
+
+      for (j = 0; tab_groups[j]; ++j)
+        {
+          const char *tab_group = tab_groups[j];
+          InitialTab *it;
+          char *profile;
+
+          profile = g_key_file_get_string (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID, NULL);
+          it = initial_tab_new (profile, TRUE);
+          g_free (profile);
+
+          iw->tabs = g_list_append (iw->tabs, it);
+
+/*          it->width = g_key_file_get_integer (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_WIDTH, NULL);
+          it->height = g_key_file_get_integer (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT, NULL);*/
+          it->working_dir = terminal_util_key_file_get_string_unescape (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY, NULL);
+          it->title = g_key_file_get_string (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_TITLE, NULL);
+
+          if (g_key_file_has_key (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND, NULL) &&
+              !(it->exec_argv = terminal_util_key_file_get_argv (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND, NULL, error)))
+            {
+              have_error = TRUE;
+              break;
+            }
+        }
+
+      g_strfreev (tab_groups);
+
+      if (have_error)
+        break;
+    }
+
+  g_strfreev (groups);
+
+  if (have_error)
+    {
+      g_list_foreach (initial_windows, (GFunc) initial_window_free, NULL);
+      g_list_free (initial_windows);
+      return FALSE;
+    }
+
+  options->initial_windows = g_list_concat (options->initial_windows, initial_windows);
+
+  return TRUE;
+}
+
 void
 terminal_options_free (TerminalOptions *options)
 {
@@ -777,6 +895,24 @@
       N_("Do not register with the activation nameserver, do not re-use an active terminal"),
       NULL
     },
+    {
+      "load-config",
+      0,
+      G_OPTION_FLAG_FILENAME,
+      G_OPTION_ARG_CALLBACK,
+      option_load_save_config_cb,
+      N_("Load a terminal configuration file"),
+      N_("FILE")
+    },
+    {
+      "save-config",
+      0,
+      G_OPTION_FLAG_FILENAME,
+      G_OPTION_ARG_CALLBACK,
+      option_load_save_config_cb,
+      N_("Save the terminal configuration to a file"),
+      N_("FILE")
+    },
     { "version", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
     { NULL, 0, 0, 0, NULL, NULL, NULL }
   };

Modified: trunk/src/terminal-options.h
==============================================================================
--- trunk/src/terminal-options.h	(original)
+++ trunk/src/terminal-options.h	Sat Nov 29 19:49:14 2008
@@ -48,6 +48,10 @@
   gboolean  execute;
   gboolean  use_factory;
   double    zoom;
+
+  char    *config_file;
+  gboolean load_config;
+  gboolean save_config;
 } TerminalOptions;
 
 typedef struct
@@ -87,6 +91,10 @@
                                          GError **error,
                                          ...);
 
+gboolean terminal_options_merge_config (TerminalOptions *options,
+                                        GKeyFile *key_file,
+                                        GError **error);
+
 void terminal_options_free (TerminalOptions *options);
 
 G_END_DECLS

Modified: trunk/src/terminal-screen.c
==============================================================================
--- trunk/src/terminal-screen.c	(original)
+++ trunk/src/terminal-screen.c	Sat Nov 29 19:49:14 2008
@@ -654,10 +654,38 @@
   G_OBJECT_CLASS (terminal_screen_parent_class)->finalize (object);
 }
 
-TerminalScreen*
-terminal_screen_new (void)
+TerminalScreen *
+terminal_screen_new (TerminalProfile *profile,
+                     char           **override_command,
+                     const char      *title,
+                     const char      *working_dir,
+                     char           **child_env,
+                     double           zoom)
 {
-  return g_object_new (TERMINAL_TYPE_SCREEN, NULL);
+  TerminalScreen *screen;
+
+  g_return_val_if_fail (TERMINAL_IS_PROFILE (profile), NULL);
+
+  screen = g_object_new (TERMINAL_TYPE_SCREEN, NULL);
+
+  terminal_screen_set_profile (screen, profile);
+
+  if (title)
+    terminal_screen_set_override_title (screen, title);
+
+  if (working_dir)
+    terminal_screen_set_working_dir (screen, working_dir);
+
+  if (override_command)
+    terminal_screen_set_override_command (screen, override_command);
+
+  if (child_env)
+    terminal_screen_set_initial_environment (screen, child_env);
+
+  terminal_screen_set_font_scale (screen, zoom);
+  terminal_screen_set_font (screen);
+
+  return screen;
 }
 
 const char*
@@ -2214,3 +2242,36 @@
   g_free (match);
   return NULL;
 }
+
+void
+terminal_screen_save_config (TerminalScreen *screen,
+                             GKeyFile *key_file,
+                             const char *group)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  VteTerminal *terminal = VTE_TERMINAL (screen);
+  TerminalProfile *profile = priv->profile;
+  const char *profile_id, *dir;
+
+  profile_id = terminal_profile_get_property_string (profile, TERMINAL_PROFILE_NAME);
+  g_key_file_set_string (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID, profile_id);
+
+  if (priv->override_command)
+    terminal_util_key_file_set_argv (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND,
+                                     -1, priv->override_command);
+
+  /* FIXMEchpe: only persist user-set titles here */
+  if (priv->raw_title)
+    g_key_file_set_string (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_TITLE, priv->raw_title);
+
+  dir = terminal_screen_get_working_dir (screen);
+  if (dir != NULL && *dir != '\0') /* should always be TRUE anyhow */
+    terminal_util_key_file_set_string_escape (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY, dir);
+
+  g_key_file_set_double (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_ZOOM, priv->font_scale);
+
+  g_key_file_set_integer (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_WIDTH,
+                          vte_terminal_get_column_count (terminal));
+  g_key_file_set_integer (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT,
+                          vte_terminal_get_row_count (terminal));
+}

Modified: trunk/src/terminal-screen.h
==============================================================================
--- trunk/src/terminal-screen.h	(original)
+++ trunk/src/terminal-screen.h	Sat Nov 29 19:49:14 2008
@@ -74,7 +74,12 @@
 
 GType terminal_screen_get_type (void) G_GNUC_CONST;
 
-TerminalScreen* terminal_screen_new                    (void);
+TerminalScreen *terminal_screen_new (TerminalProfile *profile,
+                                     char           **override_command,
+                                     const char      *title,
+                                     const char      *working_dir,
+                                     char           **child_env,
+                                     double           zoom);
 
 void terminal_screen_set_profile (TerminalScreen *screen,
                                   TerminalProfile *profile);
@@ -122,6 +127,10 @@
 
 void _terminal_screen_update_scrollbar (TerminalScreen *screen);
 
+void terminal_screen_save_config (TerminalScreen *screen,
+                                  GKeyFile *key_file,
+                                  const char *group);
+
 /* Allow scales a bit smaller and a bit larger than the usual pango ranges */
 #define TERMINAL_SCALE_XXX_SMALL   (PANGO_SCALE_XX_SMALL/1.2)
 #define TERMINAL_SCALE_XXXX_SMALL  (TERMINAL_SCALE_XXX_SMALL/1.2)

Modified: trunk/src/terminal-util.c
==============================================================================
--- trunk/src/terminal-util.c	(original)
+++ trunk/src/terminal-util.c	Sat Nov 29 19:49:14 2008
@@ -379,6 +379,92 @@
   return TRUE;
 }
 
+/* Like g_key_file_set_string, but escapes characters so that
+ * the stored string is ASCII. Use when the input string may not
+ * be UTF-8.
+ */
+void
+terminal_util_key_file_set_string_escape (GKeyFile *key_file,
+                                          const char *group,
+                                          const char *key,
+                                          const char *string)
+{
+  char *escaped;
+
+  /* FIXMEchpe: be more intelligent and only escape characters that aren't UTF-8 */
+  escaped = g_strescape (string, NULL);
+  g_key_file_set_string (key_file, group, key, escaped);
+  g_free (escaped);
+}
+
+char *
+terminal_util_key_file_get_string_unescape (GKeyFile *key_file,
+                                            const char *group,
+                                            const char *key,
+                                            GError **error)
+{
+  char *escaped, *unescaped;
+
+  escaped = g_key_file_get_string (key_file, group, key, error);
+  if (!escaped)
+    return NULL;
+
+  unescaped = g_strcompress (escaped);
+  g_free (escaped);
+
+  return unescaped;
+}
+
+void
+terminal_util_key_file_set_argv (GKeyFile *key_file,
+                                 const char *group,
+                                 const char *key,
+                                 int argc,
+                                 char **argv)
+{
+  char **quoted_argv;
+  char *flat;
+  int i;
+
+  if (argc < 0)
+    argc = g_strv_length (argv);
+
+  quoted_argv = g_new (char*, argc + 1);
+  for (i = 0; i < argc; ++i)
+    quoted_argv[i] = g_shell_quote (argv[i]);
+  quoted_argv[argc] = NULL;
+
+  flat = g_strjoinv (" ", quoted_argv);
+  terminal_util_key_file_set_string_escape (key_file, group, key, flat);
+
+  g_free (flat);
+  g_strfreev (quoted_argv);
+}
+
+char **
+terminal_util_key_file_get_argv (GKeyFile *key_file,
+                                 const char *group,
+                                 const char *key,
+                                 int *argc,
+                                 GError **error)
+{
+  char **argv;
+  char *flat;
+  gboolean retval;
+
+  flat = terminal_util_key_file_get_string_unescape (key_file, group, key, error);
+  if (!flat)
+    return NULL;
+
+  retval = g_shell_parse_argv (flat, argc, &argv, error);
+  g_free (flat);
+
+  if (retval)
+    return argv;
+
+  return NULL;
+}
+
 /* Bidirectional object/widget binding */
 
 typedef struct {
@@ -646,3 +732,4 @@
   object_change_notify_cb (change);
   change->object_notify_id = g_signal_connect_swapped (object, notify_signal, G_CALLBACK (object_change_notify_cb), change);
 }
+

Modified: trunk/src/terminal-util.h
==============================================================================
--- trunk/src/terminal-util.h	(original)
+++ trunk/src/terminal-util.h	Sat Nov 29 19:49:14 2008
@@ -59,6 +59,26 @@
 
 gboolean terminal_util_dialog_response_on_delete (GtkWindow *widget);
 
+void terminal_util_key_file_set_string_escape    (GKeyFile *key_file,
+                                                  const char *group,
+                                                  const char *key,
+                                                  const char *string);
+char *terminal_util_key_file_get_string_unescape (GKeyFile *key_file,
+                                                  const char *group,
+                                                  const char *key,
+                                                  GError **error);
+
+void terminal_util_key_file_set_argv      (GKeyFile *key_file,
+                                           const char *group,
+                                           const char *key,
+                                           int argc,
+                                           char **argv);
+char **terminal_util_key_file_get_argv    (GKeyFile *key_file,
+                                           const char *group,
+                                           const char *key,
+                                           int *argc,
+                                           GError **error);
+
 typedef enum {
   FLAG_INVERT_BOOL  = 1 << 0,
 } PropertyChangeFlags;

Modified: trunk/src/terminal-window.c
==============================================================================
--- trunk/src/terminal-window.c	(original)
+++ trunk/src/terminal-window.c	Sat Nov 29 19:49:14 2008
@@ -3370,3 +3370,70 @@
 
   return priv->ui_manager;
 }
+
+void
+terminal_window_save_state (TerminalWindow *window,
+                            GKeyFile *key_file,
+                            const char *group)
+{
+  TerminalWindowPrivate *priv = window->priv;
+  GList *tabs, *lt;
+  TerminalScreen *active_screen;
+  GdkWindowState state;
+  GPtrArray *tab_names_array;
+  char **tab_names;
+  gsize len;
+
+  //XXXif (priv->menub)//XXX
+  g_key_file_set_boolean (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE,
+                          priv->menubar_visible);
+
+  g_key_file_set_string (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_ROLE,
+                         gtk_window_get_role (GTK_WINDOW (window)));
+
+  state = gdk_window_get_state (GTK_WIDGET (window)->window);
+  if (state & GDK_WINDOW_STATE_MAXIMIZED)
+    g_key_file_set_boolean (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_MAXIMIZED, TRUE);
+  if (state & GDK_WINDOW_STATE_FULLSCREEN)
+    g_key_file_set_boolean (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_FULLSCREEN, TRUE);
+
+  active_screen = terminal_window_get_active (window);
+  tabs = terminal_window_list_screen_containers (window);
+
+  tab_names_array = g_ptr_array_sized_new (g_list_length (tabs) + 1);
+
+  for (lt = tabs; lt != NULL; lt = lt->next)
+    {
+      TerminalScreen *screen;
+      char *tab_group;
+
+      tab_group = g_strdup_printf ("Terminal%p", screen);
+      g_ptr_array_add (tab_names_array, tab_group);
+
+      screen = terminal_screen_container_get_screen (GTK_WIDGET (lt->data));
+      terminal_screen_save_config (screen, key_file, tab_group);
+
+      if (screen == active_screen)
+        {
+          int w, h, x, y;
+          char *geometry;
+
+          g_key_file_set_string (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_ACTIVE_TAB, tab_group);
+
+          /* FIXME saving the geometry is not great :-/ */
+          terminal_screen_get_size (screen, &w, &h);
+          gtk_window_get_position (GTK_WINDOW (window), &x, &y);
+          geometry = g_strdup_printf ("%dx%d+%d+%d", w, h, x, y);
+          g_key_file_set_string (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_GEOMETRY, geometry);
+          g_free (geometry);
+        }
+    }
+
+  g_list_free (tabs);
+
+  g_ptr_array_add (tab_names_array, NULL);
+  len = tab_names_array->len;
+  tab_names = (char **) g_ptr_array_free (tab_names_array, FALSE);
+  g_key_file_set_string_list (key_file, group, TERMINAL_CONFIG_WINDOW_PROP_TABS, (const char * const *) tab_names, len);
+  g_strfreev (tab_names);
+}

Modified: trunk/src/terminal-window.h
==============================================================================
--- trunk/src/terminal-window.h	(original)
+++ trunk/src/terminal-window.h	Sat Nov 29 19:49:14 2008
@@ -98,6 +98,10 @@
 
 gboolean terminal_window_uses_argb_visual (TerminalWindow *window);
 
+void terminal_window_save_state (TerminalWindow *window,
+                                 GKeyFile *key_file,
+                                 const char *group);
+
 G_END_DECLS
 
 #endif /* TERMINAL_WINDOW_H */

Modified: trunk/src/terminal.c
==============================================================================
--- trunk/src/terminal.c	(original)
+++ trunk/src/terminal.c	Sat Nov 29 19:49:14 2008
@@ -35,6 +35,7 @@
 
 #ifdef WITH_SMCLIENT
 #include "eggsmclient.h"
+#include "eggdesktopfile.h"
 #endif
 
 #include <dbus/dbus-protocol.h>
@@ -384,10 +385,14 @@
   gtk_about_dialog_set_url_hook (about_url_hook, NULL, NULL);
   gtk_about_dialog_set_email_hook (about_email_hook, NULL, NULL);
 
+#ifdef WITH_SMCLIENT
+  //egg_set_desktop_file (TERM_DATADIR G_DIR_SEPARATOR_S  // FIXME)
+#endif
+
   terminal_app_initialize (options->use_factory);
   g_signal_connect (terminal_app_get (), "quit", G_CALLBACK (gtk_main_quit), NULL);
 
-  terminal_app_handle_options (terminal_app_get (), options);
+  terminal_app_handle_options (terminal_app_get (), options, NULL);
   terminal_options_free (options);
 
   gtk_main ();
@@ -405,7 +410,7 @@
 static gboolean
 handle_new_terminal_event (TerminalOptions *options)
 {
-  terminal_app_handle_options (terminal_app_get (), options);
+  terminal_app_handle_options (terminal_app_get (), options, NULL);
 
   return FALSE;
 }



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