Exemple #1
0
/**
 * glk_exit:
 *
 * If you want to shut down your program in the middle of your `glk_main()`
 * function, you can call glk_exit().
 *
 * This function does not return.
 *
 * If you print some text to a window and then shut down your program, you can
 * assume that the player will be able to read it. Most likely the Glk library
 * will give a “`Hit any key to exit`” prompt.
 * (There are other possiblities, however.
 * A terminal-window version of Glk might simply exit and leave the last screen
 * state visible in the terminal window.)
 *
 * <note><para>
 * You should only shut down your program with glk_exit() or by returning from
 * your <function>glk_main()</function> function. If you call the ANSI
 * <function>exit()</function> function, bad things may happen. Some versions of
 * the Glk library may be designed for multiple sessions, for example, and you
 * would be cutting off all the sessions instead of just yours. You would
 * probably also prevent final text from being visible to the player.
 * </para></note>
 *
 * > # Chimara #
 * > If there are any windows open at the time glk_exit() is called, then
 * > Chimara will leave them open.
 * > This way, the final text remains visible.
 * > Note that bad things most definitely <emphasis>will</emphasis> happen if
 * > you use the ANSI `exit()`.
 */
void
glk_exit(void)
{
    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);
    }

    /* Wait for a keypress if any text grid or buffer windows are open */
    gboolean should_wait = FALSE;
    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);
            should_wait = TRUE;
        }
    }
    if (should_wait)
        g_cond_wait(&glk_data->shutdown_key_pressed, &glk_data->shutdown_lock);
    g_mutex_unlock(&glk_data->shutdown_lock);

    shutdown_glk_post();

    gdk_threads_add_idle((GSourceFunc)emit_stopped_signal, glk_data->self);

    g_thread_exit(NULL);
}
Exemple #2
0
/* Internal function: abort this Glk program, freeing resources and calling the
user's interrupt handler. */
static void
abort_glk(void)
{
	ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
	if(glk_data->interrupt_handler)
		(*(glk_data->interrupt_handler))();
	shutdown_glk_pre();
	shutdown_glk_post();
	/* If program is terminated by g_thread_exit() instead of returning from the
	 glk_main() function, then the line in glk_exit() where the "stopped" 
	 signal is emitted will not be reached. So we have to emit it here. */
	if(!glk_data->in_startup)
		g_signal_emit_by_name(glk_data->self, "stopped");
	g_thread_exit(NULL);
}