#include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glk_set_interrupt_handler:
void
glk_set_interrupt_handler(void (*func)(void))
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
glk_data->interrupt_handler = func;
}
static void
abort_glk()
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
if(glk_data->interrupt_handler)
(*(glk_data->interrupt_handler))();
g_signal_emit_by_name(glk_data->self, "stopped");
g_thread_exit(NULL);
}
-/* Internal function: Signal this Glk thread to abort. Does nothing if the abort
-mutex has already been freed. (That means the thread already ended.) */
-void
-signal_abort()
-{
- if(glk_data && glk_data->abort_lock) {
- g_mutex_lock(glk_data->abort_lock);
- glk_data->abort_signalled = TRUE;
- g_mutex_unlock(glk_data->abort_lock);
- /* Stop blocking on the event queue condition */
- event_throw(evtype_Abort, NULL, 0, 0);
- }
-}
-
/* Internal function: check if the Glk program has been interrupted. */
void
check_for_abort()
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
g_mutex_lock(glk_data->abort_lock);
if(glk_data->abort_signalled)
{
#define ABORT_H
G_GNUC_INTERNAL void check_for_abort();
-G_GNUC_INTERNAL void signal_abort();
#endif
if(!priv->ignore_next_arrange_event)
{
if(arrange)
- event_throw(evtype_Arrange, arrange == priv->root_window->data? NULL : arrange, 0, 0);
+ event_throw(CHIMARA_GLK(widget), evtype_Arrange, arrange == priv->root_window->data? NULL : arrange, 0, 0);
}
else
priv->ignore_next_arrange_event = FALSE;
glk_main_t glk_main;
glkunix_startup_code_t glkunix_startup_code;
glkunix_startup_t args;
+ ChimaraGlkPrivate *glk_data;
};
/* glk_enter() is the actual function called in the new thread in which glk_main() runs. */
static gpointer
glk_enter(struct StartupData *startup)
{
- extern ChimaraGlkPrivate *glk_data;
+ extern GPrivate *glk_data_key;
+ g_private_set(glk_data_key, startup->glk_data);
/* Run startup function */
if(startup->glkunix_startup_code) {
- glk_data->in_startup = TRUE;
+ startup->glk_data->in_startup = TRUE;
int result = startup->glkunix_startup_code(&startup->args);
- glk_data->in_startup = FALSE;
+ startup->glk_data->in_startup = FALSE;
int i = 0;
while(i < startup->args.argc)
}
/* Run main function */
- g_signal_emit_by_name(glk_data->self, "started");
+ g_signal_emit_by_name(startup->glk_data->self, "started");
(startup->glk_main)();
- g_slice_free(struct StartupData, startup);
- g_signal_emit_by_name(glk_data->self, "stopped");
+ g_signal_emit_by_name(startup->glk_data->self, "stopped");
+ g_slice_free(struct StartupData, startup);
return NULL;
}
startup->args.argv[0] = g_strdup(plugin);
}
- extern ChimaraGlkPrivate *glk_data;
- /* Set the thread's private data */
- /* TODO: Do this with a GPrivate */
- glk_data = priv;
+ /* Initialize thread-private data */
+ extern GPrivate *glk_data_key;
+ glk_data_key = g_private_new(NULL);
+ startup->glk_data = priv;
/* Run in a separate thread */
priv->thread = g_thread_create((GThreadFunc)glk_enter, startup, TRUE, error);
{
g_return_if_fail(glk || CHIMARA_IS_GLK(glk));
/* TODO: check if glk is actually running a program */
- signal_abort();
+ ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+ if(priv->abort_lock) {
+ g_mutex_lock(priv->abort_lock);
+ priv->abort_signalled = TRUE;
+ g_mutex_unlock(priv->abort_lock);
+ /* Stop blocking on the event queue condition */
+ event_throw(glk, evtype_Abort, NULL, 0, 0);
+ }
}
/**
#include "glk.h"
#include <string.h>
+#include "chimara-glk.h"
#include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
#define EVENT_TIMEOUT_MICROSECONDS (3000000)
full, wait for max three seconds and then drop the event. If the event queue is
NULL, i.e. freed, then fail silently. */
void
-event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
+event_throw(ChimaraGlk *glk, glui32 type, winid_t win, glui32 val1, glui32 val2)
{
- if(!glk_data->event_queue)
+ ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+
+ if(!priv->event_queue)
return;
GTimeVal timeout;
g_get_current_time(&timeout);
g_time_val_add(&timeout, EVENT_TIMEOUT_MICROSECONDS);
- g_mutex_lock(glk_data->event_lock);
+ g_mutex_lock(priv->event_lock);
/* Wait for room in the event queue */
- while( g_queue_get_length(glk_data->event_queue) >= EVENT_QUEUE_MAX_LENGTH )
- if( !g_cond_timed_wait(glk_data->event_queue_not_full, glk_data->event_lock, &timeout) )
+ while( g_queue_get_length(priv->event_queue) >= EVENT_QUEUE_MAX_LENGTH )
+ if( !g_cond_timed_wait(priv->event_queue_not_full, priv->event_lock, &timeout) )
{
/* Drop the event after 3 seconds */
- g_mutex_unlock(glk_data->event_lock);
+ g_mutex_unlock(priv->event_lock);
return;
}
event->win = win;
event->val1 = val1;
event->val2 = val2;
- g_queue_push_head(glk_data->event_queue, event);
+ g_queue_push_head(priv->event_queue, event);
/* Signal that there is an event */
- g_cond_signal(glk_data->event_queue_not_empty);
+ g_cond_signal(priv->event_queue_not_empty);
- g_mutex_unlock(glk_data->event_lock);
+ g_mutex_unlock(priv->event_lock);
}
/**
{
g_return_if_fail(event != NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
g_mutex_lock(glk_data->event_lock);
/* Wait for an event */
{
g_return_if_fail(event != NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
event->type = evtype_None;
g_mutex_lock(glk_data->event_lock);
#include <glib.h>
#include "glk.h"
+#include "chimara-glk.h"
#define EVENT_QUEUE_MAX_LENGTH (100)
#define evtype_Abort (-1)
-G_GNUC_INTERNAL void event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2);
+G_GNUC_INTERNAL void event_throw(ChimaraGlk *glk, glui32 type, winid_t win, glui32 val1, glui32 val2);
#endif
#include "magic.h"
#include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glk_fileref_iterate:
glk_fileref_iterate(frefid_t fref, glui32 *rockptr)
{
VALID_FILEREF_OR_NULL(fref, return NULL);
-
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
GList *retnode;
if(fref == NULL)
{
g_return_val_if_fail(filename != NULL, NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
frefid_t f = g_new0(struct glk_fileref_struct, 1);
f->magic = MAGIC_FILEREF;
f->rock = rock;
for each usage */
GtkWidget *chooser;
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
gdk_threads_enter();
switch(fmode)
{
g_return_val_if_fail(name != NULL && strlen(name) > 0, NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
/* Do any string-munging here to remove illegal Latin-1 characters from
filename. On ext3, the only illegal characters are '/' and '\0'. */
-
- char *ptr = name;
- while(*ptr++)
- if(*ptr == '/')
- *ptr = '_';
+ g_strdelimit(name, "/", '_');
/* Find out what encoding filenames are in */
const gchar **charsets; /* Do not free */
glk_fileref_destroy(frefid_t fref)
{
VALID_FILEREF(fref, return);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
if(fref->filename)
#include "chimara-glk-private.h"
#include "gi_blorb.h"
-G_GNUC_INTERNAL ChimaraGlkPrivate *glk_data = NULL;
+G_GNUC_INTERNAL GPrivate *glk_data_key = NULL;
/**
* glk_exit:
void
glk_exit(void)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
if(!glk_data->in_startup)
g_signal_emit_by_name(glk_data->self, "stopped");
glk_stream_close(glk_data->resource_file, NULL);
}
- glk_data = NULL;
g_thread_exit(NULL);
}
#include "fileref.h"
#include "stream.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glkunix_stream_open_pathname:
strid_t
glkunix_stream_open_pathname(char *pathname, glui32 usage, glui32 rock)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
if(!glk_data->in_startup)
ILLEGAL("glkunix_stream_open_pathname() may only be called from "
"glkunix_startup_code().");
{
g_return_if_fail(filename);
g_return_if_fail(strlen(filename) > 0);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
gchar *dirname = g_path_get_dirname(filename);
if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
keycode = keycode_Unknown;
}
- event_throw(evtype_CharInput, win, keycode, 0);
+ event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(widget, CHIMARA_TYPE_GLK)), evtype_CharInput, win, keycode, 0);
/* Only one keypress will be handled */
win->input_request_type = INPUT_REQUEST_NONE;
gtk_text_view_set_editable(GTK_TEXT_VIEW(win->widget), FALSE);
int chars_written = flush_text_buffer(win);
- event_throw(evtype_LineInput, win, chars_written, 0);
+ event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
}
}
g_signal_handler_block( G_OBJECT(win->widget), win->keypress_handler );
int chars_written = flush_text_grid(win);
- event_throw(evtype_LineInput, win, chars_written, 0);
+ event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(GTK_WIDGET(input_entry), CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
}
#include "resource.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* giblorb_set_resource_map:
giblorb_err_t
giblorb_set_resource_map(strid_t file)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
giblorb_map_t *newmap; /* create map allocates memory */
giblorb_err_t error = giblorb_create_map(file, &newmap);
giblorb_map_t*
giblorb_get_resource_map()
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
if(glk_data->resource_map == NULL) {
WARNING("Resource map not set yet.\n");
}
#include <glib/gstdio.h>
#include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/* Internal function: create a stream with a specified rock value */
static strid_t
stream_new_common(glui32 rock, glui32 fmode, enum StreamType type)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
strid_t str = g_new0(struct glk_stream_struct, 1);
str->magic = MAGIC_STREAM;
str->rock = rock;
glk_stream_iterate(strid_t str, glui32 *rockptr)
{
VALID_STREAM_OR_NULL(str, return NULL);
-
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
GList *retnode;
if(str == NULL)
glk_stream_set_current(strid_t str)
{
VALID_STREAM_OR_NULL(str, return);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
if(str != NULL && str->file_mode == filemode_Read)
{
strid_t
glk_stream_get_current()
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
return glk_data->current_stream;
}
void
glk_put_char(unsigned char ch)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_char_stream(glk_data->current_stream, ch);
}
void
glk_put_char_uni(glui32 ch)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_char_stream_uni(glk_data->current_stream, ch);
}
void
glk_put_string(char *s)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_string_stream(glk_data->current_stream, s);
}
void
glk_put_string_uni(glui32 *s)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_string_stream_uni(glk_data->current_stream, s);
}
void
glk_put_buffer(char *buf, glui32 len)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_buffer_stream(glk_data->current_stream, buf, len);
}
void
glk_put_buffer_uni(glui32 *buf, glui32 len)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
VALID_STREAM(glk_data->current_stream, return);
glk_put_buffer_stream_uni(glk_data->current_stream, buf, len);
}
void
stream_close_common(strid_t str, stream_result_t *result)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
/* Remove the stream from the global stream list */
glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
#include "style.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glk_set_style:
void
glk_set_style(glui32 styl)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
g_return_if_fail(glk_data->current_stream != NULL);
glk_set_style_stream(glk_data->current_stream, styl);
}
{
g_return_if_fail(buffer != NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
gtk_text_buffer_create_tag(buffer, "normal", NULL);
gtk_text_buffer_create_tag(buffer, "emphasized", "style", PANGO_STYLE_ITALIC, NULL);
gtk_text_buffer_create_tag(buffer, "preformatted", "font-desc", glk_data->monospace_font_desc, NULL);
{
g_return_if_fail(tag != NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
GObject *tag_object = G_OBJECT(tag);
gint reverse_color = 0;
#include "timer.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glk_request_timer_events:
void
glk_request_timer_events(glui32 millisecs)
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
// Stop any existing timer
if(glk_data->timer_id != 0) {
g_source_remove(glk_data->timer_id);
if(millisecs == 0)
return;
- glk_data->timer_id = g_timeout_add(millisecs, push_timer_event, NULL);
+ glk_data->timer_id = g_timeout_add(millisecs, (GSourceFunc)push_timer_event, glk_data->self);
}
/*
* Will always return TRUE
*/
gboolean
-push_timer_event(gpointer data)
+push_timer_event(ChimaraGlk *glk)
{
- event_throw(evtype_Timer, NULL, 0, 0);
+ event_throw(glk, evtype_Timer, NULL, 0, 0);
return TRUE;
}
#include <glib.h>
#include "event.h"
+#include "chimara-glk.h"
#include "chimara-glk-private.h"
-G_GNUC_INTERNAL gboolean push_timer_event(gpointer data);
+G_GNUC_INTERNAL gboolean push_timer_event(ChimaraGlk *glk);
#endif
+#include <glib.h>
#include "window.h"
#include "magic.h"
#include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
/**
* glk_window_iterate:
{
VALID_WINDOW_OR_NULL(win, return NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
GNode *retnode;
if(win == NULL)
winid_t
glk_window_get_root()
{
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
if(glk_data->root_window == NULL)
return NULL;
return (winid_t)glk_data->root_window->data;
g_return_val_if_fail(method == (method & (winmethod_DirMask | winmethod_DivisionMask)), NULL);
g_return_val_if_fail(!(((method & winmethod_DivisionMask) == winmethod_Proportional) && size > 100), NULL);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
if(split == NULL && glk_data->root_window != NULL)
{
ILLEGAL("Tried to open a new root window, but there is already a root window");
glk_window_close(winid_t win, stream_result_t *result)
{
VALID_WINDOW(win, return);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
gdk_threads_enter(); /* Prevent redraw while we're trashing the window */
{
VALID_WINDOW(win, return);
g_return_if_fail(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
switch(win->type)
{
{
VALID_WINDOW(win, return);
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
switch(win->type)
{
case wintype_Blank:
}
g_return_if_fail(method == (method & (winmethod_DirMask | winmethod_DivisionMask)));
g_return_if_fail(!(((method & winmethod_DivisionMask) == winmethod_Proportional) && size > 100));
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
win->split_method = method;
win->constraint_size = size;
{
VALID_WINDOW(win, return);
g_return_if_fail(win->type == wintype_TextGrid);
+
+ ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
/* Wait until the window's size is current */
g_mutex_lock(glk_data->arrange_lock);