[aisleriot/wip/redesign: 2/17] conf: Port some settings to GSettings



commit ecab5b209c1684c51144a5694a51c4fff26dec91
Author: Christian Persch <chpe gnome org>
Date:   Tue Jun 25 20:35:35 2013 +0200

    conf: Port some settings to GSettings

 src/Makefile.am                        |   15 +++-
 src/ar-application.c                   |   85 ++++++++++++++++++++-
 src/ar-application.h                   |   21 ++++--
 src/ar-game-chooser.c                  |   32 ++++++--
 src/board-noclutter.c                  |    1 -
 src/board.c                            |    2 -
 src/game.c                             |   47 ++++++++----
 src/game.h                             |    3 +
 src/org.gnome.Aisleriot.gschema.xml.in |  127 ++++++++++++++++++++++++++++++++
 src/sol.c                              |   17 +----
 src/stats-dialog.c                     |   34 +++++----
 src/stats-dialog.h                     |    2 +-
 src/window.c                           |  122 ++++++++++++++++++-------------
 13 files changed, 385 insertions(+), 123 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 7a62493..06b48f5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,7 @@ sol_SOURCES = \
        ar-clock.h \
        ar-cursor.c     \
        ar-cursor.h     \
+       ar-defines.h \
        ar-game-chooser.c \
        ar-game-chooser.h \
        ar-resources.c  \
@@ -27,8 +28,6 @@ sol_SOURCES = \
        ar-style-gtk.h  \
        board-noclutter.c \
        board-noclutter.h \
-       conf.c          \
-       conf.h          \
        game.c          \
        game.h          \
        sol.c           \
@@ -83,6 +82,7 @@ sol_clutter_SOURCES = \
        ar-clutter-embed.h \
        ar-cursor.c     \
        ar-cursor.h     \
+       ar-defines.h \
        ar-game-chooser.c \
        ar-game-chooser.h \
        ar-resources.c  \
@@ -100,8 +100,6 @@ sol_clutter_SOURCES = \
        board.h         \
        card.c          \
        card.h          \
-       conf.c          \
-       conf.h          \
        game.c          \
        game.h          \
        sol.c           \
@@ -137,6 +135,12 @@ BUILT_SOURCES = \
 ar-resources.h ar-resources.c: aisleriot.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) 
--generate-dependencies aisleriot.gresource.xml)
        $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir . --generate 
--c-name aisleriot $<
 
+gsettingsschema_in_files = \
+       org.gnome.Aisleriot.gschema.xml.in \
+       $(NULL)
+
+gsettings_SCHEMAS = $(gsettingsschema_in_files:.gschema.xml.in=.gschema.xml)
+
 schema_in_files = aisleriot.schemas.in
 if HAVE_GNOME
 schemadir = $(GCONF_SCHEMA_FILE_DIR)
@@ -165,6 +169,7 @@ EXTRA_DIST = \
        $(icon_DATA)            \
        $(allicons)             \
        $(schema_in_files)      \
+       $(gsettingsschema_in_files) \
        aisleriot-ui.xml        \
        aisleriot-debug-ui.xml  \
        game-names.h
@@ -179,5 +184,7 @@ DISTCLEANFILES = \
        $(service_DATA)
 
 @INTLTOOL_SCHEMAS_RULE@
+ INTLTOOL_XML_NOMERGE_RULE@
+ GSETTINGS_RULES@
 
 -include $(top_srcdir)/git.mk
diff --git a/src/ar-application.c b/src/ar-application.c
index 65bf938..9405af3 100644
--- a/src/ar-application.c
+++ b/src/ar-application.c
@@ -1,6 +1,6 @@
 /*
  * Copyright © 1998, 2001, 2003, 2006 Jonathan Blandford <jrb alum mit edu>
- * Copyright © 2007 Christian Persch
+ * Copyright © 2007, 2013 Christian Persch
  * Copyright © 2007 Andreas Røsdal <andreasr gnome org>
  * Copyright © 2013 William Jon McCann
  *
@@ -19,13 +19,19 @@
  */
 
 #include "config.h"
+#define G_SETTINGS_ENABLE_BACKEND
 
 #include "ar-application.h"
+#include "ar-defines.h"
+#include "ar-runtime.h"
 
+#include <errno.h>
 #include <stdlib.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gsettingsbackend.h>
 #include <gtk/gtk.h>
 
 #ifdef HAVE_CLUTTER
@@ -39,7 +45,6 @@
 #include "ar-sound.h"
 #include "ar-string-utils.h"
 
-#include "conf.h"
 #include "window.h"
 #include "game.h"
 #include "util.h"
@@ -61,6 +66,9 @@ struct _ArApplicationPrivate
   char *variation;
   gint seed; /* unused */
   gboolean freecell; /* unused */
+
+  GSettingsBackend *state_keyfile_backend;
+  GSettingsBackend *scores_keyfile_backend;
 };
 
 #if !GTK_CHECK_VERSION (3, 6, 0)
@@ -198,12 +206,28 @@ ar_application_startup (GApplication *application)
   ArApplicationPrivate *priv = self->priv;
   GMenu *menu;
   GMenu *section;
+  char *path;
 
   G_APPLICATION_CLASS (ar_application_parent_class)->startup (application);
 
   ar_sound_enable (FALSE);
   ar_stock_init ();
 
+  path = g_build_filename (g_get_user_config_dir (), "aisleriot", NULL);
+  if (g_mkdir_with_parents (path, 0700 /* as per XDG base dir spec */) < 0 && errno != EEXIST)
+    g_printerr ("Failed to create config directory \"%s\": %s\n", path, g_strerror (errno));
+  g_free (path);
+
+  path = g_build_filename (g_get_user_config_dir (), "aisleriot", "state.ini", NULL);
+  priv->state_keyfile_backend = g_keyfile_settings_backend_new (path,
+                                                                "/org/gnome/aisleriot/",
+                                                                NULL);
+
+  path = g_build_filename (g_get_user_config_dir (), "aisleriot", "scores.ini", NULL);
+  priv->scores_keyfile_backend = g_keyfile_settings_backend_new (path,
+                                                                 "/org/gnome/aisleriot/scores/",
+                                                                 NULL);
+
   gtk_window_set_default_icon_name (priv->freecell ? "gnome-freecell" : "gnome-aisleriot");
 
   g_action_map_add_action_entries (G_ACTION_MAP (self),
@@ -252,11 +276,15 @@ static void
 ar_application_dispose (GObject *object)
 {
   ArApplication *self = AR_APPLICATION (object);
-
-  G_OBJECT_CLASS (ar_application_parent_class)->dispose (object);
+  ArApplicationPrivate *priv = self->priv;
 
   g_free (self->priv->variation);
   self->priv->variation = NULL;
+
+  g_clear_object (&priv->state_keyfile_backend);
+  g_clear_object (&priv->scores_keyfile_backend);
+
+  G_OBJECT_CLASS (ar_application_parent_class)->dispose (object);
 }
 
 static void
@@ -296,3 +324,52 @@ ar_application_new (const char *variation,
 
   return GTK_APPLICATION (app);
 }
+
+GSettings *
+ar_application_state_settings_new (ArApplication *application,
+                                   const char *schema)
+{
+  g_return_val_if_fail (AR_IS_APPLICATION (application), NULL);
+  g_return_val_if_fail (schema != NULL, NULL);
+
+  return g_settings_new_with_backend (schema,
+                                      application->priv->state_keyfile_backend);
+}
+
+GSettings *
+ar_application_scores_settings_new (ArApplication *application,
+                                    const char *game)
+{
+  char *path;
+  GSettings *settings;
+
+  g_return_val_if_fail (AR_IS_APPLICATION (application), NULL);
+  g_return_val_if_fail (game != NULL, NULL);
+
+  path = g_strdup_printf ("/org/gnome/aisleriot/scores/%s/", game);
+  settings = g_settings_new_with_backend_and_path (AR_SCORES_SCHEMA,
+                                                   application->priv->scores_keyfile_backend,
+                                                   path);
+  g_free (path);
+
+  return settings;
+}
+
+GSettings *
+ar_application_options_settings_new (ArApplication *application,
+                                     const char *game)
+{
+  char *path;
+  GSettings *settings;
+
+  g_return_val_if_fail (AR_IS_APPLICATION (application), NULL);
+  g_return_val_if_fail (game != NULL, NULL);
+
+  path = g_strdup_printf ("/org/gnome/aisleriot/options/%s/", game);
+  settings = g_settings_new_with_backend_and_path (AR_OPTIONS_SCHEMA,
+                                                   application->priv->state_keyfile_backend,
+                                                   path);
+  g_free (path);
+
+  return settings;
+}
diff --git a/src/ar-application.h b/src/ar-application.h
index f5ac430..df5f381 100644
--- a/src/ar-application.h
+++ b/src/ar-application.h
@@ -22,12 +22,12 @@
 
 G_BEGIN_DECLS
 
-#define AR_TYPE_APPLICATION               (ar_application_get_type ())
-#define AR_APPLICATION(o)                 (G_TYPE_CHECK_INSTANCE_CAST ((o), AR_TYPE_APPLICATION, 
ArApplication))
-#define AR_APPLICATION_CLASS(k)           (G_TYPE_CHECK_CLASS_CAST((k), AR_TYPE_APPLICATION, 
ArApplicationClass))
-#define AISLERIOT_IS_APPLICATION(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), AR_TYPE_APPLICATION))
-#define AISLERIOT_IS_APPLICATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), AR_TYPE_APPLICATION))
-#define AR_APPLICATION_GET_CLASS(o)       (G_TYPE_INSTANCE_GET_CLASS ((o), AR_TYPE_APPLICATION, 
ArApplicationClass))
+#define AR_TYPE_APPLICATION         (ar_application_get_type ())
+#define AR_APPLICATION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), AR_TYPE_APPLICATION, ArApplication))
+#define AR_APPLICATION_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), AR_TYPE_APPLICATION, ArApplicationClass))
+#define AR_IS_APPLICATION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), AR_TYPE_APPLICATION))
+#define AR_IS_APPLICATION_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), AR_TYPE_APPLICATION))
+#define AR_APPLICATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), AR_TYPE_APPLICATION, 
ArApplicationClass))
 
 typedef struct _ArApplication       ArApplication;
 typedef struct _ArApplicationPrivate ArApplicationPrivate;
@@ -38,6 +38,15 @@ GType ar_application_get_type (void);
 GtkApplication *ar_application_new (const char *variation,
                                     gboolean freecell);
 
+GSettings *ar_application_state_settings_new (ArApplication *application,
+                                              const char *schema);
+
+GSettings *ar_application_scores_settings_new (ArApplication *application,
+                                               const char *game);
+
+GSettings *ar_application_options_settings_new (ArApplication *application,
+                                                const char *game);
+
 G_END_DECLS
 
 #endif /* !AR_APPLICATION_H */
diff --git a/src/ar-game-chooser.c b/src/ar-game-chooser.c
index 686fb53..4fea5a1 100644
--- a/src/ar-game-chooser.c
+++ b/src/ar-game-chooser.c
@@ -1,5 +1,5 @@
 /*  
- * Copyright © 2009 Christian Persch <chpe gnome org>
+ * Copyright © 2009, 2013 Christian Persch <chpe gnome org>
  * 
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 
 #include "ar-game-chooser.h"
 
@@ -23,10 +23,11 @@
 
 #include <glib/gi18n.h>
 
+#include "ar-application.h"
 #include "ar-debug.h"
+#include "ar-defines.h"
 #include "ar-runtime.h"
 #include "ar-string-utils.h"
-#include "conf.h"
 
 struct _ArGameChooser
 {
@@ -43,7 +44,7 @@ struct _ArGameChooserClass
 
 struct _ArGameChooserPrivate {
   AisleriotWindow *window;
-
+  GSettings *state_settings;
   GtkListStore *store;
   GtkTreeSelection *selection;
 };
@@ -163,14 +164,16 @@ row_separator_func (GtkTreeModel *model,
 }
 
 static char **
-get_unique_recent_modules (const char *current_module)
+get_unique_recent_modules (ArGameChooser *chooser,
+                           const char *current_module)
 {
+  ArGameChooserPrivate *priv = chooser->priv;
   char **recent_games, **new_recent;
   gsize i;
   gsize n_recent = 0;
   gsize n_new_recent = 0;
 
-  recent_games = ar_conf_get_string_list (NULL, aisleriot_conf_get_key (CONF_RECENT_GAMES), &n_recent, NULL);
+  g_settings_get (priv->state_settings, AR_STATE_RECENT_GAMES_KEY, "^as", &recent_games);
 
   if (recent_games == NULL) {
     new_recent = g_new (char *, 2);
@@ -219,7 +222,7 @@ add_recent_items (ArGameChooser *chooser)
   int i;
 
   current_game_module = aisleriot_window_get_game_module (priv->window);
-  games = get_unique_recent_modules (current_game_module);
+  games = get_unique_recent_modules (chooser, current_game_module);
 
   for (i = 0; games[i] != NULL; ++i) {
     store_add_module (priv->store, games[i], MAX_RECENT - i);
@@ -293,6 +296,9 @@ ar_game_chooser_constructor (GType type,
 
   g_assert (priv->window != NULL);
 
+  priv->state_settings = ar_application_state_settings_new (AR_APPLICATION (g_application_get_default ()),
+                                                            AR_STATE_SCHEMA);
+
   priv->store = list = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
 
   add_recent_items (chooser);
@@ -401,6 +407,17 @@ ar_game_chooser_constructor (GType type,
 }
 
 static void
+ar_game_chooser_finalize (GObject *object)
+{
+  ArGameChooser *chooser = AR_GAME_CHOOSER (object);
+  ArGameChooserPrivate *priv = chooser->priv;
+
+  g_clear_object (&priv->state_settings);
+
+  G_OBJECT_CLASS (ar_game_chooser_parent_class)->finalize (object);
+}
+
+static void
 ar_game_chooser_set_property (GObject      *object,
                               guint         property_id,
                               const GValue *value,
@@ -427,6 +444,7 @@ ar_game_chooser_class_init (ArGameChooserClass *klass)
   g_type_class_add_private (klass, sizeof (ArGameChooserPrivate));
 
   object_class->constructor = ar_game_chooser_constructor;
+  object_class->finalize = ar_game_chooser_finalize;
   object_class->set_property = ar_game_chooser_set_property;
 
   /**
diff --git a/src/board-noclutter.c b/src/board-noclutter.c
index b44507c..af42411 100644
--- a/src/board-noclutter.c
+++ b/src/board-noclutter.c
@@ -32,7 +32,6 @@
 #include "ar-runtime.h"
 #include "ar-sound.h"
 
-#include "conf.h"
 #include "game.h"
 #include "ar-cursor.h"
 #include "ar-card-surface-cache.h"
diff --git a/src/board.c b/src/board.c
index deb49be..93ef208 100644
--- a/src/board.c
+++ b/src/board.c
@@ -34,8 +34,6 @@
 #include "ar-marshal.h"
 #include "ar-sound.h"
 
-#include "conf.h"
-
 #include "game.h"
 #include "card.h"
 #include "slot-renderer.h"
diff --git a/src/game.c b/src/game.c
index ea18e11..83e7f8e 100644
--- a/src/game.c
+++ b/src/game.c
@@ -1,6 +1,6 @@
 /*
  * Copyright © 1998, 2003 Jonathan Blandford <jrb alum mit edu>
- * Copyright © 2007, 2011 Christian Persch
+ * Copyright © 2007, 2011, 2013 Christian Persch
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 
 #include <string.h>
 #include <unistd.h>
@@ -31,11 +31,12 @@
 #include <clutter/clutter.h>
 #endif
 
+#include "ar-application.h"
 #include "ar-debug.h"
+#include "ar-defines.h"
 #include "ar-runtime.h"
 #include "ar-string-utils.h"
 
-#include "conf.h"
 #include "util.h"
 
 #include "game.h"
@@ -87,6 +88,8 @@ struct _AisleriotGame
 {
   GObject parent_instance;
 
+  GSettings *scores_settings;
+
   GPtrArray *slots;
 
   char *game_module;
@@ -217,28 +220,28 @@ set_game_dealable (AisleriotGame *game,
 static void
 update_statistics (AisleriotGame *game)
 {
-  AisleriotStatistic current_stats;
-  time_t t;
-
-  aisleriot_conf_get_statistic (game->game_module, &current_stats);
+  guint32 wins, total, best_time, worst_time, t;
 
-  current_stats.total++;
+  total = g_settings_get_uint (game->scores_settings, AR_SCORES_TOTAL_KEY);
+  g_settings_set_uint (game->scores_settings, AR_SCORES_TOTAL_KEY, total + 1);
 
   if (game->state == GAME_WON) {
-    current_stats.wins++;
+    wins = g_settings_get_uint (game->scores_settings, AR_SCORES_WINS_KEY);
+    g_settings_set_uint (game->scores_settings, AR_SCORES_WINS_KEY, wins + 1);
 
-    t = (time_t) (g_timer_elapsed (game->timer, NULL) + 0.5);
+    t = (guint32) (g_timer_elapsed (game->timer, NULL) + 0.5);
     if (t > 0) {
-      if ((current_stats.best == 0) || (t < current_stats.best)) {
-       current_stats.best = t;
+      best_time = g_settings_get_uint (game->scores_settings, AR_SCORES_BEST_TIME_KEY);
+      worst_time = g_settings_get_uint (game->scores_settings, AR_SCORES_WORST_TIME_KEY);
+
+      if ((best_time == 0) || (t < best_time)) {
+        g_settings_set_uint (game->scores_settings, AR_SCORES_BEST_TIME_KEY, t);
       }
-      if (t > current_stats.worst) {
-       current_stats.worst = t;
+      if (t > worst_time) {
+        g_settings_set_uint (game->scores_settings, AR_SCORES_WORST_TIME_KEY, t);
       }
     }
   }
-
-  aisleriot_conf_set_statistic (game->game_module, &current_stats);
 }
 
 static void
@@ -1220,6 +1223,8 @@ aisleriot_game_finalize (GObject *object)
 
   free (game->score);
 
+  g_clear_object (&game->scores_settings);
+
   app_game = NULL;
 
   G_OBJECT_CLASS (aisleriot_game_parent_class)->finalize (object);
@@ -1779,6 +1784,10 @@ aisleriot_game_load_game (AisleriotGame *game,
 
   set_game_state (game, GAME_LOADED);
 
+  g_clear_object (&game->scores_settings);
+  game->scores_settings = ar_application_scores_settings_new (AR_APPLICATION (g_application_get_default ()),
+                                                              game_module);
+
   g_object_notify (object, "game-file");
 
   g_object_thaw_notify (object);
@@ -2683,3 +2692,9 @@ ar_get_game_modules (void)
 
   return (char **) g_ptr_array_free (array, FALSE);
 }
+
+GSettings *
+aisleriot_game_get_scores_settings (AisleriotGame *game)
+{
+  return game->scores_settings;
+}
diff --git a/src/game.h b/src/game.h
index 4238569..5d64e79 100644
--- a/src/game.h
+++ b/src/game.h
@@ -18,6 +18,7 @@
 #ifndef AISLERIOT_GAME_H
 #define AISLERIOT_GAME_H
 
+#include <gio/gio.h>
 #include <gdk/gdk.h>
 
 #include "ar-card.h"
@@ -245,6 +246,8 @@ void aisleriot_game_reset_old_cards (ArSlot *slot);
 
 const char *aisleriot_game_get_score (AisleriotGame *game);
 
+GSettings *aisleriot_game_get_scores_settings (AisleriotGame *game);
+
 char **ar_get_game_modules (void);
 
 G_END_DECLS
diff --git a/src/org.gnome.Aisleriot.gschema.xml.in b/src/org.gnome.Aisleriot.gschema.xml.in
new file mode 100644
index 0000000..deec6b2
--- /dev/null
+++ b/src/org.gnome.Aisleriot.gschema.xml.in
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright © 2013 Christian Persch
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<schemalist gettext-domain="aisleriot">
+
+  <schema id="org.gnome.Aisleriot.Settings"
+          path="/org/gnome/aisleriot/settings/">
+
+    <key name="show-toolbar" type="b">
+      <default>true</default>
+      <_summary>Whether to show the toolbar</_summary>
+    </key>
+
+    <key name="show-statusbar" type="b">
+      <default>true</default>
+      <_summary>Whether to show the statusbar</_summary>
+    </key>
+
+    <key name="click-to-move" type="b">
+      <default>true</default>
+      <_summary>Whether click-to-move mode is enabled</_summary>
+    </key>
+
+    <key name="enable-sound" type="b">
+      <default>true</default>
+      <_summary>Enable sound effects</_summary>
+    </key>
+
+    <key name="enable-animations" type="b">
+      <default>true</default>
+      <_summary>Enable animations</_summary>
+    </key>
+
+    <key name="card-theme" type="s">
+      <default>''</default>
+      <_summary>Which card theme to use</_summary>
+    </key>
+
+  </schema>
+
+  <schema id="org.gnome.Aisleriot.State.Games"
+          path="/org/gnome/aisleriot/state/games/">
+
+    <key name="last-game" type="s">
+      <default>'klondike'</default>
+      <_summary>The game played last</_summary>
+    </key>
+
+    <key name="recent-games" type="as">
+      <default>[]</default>
+      <_summary>A list of recently played games</_summary>
+    </key>
+      
+  </schema>
+
+  <!-- This schema is relocatable -->
+  <schema id="org.gnome.Aisleriot.State.Window" gettext-domain="aisleriot">
+
+    <key name="maximized" type="b">
+      <default>false</default>
+      <_summary>Whether the window is maximized</_summary>
+    </key>
+
+    <key name="fullscreen" type="b">
+      <default>false</default>
+      <_summary>Whether the window is fullscreen</_summary>
+    </key>
+
+    <key name="width" type="i">
+      <!-- <range min="-1" max="65535" /> -->
+      <default>-1</default>
+      <_summary>Window width</_summary>
+    </key>
+
+    <key name="height" type="i">
+      <!-- <range min="-1" max="65535" /> -->
+      <default>-1</default>
+      <_summary>Window height</_summary>
+    </key>
+
+  </schema>
+
+  <!-- This schema is relocatable -->
+  <schema id="org.gnome.Aisleriot.Game.Scores" gettext-domain="aisleriot">
+
+    <key name="wins" type="u">
+      <default>0</default>
+    </key>
+
+    <key name="total" type="u">
+      <default>0</default>
+    </key>
+
+    <key name="best-time" type="u">
+      <default>0</default>
+    </key>
+
+    <key name="worst-time" type="u">
+      <default>0</default>
+    </key>
+
+  </schema>
+
+  <!-- This schema is relocatable -->
+  <schema id="org.gnome.Aisleriot.Game.Options" gettext-domain="aisleriot">
+
+    <key name="options" type="u">
+      <default>0</default>
+    </key>
+
+  </schema>
+
+</schemalist>
diff --git a/src/sol.c b/src/sol.c
index 993baa9..26273de 100644
--- a/src/sol.c
+++ b/src/sol.c
@@ -17,7 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 
 #include <string.h>
 
@@ -40,7 +40,6 @@
 #include "ar-sound.h"
 
 #include "ar-string-utils.h"
-#include "conf.h"
 #include "window.h"
 #include "game.h"
 #include "util.h"
@@ -116,8 +115,6 @@ main_prog (void *closure, int argc, char *argv[])
 
   g_set_application_name (data.freecell ? _("FreeCell Solitaire") : _("AisleRiot"));
 
-  aisleriot_conf_init ();
-
   /* If we are asked for a specific game, check that it is valid. */
   if (!data.freecell &&
       data.variation != NULL) {
@@ -131,22 +128,10 @@ main_prog (void *closure, int argc, char *argv[])
     data.variation = game_module;
   }
 
-  if (!data.freecell && !data.variation) {
-    char *pref;
-
-    pref = ar_conf_get_string_with_default (NULL, aisleriot_conf_get_key (CONF_VARIATION), 
DEFAULT_VARIATION);
-    data.variation = ar_filename_to_game_module (pref);
-    g_free (pref);
-  }
-
-  g_assert (data.variation != NULL || data.freecell);
-
   application = ar_application_new (data.variation, data.freecell);
   status = g_application_run (G_APPLICATION (application), 0, NULL);
   g_object_unref (application);
 
-  aisleriot_conf_shutdown ();
-
 cleanup:
   g_free (data.variation);
 
diff --git a/src/stats-dialog.c b/src/stats-dialog.c
index c649d72..195eb8a 100644
--- a/src/stats-dialog.c
+++ b/src/stats-dialog.c
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2003 Callum McKenzie <callum physics otago ac nz>
- * Copyright © 2007 Christian Persch
+ * Copyright © 2007, 2013 Christian Persch
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 
 #include <glib/gi18n.h>
 
@@ -25,9 +25,7 @@
 #include "util.h"
 
 #include "ar-stock.h"
-
-#include "conf.h"
-#include "util.h"
+#include "ar-defines.h"
 
 #include "stats-dialog.h"
 
@@ -202,24 +200,30 @@ aisleriot_stats_dialog_new (void)
 
 void
 aisleriot_stats_dialog_update (AisleriotStatsDialog *dialog,
-                               AisleriotStatistic *current_stats)
+                               GSettings *stats_settings)
 {
   AisleriotStatsDialogPrivate *priv = dialog->priv;
   char text[128];
+  guint32 wins, total, best_time, worst_time;
+
+  wins = g_settings_get_uint (stats_settings, AR_SCORES_WINS_KEY);
+  total = g_settings_get_uint (stats_settings, AR_SCORES_TOTAL_KEY);
+  best_time = g_settings_get_uint (stats_settings, AR_SCORES_BEST_TIME_KEY);
+  worst_time = g_settings_get_uint (stats_settings, AR_SCORES_WORST_TIME_KEY);
 
   /* Translators: Translate this to "%Id" if you want to use localised digits,
    * and to "%d" otherwise. Do not translate it to anything else!
    */
-  g_snprintf (text, sizeof (text), _("%d"), current_stats->wins);
+  g_snprintf (text, sizeof (text), _("%d"), wins);
   gtk_label_set_text (priv->wins_label, text);
 
   /* Translators: Translate this to "%Id" if you want to use localised digits,
    * and to "%d" otherwise. Do not translate it to anything else!
    */
-  g_snprintf (text, sizeof (text), _("%d"), current_stats->total);
+  g_snprintf (text, sizeof (text), _("%d"), total);
   gtk_label_set_text (priv->total_label, text);
 
-  if (current_stats->total != 0) {
+  if (total != 0) {
     /* Translators: Translate the "%d" in this string this to "%Id" if you
      * want to use localised digits, and to "%d" otherwise.
      * Do not translate the "%d" part to anything else!
@@ -228,26 +232,24 @@ aisleriot_stats_dialog_update (AisleriotStatsDialog *dialog,
      * "%" (U+0025 PERCENT SIGN) you do NOT need to escape it with another "%"!
      */
     g_snprintf (text, sizeof (text), _("%d%%"),
-                (int) (100.0 * ((double) current_stats->wins) / ((double) current_stats->total) + 0.5));
+                (int) (100.0 * ((double) wins) / ((double) total) + 0.5));
     gtk_label_set_text (priv->percentage_label, text);
   } else
     /* For translators: N/A means "Not Applicable", use whatever
      * abbreviation you have for a value that has no meaning. */
     gtk_label_set_text (priv->percentage_label, _("N/A"));
 
-  if (current_stats->best != 0) {
+  if (best_time != 0) {
     /* Translators: this represents minutes:seconds. */
     g_snprintf (text, sizeof (text), _("%d:%02d"),
-                current_stats->best / 60,
-                current_stats->best % 60);
+                best_time / 60, best_time % 60);
     gtk_label_set_text (priv->best_label, text);
   } else
     gtk_label_set_text (priv->best_label, _("N/A"));
 
-  if (current_stats->worst != 0) {
+  if (worst_time != 0) {
     g_snprintf (text, sizeof (text), _("%d:%02d"),
-                current_stats->worst / 60,
-                current_stats->worst % 60);
+                worst_time / 60, worst_time % 60);
     gtk_label_set_text (priv->worst_label, text);
   } else
     gtk_label_set_text (priv->worst_label, _("N/A"));
diff --git a/src/stats-dialog.h b/src/stats-dialog.h
index fcff75b..e29bfcb 100644
--- a/src/stats-dialog.h
+++ b/src/stats-dialog.h
@@ -53,7 +53,7 @@ GType aisleriot_stats_dialog_get_type (void);
 AisleriotStatsDialog *aisleriot_stats_dialog_new (void);
 
 void aisleriot_stats_dialog_update (AisleriotStatsDialog * dialog,
-                                    AisleriotStatistic * statistic);
+                                    GSettings *stats_settings);
 
 void aisleriot_stats_dialog_set_name (AisleriotStatsDialog * dialog,
                                       const char *game_name);
diff --git a/src/window.c b/src/window.c
index e872218..e6b40f7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2,7 +2,7 @@
 /*
  * Copyright © 1998, 2003 Jonathan Blandford <jrb alum mit edu>
  * Copyright © 2003 Callum McKenzie <callum physics otago ac nz>
- * Copyright © 2007, 2008, 2009, 2010 Christian Persch
+ * Copyright © 2007, 2008, 2009, 2010, 2013 Christian Persch
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 
+#include "ar-application.h"
 #include "ar-clock.h"
 #include "ar-debug.h"
 #include "ar-stock.h"
@@ -48,9 +49,9 @@
 #include "board-noclutter.h"
 #endif
 
+#include "ar-defines.h"
 #include "ar-card-theme.h"
 #include "ar-card-themes.h"
-#include "conf.h"
 #include "game.h"
 #include "stats-dialog.h"
 #include "util.h"
@@ -95,6 +96,10 @@ enum
 
 struct _AisleriotWindowPrivate
 {
+  GSettings *settings;
+  GSettings *state_settings;
+  GSettings *game_options_settings;
+
   AisleriotGame *game;
   ArStyle *board_style;
 #ifdef HAVE_CLUTTER
@@ -271,7 +276,6 @@ static void
 update_statistics_display (AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
-  AisleriotStatistic current_stats;
   char *game_name;
 
   if (!priv->stats_dialog)
@@ -281,10 +285,8 @@ update_statistics_display (AisleriotWindow *window)
   aisleriot_stats_dialog_set_name (priv->stats_dialog, game_name);
   g_free (game_name);
 
-  aisleriot_conf_get_statistic (aisleriot_game_get_game_module (priv->game),
-                                &current_stats);
-
-  aisleriot_stats_dialog_update (priv->stats_dialog, &current_stats);
+  aisleriot_stats_dialog_update (priv->stats_dialog,
+                                 aisleriot_game_get_scores_settings (priv->game));
 }
 
 static void
@@ -295,11 +297,15 @@ stats_dialog_response_cb (GtkWidget *widget,
   AisleriotWindowPrivate *priv = window->priv;
 
   if (response == GTK_RESPONSE_REJECT) {
-    AisleriotStatistic current_stats = { 0, 0, 0, 0 };
+    GSettings *stats_settings;
+
+    stats_settings = aisleriot_game_get_scores_settings (priv->game);
+    g_settings_set_uint (stats_settings, AR_SCORES_WINS_KEY, 0);
+    g_settings_set_uint (stats_settings, AR_SCORES_TOTAL_KEY, 0);
+    g_settings_set_uint (stats_settings, AR_SCORES_BEST_TIME_KEY, 0);
+    g_settings_set_uint (stats_settings, AR_SCORES_WORST_TIME_KEY, 0);
 
-    aisleriot_conf_set_statistic (aisleriot_game_get_game_module (priv->game),
-                                  &current_stats);
-    aisleriot_stats_dialog_update (priv->stats_dialog, &current_stats);
+    aisleriot_stats_dialog_update (priv->stats_dialog, stats_settings);
 
     return;
   }
@@ -337,12 +343,6 @@ aisleriot_window_change_game (AisleriotWindow *window)
 }
 
 void
-aisleriot_window_show_set_fullscreen (AisleriotWindow *window,
-                                      gboolean         active)
-{
-}
-
-void
 aisleriot_window_show_statistics_dialog (AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
@@ -880,7 +880,7 @@ toolbar_toggled_cb (GtkToggleAction *action,
 
   priv->toolbar_visible = state != FALSE;
 
-  ar_conf_set_boolean (NULL, aisleriot_conf_get_key (CONF_SHOW_TOOLBAR), state);
+  g_settings_set_boolean (priv->settings, AR_SETTINGS_SHOW_TOOLBAR_KEY, state);
 
   set_fullscreen_button_active (window);
 }
@@ -901,7 +901,7 @@ statusbar_toggled_cb (GtkToggleAction *action,
 
   priv->statusbar_visible = state != FALSE;
 
-  ar_conf_set_boolean (NULL, aisleriot_conf_get_key (CONF_SHOW_STATUSBAR), state);
+  g_settings_set_boolean (priv->settings, AR_SETTINGS_SHOW_STATUSBAR_KEY, state);
 }
 
 static void
@@ -958,8 +958,8 @@ clickmove_toggle_cb (GtkToggleAction *action,
 
   aisleriot_game_set_click_to_move (priv->game, click_to_move);
   ar_style_set_click_to_move (priv->board_style, click_to_move);
-  
-  ar_conf_set_boolean (NULL, aisleriot_conf_get_key (CONF_CLICK_TO_MOVE), click_to_move);
+
+  g_settings_set_boolean (priv->settings, AR_SETTINGS_CLICK_TO_MOVE_KEY, click_to_move);
 }
 
 static void
@@ -967,13 +967,14 @@ sound_toggle_cb (GtkToggleAction *action,
                  AisleriotWindow *window)
 {
 #ifdef ENABLE_SOUND
+  AisleriotWindowPrivate *priv = window->priv;
   gboolean sound_enabled;
 
   sound_enabled = gtk_toggle_action_get_active (action);
 
   ar_sound_enable (sound_enabled);
-  
-  ar_conf_set_boolean (NULL, aisleriot_conf_get_key (CONF_SOUND), sound_enabled);
+
+  g_settings_set_boolean (priv->settings, AR_SETTINGS_ENABLE_SOUND_KEY, sound_enabled);
 #endif /* ENABLE_SOUND */
 }
 
@@ -989,7 +990,7 @@ animations_toggle_cb (GtkToggleAction *action,
 
   ar_style_set_enable_animations (priv->board_style, enabled);
   
-  ar_conf_set_boolean (NULL, aisleriot_conf_get_key (CONF_ANIMATIONS), enabled);
+  g_settings_set (priv->settings, AR_SETTINGS_ENABLE_ANIMATIONS_KEY, sound_enabled);
 #endif /* HAVE_CLUTTER */
 }
 
@@ -1110,7 +1111,7 @@ option_cb (GtkToggleAction *action,
 
   value = aisleriot_game_change_options (priv->game, changed_mask, changed_value);
 
-  aisleriot_conf_set_options (aisleriot_game_get_game_module (priv->game), (int) value);
+  g_settings_set_uint (priv->game_options_settings, AR_OPTIONS_KEY, value);
 
   /* Now re-deal, so the option is applied */
   aisleriot_game_new_game (priv->game);
@@ -1141,9 +1142,8 @@ install_options_menu (AisleriotWindow *window)
   /* Only apply the options if they exist. Otherwise the options in the menu
    * and the real game options are out of sync until first changed by the user.
    */
-  if (aisleriot_conf_get_options (aisleriot_game_get_game_module (priv->game), &options_value)) {
-    aisleriot_game_change_options (priv->game, AISLERIOT_GAME_OPTIONS_MAX, options_value);
-  }
+  options_value = g_settings_get_uint (priv->game_options_settings, AR_OPTIONS_KEY);
+  aisleriot_game_change_options (priv->game, AISLERIOT_GAME_OPTIONS_MAX, options_value);
 
   /* To get radio buttons in the menu insert an atom into the option list
    * in your scheme code. To get back out of radio-button mode insert 
@@ -1216,13 +1216,14 @@ static void
 add_recently_played_game (AisleriotWindow *window,
                           const char *game_module)
 {
+  AisleriotWindowPrivate *priv = window->priv;
   char **recent_games, **new_recent;
   gsize i, n_recent = 0, n_new_recent = 0;
 
   if (!game_module)
     return;
 
-  recent_games = ar_conf_get_string_list (NULL, aisleriot_conf_get_key (CONF_RECENT_GAMES), &n_recent, NULL);
+  g_settings_get (priv->state_settings, AR_STATE_RECENT_GAMES_KEY, "^as", &recent_games);
 
   if (recent_games == NULL) {
     new_recent = g_new (char *, 2);
@@ -1230,6 +1231,7 @@ add_recently_played_game (AisleriotWindow *window,
     new_recent[1] = NULL;
     n_new_recent = 1;
   } else {
+    n_recent = g_strv_length (recent_games);
     new_recent = g_new (char *, MIN (n_recent + 1, MAX_RECENT) + 1);
     n_new_recent = 0;
 
@@ -1247,8 +1249,8 @@ add_recently_played_game (AisleriotWindow *window,
     g_strfreev (recent_games);
   }
 
-  ar_conf_set_string_list (NULL, aisleriot_conf_get_key (CONF_RECENT_GAMES),
-                              (const char * const *) new_recent, n_new_recent);
+  g_settings_set_strv (priv->state_settings, AR_STATE_RECENT_GAMES_KEY,
+                       (const char * const *) new_recent);
   g_strfreev (new_recent);
 }
 
@@ -1256,6 +1258,7 @@ static void
 recent_game_cb (GtkAction *action,
                 AisleriotWindow *window)
 {
+  AisleriotWindowPrivate *priv = window->priv;
   const char *game_module;
 
   game_module = g_object_get_data (G_OBJECT (action), "game");
@@ -1263,7 +1266,7 @@ recent_game_cb (GtkAction *action,
 
   aisleriot_window_set_game_module (window, game_module, NULL);
 
-  ar_conf_set_string (NULL, aisleriot_conf_get_key (CONF_VARIATION), game_module);
+  g_settings_set_string (priv->state_settings, AR_STATE_LAST_GAME_KEY, game_module);
 }
 
 static void
@@ -1290,9 +1293,9 @@ install_recently_played_menu (AisleriotWindow *window)
 
   priv->recent_games_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
 
-  recent_games = ar_conf_get_string_list (NULL, aisleriot_conf_get_key (CONF_RECENT_GAMES), &n_recent, NULL);
+  g_settings_get (priv->state_settings, AR_STATE_RECENT_GAMES_KEY, "^as", &recent_games);
 
-  for (i = 0; i < n_recent; ++i) {
+  for (i = 0; recent_games[i]; ++i) {
     GtkAction *action;
     char actionname[32];
     char *game_name, *tooltip;
@@ -1405,7 +1408,7 @@ card_theme_changed_cb (GtkToggleAction *action,
   aisleriot_window_take_card_theme (window, theme);
 
   theme_name = ar_card_theme_info_get_persistent_name (new_theme_info);
-  ar_conf_set_string (NULL, aisleriot_conf_get_key (CONF_THEME), theme_name);
+  g_settings_set_string (priv->settings, AR_SETTINGS_CARD_THEME_KEY, theme_name);
 }
 
 static void
@@ -1606,6 +1609,7 @@ game_type_changed_cb (AisleriotGame *game,
 {
   AisleriotWindowPrivate *priv = window->priv;
   char *game_name;
+  const char *game_module;
   guint features;
   gboolean dealable;
   gboolean show_scores;
@@ -1621,10 +1625,15 @@ game_type_changed_cb (AisleriotGame *game,
 
   g_free (game_name);
 
-  add_recently_played_game (window, aisleriot_game_get_game_module (game));
+  game_module = aisleriot_game_get_game_module (game);
+  add_recently_played_game (window, game_module);
 
   install_recently_played_menu (window);
 
+  g_clear_object (&priv->game_options_settings);
+  priv->game_options_settings = ar_application_options_settings_new (AR_APPLICATION 
(g_application_get_default ()),
+                                                                     game_module);
+
   install_options_menu (window);
 
   update_statistics_display (window);
@@ -2100,7 +2109,7 @@ aisleriot_window_init (AisleriotWindow *window)
   GtkWidget *main_vbox;
   GtkAccelGroup *accel_group;
   GtkAction *action;
-  char *theme_name;
+  const char *theme_name;
   ArCardTheme *theme;
   guint i;
   GtkStatusbar *statusbar;
@@ -2114,6 +2123,10 @@ aisleriot_window_init (AisleriotWindow *window)
 
   priv = window->priv = AISLERIOT_WINDOW_GET_PRIVATE (window);
 
+  priv->settings = g_settings_new (AR_SETTINGS_SCHEMA);
+  priv->state_settings = ar_application_state_settings_new (AR_APPLICATION (g_application_get_default ()),
+                                                            AR_STATE_SCHEMA);
+
   priv->fullscreen = FALSE;
 
   priv->game = aisleriot_game_new ();
@@ -2151,9 +2164,8 @@ aisleriot_window_init (AisleriotWindow *window)
   priv->board = AISLERIOT_BOARD (aisleriot_board_new (priv->board_style, priv->game));
 #endif /* HAVE_CLUTTER */
 
-  theme_name = ar_conf_get_string (NULL, aisleriot_conf_get_key (CONF_THEME), NULL);
+  g_settings_get (priv->settings, AR_SETTINGS_CARD_THEME_KEY, "&s", &theme_name);
   theme = ar_card_themes_get_theme_by_name (priv->theme_manager, theme_name);
-  g_free (theme_name);
   if (!theme) {
     /* Last-ditch fallback: try getting *any* theme */
     theme = ar_card_themes_get_theme_any (priv->theme_manager);
@@ -2279,12 +2291,12 @@ aisleriot_window_init (AisleriotWindow *window)
   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
 
   action = gtk_action_group_get_action (priv->action_group, "Toolbar");
-  priv->toolbar_visible = ar_conf_get_boolean (NULL, aisleriot_conf_get_key (CONF_SHOW_TOOLBAR), NULL) != 
FALSE;
+  priv->toolbar_visible = g_settings_get_boolean (priv->settings, AR_SETTINGS_SHOW_TOOLBAR_KEY);
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
                                 priv->toolbar_visible);
   action = gtk_action_group_get_action (priv->action_group, "ClickToMove");
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-                                ar_conf_get_boolean (NULL, aisleriot_conf_get_key (CONF_CLICK_TO_MOVE), 
NULL));
+                                g_settings_get_boolean (priv->settings, AR_SETTINGS_CLICK_TO_MOVE_KEY));
 
   action = gtk_action_group_get_action (priv->action_group, "RecentMenu");
   g_object_set (action, "hide-if-empty", FALSE, NULL);
@@ -2292,12 +2304,12 @@ aisleriot_window_init (AisleriotWindow *window)
 #ifdef ENABLE_SOUND
   action = gtk_action_group_get_action (priv->action_group, "Sound");
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-                                ar_conf_get_boolean (NULL, aisleriot_conf_get_key (CONF_SOUND), NULL));
+                                g_settings_get_boolean (priv->settings, AR_SETTINGS_ENABLE_SOUND_KEY));
   gtk_action_set_visible (action, ar_sound_is_available ());
 #endif /* ENABLE_SOUND */
 
   action = gtk_action_group_get_action (priv->action_group, "Statusbar");
-  priv->statusbar_visible = ar_conf_get_boolean (NULL, aisleriot_conf_get_key (CONF_SHOW_STATUSBAR), NULL) 
!= FALSE;
+  priv->statusbar_visible = g_settings_get_boolean (priv->settings, AR_SETTINGS_SHOW_STATUSBAR_KEY);
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
                                 priv->statusbar_visible);
 
@@ -2306,7 +2318,7 @@ aisleriot_window_init (AisleriotWindow *window)
 #ifdef HAVE_CLUTTER
   action = gtk_action_group_get_action (priv->action_group, "Animations");
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-                                ar_conf_get_boolean (NULL, aisleriot_conf_get_key (CONF_ANIMATIONS), NULL));
+                                g_settings_get_boolean (priv->settings, AR_SETTINGS_ENABLE_ANIMATIONS_KEY));
 
 #endif /* HAVE_CLUTTER */
 
@@ -2407,6 +2419,10 @@ aisleriot_window_dispose (GObject *object)
     priv->load_idle_id = 0;
   }
 
+  g_clear_object (&priv->settings);
+  g_clear_object (&priv->state_settings);
+  g_clear_object (&priv->game_options_settings);
+
   G_OBJECT_CLASS (aisleriot_window_parent_class)->dispose (object);
 }
 
@@ -2513,7 +2529,6 @@ load_idle_cb (LoadIdleData *data)
   AisleriotWindowPrivate *priv = data->window->priv;
   GError *error = NULL;
   GRand *rand;
-  char *pref;
 
   if (!aisleriot_game_load_game (priv->game, data->game_module, &error)) {
     GtkWidget *dialog;
@@ -2553,9 +2568,7 @@ load_idle_cb (LoadIdleData *data)
   /* Now that we know we can successfully load this variation,
    * store it in conf
    */
-  pref = g_strconcat (data->game_module, ".scm", NULL);
-  ar_conf_set_string (NULL, aisleriot_conf_get_key (CONF_VARIATION), pref);
-  g_free (pref);
+  g_settings_set_string (priv->state_settings, AR_STATE_LAST_GAME_KEY, data->game_module);
 
   rand = data->rand;
   data->rand = NULL;
@@ -2582,7 +2595,7 @@ free_load_idle_data (LoadIdleData *data)
 /**
  * aisleriot_window_set_game:
  * @window:
- * @game_module: a UTF-8 string
+ * @game_module: (allow-none): a UTF-8 string, or %NULL
  * @rand: (allow-none) (transfer full): a #GRand, or %NULL
  *
  * Loads the game variation defined in the @game_module file.
@@ -2604,9 +2617,18 @@ aisleriot_window_set_game_module (AisleriotWindow *window,
 
   data = g_slice_new (LoadIdleData);
   data->window = window;
-  data->game_module = g_strdup (game_module);
   data->rand = rand; /* adopted */
 
+  if (game_module) {
+    data->game_module = g_strdup (game_module);
+  } else {
+    char *pref;
+
+    pref = g_settings_get_string (priv->state_settings, AR_STATE_LAST_GAME_KEY);
+    data->game_module = ar_filename_to_game_module (pref);
+    g_free (pref);
+  }
+
   priv->load_idle_id = g_idle_add_full (G_PRIORITY_LOW,
                                         (GSourceFunc) load_idle_cb,
                                         data,



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