X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fchimara-glk.c;h=bf0e60b7fc72cc2fd332de6be14dc406792df88d;hb=c6009981145d784b85990702617018ebc5d6cc8a;hp=1ddeb7911e8a859294f51de746597dbf81f726f1;hpb=c13096143e7d543149ae9cb4a9237171804d2321;p=rodin%2Fchimara.git diff --git a/libchimara/chimara-glk.c b/libchimara/chimara-glk.c index 1ddeb79..bf0e60b 100644 --- a/libchimara/chimara-glk.c +++ b/libchimara/chimara-glk.c @@ -11,6 +11,7 @@ #include "abort.h" #include "window.h" #include "glkstart.h" +#include "glkunix.h" #define CHIMARA_GLK_MIN_WIDTH 0 #define CHIMARA_GLK_MIN_HEIGHT 0 @@ -41,7 +42,7 @@ */ typedef void (* glk_main_t) (void); -typedef void (* glkunix_startup_code_t) (glkunix_startup_t*); +typedef int (* glkunix_startup_code_t) (glkunix_startup_t*); enum { PROP_0, @@ -84,6 +85,8 @@ chimara_glk_init(ChimaraGlk *self) priv->abort_lock = NULL; priv->abort_signalled = FALSE; priv->arrange_lock = NULL; + priv->rearranged = NULL; + priv->needs_rearrange = FALSE; priv->ignore_next_arrange_event = FALSE; priv->interrupt_handler = NULL; priv->root_window = NULL; @@ -91,6 +94,8 @@ chimara_glk_init(ChimaraGlk *self) priv->current_stream = NULL; priv->stream_list = NULL; priv->timer_id = 0; + priv->in_startup = FALSE; + priv->current_dir = NULL; } static void @@ -172,7 +177,7 @@ chimara_glk_finalize(GObject *object) /* Free the window arrangement signalling */ g_mutex_lock(priv->arrange_lock); - /* Make sure no other thread is busy with this */ + g_cond_free(priv->rearranged); g_mutex_unlock(priv->arrange_lock); g_mutex_free(priv->arrange_lock); priv->arrange_lock = NULL; @@ -180,6 +185,7 @@ chimara_glk_finalize(GObject *object) /* Free private data */ pango_font_description_free(priv->default_font_desc); pango_font_description_free(priv->monospace_font_desc); + g_free(priv->current_dir); G_OBJECT_CLASS(chimara_glk_parent_class)->finalize(object); } @@ -470,6 +476,8 @@ chimara_glk_size_allocate(GtkWidget *widget, GtkAllocation *allocation) } else priv->ignore_next_arrange_event = FALSE; + priv->needs_rearrange = FALSE; + g_cond_signal(priv->rearranged); g_mutex_unlock(priv->arrange_lock); } } @@ -616,7 +624,7 @@ chimara_glk_class_init(ChimaraGlkClass *klass) * ChimaraGlk:monospace-font-description: * * Pointer to a #PangoFontDescription describing the default monospace font, - * to be used in text grid windows and #style_Preformatted, for example. + * to be used in text grid windows and %style_Preformatted, for example. * * Default value: font description created from the string * Monospace @@ -662,6 +670,7 @@ chimara_glk_new(void) priv->event_queue_not_full = g_cond_new(); priv->abort_lock = g_mutex_new(); priv->arrange_lock = g_mutex_new(); + priv->rearranged = g_cond_new(); return GTK_WIDGET(self); } @@ -921,12 +930,19 @@ glk_enter(gpointer glk_main) * @glk: a #ChimaraGlk widget * @plugin: path to a plugin module compiled with glk.h + * @argc: Number of command line arguments in @argv + * @argv: Array of command line arguments to pass to the plugin * @error: location to store a GError, or * %NULL * - * Opens a Glk program compiled as a plugin and runs its glk_main() function in + * Opens a Glk program compiled as a plugin. Sorts out its command line + * arguments from #glkunix_arguments, calls its startup function + * glkunix_startup_code(), and then calls its main function glk_main() in * a separate thread. On failure, returns %FALSE and sets @error. * + * The plugin must at least export a glk_main() function; #glkunix_arguments and + * glkunix_startup_code() are optional. + * * Return value: %TRUE if the Glk program was started successfully. */ gboolean @@ -937,7 +953,6 @@ chimara_glk_run(ChimaraGlk *glk, gchar *plugin, int argc, char *argv[], GError * ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk); - /* Open the module to run */ glk_main_t glk_main; glkunix_startup_code_t glkunix_startup_code; @@ -955,20 +970,43 @@ chimara_glk_run(ChimaraGlk *glk, gchar *plugin, int argc, char *argv[], GError * return FALSE; } - extern ChimaraGlkPrivate *glk_data; + extern ChimaraGlkPrivate *glk_data; /* Set the thread's private data */ /* TODO: Do this with a GPrivate */ glk_data = priv; - + if( g_module_symbol(priv->program, "glkunix_startup_code", (gpointer *) &glkunix_startup_code) ) { glkunix_startup_t data; - data.argc = argc; - data.argv = argv; + glkunix_argumentlist_t *glkunix_arguments; + gboolean startup_succeeded; - glkunix_startup_code(&data); - } + if( !(g_module_symbol(priv->program, "glkunix_arguments", (gpointer *) &glkunix_arguments) && parse_command_line(glkunix_arguments, argc, argv, &data)) ) + { + /* arguments could not be parsed, so create data ourselves */ + data.argc = 1; + data.argv = g_new0(gchar *, 1); + } + /* Set the program name */ + data.argv[0] = g_strdup(plugin); + + priv->in_startup = TRUE; + startup_succeeded = glkunix_startup_code(&data); + priv->in_startup = FALSE; + + int i=0; + while(i < data.argc) + g_free(data.argv[i++]); + g_free(data.argv); + + if(!startup_succeeded) + { + chimara_glk_stopped(glk); + return FALSE; + } + } + /* Run in a separate thread */ priv->thread = g_thread_create(glk_enter, glk_main, TRUE, error);