5 #include "chimara-glk.h"
6 #include "chimara-glk-private.h"
10 G_GNUC_INTERNAL GPrivate *glk_data_key = NULL;
15 * If you want to shut down your program in the middle of your <function>
16 * glk_main()</function> function, you can call glk_exit().
18 * This function does not return.
20 * If you print some text to a window and then shut down your program, you can
21 * assume that the player will be able to read it. Most likely the Glk library
22 * will give a <quote><computeroutput>Hit any key to
23 * exit</computeroutput></quote> prompt. (There are other possiblities, however.
24 * A terminal-window version of Glk might simply exit and leave the last screen
25 * state visible in the terminal window.)
28 * You should only shut down your program with glk_exit() or by returning from
29 * your <function>glk_main()</function> function. If you call the ANSI
30 * <function>exit()</function> function, bad things may happen. Some versions of
31 * the Glk library may be designed for multiple sessions, for example, and you
32 * would be cutting off all the sessions instead of just yours. You would
33 * probably also prevent final text from being visible to the player.
35 * <note><title>Chimara</title>
37 * If there are any windows open at the time glk_exit() is called, then Chimara
38 * will leave them open. This way, the final text remains visible. Note that bad
39 * things most definitely <emphasis>will</emphasis> happen if you use the ANSI
40 * <function>exit()</function>.
46 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
50 /* Find the biggest text buffer window */
51 winid_t win, largewin = NULL;
53 for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) {
54 if(win->type == wintype_TextBuffer) {
58 glk_window_get_size(largewin, &w, &h);
61 glk_window_get_size(win, &w, &h);
62 if(w * h > largearea) {
70 glk_set_window(largewin);
71 glk_set_style(style_Alert);
73 glk_put_string(glk_data->final_message);
75 flush_window_buffer(largewin);
78 g_mutex_lock(glk_data->shutdown_lock);
79 for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL)) {
80 if(win->type == wintype_TextGrid || win->type == wintype_TextBuffer)
81 g_signal_handler_unblock(win->widget, win->shutdown_keypress_handler);
83 g_cond_wait(glk_data->shutdown_key_pressed, glk_data->shutdown_lock);
84 g_mutex_unlock(glk_data->shutdown_lock);
88 g_signal_emit_by_name(glk_data->self, "stopped");
96 * Carries out platform-dependent actions such as yielding time to the operating
97 * system and checking for interrupts. glk_tick() should be called every so
98 * often when there is a long interval between calls of glk_select() or
99 * glk_select_poll(). This call is fast; in fact, on average, it does nothing at
100 * all. So you can call it often.
103 * In a virtual machine interpreter, once per opcode is appropriate. In a
104 * program with lots of computation, pick a comparable rate.
107 * glk_tick() does not try to update the screen, or check for player input, or
108 * any other interface task. For that, you should call glk_select() or
109 * glk_select_poll(). See <link linkend="chimara-Events">Events</link>.
112 * <para>Captious critics have pointed out that in the sample program
113 * <filename>model.c</filename>, I do not call glk_tick() at all. This is
114 * because <filename>model.c</filename> has no heavy loops. It does a bit of
115 * work for each command, and then cycles back to the top of the event loop.
116 * The glk_select() call, of course, blocks waiting for input, so it does all
117 * the yielding and interrupt-checking one could imagine.
119 * <para>Basically, you must ensure there's some fixed upper bound on the
120 * amount of computation that can occur before a glk_tick() (or glk_select())
121 * occurs. In a VM interpreter, where the VM code might contain an infinite
122 * loop, this is critical. In a C program, you can often eyeball it.
124 * <para>But the next version of <filename>model.c</filename> will have a
125 * glk_tick() in the ornate printing loop of
126 * <function>verb_yada()</function>. Just to make the point.
135 /* Do one iteration of the main loop if there are any events */
137 if(gtk_events_pending())
138 gtk_main_iteration();