Applied patches to Git interpreter from Gargoyle source code
[rodin/chimara.git] / libchimara / glk.c
1 #include <gtk/gtk.h>
2
3 #include "glk.h"
4 #include "abort.h"
5 #include "chimara-glk.h"
6 #include "chimara-glk-private.h"
7 #include "gi_blorb.h"
8
9 G_GNUC_INTERNAL GPrivate *glk_data_key = NULL;
10
11 /**
12  * glk_exit:
13  * 
14  * If you want to shut down your program in the middle of your <function>
15  * glk_main()</function> function, you can call glk_exit().
16  *
17  * This function does not return.
18  *
19  * If you print some text to a window and then shut down your program, you can
20  * assume that the player will be able to read it. Most likely the Glk library
21  * will give a <quote><computeroutput>Hit any key to 
22  * exit</computeroutput></quote> prompt. (There are other possiblities, however.
23  * A terminal-window version of Glk might simply exit and leave the last screen
24  * state visible in the terminal window.)
25  *
26  * <note><para>
27  * You should only shut down your program with glk_exit() or by returning from
28  * your <function>glk_main()</function> function. If you call the ANSI 
29  * <function>exit()</function> function, bad things may happen. Some versions of
30  * the Glk library may be designed for multiple sessions, for example, and you
31  * would be cutting off all the sessions instead of just yours. You would 
32  * probably also prevent final text from being visible to the player.
33  * </para></note>
34  * <note><title>Chimara</title>
35  * <para>
36  * If there are any windows open at the time glk_exit() is called, then Chimara
37  * will leave them open. This way, the final text remains visible. Note that bad  
38  * things most definitely <emphasis>will</emphasis> happen if you use the ANSI
39  * <function>exit()</function>.
40  * </para></note>
41  */
42 void
43 glk_exit(void)
44 {
45         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
46         
47         if(!glk_data->in_startup)
48                 g_signal_emit_by_name(glk_data->self, "stopped");
49
50         /* Stop any timers */
51         glk_request_timer_events(0);
52
53         /* Close any open resource files */
54         if(glk_data->resource_map != NULL) {
55                 giblorb_destroy_map(glk_data->resource_map);
56                 glk_stream_close(glk_data->resource_file, NULL);
57         }
58
59         g_thread_exit(NULL);
60 }
61
62 /**
63  * glk_tick:
64  *
65  * Carries out platform-dependent actions such as yielding time to the operating
66  * system and checking for interrupts. glk_tick() should be called every so 
67  * often when there is a long interval between calls of glk_select() or 
68  * glk_select_poll(). This call is fast; in fact, on average, it does nothing at
69  * all. So you can call it often.
70  *
71  * <note><para>
72  *   In a virtual machine interpreter, once per opcode is appropriate. In a
73  *   program with lots of computation, pick a comparable rate.
74  * </para></note>
75  * 
76  * glk_tick() does not try to update the screen, or check for player input, or
77  * any other interface task. For that, you should call glk_select() or 
78  * glk_select_poll(). See <link linkend="chimara-Events">Events</link>.
79  * 
80  * <note>
81  *   <para>Captious critics have pointed out that in the sample program
82  *   <filename>model.c</filename>, I do not call glk_tick() at all. This is
83  *   because <filename>model.c</filename> has no heavy loops. It does a bit of
84  *   work for each command, and then cycles back to the top of the event loop.
85  *   The glk_select() call, of course, blocks waiting for input, so it does all
86  *   the yielding and interrupt-checking one could imagine.
87  *   </para>
88  *   <para>Basically, you must ensure there's some fixed upper bound on the
89  *   amount of computation that can occur before a glk_tick() (or glk_select())
90  *   occurs. In a VM interpreter, where the VM code might contain an infinite
91  *   loop, this is critical. In a C program, you can often eyeball it.
92  *   </para>
93  *   <para>But the next version of <filename>model.c</filename> will have a
94  *   glk_tick() in the ornate printing loop of <function>verb_yada()</function>.
95  *   Just to make the point.
96  *   </para>
97  * </note>
98  */
99 void
100 glk_tick()
101 {
102         check_for_abort();
103         
104         /* Do one iteration of the main loop if there are any events */
105         gdk_threads_enter();
106         if(gtk_events_pending())
107                 gtk_main_iteration();
108         gdk_threads_leave();
109 }
110