- Fixed a bug that made Nitfol crash since [130]
authorfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Wed, 21 Oct 2009 21:05:45 +0000 (21:05 +0000)
committerfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Wed, 21 Oct 2009 21:05:45 +0000 (21:05 +0000)
- Added function to tell whether game is running
- Added properties and "command" signal to ChimaraIF
- Added ChimaraIF to the documentation

docs/reference/chimara.types
interpreters/nitfol/nitfol.opt
libchimara/chimara-glk-private.h
libchimara/chimara-glk.c
libchimara/chimara-glk.h
libchimara/chimara-if.c
libchimara/chimara-if.h
libchimara/window.c
tests/main.c

index 6d0bd5710f3550e6d11f6f9f4019c48055340b22..c2c6f96169259af32fb9329eac0d851dff20a4b6 100644 (file)
@@ -1 +1,2 @@
 chimara_glk_get_type
+chimara_if_get_type
\ No newline at end of file
index c622c590455f5a2f5f697431820d10b9adffa0eb..100bb40e32923dfaa29041a0a92b537af0aa65db 100644 (file)
@@ -3,7 +3,7 @@
 # You can alter the 'default' part to change the game's default options.
 
 # Longest name         Long    short   description                             type    default code
-"Ignore errors"                ignore  i       "Ignore Z-machine strictness errors"    flag    1       { ignore_errors = flag; }
+"Ignore errors"                ignore  i       "Ignore Z-machine strictness errors"    flag    0       { ignore_errors = flag; }
 Normally nitfol checks for illegal and undefined Z-machine behaviour and alerts the user.  If you're playing someone else's buggy game, this can be annoying and you should use this option.
 
 "Inferior debugger"    fullname f      "For running under Emacs or DDD"        flag    0       { fullname = flag; }
index 5ea1e54a51853274826aff1775c9a6d15d642926..1ce36c377103f24225a9b1bf6f0c7076e8dd7caf 100644 (file)
@@ -36,6 +36,8 @@ struct _ChimaraGlkPrivate {
        struct StyleSet *current_styles;
 
        /* *** Threading data *** */
+       /* Whether program is running */
+       gboolean running;
     /* Glk program loaded in widget */
     GModule *program;
     /* Thread in which Glk program is run */
@@ -84,8 +86,8 @@ struct _ChimaraGlkPrivate {
        gchar *current_dir;
 };
 
-#define CHIMARA_GLK_PRIVATE(obj) \
-       (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHIMARA_TYPE_GLK, ChimaraGlkPrivate))
+#define CHIMARA_GLK_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHIMARA_TYPE_GLK, ChimaraGlkPrivate))
+#define CHIMARA_GLK_USE_PRIVATE(o, n) ChimaraGlkPrivate *n = CHIMARA_GLK_PRIVATE(o)
        
 G_END_DECLS
 
index 6669dc6b0f524c8b1497b43e469876e98cab1a11..eae3988b1fb7a25afa9e29fee8e6640af49de289 100644 (file)
@@ -86,6 +86,7 @@ chimara_glk_init(ChimaraGlk *self)
        priv->css_file = "style.css";
        priv->default_styles = g_new0(StyleSet,1);
        priv->current_styles = g_new0(StyleSet,1);
+       priv->running = FALSE;
     priv->program = NULL;
     priv->thread = NULL;
     priv->event_queue = g_queue_new();
@@ -538,7 +539,8 @@ chimara_glk_forall(GtkContainer *container, gboolean include_internals, GtkCallb
 static void
 chimara_glk_stopped(ChimaraGlk *self)
 {
-    ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(self);
+    CHIMARA_GLK_USE_PRIVATE(self, priv);
+    priv->running = FALSE;
 
     /* Free the plugin */
        if( priv->program && !g_module_close(priv->program) )
@@ -548,7 +550,8 @@ chimara_glk_stopped(ChimaraGlk *self)
 static void
 chimara_glk_started(ChimaraGlk *self)
 {
-       /* Default signal handler */
+       CHIMARA_GLK_USE_PRIVATE(self, priv);
+       priv->running = TRUE;
 }
 
 static void
@@ -726,6 +729,21 @@ chimara_glk_class_init(ChimaraGlkClass *klass)
 
 /* PUBLIC FUNCTIONS */
 
+/**
+ * chimara_error_quark:
+ *
+ * The error domain for errors from Chimara widgets.
+ *
+ * Returns: The string <quote>chimara-error-quark</quote> as a <link 
+ * linkend="GQuark">GQuark</link>.
+ */
+GQuark
+chimara_error_quark(void)
+{
+       chimara_init(); /* This is a library entry point */
+       return g_quark_from_static_string("chimara-error-quark");
+}
+
 /**
  * chimara_glk_new:
  *
@@ -1052,14 +1070,12 @@ chimara_glk_run(ChimaraGlk *glk, const gchar *plugin, int argc, char *argv[], GE
     
     if(!priv->program)
     {
-        g_warning( "Error opening module: %s", g_module_error() );
-        /* TODO: set error */
+       g_set_error(error, CHIMARA_ERROR, CHIMARA_LOAD_MODULE_ERROR, _("Error opening module: %s"), g_module_error());
         return FALSE;
     }
     if( !g_module_symbol(priv->program, "glk_main", (gpointer *) &startup->glk_main) )
     {
-        g_warning( "Error finding glk_main(): %s", g_module_error() );
-        /* TODO: set error */
+       g_set_error(error, CHIMARA_ERROR, CHIMARA_NO_GLK_MAIN, _("Error finding glk_main(): %s"), g_module_error());
         return FALSE;
     }
 
@@ -1098,8 +1114,11 @@ void
 chimara_glk_stop(ChimaraGlk *glk)
 {
     g_return_if_fail(glk || CHIMARA_IS_GLK(glk));
-    /* TODO: check if glk is actually running a program */
-       ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+    CHIMARA_GLK_USE_PRIVATE(glk, priv);
+    /* Don't do anything if not running a program */
+    if(!priv->running)
+       return;
+    
        if(priv->abort_lock) {
                g_mutex_lock(priv->abort_lock);
                priv->abort_signalled = TRUE;
@@ -1120,7 +1139,17 @@ void
 chimara_glk_wait(ChimaraGlk *glk)
 {
     g_return_if_fail(glk || CHIMARA_IS_GLK(glk));
-    
-    ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+    CHIMARA_GLK_USE_PRIVATE(glk, priv);
+    /* Don't do anything if not running a program */
+    if(!priv->running)
+       return;
     g_thread_join(priv->thread);
 }
+
+gboolean
+chimara_glk_get_running(ChimaraGlk *glk)
+{
+       g_return_val_if_fail(glk || CHIMARA_IS_GLK(glk), FALSE);
+       CHIMARA_GLK_USE_PRIVATE(glk, priv);
+       return priv->running;
+}
index fc3ab79439b9ad987825d3ffc011ce8e5f90bed4..ad7e2ec55f15da3f3a0add093b33b0f73c02bab3 100644 (file)
@@ -38,6 +38,20 @@ typedef struct _ChimaraGlkClass {
        void(* text_buffer_output) (ChimaraGlk *self, guint32 window_rock, gchar *text);
 } ChimaraGlkClass;
 
+typedef enum _ChimaraError {
+       CHIMARA_LOAD_MODULE_ERROR,
+       CHIMARA_NO_GLK_MAIN,
+       CHIMARA_PLUGIN_NOT_FOUND
+} ChimaraError;
+
+/**
+ * CHIMARA_ERROR:
+ *
+ * The domain of errors raised by Chimara widgets.
+ */
+#define CHIMARA_ERROR chimara_error_quark()
+
+GQuark chimara_error_quark(void);
 GType chimara_glk_get_type(void) G_GNUC_CONST;
 GtkWidget *chimara_glk_new(void);
 void chimara_glk_set_interactive(ChimaraGlk *glk, gboolean interactive);
@@ -55,6 +69,7 @@ guint chimara_glk_get_spacing(ChimaraGlk *glk);
 gboolean chimara_glk_run(ChimaraGlk *glk, const gchar *plugin, int argc, char *argv[], GError **error);
 void chimara_glk_stop(ChimaraGlk *glk);
 void chimara_glk_wait(ChimaraGlk *glk);
+gboolean chimara_glk_get_running(ChimaraGlk *glk);
 
 G_END_DECLS
 
index 16175d7f603f9d45a2c92592a0f0b4268ee53cac..fb1d6b52f4a5ad12dddef5c21b809e9bdcbc72b5 100644 (file)
@@ -33,20 +33,44 @@ static gchar *plugin_names[CHIMARA_IF_NUM_INTERPRETERS] = {
        "frotz", "nitfol", "glulxe", "git"
 };
 
+typedef enum _ChimaraIFFlags {
+       CHIMARA_IF_PIRACY_MODE = 1 << 0,
+       CHIMARA_IF_TANDY_BIT = 1 << 1,
+       CHIMARA_IF_EXPAND_ABBREVIATIONS = 1 << 2,
+       CHIMARA_IF_IGNORE_ERRORS = 1 << 3,
+       CHIMARA_IF_TYPO_CORRECTION = 1 << 4
+} ChimaraIFFlags;
+
 typedef struct _ChimaraIFPrivate {
        ChimaraIFInterpreter preferred_interpreter[CHIMARA_IF_NUM_FORMATS];
+       ChimaraIFFormat format;
+       ChimaraIFInterpreter interpreter;
+       ChimaraIFFlags flags;
+       ChimaraIFZmachineVersion interpreter_number;
+       gint random_seed;
+       gboolean random_seed_set;
+       /* Holding buffers for input and response */
+       gchar *input;
+       GString *response;
 } ChimaraIFPrivate;
 
 #define CHIMARA_IF_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_IF, ChimaraIFPrivate))
 #define CHIMARA_IF_USE_PRIVATE(o, n) ChimaraIFPrivate *n = CHIMARA_IF_PRIVATE(o)
 
 enum {
-       PROP_0
+       PROP_0,
+       PROP_PIRACY_MODE,
+       PROP_TANDY_BIT,
+       PROP_EXPAND_ABBREVIATIONS,
+       PROP_IGNORE_ERRORS,
+       PROP_TYPO_CORRECTION,
+       PROP_INTERPRETER_NUMBER,
+       PROP_RANDOM_SEED,
+       PROP_RANDOM_SEED_SET
 };
 
 enum {
        COMMAND,
-
        LAST_SIGNAL
 };
 
@@ -54,6 +78,48 @@ static guint chimara_if_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE(ChimaraIF, chimara_if, CHIMARA_TYPE_GLK);
 
+static void
+chimara_if_waiting(ChimaraGlk *glk)
+{
+       CHIMARA_IF_USE_PRIVATE(glk, priv);
+
+       gchar *response = g_string_free(priv->response, FALSE);
+       priv->response = g_string_new("");
+       
+       g_signal_emit_by_name(glk, "command", priv->input, response);
+       
+       g_free(priv->input);
+       g_free(response);
+       priv->input = NULL;
+}
+
+static void
+chimara_if_stopped(ChimaraGlk *glk)
+{
+       CHIMARA_IF_USE_PRIVATE(glk, priv);
+       
+       if(priv->input || priv->response->len > 0)
+               chimara_if_waiting(glk); /* Send one last command signal */
+       
+       priv->format = CHIMARA_IF_FORMAT_NONE;
+       priv->interpreter = CHIMARA_IF_INTERPRETER_NONE;
+}
+
+static void
+chimara_if_line_input(ChimaraGlk *glk, guint32 win_rock, gchar *input)
+{
+       CHIMARA_IF_USE_PRIVATE(glk, priv);
+       g_assert(priv->input == NULL);
+       priv->input = g_strdup(input);
+}
+
+static void
+chimara_if_text_buffer_output(ChimaraGlk *glk, guint32 win_rock, gchar *output)
+{
+       CHIMARA_IF_USE_PRIVATE(glk, priv);
+       g_string_append(priv->response, output);
+}
+
 static void
 chimara_if_init(ChimaraIF *self)
 {
@@ -64,13 +130,53 @@ chimara_if_init(ChimaraIF *self)
        priv->preferred_interpreter[CHIMARA_IF_FORMAT_Z_BLORB] = CHIMARA_IF_INTERPRETER_FROTZ;
        priv->preferred_interpreter[CHIMARA_IF_FORMAT_GLULX] = CHIMARA_IF_INTERPRETER_GLULXE;
        priv->preferred_interpreter[CHIMARA_IF_FORMAT_GLULX_BLORB] = CHIMARA_IF_INTERPRETER_GLULXE;
+       priv->format = CHIMARA_IF_FORMAT_NONE;
+       priv->interpreter = CHIMARA_IF_INTERPRETER_NONE;
+       priv->flags = CHIMARA_IF_TYPO_CORRECTION;
+       priv->interpreter_number = CHIMARA_IF_ZMACHINE_DEFAULT;
+       priv->random_seed_set = FALSE;
+       priv->input = NULL;
+       priv->response = g_string_new("");
+       
+       /* Connect to signals of ChimaraGlk parent */
+       g_signal_connect(self, "stopped", G_CALLBACK(chimara_if_stopped), NULL);
+       g_signal_connect(self, "waiting", G_CALLBACK(chimara_if_waiting), NULL);
+       g_signal_connect(self, "line-input", G_CALLBACK(chimara_if_line_input), NULL);
+       g_signal_connect(self, "text-buffer-output", G_CALLBACK(chimara_if_text_buffer_output), NULL);
 }
 
+#define PROCESS_FLAG(flags, flag, val) (flags) = (val)? (flags) | (flag) : (flags) & ~(flag)
+
 static void
 chimara_if_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
+       CHIMARA_IF_USE_PRIVATE(object, priv);
     switch(prop_id)
     {
+       case PROP_PIRACY_MODE:
+               PROCESS_FLAG(priv->flags, CHIMARA_IF_PIRACY_MODE, g_value_get_boolean(value));
+               break;
+       case PROP_TANDY_BIT:
+               PROCESS_FLAG(priv->flags, CHIMARA_IF_TANDY_BIT, g_value_get_boolean(value));
+               break;
+       case PROP_EXPAND_ABBREVIATIONS:
+               PROCESS_FLAG(priv->flags, CHIMARA_IF_EXPAND_ABBREVIATIONS, g_value_get_boolean(value));
+               break;
+       case PROP_IGNORE_ERRORS:
+               PROCESS_FLAG(priv->flags, CHIMARA_IF_IGNORE_ERRORS, g_value_get_boolean(value));
+               break;
+       case PROP_TYPO_CORRECTION:
+               PROCESS_FLAG(priv->flags, CHIMARA_IF_TYPO_CORRECTION, g_value_get_boolean(value));
+               break;
+       case PROP_INTERPRETER_NUMBER:
+               priv->interpreter_number = g_value_get_uint(value);
+               break;
+       case PROP_RANDOM_SEED:
+               priv->random_seed = g_value_get_int(value);
+               break;
+       case PROP_RANDOM_SEED_SET:
+               priv->random_seed_set = g_value_get_boolean(value);
+               break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     }
@@ -79,9 +185,33 @@ chimara_if_set_property(GObject *object, guint prop_id, const GValue *value, GPa
 static void
 chimara_if_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
+       CHIMARA_IF_USE_PRIVATE(object, priv);
     switch(prop_id)
     {
-
+       case PROP_PIRACY_MODE:
+               g_value_set_boolean(value, priv->flags & CHIMARA_IF_PIRACY_MODE);
+               break;
+       case PROP_TANDY_BIT:
+               g_value_set_boolean(value, priv->flags & CHIMARA_IF_TANDY_BIT);
+               break;
+       case PROP_EXPAND_ABBREVIATIONS:
+               g_value_set_boolean(value, priv->flags & CHIMARA_IF_EXPAND_ABBREVIATIONS);
+               break;
+       case PROP_IGNORE_ERRORS:
+               g_value_set_boolean(value, priv->flags & CHIMARA_IF_IGNORE_ERRORS);
+               break;
+       case PROP_TYPO_CORRECTION:
+               g_value_set_boolean(value, priv->flags & CHIMARA_IF_TYPO_CORRECTION);
+               break;
+       case PROP_INTERPRETER_NUMBER:
+               g_value_set_uint(value, priv->interpreter_number);
+               break;
+       case PROP_RANDOM_SEED:
+               g_value_set_int(value, priv->random_seed);
+               break;
+       case PROP_RANDOM_SEED_SET:
+               g_value_set_boolean(value, priv->random_seed_set);
+               break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     }
@@ -99,6 +229,11 @@ chimara_if_command(ChimaraIF *self, gchar *input, gchar *response)
        /* Default signal handler */
 }
 
+/* G_PARAM_STATIC_STRINGS only appeared in GTK 2.13.0 */
+#ifndef G_PARAM_STATIC_STRINGS
+#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
+#endif
+
 static void
 chimara_if_class_init(ChimaraIFClass *klass)
 {
@@ -118,8 +253,56 @@ chimara_if_class_init(ChimaraIFClass *klass)
                G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
 
        /* Properties */
-       /* Gtk-Doc for property */
-       /* g_object_class_install_property(object_class, PROPERTY, ...); */
+       g_object_class_install_property(object_class, PROP_PIRACY_MODE,
+               g_param_spec_boolean("piracy-mode", _("Piracy mode"), 
+               _("Pretend the game is pirated"), FALSE,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       /**
+        * ChimaraIF:tandy-bit:
+        * 
+        * Some early Infocom games were sold by the Tandy Corporation. Setting this
+        * property to %TRUE changes the wording of some Version 3 Infocom games 
+        * slightly, so as to be less offensive. See <ulink 
+        * url="http://www.ifarchive.org/if-archive/infocom/info/tandy_bits.html">
+        * http://www.ifarchive.org/if-archive/infocom/info/tandy_bits.html</ulink>.
+        * 
+        * Only works on Z-machine interpreters.
+        */
+       g_object_class_install_property(object_class, PROP_TANDY_BIT,
+               g_param_spec_boolean("tandy-bit", _("Tandy bit"), 
+               _("Censor certain Infocom games"), FALSE, 
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       
+       g_object_class_install_property(object_class, PROP_EXPAND_ABBREVIATIONS,
+               g_param_spec_boolean("expand-abbreviations", _("Expand abbreviations"),
+               _("Expand abbreviations such as X for EXAMINE"), FALSE,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       
+       g_object_class_install_property(object_class, PROP_IGNORE_ERRORS,
+               g_param_spec_boolean("ignore-errors", _("Ignore errors"), 
+               _("Do not warn the user about Z-machine errors"), FALSE,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       
+       g_object_class_install_property(object_class, PROP_TYPO_CORRECTION,
+               g_param_spec_boolean("typo-correction", _("Typo correction"),
+               _("Try to remedy typos if the interpreter supports it"), TRUE,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       
+       g_object_class_install_property(object_class, PROP_INTERPRETER_NUMBER,
+               g_param_spec_uint("interpreter-number", _("Interpreter number"),
+               _("Platform the Z-machine should pretend it is running on"), 
+               CHIMARA_IF_ZMACHINE_DEFAULT, CHIMARA_IF_ZMACHINE_MAXVAL, CHIMARA_IF_ZMACHINE_DEFAULT,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+       
+       g_object_class_install_property(object_class, PROP_RANDOM_SEED,
+               g_param_spec_int("random-seed", _("Random seed"),
+               _("Seed for the random number generator"), G_MININT, G_MAXINT, 0,
+               G_PARAM_READWRITE | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
+               
+       g_object_class_install_property(object_class, PROP_RANDOM_SEED_SET,
+               g_param_spec_boolean("random-seed-set", _("Random seed set"),
+               _("Whether the seed for the random number generator should be set manually"), FALSE,
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS));
 
        /* Private data */
        g_type_class_add_private(klass, sizeof(ChimaraIFPrivate));
@@ -166,42 +349,6 @@ chimara_if_get_preferred_interpreter(ChimaraIF *self, ChimaraIFFormat format)
        return priv->preferred_interpreter[format];
 }
 
-/* Opens a '.la' file and finds the name of the plugin library. g_free() the
- * string when done. */
-static gchar *
-find_dlname(const gchar *pluginfile, GError **error)
-{
-       /* Find the name of the shared library */
-       gchar *dlname;
-       FILE *plugin = fopen(pluginfile, "r");
-       if(!plugin)
-       {
-               g_set_error(error, G_FILE_ERROR, errno, "Error opening '%s': %s", pluginfile, g_strerror(errno));
-               return NULL;
-       }
-       gchar line[256];
-       while( fgets(line, 256, plugin) != NULL)
-       {       
-               if(g_str_has_prefix(line, "dlname='"))
-               {
-                       dlname = g_strndup(line + 8, strlen(line) - 10);
-                       break;
-               }
-       }
-       free(line);
-       if(!dlname)
-       {
-               g_set_error(error, G_FILE_ERROR, errno, "Error reading '%s': %s", pluginfile, g_strerror(errno));
-               return NULL;
-       }
-       if(fclose(plugin))
-       {
-               g_set_error(error, G_FILE_ERROR, errno, "Error closing '%s': %s", pluginfile, g_strerror(errno));
-               return NULL;
-       }
-       return dlname;
-}
-
 gboolean 
 chimara_if_run_game(ChimaraIF *self, gchar *gamefile, GError **error)
 {
@@ -228,45 +375,103 @@ chimara_if_run_game(ChimaraIF *self, gchar *gamefile, GError **error)
        
        /* Now decide what interpreter to use */
        ChimaraIFInterpreter interpreter = priv->preferred_interpreter[format];
-       gchar *libtoolfile = g_strconcat(plugin_names[interpreter], ".la", NULL);
-#ifndef RELEASE
+       gchar *pluginfile = g_strconcat(plugin_names[interpreter], "." G_MODULE_SUFFIX, NULL);
+
        /* If there is a plugin in the source tree, use that */
-       gboolean use_installed = FALSE;
-       gchar *libtoolpath = g_build_filename("..", "interpreters", plugin_names[interpreter], libtoolfile, NULL);
-       if( !g_file_test(libtoolpath, G_FILE_TEST_EXISTS) ) 
+       gchar *pluginpath = g_build_filename("..", "interpreters", plugin_names[interpreter], LT_OBJDIR, pluginfile, NULL);
+       if( !g_file_test(pluginpath, G_FILE_TEST_EXISTS) ) 
        {
-               g_free(libtoolpath);
-#endif
-               gchar *libtoolpath = g_build_filename(PLUGINDIR, libtoolfile, NULL);
-               if( !g_file_test(libtoolpath, G_FILE_TEST_EXISTS) ) 
+               g_free(pluginpath);
+               pluginpath = g_build_filename(PLUGINDIR, pluginfile, NULL);
+               if( !g_file_test(pluginpath, G_FILE_TEST_EXISTS) ) 
                {
-                       g_free(libtoolpath);
-                       g_free(libtoolfile);
-                       g_warning("Cannot open %s plugin file", interpreter_names[interpreter]);
-                       /* TODO: set error */
+                       g_free(pluginpath);
+                       g_free(pluginfile);
+                       g_set_error(error, CHIMARA_ERROR, CHIMARA_PLUGIN_NOT_FOUND, _("No appropriate %s interpreter plugin was found"), interpreter_names[interpreter]);
                        return FALSE;
                }
-#ifndef RELEASE
-               use_installed = TRUE;
        }
-#endif
-       g_free(libtoolfile);
+       g_free(pluginfile);
+
+       /* Decide what arguments to pass to the interpreters; currently only the
+       Z-machine interpreters accept command line arguments other than the game */
+       GSList *args = NULL;
+       gchar *terpnumstr = NULL, *randomstr = NULL;
+       args = g_slist_prepend(args, pluginpath);
+       args = g_slist_prepend(args, gamefile);
+       switch(interpreter)
+       {
+               case CHIMARA_IF_INTERPRETER_FROTZ:
+                       if(priv->flags & CHIMARA_IF_PIRACY_MODE)
+                               args = g_slist_prepend(args, "-P");
+                       if(priv->flags & CHIMARA_IF_TANDY_BIT)
+                               args = g_slist_prepend(args, "-t");
+                       if(priv->flags & CHIMARA_IF_EXPAND_ABBREVIATIONS)
+                               args = g_slist_prepend(args, "-x");
+                       if(priv->flags & CHIMARA_IF_IGNORE_ERRORS)
+                               args = g_slist_prepend(args, "-i");
+                       if(priv->interpreter_number != CHIMARA_IF_ZMACHINE_DEFAULT)
+                       {
+                               terpnumstr = g_strdup_printf("-I%u", priv->interpreter_number);
+                               args = g_slist_prepend(args, terpnumstr);
+                       }
+                       if(priv->random_seed_set)
+                       {
+                               randomstr = g_strdup_printf("-s%d", priv->random_seed);
+                               args = g_slist_prepend(args, randomstr);
+                       }
+                       break;
+               case CHIMARA_IF_INTERPRETER_NITFOL:
+                       if(priv->flags & CHIMARA_IF_PIRACY_MODE)
+                               args = g_slist_prepend(args, "-pirate");
+                       if(priv->flags & CHIMARA_IF_TANDY_BIT)
+                               args = g_slist_prepend(args, "-tandy");
+                       if(!(priv->flags & CHIMARA_IF_EXPAND_ABBREVIATIONS))
+                               args = g_slist_prepend(args, "-no-expand");
+                       if(priv->flags & CHIMARA_IF_IGNORE_ERRORS)
+                               args = g_slist_prepend(args, "-ignore");
+                       if(!(priv->flags & CHIMARA_IF_TYPO_CORRECTION))
+                               args = g_slist_prepend(args, "-no-spell");
+                       if(priv->interpreter_number != CHIMARA_IF_ZMACHINE_DEFAULT)
+                       {
+                               terpnumstr = g_strdup_printf("-terpnum%u", priv->interpreter_number);
+                               args = g_slist_prepend(args, terpnumstr);
+                       }
+                       if(priv->random_seed_set)
+                       {
+                               randomstr = g_strdup_printf("-random%d", priv->random_seed);
+                               args = g_slist_prepend(args, randomstr);
+                       }
+                       break;
+               default:
+                       ;
+       }
        
-       gchar *dlname = find_dlname(libtoolpath, error);
-       g_free(libtoolpath);
-       if(!dlname)
-               return FALSE;
-       gchar *pluginpath;
-#ifndef RELEASE
-       if(use_installed)
-#endif
-               pluginpath = g_build_filename(PLUGINDIR, dlname, NULL);
-#ifndef RELEASE
-       else
-               pluginpath = g_build_filename("..", "interpreters", plugin_names[interpreter], LT_OBJDIR, dlname, NULL);
-#endif
-       char *argv[3] = { pluginpath, gamefile, NULL };
-       gboolean retval = chimara_glk_run(CHIMARA_GLK(self), pluginpath, 2, argv, error);
-       g_free(dlname);
+       /* Allocate argv to hold the arguments */
+       int argc = g_slist_length(args);
+       args = g_slist_prepend(args, NULL);
+       char **argv = g_new0(char *, argc + 1);
+       
+       /* Fill argv */
+       args = g_slist_reverse(args);
+       int count;
+       GSList *ptr;
+       for(count = 0, ptr = args; ptr; count++, ptr = g_slist_next(ptr))
+               argv[count] = ptr->data;
+       
+       gboolean retval = chimara_glk_run(CHIMARA_GLK(self), pluginpath, argc, argv, error);
+       g_free(argv);
+       if(terpnumstr)
+               g_free(terpnumstr);
+       if(randomstr)
+               g_free(randomstr);
+       g_free(pluginpath);
+       
+       /* Set current format and interpreter if plugin was started successfully */
+       if(retval)
+       {
+               priv->format = format;
+               priv->interpreter = interpreter;
+       }
        return retval;
 }
index f081aaf3e7392687b3e1e5dcc65cad57394a8d9e..006829206867586dc859eb68d96050b80a3fcf7d 100644 (file)
@@ -14,6 +14,7 @@ G_BEGIN_DECLS
 #define CHIMARA_IF_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), CHIMARA_TYPE_IF, ChimaraIFClass))
 
 typedef enum _ChimaraIFFormat {
+       CHIMARA_IF_FORMAT_NONE = -1,
        CHIMARA_IF_FORMAT_Z5,
        CHIMARA_IF_FORMAT_Z6,
        CHIMARA_IF_FORMAT_Z8,
@@ -24,6 +25,7 @@ typedef enum _ChimaraIFFormat {
 } ChimaraIFFormat;
 
 typedef enum _ChimaraIFInterpreter {
+       CHIMARA_IF_INTERPRETER_NONE = -1,
        CHIMARA_IF_INTERPRETER_FROTZ,
        CHIMARA_IF_INTERPRETER_NITFOL,
        CHIMARA_IF_INTERPRETER_GLULXE,
@@ -31,6 +33,22 @@ typedef enum _ChimaraIFInterpreter {
        CHIMARA_IF_NUM_INTERPRETERS
 } ChimaraIFInterpreter;
 
+typedef enum _ChimaraIFZmachineVersion {
+       CHIMARA_IF_ZMACHINE_DEFAULT = 0,
+       CHIMARA_IF_ZMACHINE_DECSYSTEM_20,
+       CHIMARA_IF_ZMACHINE_APPLE_IIE,
+       CHIMARA_IF_ZMACHINE_MACINTOSH,
+       CHIMARA_IF_ZMACHINE_AMIGA,
+       CHIMARA_IF_ZMACHINE_ATARI_ST,
+       CHIMARA_IF_ZMACHINE_IBM_PC,
+       CHIMARA_IF_ZMACHINE_COMMODORE_128,
+       CHIMARA_IF_ZMACHINE_COMMODORE_64,
+       CHIMARA_IF_ZMACHINE_APPLE_IIC,
+       CHIMARA_IF_ZMACHINE_APPLE_IIGS,
+       CHIMARA_IF_ZMACHINE_TANDY_COLOR,
+       CHIMARA_IF_ZMACHINE_MAXVAL = CHIMARA_IF_ZMACHINE_TANDY_COLOR
+} ChimaraIFZmachineVersion;
+
 typedef struct _ChimaraIF {
        ChimaraGlk parent_instance;
 } ChimaraIF;
@@ -46,6 +64,8 @@ GtkWidget *chimara_if_new(void);
 void chimara_if_set_preferred_interpreter(ChimaraIF *self, ChimaraIFFormat format, ChimaraIFInterpreter interpreter);
 ChimaraIFInterpreter chimara_if_get_preferred_interpreter(ChimaraIF *self, ChimaraIFFormat format);
 gboolean chimara_if_run_game(ChimaraIF *self, gchar *gamefile, GError **error);
+ChimaraIFFormat chimara_if_get_format(ChimaraIF *self);
+ChimaraIFInterpreter chimara_if_get_interpreter(ChimaraIF *self);
 
 G_END_DECLS
 
index c835ccb31534e8f4816cca5aa397f2322d70864f..b3995f09189b8234982a3df80977ef9114f487b8 100644 (file)
@@ -35,7 +35,7 @@ window_new_common(glui32 rock)
 }
 
 static void
-window_close_common(winid_t win)
+window_close_common(winid_t win, gboolean destroy_node)
 {
        ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
        
@@ -45,7 +45,8 @@ window_close_common(winid_t win)
         win->disprock.ptr = NULL;
     }
 
-       g_node_destroy(win->window_node);
+       if(destroy_node)
+               g_node_destroy(win->window_node);
        win->magic = MAGIC_FREE;
        g_free(win);
 }
@@ -660,7 +661,7 @@ free_winids_below(winid_t win)
                free_winids_below(win->window_node->children->data);
                free_winids_below(win->window_node->children->next->data);
        }
-       window_close_common(win);
+       window_close_common(win, FALSE);
 }
 
 /**
@@ -774,14 +775,14 @@ glk_window_close(winid_t win, stream_result_t *result)
                                g_node_append(new_parent_node, sibling_node);
                }
 
-               window_close_common( (winid_t) pair_node->data );
+               window_close_common( (winid_t) pair_node->data, TRUE);
        } 
        else /* it was the root window */
        {
                glk_data->root_window = NULL;
        }
 
-       window_close_common(win);
+       window_close_common(win, FALSE);
 
        /* Schedule a redraw */
        g_mutex_lock(glk_data->arrange_lock);
index 5c38111167ad9e63571cb7a17bbe0967b22cbc93..60891d3ea273f92feab5cc818167e794f919b1ca 100644 (file)
@@ -66,7 +66,7 @@ on_stopped(ChimaraGlk *glk)
 static void
 on_command(ChimaraGlk *glk, gchar *input, gchar *response)
 {
-       g_printerr("Command!\n");
+       g_print("Command: %s\nResponse: %s\n", input, response);
 }
 
 static GObject *
@@ -115,7 +115,11 @@ create_window(void)
        }
        
        glk = chimara_if_new();
-       g_object_set(glk, "border-width", 6, "spacing", 6, NULL);
+       g_object_set(glk, 
+               "border-width", 6, 
+               "spacing", 6,
+               "ignore-errors", TRUE,
+               NULL);
        chimara_glk_set_default_font_string(CHIMARA_GLK(glk), "Serif 12");
        chimara_glk_set_monospace_font_string(CHIMARA_GLK(glk), "Monospace 12");
        g_signal_connect(glk, "started", G_CALLBACK(on_started), NULL);