*/
static gboolean supported_formats[CHIMARA_IF_NUM_FORMATS][CHIMARA_IF_NUM_INTERPRETERS] = {
- /* Frotz Nitfol Glulxe Git */
- { TRUE, TRUE, FALSE, FALSE }, /* Z5 */
- { TRUE, TRUE, FALSE, FALSE }, /* Z6 */
- { TRUE, TRUE, FALSE, FALSE }, /* Z8 */
- { TRUE, TRUE, FALSE, FALSE }, /* Zblorb */
- { FALSE, FALSE, TRUE, TRUE }, /* Glulx */
- { FALSE, FALSE, TRUE, TRUE } /* Gblorb */
+ /* Frotz Nitfol Glulxe Git Bocfel */
+ { TRUE, TRUE, FALSE, FALSE, TRUE }, /* Z5 */
+ { TRUE, TRUE, FALSE, FALSE, TRUE }, /* Z6 */
+ { TRUE, TRUE, FALSE, FALSE, TRUE }, /* Z8 */
+ { TRUE, TRUE, FALSE, FALSE, TRUE }, /* Zblorb */
+ { FALSE, FALSE, TRUE, TRUE, FALSE }, /* Glulx */
+ { FALSE, FALSE, TRUE, TRUE, FALSE } /* Gblorb */
};
static gchar *format_names[CHIMARA_IF_NUM_FORMATS] = {
N_("Z-code version 5"),
N_("Blorbed Glulx")
};
static gchar *interpreter_names[CHIMARA_IF_NUM_INTERPRETERS] = {
- N_("Frotz"), N_("Nitfol"), N_("Glulxe"), N_("Git")
+ N_("Frotz"), N_("Nitfol"), N_("Glulxe"), N_("Git"), N_("Bocfel")
};
static gchar *plugin_names[CHIMARA_IF_NUM_INTERPRETERS] = {
- "frotz", "nitfol", "glulxe", "git"
+ "frotz", "nitfol", "glulxe", "git", "bocfel"
};
typedef enum _ChimaraIFFlags {
gint random_seed;
gboolean random_seed_set;
gchar *graphics_file;
- /* Holding buffers for input and response */
- gchar *input;
- GString *response;
+ /* Holding buffers for inputs and responses */
+ GHashTable *active_inputs;
+ GSList *window_librock_list;
} ChimaraIFPrivate;
+typedef struct {
+ char *input;
+ GString *response;
+ gboolean active;
+} InputResponse;
+
#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)
G_DEFINE_TYPE(ChimaraIF, chimara_if, CHIMARA_TYPE_GLK);
+static InputResponse *
+input_response_new(void)
+{
+ InputResponse *retval = g_slice_new0(InputResponse);
+ retval->response = g_string_new("");
+ return retval;
+}
+
static void
-chimara_if_waiting(ChimaraGlk *glk)
+input_response_destroy(InputResponse *inp)
+{
+ g_free(inp->input);
+ g_string_free(inp->response, TRUE);
+ g_slice_free(InputResponse, inp);
+}
+
+static InputResponse *
+ensure_input_response_object(ChimaraIFPrivate *priv, char *string_id)
+{
+ InputResponse *retval = g_hash_table_lookup(priv->active_inputs, string_id);
+ if(retval == NULL)
+ {
+ char *new_key = g_strdup(string_id);
+ priv->window_librock_list = g_slist_prepend(priv->window_librock_list, new_key);
+ retval = input_response_new();
+ g_hash_table_insert(priv->active_inputs, new_key, retval);
+ }
+ return retval;
+}
+
+static void
+emit_command_signal_on_active_inputs(char *window_librock, ChimaraGlk *glk)
{
CHIMARA_IF_USE_PRIVATE(glk, priv);
+ InputResponse *inp = g_hash_table_lookup(priv->active_inputs, window_librock);
+ if(!inp->active)
+ return;
- gchar *response = g_string_free(priv->response, FALSE);
- priv->response = g_string_new("");
+ char *response = g_strdup(inp->response->str);
+ g_string_truncate(inp->response, 0);
gdk_threads_enter();
- g_signal_emit_by_name(glk, "command", priv->input, response);
+ g_signal_emit_by_name(glk, "command", inp->input, response);
gdk_threads_leave();
- g_free(priv->input);
+ g_free(inp->input);
g_free(response);
- priv->input = NULL;
+ inp->input = NULL;
+ inp->active = FALSE;
+}
+
+static void
+chimara_if_waiting(ChimaraGlk *glk)
+{
+ CHIMARA_IF_USE_PRIVATE(glk, priv);
+ g_slist_foreach(priv->window_librock_list, (GFunc)emit_command_signal_on_active_inputs, glk);
}
static void
{
CHIMARA_IF_USE_PRIVATE(glk, priv);
- if(priv->input || priv->response->len > 0)
- chimara_if_waiting(glk); /* Send one last command signal */
+ /* Send one last command signal for any active inputs */
+ g_slist_foreach(priv->window_librock_list, (GFunc)emit_command_signal_on_active_inputs, glk);
priv->format = CHIMARA_IF_FORMAT_NONE;
priv->interpreter = CHIMARA_IF_INTERPRETER_NONE;
}
static void
-chimara_if_char_input(ChimaraGlk *glk, guint32 win_rock, guint keysym)
+chimara_if_char_input(ChimaraGlk *glk, guint32 win_rock, char *string_id, unsigned keysym)
{
CHIMARA_IF_USE_PRIVATE(glk, priv);
- g_assert(priv->input == NULL);
+ InputResponse *inp = ensure_input_response_object(priv, string_id);
+ g_assert(!inp->active);
gchar outbuf[6];
gint outbuflen = g_unichar_to_utf8(gdk_keyval_to_unicode(keysym), outbuf);
- priv->input = g_strndup(outbuf, outbuflen);
+ inp->input = g_strndup(outbuf, outbuflen);
+ inp->active = TRUE;
}
static void
-chimara_if_line_input(ChimaraGlk *glk, guint32 win_rock, gchar *input)
+chimara_if_line_input(ChimaraGlk *glk, guint32 win_rock, char *string_id, char *input)
{
CHIMARA_IF_USE_PRIVATE(glk, priv);
- g_assert(priv->input == NULL);
- priv->input = g_strdup(input);
+ InputResponse *inp = ensure_input_response_object(priv, string_id);
+ g_assert(!inp->active);
+ inp->input = g_strdup(input);
+ inp->active = TRUE;
}
static void
-chimara_if_text_buffer_output(ChimaraGlk *glk, guint32 win_rock, gchar *output)
+chimara_if_text_buffer_output(ChimaraGlk *glk, guint32 win_rock, char *string_id, char *output)
{
CHIMARA_IF_USE_PRIVATE(glk, priv);
- g_string_append(priv->response, output);
+ InputResponse *inp = ensure_input_response_object(priv, string_id);
+ g_string_append(inp->response, output);
+ inp->active = TRUE;
}
static void
chimara_if_init(ChimaraIF *self)
{
+ chimara_init(); /* This is a library entry point */
+
CHIMARA_IF_USE_PRIVATE(self, priv);
priv->preferred_interpreter[CHIMARA_IF_FORMAT_Z5] = CHIMARA_IF_INTERPRETER_FROTZ;
priv->preferred_interpreter[CHIMARA_IF_FORMAT_Z6] = CHIMARA_IF_INTERPRETER_NITFOL;
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->graphics_file = NULL;
- priv->input = NULL;
- priv->response = g_string_new("");
+ priv->active_inputs = g_hash_table_new_full(g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)input_response_destroy);
/* Connect to signals of ChimaraGlk parent */
g_signal_connect(self, "stopped", G_CALLBACK(chimara_if_stopped), NULL);
{
CHIMARA_IF_USE_PRIVATE(object, priv);
g_free(priv->graphics_file);
+ g_hash_table_destroy(priv->active_inputs);
+ g_slist_free(priv->window_librock_list); /* values are already freed in hashtable */
G_OBJECT_CLASS(chimara_if_parent_class)->finalize(object);
}
-static void
-chimara_if_command(ChimaraIF *self, gchar *input, gchar *response)
-{
- /* Default signal handler */
-}
-
-/* COMPAT: G_PARAM_STATIC_STRINGS only appeared in GTK 2.13.0 */
-#ifndef G_PARAM_STATIC_STRINGS
-
-/* COMPAT: G_PARAM_STATIC_NAME and friends only appeared in GTK 2.8 */
-#if GTK_CHECK_VERSION(2,8,0)
-#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
-#else
-#define G_PARAM_STATIC_STRINGS (0)
-#endif
-
-#endif
-
static void
chimara_if_class_init(ChimaraIFClass *klass)
{
object_class->finalize = chimara_if_finalize;
/* Signals */
- klass->command = chimara_if_command;
/**
* ChimaraIF::command:
* @self: The widget that received the signal