X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fglk.c;h=b86daed07971769f49f861c460f4ea8836b79258;hb=e4a75256e901a89729c48fcc2f9229cd0cfe9124;hp=c4f395441de42e7331bdc3cb3bf4be1bc9236ee7;hpb=78652af29a2f39e626febd5f4213da57d3a13901;p=projects%2Fchimara%2Fchimara.git diff --git a/libchimara/glk.c b/libchimara/glk.c index c4f3954..b86daed 100644 --- a/libchimara/glk.c +++ b/libchimara/glk.c @@ -5,8 +5,9 @@ #include "chimara-glk.h" #include "chimara-glk-private.h" #include "gi_blorb.h" +#include "window.h" -ChimaraGlkPrivate *glk_data = NULL; +G_GNUC_INTERNAL GPrivate *glk_data_key = NULL; /** * glk_exit: @@ -42,18 +43,50 @@ ChimaraGlkPrivate *glk_data = NULL; void glk_exit(void) { - g_signal_emit_by_name(glk_data->self, "stopped"); - - /* Stop any timers */ - glk_request_timer_events(0); + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + + shutdown_glk_pre(); + + /* Find the biggest text buffer window */ + winid_t win, largewin = NULL; + glui32 largearea = 0; + for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) { + if(win->type == wintype_TextBuffer) { + glui32 w, h; + if(!largewin) { + largewin = win; + glk_window_get_size(largewin, &w, &h); + largearea = w * h; + } else { + glk_window_get_size(win, &w, &h); + if(w * h > largearea) { + largewin = win; + largearea = w * h; + } + } + } + } + if(largewin) { + glk_set_window(largewin); + glk_set_style(style_Alert); + glk_put_string("\n"); + glk_put_string(glk_data->final_message); + glk_put_string("\n"); + flush_window_buffer(largewin); + } - /* Close any open resource files */ - if(glk_data->resource_map != NULL) { - giblorb_destroy_map(glk_data->resource_map); - glk_stream_close(glk_data->resource_file, NULL); + g_mutex_lock(&glk_data->shutdown_lock); + for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) { + if(win->type == wintype_TextGrid || win->type == wintype_TextBuffer) + g_signal_handler_unblock(win->widget, win->shutdown_keypress_handler); } + g_cond_wait(&glk_data->shutdown_key_pressed, &glk_data->shutdown_lock); + g_mutex_unlock(&glk_data->shutdown_lock); + + shutdown_glk_post(); - glk_data = NULL; + g_signal_emit_by_name(glk_data->self, "stopped"); + g_thread_exit(NULL); } @@ -67,8 +100,10 @@ glk_exit(void) * all. So you can call it often. * * - * In a virtual machine interpreter, once per opcode is appropriate. In a - * program with lots of computation, pick a comparable rate. + * In a virtual machine interpreter, once per opcode is appropriate. A more + * parsimonious approach would be once per branch and function call opcode; + * this guarantees it will be called inside loops. In a program with lots of + * computation, pick a comparable rate. * * * glk_tick() does not try to update the screen, or check for player input, or @@ -89,8 +124,8 @@ glk_exit(void) * loop, this is critical. In a C program, you can often eyeball it. * * But the next version of model.c will have a - * glk_tick() in the ornate printing loop of verb_yada(). - * Just to make the point. + * glk_tick() in the ornate printing loop of + * verb_yada(). Just to make the point. * * */