Update Dispatch layer
[projects/chimara/chimara.git] / libchimara / gi_dispa.c
1 /* gi_dispa.c: Dispatch layer for Glk API, version 0.7.4.
2     Designed by Andrew Plotkin <erkyrath@eblong.com>
3     http://eblong.com/zarf/glk/
4
5     This file is copyright 1998-2012 by Andrew Plotkin. You may copy,
6     distribute, and incorporate it into your own programs, by any means
7     and under any conditions, as long as you do not modify it. You may
8     also modify this file, incorporate it into your own programs,
9     and distribute the modified version, as long as you retain a notice
10     in your program or documentation which mentions my name and the URL
11     shown above.
12 */
13
14 /* This code should be linked into every Glk library, without change. 
15     Get the latest version from the URL above. */
16
17 #include "glk.h"
18 #include "gi_dispa.h"
19
20 #ifndef NULL
21 #define NULL 0
22 #endif
23
24 #define NUMCLASSES   \
25     (sizeof(class_table) / sizeof(gidispatch_intconst_t))
26
27 #define NUMINTCONSTANTS   \
28     (sizeof(intconstant_table) / sizeof(gidispatch_intconst_t))
29
30 #define NUMFUNCTIONS   \
31     (sizeof(function_table) / sizeof(gidispatch_function_t))
32
33 /* The constants in this table must be ordered alphabetically. */
34 static gidispatch_intconst_t class_table[] = {
35     { "fileref", (2) },   /* "Qc" */
36     { "schannel", (3) },  /* "Qd" */
37     { "stream", (1) },    /* "Qb" */
38     { "window", (0) },    /* "Qa" */
39 };
40
41 /* The constants in this table must be ordered alphabetically. */
42 static gidispatch_intconst_t intconstant_table[] = {
43     { "evtype_Arrange", (5)  },
44     { "evtype_CharInput", (2) },
45     { "evtype_Hyperlink", (8) },
46     { "evtype_LineInput", (3) },
47     { "evtype_MouseInput", (4) },
48     { "evtype_None", (0) },
49     { "evtype_Redraw", (6) },
50     { "evtype_SoundNotify", (7) },
51     { "evtype_Timer", (1) },
52     { "evtype_VolumeNotify", (9) },
53
54     { "filemode_Read", (0x02) },
55     { "filemode_ReadWrite", (0x03) },
56     { "filemode_Write", (0x01) },
57     { "filemode_WriteAppend", (0x05) },
58
59     { "fileusage_BinaryMode", (0x000) },
60     { "fileusage_Data", (0x00) },
61     { "fileusage_InputRecord", (0x03) },
62     { "fileusage_SavedGame", (0x01) },
63     { "fileusage_TextMode",   (0x100) },
64     { "fileusage_Transcript", (0x02) },
65     { "fileusage_TypeMask", (0x0f) },
66
67     { "gestalt_CharInput", (1) },
68     { "gestalt_CharOutput", (3) },
69     { "gestalt_CharOutput_ApproxPrint", (1) },
70     { "gestalt_CharOutput_CannotPrint", (0) },
71     { "gestalt_CharOutput_ExactPrint", (2) },
72     { "gestalt_DateTime", (20) },
73     { "gestalt_DrawImage", (7) },
74     { "gestalt_Graphics", (6) },
75     { "gestalt_GraphicsTransparency", (14) },
76     { "gestalt_HyperlinkInput", (12) },
77     { "gestalt_Hyperlinks", (11) },
78     { "gestalt_LineInput", (2) },
79     { "gestalt_LineInputEcho", (17) },
80     { "gestalt_LineTerminatorKey", (19) },
81     { "gestalt_LineTerminators", (18) },
82     { "gestalt_MouseInput", (4) },
83     { "gestalt_ResourceStream", (22) },
84     { "gestalt_Sound", (8) },
85     { "gestalt_Sound2", (21) },
86     { "gestalt_SoundMusic", (13) },
87     { "gestalt_SoundNotify", (10) },
88     { "gestalt_SoundVolume", (9) },
89     { "gestalt_Timer", (5) },
90     { "gestalt_Unicode", (15) },
91     { "gestalt_UnicodeNorm", (16) },
92     { "gestalt_Version", (0) },
93
94     { "imagealign_InlineCenter",  (0x03) },
95     { "imagealign_InlineDown",  (0x02) },
96     { "imagealign_MarginLeft",  (0x04) },
97     { "imagealign_MarginRight",  (0x05) },
98     { "imagealign_InlineUp",  (0x01) },
99
100     { "keycode_Delete",   (0xfffffff9) },
101     { "keycode_Down",     (0xfffffffb) },
102     { "keycode_End",      (0xfffffff3) },
103     { "keycode_Escape",   (0xfffffff8) },
104     { "keycode_Func1",    (0xffffffef) },
105     { "keycode_Func10",   (0xffffffe6) },
106     { "keycode_Func11",   (0xffffffe5) },
107     { "keycode_Func12",   (0xffffffe4) },
108     { "keycode_Func2",    (0xffffffee) },
109     { "keycode_Func3",    (0xffffffed) },
110     { "keycode_Func4",    (0xffffffec) },
111     { "keycode_Func5",    (0xffffffeb) },
112     { "keycode_Func6",    (0xffffffea) },
113     { "keycode_Func7",    (0xffffffe9) },
114     { "keycode_Func8",    (0xffffffe8) },
115     { "keycode_Func9",    (0xffffffe7) },
116     { "keycode_Home",     (0xfffffff4) },
117     { "keycode_Left",     (0xfffffffe) },
118     { "keycode_MAXVAL",   (28)  },
119     { "keycode_PageDown", (0xfffffff5) },
120     { "keycode_PageUp",   (0xfffffff6) },
121     { "keycode_Return",   (0xfffffffa) },
122     { "keycode_Right",    (0xfffffffd) },
123     { "keycode_Tab",      (0xfffffff7) },
124     { "keycode_Unknown",  (0xffffffff) },
125     { "keycode_Up",       (0xfffffffc) },
126
127     { "seekmode_Current", (1) },
128     { "seekmode_End", (2) },
129     { "seekmode_Start", (0) },
130
131     { "style_Alert", (5) },
132     { "style_BlockQuote", (7) },
133     { "style_Emphasized", (1) },
134     { "style_Header", (3) },
135     { "style_Input", (8) },
136     { "style_NUMSTYLES", (11) },
137     { "style_Normal", (0) },
138     { "style_Note", (6) },
139     { "style_Preformatted", (2) },
140     { "style_Subheader", (4) },
141     { "style_User1", (9) },
142     { "style_User2", (10) },
143     { "stylehint_BackColor", (8) },
144     { "stylehint_Indentation", (0) },
145     { "stylehint_Justification", (2)  },
146     { "stylehint_NUMHINTS", (10) },
147     { "stylehint_Oblique", (5) },
148     { "stylehint_ParaIndentation", (1) },
149     { "stylehint_Proportional", (6) },
150     { "stylehint_ReverseColor", (9) },
151     { "stylehint_Size", (3) },
152     { "stylehint_TextColor", (7) },
153     { "stylehint_Weight", (4) },
154     { "stylehint_just_Centered", (2) },
155     { "stylehint_just_LeftFlush", (0) },
156     { "stylehint_just_LeftRight", (1) },
157     { "stylehint_just_RightFlush", (3) },
158
159     { "winmethod_Above", (0x02)  },
160     { "winmethod_Below", (0x03)  },
161     { "winmethod_Border", (0x000)  },
162     { "winmethod_BorderMask", (0x100)  },
163     { "winmethod_DirMask", (0x0f) },
164     { "winmethod_DivisionMask", (0xf0) },
165     { "winmethod_Fixed", (0x10) },
166     { "winmethod_Left",  (0x00)  },
167     { "winmethod_NoBorder", (0x100)  },
168     { "winmethod_Proportional", (0x20) },
169     { "winmethod_Right", (0x01)  },
170
171     { "wintype_AllTypes", (0)  },
172     { "wintype_Blank", (2)  },
173     { "wintype_Graphics", (5)  },
174     { "wintype_Pair", (1)  },
175     { "wintype_TextBuffer", (3) },
176     { "wintype_TextGrid", (4) },
177 };
178
179 /* The functions in this table must be ordered by id. */
180 static gidispatch_function_t function_table[] = {
181     { 0x0001, glk_exit, "exit" },
182     { 0x0002, glk_set_interrupt_handler, "set_interrupt_handler" },
183     { 0x0003, glk_tick, "tick" },
184     { 0x0004, glk_gestalt, "gestalt" },
185     { 0x0005, glk_gestalt_ext, "gestalt_ext" },
186     { 0x0020, glk_window_iterate, "window_iterate" },
187     { 0x0021, glk_window_get_rock, "window_get_rock" },
188     { 0x0022, glk_window_get_root, "window_get_root" },
189     { 0x0023, glk_window_open, "window_open" },
190     { 0x0024, glk_window_close, "window_close" },
191     { 0x0025, glk_window_get_size, "window_get_size" },
192     { 0x0026, glk_window_set_arrangement, "window_set_arrangement" },
193     { 0x0027, glk_window_get_arrangement, "window_get_arrangement" },
194     { 0x0028, glk_window_get_type, "window_get_type" },
195     { 0x0029, glk_window_get_parent, "window_get_parent" },
196     { 0x002A, glk_window_clear, "window_clear" },
197     { 0x002B, glk_window_move_cursor, "window_move_cursor" },
198     { 0x002C, glk_window_get_stream, "window_get_stream" },
199     { 0x002D, glk_window_set_echo_stream, "window_set_echo_stream" },
200     { 0x002E, glk_window_get_echo_stream, "window_get_echo_stream" },
201     { 0x002F, glk_set_window, "set_window" },
202     { 0x0030, glk_window_get_sibling, "window_get_sibling" },
203     { 0x0040, glk_stream_iterate, "stream_iterate" },
204     { 0x0041, glk_stream_get_rock, "stream_get_rock" },
205     { 0x0042, glk_stream_open_file, "stream_open_file" },
206     { 0x0043, glk_stream_open_memory, "stream_open_memory" },
207     { 0x0044, glk_stream_close, "stream_close" },
208     { 0x0045, glk_stream_set_position, "stream_set_position" },
209     { 0x0046, glk_stream_get_position, "stream_get_position" },
210     { 0x0047, glk_stream_set_current, "stream_set_current" },
211     { 0x0048, glk_stream_get_current, "stream_get_current" },
212     { 0x0060, glk_fileref_create_temp, "fileref_create_temp" },
213     { 0x0061, glk_fileref_create_by_name, "fileref_create_by_name" },
214     { 0x0062, glk_fileref_create_by_prompt, "fileref_create_by_prompt" },
215     { 0x0063, glk_fileref_destroy, "fileref_destroy" },
216     { 0x0064, glk_fileref_iterate, "fileref_iterate" },
217     { 0x0065, glk_fileref_get_rock, "fileref_get_rock" },
218     { 0x0066, glk_fileref_delete_file, "fileref_delete_file" },
219     { 0x0067, glk_fileref_does_file_exist, "fileref_does_file_exist" },
220     { 0x0068, glk_fileref_create_from_fileref, "fileref_create_from_fileref" },
221     { 0x0080, glk_put_char, "put_char" },
222     { 0x0081, glk_put_char_stream, "put_char_stream" },
223     { 0x0082, glk_put_string, "put_string" },
224     { 0x0083, glk_put_string_stream, "put_string_stream" },
225     { 0x0084, glk_put_buffer, "put_buffer" },
226     { 0x0085, glk_put_buffer_stream, "put_buffer_stream" },
227     { 0x0086, glk_set_style, "set_style" },
228     { 0x0087, glk_set_style_stream, "set_style_stream" },
229     { 0x0090, glk_get_char_stream, "get_char_stream" },
230     { 0x0091, glk_get_line_stream, "get_line_stream" },
231     { 0x0092, glk_get_buffer_stream, "get_buffer_stream" },
232     { 0x00A0, glk_char_to_lower, "char_to_lower" },
233     { 0x00A1, glk_char_to_upper, "char_to_upper" },
234     { 0x00B0, glk_stylehint_set, "stylehint_set" },
235     { 0x00B1, glk_stylehint_clear, "stylehint_clear" },
236     { 0x00B2, glk_style_distinguish, "style_distinguish" },
237     { 0x00B3, glk_style_measure, "style_measure" },
238     { 0x00C0, glk_select, "select" },
239     { 0x00C1, glk_select_poll, "select_poll" },
240     { 0x00D0, glk_request_line_event, "request_line_event" },
241     { 0x00D1, glk_cancel_line_event, "cancel_line_event" },
242     { 0x00D2, glk_request_char_event, "request_char_event" },
243     { 0x00D3, glk_cancel_char_event, "cancel_char_event" },
244     { 0x00D4, glk_request_mouse_event, "request_mouse_event" },
245     { 0x00D5, glk_cancel_mouse_event, "cancel_mouse_event" },
246     { 0x00D6, glk_request_timer_events, "request_timer_events" },
247 #ifdef GLK_MODULE_IMAGE
248     { 0x00E0, glk_image_get_info, "image_get_info" },
249     { 0x00E1, glk_image_draw, "image_draw" },
250     { 0x00E2, glk_image_draw_scaled, "image_draw_scaled" },
251     { 0x00E8, glk_window_flow_break, "window_flow_break" },
252     { 0x00E9, glk_window_erase_rect, "window_erase_rect" },
253     { 0x00EA, glk_window_fill_rect, "window_fill_rect" },
254     { 0x00EB, glk_window_set_background_color, "window_set_background_color" },
255 #endif /* GLK_MODULE_IMAGE */
256 #ifdef GLK_MODULE_SOUND
257     { 0x00F0, glk_schannel_iterate, "schannel_iterate" },
258     { 0x00F1, glk_schannel_get_rock, "schannel_get_rock" },
259     { 0x00F2, glk_schannel_create, "schannel_create" },
260     { 0x00F3, glk_schannel_destroy, "schannel_destroy" },
261     { 0x00F8, glk_schannel_play, "schannel_play" },
262     { 0x00F9, glk_schannel_play_ext, "schannel_play_ext" },
263     { 0x00FA, glk_schannel_stop, "schannel_stop" },
264     { 0x00FB, glk_schannel_set_volume, "schannel_set_volume" },
265     { 0x00FC, glk_sound_load_hint, "sound_load_hint" },
266 #ifdef GLK_MODULE_SOUND2
267     { 0x00F4, glk_schannel_create_ext, "schannel_create_ext" },
268     { 0x00F7, glk_schannel_play_multi, "schannel_play_multi" },
269     { 0x00FD, glk_schannel_set_volume_ext, "schannel_set_volume_ext" },
270     { 0x00FE, glk_schannel_pause, "schannel_pause" },
271     { 0x00FF, glk_schannel_unpause, "schannel_unpause" },
272 #endif /* GLK_MODULE_SOUND2 */
273 #endif /* GLK_MODULE_SOUND */
274 #ifdef GLK_MODULE_HYPERLINKS
275     { 0x0100, glk_set_hyperlink, "set_hyperlink" },
276     { 0x0101, glk_set_hyperlink_stream, "set_hyperlink_stream" },
277     { 0x0102, glk_request_hyperlink_event, "request_hyperlink_event" },
278     { 0x0103, glk_cancel_hyperlink_event, "cancel_hyperlink_event" },
279 #endif /* GLK_MODULE_HYPERLINKS */
280 #ifdef GLK_MODULE_UNICODE
281     { 0x0120, glk_buffer_to_lower_case_uni, "buffer_to_lower_case_uni" },
282     { 0x0121, glk_buffer_to_upper_case_uni, "buffer_to_upper_case_uni" },
283     { 0x0122, glk_buffer_to_title_case_uni, "buffer_to_title_case_uni" },
284     { 0x0128, glk_put_char_uni, "put_char_uni" },
285     { 0x0129, glk_put_string_uni, "put_string_uni" },
286     { 0x012A, glk_put_buffer_uni, "put_buffer_uni" },
287     { 0x012B, glk_put_char_stream_uni, "put_char_stream_uni" },
288     { 0x012C, glk_put_string_stream_uni, "put_string_stream_uni" },
289     { 0x012D, glk_put_buffer_stream_uni, "put_buffer_stream_uni" },
290     { 0x0130, glk_get_char_stream_uni, "get_char_stream_uni" },
291     { 0x0131, glk_get_buffer_stream_uni, "get_buffer_stream_uni" },
292     { 0x0132, glk_get_line_stream_uni, "get_line_stream_uni" },
293     { 0x0138, glk_stream_open_file_uni, "stream_open_file_uni" },
294     { 0x0139, glk_stream_open_memory_uni, "stream_open_memory_uni" },
295     { 0x0140, glk_request_char_event_uni, "request_char_event_uni" },
296     { 0x0141, glk_request_line_event_uni, "request_line_event_uni" },
297 #endif /* GLK_MODULE_UNICODE */
298 #ifdef GLK_MODULE_UNICODE_NORM
299     { 0x0123, glk_buffer_canon_decompose_uni, "buffer_canon_decompose_uni" },
300     { 0x0124, glk_buffer_canon_normalize_uni, "buffer_canon_normalize_uni" },
301 #endif /* GLK_MODULE_UNICODE_NORM */
302 #ifdef GLK_MODULE_LINE_ECHO
303     { 0x0150, glk_set_echo_line_event, "set_echo_line_event" },
304 #endif /* GLK_MODULE_LINE_ECHO */
305 #ifdef GLK_MODULE_LINE_TERMINATORS
306     { 0x0151, glk_set_terminators_line_event, "set_terminators_line_event" },
307 #endif /* GLK_MODULE_LINE_TERMINATORS */
308 #ifdef GLK_MODULE_DATETIME
309     { 0x0160, glk_current_time, "current_time" },
310     { 0x0161, glk_current_simple_time, "current_simple_time" },
311     { 0x0168, glk_time_to_date_utc, "time_to_date_utc" },
312     { 0x0169, glk_time_to_date_local, "time_to_date_local" },
313     { 0x016A, glk_simple_time_to_date_utc, "simple_time_to_date_utc" },
314     { 0x016B, glk_simple_time_to_date_local, "simple_time_to_date_local" },
315     { 0x016C, glk_date_to_time_utc, "date_to_time_utc" },
316     { 0x016D, glk_date_to_time_local, "date_to_time_local" },
317     { 0x016E, glk_date_to_simple_time_utc, "date_to_simple_time_utc" },
318     { 0x016F, glk_date_to_simple_time_local, "date_to_simple_time_local" },
319 #endif /* GLK_MODULE_DATETIME */
320 #ifdef GLK_MODULE_RESOURCE_STREAM
321     { 0x0049, glk_stream_open_resource, "stream_open_resource" },
322     { 0x013A, glk_stream_open_resource_uni, "stream_open_resource_uni" },
323 #endif /* GLK_MODULE_RESOURCE_STREAM */
324 };
325
326 glui32 gidispatch_count_classes()
327 {
328     return NUMCLASSES;
329 }
330
331 gidispatch_intconst_t *gidispatch_get_class(glui32 index)
332 {
333     if (index < 0 || index >= NUMCLASSES)
334         return NULL;
335     return &(class_table[index]);
336 }
337
338 glui32 gidispatch_count_intconst()
339 {
340     return NUMINTCONSTANTS;
341 }
342
343 gidispatch_intconst_t *gidispatch_get_intconst(glui32 index)
344 {
345     if (index < 0 || index >= NUMINTCONSTANTS)
346         return NULL;
347     return &(intconstant_table[index]);
348 }
349
350 glui32 gidispatch_count_functions()
351 {
352     return NUMFUNCTIONS;
353 }
354
355 gidispatch_function_t *gidispatch_get_function(glui32 index)
356 {
357     if (index < 0 || index >= NUMFUNCTIONS)
358         return NULL;
359     return &(function_table[index]);
360 }
361
362 gidispatch_function_t *gidispatch_get_function_by_id(glui32 id)
363 {
364     int top, bot, val;
365     gidispatch_function_t *func;
366     
367     bot = 0;
368     top = NUMFUNCTIONS;
369     
370     while (1) {
371         val = (top+bot) / 2;
372         func = &(function_table[val]);
373         if (func->id == id)
374             return func;
375         if (bot >= top-1)
376             break;
377         if (func->id < id) {
378             bot = val+1;
379         }
380         else {
381             top = val;
382         }
383     }
384     
385     return NULL;
386 }
387
388 char *gidispatch_prototype(glui32 funcnum)
389 {
390     switch (funcnum) {
391         case 0x0001: /* exit */
392             return "0:";
393         case 0x0002: /* set_interrupt_handler */
394             /* cannot be invoked through dispatch layer */
395             return NULL;
396         case 0x0003: /* tick */
397             return "0:";
398         case 0x0004: /* gestalt */
399             return "3IuIu:Iu";
400         case 0x0005: /* gestalt_ext */
401             return "4IuIu&#Iu:Iu";
402         case 0x0020: /* window_iterate */
403             return "3Qa<Iu:Qa";
404         case 0x0021: /* window_get_rock */
405             return "2Qa:Iu";
406         case 0x0022: /* window_get_root */
407             return "1:Qa";
408         case 0x0023: /* window_open */
409             return "6QaIuIuIuIu:Qa";
410         case 0x0024: /* window_close */
411             return "2Qa<[2IuIu]:";
412         case 0x0025: /* window_get_size */
413             return "3Qa<Iu<Iu:";
414         case 0x0026: /* window_set_arrangement */
415             return "4QaIuIuQa:";
416         case 0x0027: /* window_get_arrangement */
417             return "4Qa<Iu<Iu<Qa:";
418         case 0x0028: /* window_get_type */
419             return "2Qa:Iu";
420         case 0x0029: /* window_get_parent */
421             return "2Qa:Qa";
422         case 0x002A: /* window_clear */
423             return "1Qa:";
424         case 0x002B: /* window_move_cursor */
425             return "3QaIuIu:";
426         case 0x002C: /* window_get_stream */
427             return "2Qa:Qb";
428         case 0x002D: /* window_set_echo_stream */
429             return "2QaQb:";
430         case 0x002E: /* window_get_echo_stream */
431             return "2Qa:Qb";
432         case 0x002F: /* set_window */
433             return "1Qa:";
434         case 0x0030: /* window_get_sibling */
435             return "2Qa:Qa";
436         case 0x0040: /* stream_iterate */
437             return "3Qb<Iu:Qb";
438         case 0x0041: /* stream_get_rock */
439             return "2Qb:Iu";
440         case 0x0042: /* stream_open_file */
441             return "4QcIuIu:Qb";
442         case 0x0043: /* stream_open_memory */
443             return "4&#!CnIuIu:Qb";
444         case 0x0044: /* stream_close */
445             return "2Qb<[2IuIu]:";
446         case 0x0045: /* stream_set_position */
447             return "3QbIsIu:";
448         case 0x0046: /* stream_get_position */
449             return "2Qb:Iu";
450         case 0x0047: /* stream_set_current */
451             return "1Qb:";
452         case 0x0048: /* stream_get_current */
453             return "1:Qb";
454         case 0x0060: /* fileref_create_temp */
455             return "3IuIu:Qc";
456         case 0x0061: /* fileref_create_by_name */
457             return "4IuSIu:Qc";
458         case 0x0062: /* fileref_create_by_prompt */
459             return "4IuIuIu:Qc";
460         case 0x0063: /* fileref_destroy */
461             return "1Qc:";
462         case 0x0064: /* fileref_iterate */
463             return "3Qc<Iu:Qc";
464         case 0x0065: /* fileref_get_rock */
465             return "2Qc:Iu";
466         case 0x0066: /* fileref_delete_file */
467             return "1Qc:";
468         case 0x0067: /* fileref_does_file_exist */
469             return "2Qc:Iu";
470         case 0x0068: /* fileref_create_from_fileref */
471             return "4IuQcIu:Qc";
472         case 0x0080: /* put_char */
473             return "1Cu:";
474         case 0x0081: /* put_char_stream */
475             return "2QbCu:";
476         case 0x0082: /* put_string */
477             return "1S:";
478         case 0x0083: /* put_string_stream */
479             return "2QbS:";
480         case 0x0084: /* put_buffer */
481             return "1>+#Cn:";
482         case 0x0085: /* put_buffer_stream */
483             return "2Qb>+#Cn:"; 
484         case 0x0086: /* set_style */
485             return "1Iu:";
486         case 0x0087: /* set_style_stream */
487             return "2QbIu:";
488         case 0x0090: /* get_char_stream */
489             return "2Qb:Is";
490         case 0x0091: /* get_line_stream */
491             return "3Qb<+#Cn:Iu"; 
492         case 0x0092: /* get_buffer_stream */
493             return "3Qb<+#Cn:Iu"; 
494         case 0x00A0: /* char_to_lower */
495             return "2Cu:Cu";
496         case 0x00A1: /* char_to_upper */
497             return "2Cu:Cu";
498         case 0x00B0: /* stylehint_set */
499             return "4IuIuIuIs:";
500         case 0x00B1: /* stylehint_clear */
501             return "3IuIuIu:";
502         case 0x00B2: /* style_distinguish */
503             return "4QaIuIu:Iu";
504         case 0x00B3: /* style_measure */
505             return "5QaIuIu<Iu:Iu";
506         case 0x00C0: /* select */
507             return "1<+[4IuQaIuIu]:";
508         case 0x00C1: /* select_poll */
509             return "1<+[4IuQaIuIu]:";
510         case 0x00D0: /* request_line_event */
511             return "3Qa&+#!CnIu:";
512         case 0x00D1: /* cancel_line_event */
513             return "2Qa<[4IuQaIuIu]:";
514         case 0x00D2: /* request_char_event */
515             return "1Qa:";
516         case 0x00D3: /* cancel_char_event */
517             return "1Qa:";
518         case 0x00D4: /* request_mouse_event */
519             return "1Qa:";
520         case 0x00D5: /* cancel_mouse_event */
521             return "1Qa:";
522         case 0x00D6: /* request_timer_events */
523             return "1Iu:";
524
525 #ifdef GLK_MODULE_IMAGE
526         case 0x00E0: /* image_get_info */
527             return "4Iu<Iu<Iu:Iu";
528         case 0x00E1: /* image_draw */
529             return "5QaIuIsIs:Iu";
530         case 0x00E2: /* image_draw_scaled */
531             return "7QaIuIsIsIuIu:Iu";
532         case 0x00E8: /* window_flow_break */
533             return "1Qa:";
534         case 0x00E9: /* window_erase_rect */
535             return "5QaIsIsIuIu:";
536         case 0x00EA: /* window_fill_rect */
537             return "6QaIuIsIsIuIu:";
538         case 0x00EB: /* window_set_background_color */
539             return "2QaIu:";
540 #endif /* GLK_MODULE_IMAGE */
541
542 #ifdef GLK_MODULE_SOUND
543         case 0x00F0: /* schannel_iterate */
544             return "3Qd<Iu:Qd";
545         case 0x00F1: /* schannel_get_rock */
546             return "2Qd:Iu";
547         case 0x00F2: /* schannel_create */
548             return "2Iu:Qd";
549         case 0x00F3: /* schannel_destroy */
550             return "1Qd:";
551         case 0x00F8: /* schannel_play */
552             return "3QdIu:Iu";
553         case 0x00F9: /* schannel_play_ext */
554             return "5QdIuIuIu:Iu";
555         case 0x00FA: /* schannel_stop */
556             return "1Qd:";
557         case 0x00FB: /* schannel_set_volume */
558             return "2QdIu:";
559         case 0x00FC: /* sound_load_hint */
560             return "2IuIu:";
561
562 #ifdef GLK_MODULE_SOUND2
563         case 0x00F4: /* schannel_create_ext */
564             return "3IuIu:Qd";
565         case 0x00F7: /* schannel_play_multi */
566             return "4>+#Qd>+#IuIu:Iu";
567         case 0x00FD: /* schannel_set_volume_ext */
568             return "4QdIuIuIu:";
569         case 0x00FE: /* schannel_pause */
570             return "1Qd:";
571         case 0x00FF: /* schannel_unpause */
572             return "1Qd:";
573 #endif /* GLK_MODULE_SOUND2 */
574 #endif /* GLK_MODULE_SOUND */
575
576 #ifdef GLK_MODULE_HYPERLINKS
577         case 0x0100: /* set_hyperlink */
578             return "1Iu:";
579         case 0x0101: /* set_hyperlink_stream */
580             return "2QbIu:";
581         case 0x0102: /* request_hyperlink_event */
582             return "1Qa:";
583         case 0x0103: /* cancel_hyperlink_event */
584             return "1Qa:";
585 #endif /* GLK_MODULE_HYPERLINKS */
586
587 #ifdef GLK_MODULE_UNICODE
588         case 0x0120: /* buffer_to_lower_case_uni */
589             return "3&+#IuIu:Iu";
590         case 0x0121: /* buffer_to_upper_case_uni */
591             return "3&+#IuIu:Iu";
592         case 0x0122: /* buffer_to_title_case_uni */
593             return "4&+#IuIuIu:Iu";
594         case 0x0128: /* put_char_uni */
595             return "1Iu:";
596         case 0x0129: /* put_string_uni */
597             return "1U:";
598         case 0x012A: /* put_buffer_uni */
599             return "1>+#Iu:";
600         case 0x012B: /* put_char_stream_uni */
601             return "2QbIu:";
602         case 0x012C: /* put_string_stream_uni */
603             return "2QbU:";
604         case 0x012D: /* put_buffer_stream_uni */
605             return "2Qb>+#Iu:"; 
606         case 0x0130: /* get_char_stream_uni */
607             return "2Qb:Is";
608         case 0x0131: /* get_buffer_stream_uni */
609             return "3Qb<+#Iu:Iu"; 
610         case 0x0132: /* get_line_stream_uni */
611             return "3Qb<+#Iu:Iu"; 
612         case 0x0138: /* stream_open_file_uni */
613             return "4QcIuIu:Qb";
614         case 0x0139: /* stream_open_memory_uni */
615             return "4&#!IuIuIu:Qb";
616         case 0x0140: /* request_char_event_uni */
617             return "1Qa:";
618         case 0x0141: /* request_line_event_uni */
619             return "3Qa&+#!IuIu:";
620 #endif /* GLK_MODULE_UNICODE */
621             
622 #ifdef GLK_MODULE_UNICODE_NORM
623         case 0x0123: /* buffer_canon_decompose_uni */
624             return "3&+#IuIu:Iu";
625         case 0x0124: /* buffer_canon_normalize_uni */
626             return "3&+#IuIu:Iu";
627 #endif /* GLK_MODULE_UNICODE_NORM */
628
629 #ifdef GLK_MODULE_LINE_ECHO
630         case 0x0150: /* set_echo_line_event */
631             return "2QaIu:";
632 #endif /* GLK_MODULE_LINE_ECHO */
633
634 #ifdef GLK_MODULE_LINE_TERMINATORS
635         case 0x0151: /* set_terminators_line_event */
636             return "2Qa>#Iu:";
637 #endif /* GLK_MODULE_LINE_TERMINATORS */
638             
639 #ifdef GLK_MODULE_DATETIME
640         case 0x0160: /* current_time */
641             return "1<+[3IsIuIs]:";
642         case 0x0161: /* current_simple_time */
643             return "2Iu:Is";
644         case 0x0168: /* time_to_date_utc */
645             return "2>+[3IsIuIs]<+[8IsIsIsIsIsIsIsIs]:";
646         case 0x0169: /* time_to_date_local */
647             return "2>+[3IsIuIs]<+[8IsIsIsIsIsIsIsIs]:";
648         case 0x016A: /* simple_time_to_date_utc */
649             return "3IsIu<+[8IsIsIsIsIsIsIsIs]:";
650         case 0x016B: /* simple_time_to_date_local */
651             return "3IsIu<+[8IsIsIsIsIsIsIsIs]:";
652         case 0x016C: /* date_to_time_utc */
653             return "2>+[8IsIsIsIsIsIsIsIs]<+[3IsIuIs]:";
654         case 0x016D: /* date_to_time_local */
655             return "2>+[8IsIsIsIsIsIsIsIs]<+[3IsIuIs]:";
656         case 0x016E: /* date_to_simple_time_utc */
657             return "3>+[8IsIsIsIsIsIsIsIs]Iu:Is";
658         case 0x016F: /* date_to_simple_time_local */
659             return "3>+[8IsIsIsIsIsIsIsIs]Iu:Is";
660 #endif /* GLK_MODULE_DATETIME */
661
662 #ifdef GLK_MODULE_RESOURCE_STREAM
663         case 0x0049: /* stream_open_resource */
664             return "3IuIu:Qb";
665         case 0x013A: /* stream_open_resource_uni */
666             return "3IuIu:Qb";
667 #endif /* GLK_MODULE_RESOURCE_STREAM */
668
669         default:
670             return NULL;
671     }
672 }
673
674 void gidispatch_call(glui32 funcnum, glui32 numargs, gluniversal_t *arglist)
675 {
676     switch (funcnum) {
677         case 0x0001: /* exit */
678             glk_exit();
679             break;
680         case 0x0002: /* set_interrupt_handler */
681             /* cannot be invoked through dispatch layer */
682             break;
683         case 0x0003: /* tick */
684             glk_tick();
685             break;
686         case 0x0004: /* gestalt */
687             arglist[3].uint = glk_gestalt(arglist[0].uint, arglist[1].uint);
688             break;
689         case 0x0005: /* gestalt_ext */
690             if (arglist[2].ptrflag) {
691                 arglist[6].uint = glk_gestalt_ext(arglist[0].uint, arglist[1].uint,
692                     arglist[3].array, arglist[4].uint);
693             }
694             else {
695                 arglist[4].uint = glk_gestalt_ext(arglist[0].uint, arglist[1].uint,
696                     NULL, 0);
697             }
698             break;
699         case 0x0020: /* window_iterate */
700             if (arglist[1].ptrflag) 
701                 arglist[4].opaqueref = glk_window_iterate(arglist[0].opaqueref, &arglist[2].uint);
702             else
703                 arglist[3].opaqueref = glk_window_iterate(arglist[0].opaqueref, NULL);
704             break;
705         case 0x0021: /* window_get_rock */
706             arglist[2].uint = glk_window_get_rock(arglist[0].opaqueref);
707             break;
708         case 0x0022: /* window_get_root */
709             arglist[1].opaqueref = glk_window_get_root();
710             break;
711         case 0x0023: /* window_open */
712             arglist[6].opaqueref = glk_window_open(arglist[0].opaqueref, arglist[1].uint, 
713                 arglist[2].uint, arglist[3].uint, arglist[4].uint);
714             break;
715         case 0x0024: /* window_close */
716             if (arglist[1].ptrflag) {
717                 stream_result_t dat;
718                 glk_window_close(arglist[0].opaqueref, &dat);
719                 arglist[2].uint = dat.readcount;
720                 arglist[3].uint = dat.writecount;
721             }
722             else {
723                 glk_window_close(arglist[0].opaqueref, NULL);
724             }
725             break;
726         case 0x0025: /* window_get_size */
727             {
728                 int ix = 1;
729                 glui32 *ptr1, *ptr2;
730                 if (!arglist[ix].ptrflag) {
731                     ptr1 = NULL;
732                 }
733                 else {
734                     ix++;
735                     ptr1 = &(arglist[ix].uint);
736                 }
737                 ix++;
738                 if (!arglist[ix].ptrflag) {
739                     ptr2 = NULL;
740                 }
741                 else {
742                     ix++;
743                     ptr2 = &(arglist[ix].uint);
744                 }
745                 ix++;
746                 glk_window_get_size(arglist[0].opaqueref, ptr1, ptr2);
747             }
748             break;
749         case 0x0026: /* window_set_arrangement */
750             glk_window_set_arrangement(arglist[0].opaqueref, arglist[1].uint, 
751                 arglist[2].uint, arglist[3].opaqueref);
752             break;
753         case 0x0027: /* window_get_arrangement */
754             {
755                 int ix = 1;
756                 glui32 *ptr1, *ptr2;
757                 winid_t *ptr3;
758                 if (!arglist[ix].ptrflag) {
759                     ptr1 = NULL;
760                 }
761                 else {
762                     ix++;
763                     ptr1 = &(arglist[ix].uint);
764                 }
765                 ix++;
766                 if (!arglist[ix].ptrflag) {
767                     ptr2 = NULL;
768                 }
769                 else {
770                     ix++;
771                     ptr2 = &(arglist[ix].uint);
772                 }
773                 ix++;
774                 if (!arglist[ix].ptrflag) {
775                     ptr3 = NULL;
776                 }
777                 else {
778                     ix++;
779                     ptr3 = (winid_t *)(&(arglist[ix].opaqueref));
780                 }
781                 ix++;
782                 glk_window_get_arrangement(arglist[0].opaqueref, ptr1, ptr2, ptr3);
783             }
784             break;
785         case 0x0028: /* window_get_type */
786             arglist[2].uint = glk_window_get_type(arglist[0].opaqueref);
787             break;
788         case 0x0029: /* window_get_parent */
789             arglist[2].opaqueref = glk_window_get_parent(arglist[0].opaqueref);
790             break;
791         case 0x002A: /* window_clear */
792             glk_window_clear(arglist[0].opaqueref);
793             break;
794         case 0x002B: /* window_move_cursor */
795             glk_window_move_cursor(arglist[0].opaqueref, arglist[1].uint, 
796                 arglist[2].uint);
797             break;
798         case 0x002C: /* window_get_stream */
799             arglist[2].opaqueref = glk_window_get_stream(arglist[0].opaqueref);
800             break;
801         case 0x002D: /* window_set_echo_stream */
802             glk_window_set_echo_stream(arglist[0].opaqueref, arglist[1].opaqueref);
803             break;
804         case 0x002E: /* window_get_echo_stream */
805             arglist[2].opaqueref = glk_window_get_echo_stream(arglist[0].opaqueref);
806             break;
807         case 0x002F: /* set_window */
808             glk_set_window(arglist[0].opaqueref);
809             break;
810         case 0x0030: /* window_get_sibling */
811             arglist[2].opaqueref = glk_window_get_sibling(arglist[0].opaqueref);
812             break;
813         case 0x0040: /* stream_iterate */
814             if (arglist[1].ptrflag) 
815                 arglist[4].opaqueref = glk_stream_iterate(arglist[0].opaqueref, &arglist[2].uint);
816             else
817                 arglist[3].opaqueref = glk_stream_iterate(arglist[0].opaqueref, NULL);
818             break;
819         case 0x0041: /* stream_get_rock */
820             arglist[2].uint = glk_stream_get_rock(arglist[0].opaqueref);
821             break;
822         case 0x0042: /* stream_open_file */
823             arglist[4].opaqueref = glk_stream_open_file(arglist[0].opaqueref, arglist[1].uint, 
824                 arglist[2].uint);
825             break;
826         case 0x0043: /* stream_open_memory */
827             if (arglist[0].ptrflag) 
828                 arglist[6].opaqueref = glk_stream_open_memory(arglist[1].array, 
829                     arglist[2].uint, arglist[3].uint, arglist[4].uint);
830             else
831                 arglist[4].opaqueref = glk_stream_open_memory(NULL, 
832                     0, arglist[1].uint, arglist[2].uint);
833             break;
834         case 0x0044: /* stream_close */
835             if (arglist[1].ptrflag) {
836                 stream_result_t dat;
837                 glk_stream_close(arglist[0].opaqueref, &dat);
838                 arglist[2].uint = dat.readcount;
839                 arglist[3].uint = dat.writecount;
840             }
841             else {
842                 glk_stream_close(arglist[0].opaqueref, NULL);
843             }
844             break;
845         case 0x0045: /* stream_set_position */
846             glk_stream_set_position(arglist[0].opaqueref, arglist[1].sint,
847                 arglist[2].uint);
848             break;
849         case 0x0046: /* stream_get_position */
850             arglist[2].uint = glk_stream_get_position(arglist[0].opaqueref);
851             break;
852         case 0x0047: /* stream_set_current */
853             glk_stream_set_current(arglist[0].opaqueref);
854             break;
855         case 0x0048: /* stream_get_current */
856             arglist[1].opaqueref = glk_stream_get_current();
857             break;
858         case 0x0060: /* fileref_create_temp */
859             arglist[3].opaqueref = glk_fileref_create_temp(arglist[0].uint, 
860                 arglist[1].uint);
861             break;
862         case 0x0061: /* fileref_create_by_name */
863             arglist[4].opaqueref = glk_fileref_create_by_name(arglist[0].uint, 
864                 arglist[1].charstr, arglist[2].uint);
865             break;
866         case 0x0062: /* fileref_create_by_prompt */
867             arglist[4].opaqueref = glk_fileref_create_by_prompt(arglist[0].uint, 
868                 arglist[1].uint, arglist[2].uint);
869             break;
870         case 0x0063: /* fileref_destroy */
871             glk_fileref_destroy(arglist[0].opaqueref);
872             break;
873         case 0x0064: /* fileref_iterate */
874             if (arglist[1].ptrflag) 
875                 arglist[4].opaqueref = glk_fileref_iterate(arglist[0].opaqueref, &arglist[2].uint);
876             else
877                 arglist[3].opaqueref = glk_fileref_iterate(arglist[0].opaqueref, NULL);
878             break;
879         case 0x0065: /* fileref_get_rock */
880             arglist[2].uint = glk_fileref_get_rock(arglist[0].opaqueref);
881             break;
882         case 0x0066: /* fileref_delete_file */
883             glk_fileref_delete_file(arglist[0].opaqueref);
884             break;
885         case 0x0067: /* fileref_does_file_exist */
886             arglist[2].uint = glk_fileref_does_file_exist(arglist[0].opaqueref);
887             break;
888         case 0x0068: /* fileref_create_from_fileref */
889             arglist[4].opaqueref = glk_fileref_create_from_fileref(arglist[0].uint, 
890                 arglist[1].opaqueref, arglist[2].uint);
891             break;
892         case 0x0080: /* put_char */
893             glk_put_char(arglist[0].uch);
894             break;
895         case 0x0081: /* put_char_stream */
896             glk_put_char_stream(arglist[0].opaqueref, arglist[1].uch);
897             break;
898         case 0x0082: /* put_string */
899             glk_put_string(arglist[0].charstr);
900             break;
901         case 0x0083: /* put_string_stream */
902             glk_put_string_stream(arglist[0].opaqueref, arglist[1].charstr);
903             break;
904         case 0x0084: /* put_buffer */
905             if (arglist[0].ptrflag) 
906                 glk_put_buffer(arglist[1].array, arglist[2].uint);
907             else
908                 glk_put_buffer(NULL, 0);
909             break;
910         case 0x0085: /* put_buffer_stream */
911             if (arglist[1].ptrflag) 
912                 glk_put_buffer_stream(arglist[0].opaqueref, 
913                     arglist[2].array, arglist[3].uint);
914             else
915                 glk_put_buffer_stream(arglist[0].opaqueref, 
916                     NULL, 0);
917             break;
918         case 0x0086: /* set_style */
919             glk_set_style(arglist[0].uint);
920             break;
921         case 0x0087: /* set_style_stream */
922             glk_set_style_stream(arglist[0].opaqueref, arglist[1].uint);
923             break;
924         case 0x0090: /* get_char_stream */
925             arglist[2].sint = glk_get_char_stream(arglist[0].opaqueref);
926             break;
927         case 0x0091: /* get_line_stream */
928             if (arglist[1].ptrflag) 
929                 arglist[5].uint = glk_get_line_stream(arglist[0].opaqueref, 
930                     arglist[2].array, arglist[3].uint);
931             else
932                 arglist[3].uint = glk_get_line_stream(arglist[0].opaqueref, 
933                     NULL, 0);
934             break;
935         case 0x0092: /* get_buffer_stream */
936             if (arglist[1].ptrflag) 
937                 arglist[5].uint = glk_get_buffer_stream(arglist[0].opaqueref, 
938                     arglist[2].array, arglist[3].uint);
939             else
940                 arglist[3].uint = glk_get_buffer_stream(arglist[0].opaqueref, 
941                     NULL, 0);
942             break;
943         case 0x00A0: /* char_to_lower */
944             arglist[2].uch = glk_char_to_lower(arglist[0].uch);
945             break;
946         case 0x00A1: /* char_to_upper */
947             arglist[2].uch = glk_char_to_upper(arglist[0].uch);
948             break;
949         case 0x00B0: /* stylehint_set */
950             glk_stylehint_set(arglist[0].uint, arglist[1].uint,
951                 arglist[2].uint, arglist[3].sint);
952             break;
953         case 0x00B1: /* stylehint_clear */
954             glk_stylehint_clear(arglist[0].uint, arglist[1].uint,
955                 arglist[2].uint);
956             break;
957         case 0x00B2: /* style_distinguish */
958             arglist[4].uint = glk_style_distinguish(arglist[0].opaqueref, arglist[1].uint,
959                 arglist[2].uint);
960             break;
961         case 0x00B3: /* style_measure */
962             if (arglist[3].ptrflag)
963                 arglist[6].uint = glk_style_measure(arglist[0].opaqueref, arglist[1].uint,
964                     arglist[2].uint, &(arglist[4].uint));
965             else
966                 arglist[5].uint = glk_style_measure(arglist[0].opaqueref, arglist[1].uint,
967                     arglist[2].uint, NULL);
968             break;
969         case 0x00C0: /* select */
970             if (arglist[0].ptrflag) {
971                 event_t dat;
972                 glk_select(&dat);
973                 arglist[1].uint = dat.type;
974                 arglist[2].opaqueref = dat.win;
975                 arglist[3].uint = dat.val1;
976                 arglist[4].uint = dat.val2;
977             }
978             else {
979                 glk_select(NULL);
980             }
981             break;
982         case 0x00C1: /* select_poll */
983             if (arglist[0].ptrflag) {
984                 event_t dat;
985                 glk_select_poll(&dat);
986                 arglist[1].uint = dat.type;
987                 arglist[2].opaqueref = dat.win;
988                 arglist[3].uint = dat.val1;
989                 arglist[4].uint = dat.val2;
990             }
991             else {
992                 glk_select_poll(NULL);
993             }
994             break;
995         case 0x00D0: /* request_line_event */
996             if (arglist[1].ptrflag)
997                 glk_request_line_event(arglist[0].opaqueref, arglist[2].array,
998                     arglist[3].uint, arglist[4].uint);
999             else
1000                 glk_request_line_event(arglist[0].opaqueref, NULL,
1001                     0, arglist[2].uint);
1002             break;
1003         case 0x00D1: /* cancel_line_event */
1004             if (arglist[1].ptrflag) {
1005                 event_t dat;
1006                 glk_cancel_line_event(arglist[0].opaqueref, &dat);
1007                 arglist[2].uint = dat.type;
1008                 arglist[3].opaqueref = dat.win;
1009                 arglist[4].uint = dat.val1;
1010                 arglist[5].uint = dat.val2;
1011             }
1012             else {
1013                 glk_cancel_line_event(arglist[0].opaqueref, NULL);
1014             }
1015             break;
1016         case 0x00D2: /* request_char_event */
1017             glk_request_char_event(arglist[0].opaqueref);
1018             break;
1019         case 0x00D3: /* cancel_char_event */
1020             glk_cancel_char_event(arglist[0].opaqueref);
1021             break;
1022         case 0x00D4: /* request_mouse_event */
1023             glk_request_mouse_event(arglist[0].opaqueref);
1024             break;
1025         case 0x00D5: /* cancel_mouse_event */
1026             glk_cancel_mouse_event(arglist[0].opaqueref);
1027             break;
1028         case 0x00D6: /* request_timer_events */
1029             glk_request_timer_events(arglist[0].uint);
1030             break;
1031
1032 #ifdef GLK_MODULE_IMAGE
1033         case 0x00E0: /* image_get_info */
1034             {
1035                 int ix = 1;
1036                 glui32 *ptr1, *ptr2;
1037                 if (!arglist[ix].ptrflag) {
1038                     ptr1 = NULL;
1039                 }
1040                 else {
1041                     ix++;
1042                     ptr1 = &(arglist[ix].uint);
1043                 }
1044                 ix++;
1045                 if (!arglist[ix].ptrflag) {
1046                     ptr2 = NULL;
1047                 }
1048                 else {
1049                     ix++;
1050                     ptr2 = &(arglist[ix].uint);
1051                 }
1052                 ix++;
1053                 ix++;
1054                 arglist[ix].uint = glk_image_get_info(arglist[0].uint, ptr1, ptr2);
1055             }
1056             break;
1057         case 0x00E1: /* image_draw */
1058             arglist[5].uint = glk_image_draw(arglist[0].opaqueref, 
1059                 arglist[1].uint,
1060                 arglist[2].sint, arglist[3].sint);
1061             break;
1062         case 0x00E2: /* image_draw_scaled */
1063             arglist[7].uint = glk_image_draw_scaled(arglist[0].opaqueref, 
1064                 arglist[1].uint,
1065                 arglist[2].sint, arglist[3].sint,
1066                 arglist[4].uint, arglist[5].uint);
1067             break;
1068         case 0x00E8: /* window_flow_break */
1069             glk_window_flow_break(arglist[0].opaqueref);
1070             break;
1071         case 0x00E9: /* window_erase_rect */
1072             glk_window_erase_rect(arglist[0].opaqueref,
1073                 arglist[1].sint, arglist[2].sint,
1074                 arglist[3].uint, arglist[4].uint);
1075             break;
1076         case 0x00EA: /* window_fill_rect */
1077             glk_window_fill_rect(arglist[0].opaqueref, arglist[1].uint,
1078                 arglist[2].sint, arglist[3].sint,
1079                 arglist[4].uint, arglist[5].uint);
1080             break;
1081         case 0x00EB: /* window_set_background_color */
1082             glk_window_set_background_color(arglist[0].opaqueref, arglist[1].uint);
1083             break;
1084 #endif /* GLK_MODULE_IMAGE */
1085
1086 #ifdef GLK_MODULE_SOUND
1087         case 0x00F0: /* schannel_iterate */
1088             if (arglist[1].ptrflag) 
1089                 arglist[4].opaqueref = glk_schannel_iterate(arglist[0].opaqueref, &arglist[2].uint);
1090             else
1091                 arglist[3].opaqueref = glk_schannel_iterate(arglist[0].opaqueref, NULL);
1092             break;
1093         case 0x00F1: /* schannel_get_rock */
1094             arglist[2].uint = glk_schannel_get_rock(arglist[0].opaqueref);
1095             break;
1096         case 0x00F2: /* schannel_create */
1097             arglist[2].opaqueref = glk_schannel_create(arglist[0].uint);
1098             break;
1099         case 0x00F3: /* schannel_destroy */
1100             glk_schannel_destroy(arglist[0].opaqueref);
1101             break;
1102         case 0x00F8: /* schannel_play */
1103             arglist[3].uint = glk_schannel_play(arglist[0].opaqueref, arglist[1].uint);
1104             break;
1105         case 0x00F9: /* schannel_play_ext */
1106             arglist[5].uint = glk_schannel_play_ext(arglist[0].opaqueref, 
1107                 arglist[1].uint, arglist[2].uint, arglist[3].uint);
1108             break;
1109         case 0x00FA: /* schannel_stop */
1110             glk_schannel_stop(arglist[0].opaqueref);
1111             break;
1112         case 0x00FB: /* schannel_set_volume */
1113             glk_schannel_set_volume(arglist[0].opaqueref, arglist[1].uint);
1114             break;
1115         case 0x00FC: /* sound_load_hint */
1116             glk_sound_load_hint(arglist[0].uint, arglist[1].uint);
1117             break;
1118
1119 #ifdef GLK_MODULE_SOUND2
1120         case 0x00F4: /* schannel_create_ext */
1121             arglist[3].opaqueref = glk_schannel_create_ext(arglist[0].uint, arglist[1].uint);
1122             break;
1123         case 0x00F7: /* schannel_play_multi */
1124             if (arglist[0].ptrflag && arglist[3].ptrflag)
1125                 arglist[8].uint = glk_schannel_play_multi(arglist[1].array, arglist[2].uint, arglist[4].array, arglist[5].uint, arglist[6].uint);
1126             else if (arglist[0].ptrflag)
1127                 arglist[6].uint = glk_schannel_play_multi(arglist[1].array, arglist[2].uint, NULL, 0, arglist[4].uint);
1128             else if (arglist[1].ptrflag)
1129                 arglist[6].uint = glk_schannel_play_multi(NULL, 0, arglist[2].array, arglist[3].uint, arglist[4].uint);
1130             else
1131                 arglist[4].uint = glk_schannel_play_multi(NULL, 0, NULL, 0, arglist[2].uint);
1132             break;
1133         case 0x00FD: /* schannel_set_volume_ext */
1134             glk_schannel_set_volume_ext(arglist[0].opaqueref, arglist[1].uint, arglist[2].uint, arglist[3].uint);
1135             break;
1136         case 0x00FE: /* schannel_pause */
1137             glk_schannel_pause(arglist[0].opaqueref);
1138             break;
1139         case 0x00FF: /* schannel_unpause */
1140             glk_schannel_unpause(arglist[0].opaqueref);
1141             break;
1142 #endif /* GLK_MODULE_SOUND2 */
1143 #endif /* GLK_MODULE_SOUND */
1144
1145 #ifdef GLK_MODULE_HYPERLINKS
1146         case 0x0100: /* set_hyperlink */
1147             glk_set_hyperlink(arglist[0].uint);
1148             break;
1149         case 0x0101: /* set_hyperlink_stream */
1150             glk_set_hyperlink_stream(arglist[0].opaqueref, arglist[1].uint);
1151             break;
1152         case 0x0102: /* request_hyperlink_event */
1153             glk_request_hyperlink_event(arglist[0].opaqueref);
1154             break;
1155         case 0x0103: /* cancel_hyperlink_event */
1156             glk_cancel_hyperlink_event(arglist[0].opaqueref);
1157             break;
1158 #endif /* GLK_MODULE_HYPERLINKS */
1159             
1160 #ifdef GLK_MODULE_UNICODE
1161         case 0x0120: /* buffer_to_lower_case_uni */
1162             if (arglist[0].ptrflag) 
1163                 arglist[5].uint = glk_buffer_to_lower_case_uni(arglist[1].array, arglist[2].uint, arglist[3].uint);
1164             else
1165                 arglist[3].uint = glk_buffer_to_lower_case_uni(NULL, 0, arglist[1].uint);
1166             break;
1167         case 0x0121: /* buffer_to_upper_case_uni */
1168             if (arglist[0].ptrflag) 
1169                 arglist[5].uint = glk_buffer_to_upper_case_uni(arglist[1].array, arglist[2].uint, arglist[3].uint);
1170             else
1171                 arglist[3].uint = glk_buffer_to_upper_case_uni(NULL, 0, arglist[1].uint);
1172             break;
1173         case 0x0122: /* buffer_to_title_case_uni */
1174             if (arglist[0].ptrflag) 
1175                 arglist[6].uint = glk_buffer_to_title_case_uni(arglist[1].array, arglist[2].uint, arglist[3].uint, arglist[4].uint);
1176             else
1177                 arglist[4].uint = glk_buffer_to_title_case_uni(NULL, 0, arglist[1].uint, arglist[2].uint);
1178             break;
1179         case 0x0128: /* put_char_uni */
1180             glk_put_char_uni(arglist[0].uint);
1181             break;
1182         case 0x0129: /* put_string_uni */
1183             glk_put_string_uni(arglist[0].unicharstr);
1184             break;
1185         case 0x012A: /* put_buffer_uni */
1186             if (arglist[0].ptrflag) 
1187                 glk_put_buffer_uni(arglist[1].array, arglist[2].uint);
1188             else
1189                 glk_put_buffer_uni(NULL, 0);
1190             break;
1191         case 0x012B: /* put_char_stream_uni */
1192             glk_put_char_stream_uni(arglist[0].opaqueref, arglist[1].uint);
1193             break;
1194         case 0x012C: /* put_string_stream_uni */
1195             glk_put_string_stream_uni(arglist[0].opaqueref, arglist[1].unicharstr);
1196             break;
1197         case 0x012D: /* put_buffer_stream_uni */
1198             if (arglist[1].ptrflag) 
1199                 glk_put_buffer_stream_uni(arglist[0].opaqueref, 
1200                     arglist[2].array, arglist[3].uint);
1201             else
1202                 glk_put_buffer_stream_uni(arglist[0].opaqueref, 
1203                     NULL, 0);
1204             break;
1205         case 0x0130: /* get_char_stream_uni */
1206             arglist[2].sint = glk_get_char_stream_uni(arglist[0].opaqueref);
1207             break;
1208         case 0x0131: /* get_buffer_stream_uni */
1209             if (arglist[1].ptrflag) 
1210                 arglist[5].uint = glk_get_buffer_stream_uni(arglist[0].opaqueref, 
1211                     arglist[2].array, arglist[3].uint);
1212             else
1213                 arglist[3].uint = glk_get_buffer_stream_uni(arglist[0].opaqueref, 
1214                     NULL, 0);
1215             break;
1216         case 0x0132: /* get_line_stream_uni */
1217             if (arglist[1].ptrflag) 
1218                 arglist[5].uint = glk_get_line_stream_uni(arglist[0].opaqueref, 
1219                     arglist[2].array, arglist[3].uint);
1220             else
1221                 arglist[3].uint = glk_get_line_stream_uni(arglist[0].opaqueref, 
1222                     NULL, 0);
1223             break;
1224         case 0x0138: /* stream_open_file_uni */
1225             arglist[4].opaqueref = glk_stream_open_file_uni(arglist[0].opaqueref, arglist[1].uint, 
1226                 arglist[2].uint);
1227             break;
1228         case 0x0139: /* stream_open_memory_uni */
1229             if (arglist[0].ptrflag) 
1230                 arglist[6].opaqueref = glk_stream_open_memory_uni(arglist[1].array, 
1231                     arglist[2].uint, arglist[3].uint, arglist[4].uint);
1232             else
1233                 arglist[4].opaqueref = glk_stream_open_memory_uni(NULL, 
1234                     0, arglist[1].uint, arglist[2].uint);
1235             break;
1236         case 0x0140: /* request_char_event_uni */
1237             glk_request_char_event_uni(arglist[0].opaqueref);
1238             break;
1239         case 0x0141: /* request_line_event_uni */
1240             if (arglist[1].ptrflag)
1241                 glk_request_line_event_uni(arglist[0].opaqueref, arglist[2].array,
1242                     arglist[3].uint, arglist[4].uint);
1243             else
1244                 glk_request_line_event_uni(arglist[0].opaqueref, NULL,
1245                     0, arglist[2].uint);
1246             break;
1247 #endif /* GLK_MODULE_UNICODE */
1248
1249 #ifdef GLK_MODULE_UNICODE_NORM
1250         case 0x0123: /* buffer_canon_decompose_uni */
1251             if (arglist[0].ptrflag) 
1252                 arglist[5].uint = glk_buffer_canon_decompose_uni(arglist[1].array, arglist[2].uint, arglist[3].uint);
1253             else
1254                 arglist[3].uint = glk_buffer_canon_decompose_uni(NULL, 0, arglist[1].uint);
1255             break;
1256         case 0x0124: /* buffer_canon_normalize_uni */
1257             if (arglist[0].ptrflag) 
1258                 arglist[5].uint = glk_buffer_canon_normalize_uni(arglist[1].array, arglist[2].uint, arglist[3].uint);
1259             else
1260                 arglist[3].uint = glk_buffer_canon_normalize_uni(NULL, 0, arglist[1].uint);
1261             break;
1262 #endif /* GLK_MODULE_UNICODE_NORM */
1263             
1264 #ifdef GLK_MODULE_LINE_ECHO
1265         case 0x0150: /* set_echo_line_event */
1266             glk_set_echo_line_event(arglist[0].opaqueref, arglist[1].uint);
1267             break;
1268 #endif /* GLK_MODULE_LINE_ECHO */
1269
1270 #ifdef GLK_MODULE_LINE_TERMINATORS
1271         case 0x0151: /* set_terminators_line_event */
1272             if (arglist[1].ptrflag) 
1273                 glk_set_terminators_line_event(arglist[0].opaqueref, 
1274                     arglist[2].array, arglist[3].uint);
1275             else
1276                 glk_set_terminators_line_event(arglist[0].opaqueref, 
1277                     NULL, 0);
1278             break;
1279 #endif /* GLK_MODULE_LINE_TERMINATORS */
1280             
1281 #ifdef GLK_MODULE_DATETIME
1282         case 0x0160: /* current_time */
1283             if (arglist[0].ptrflag) {
1284                 glktimeval_t dat;
1285                 glk_current_time(&dat);
1286                 arglist[1].sint = dat.high_sec;
1287                 arglist[2].uint = dat.low_sec;
1288                 arglist[3].sint = dat.microsec;
1289             }
1290             else {
1291                 glk_current_time(NULL);
1292             }
1293             break;
1294         case 0x0161: /* current_simple_time */
1295             arglist[2].sint = glk_current_simple_time(arglist[0].uint);
1296             break;
1297         case 0x0168: /* time_to_date_utc */ {
1298             glktimeval_t timeval;
1299             glktimeval_t *timeptr = NULL;
1300             glkdate_t date;
1301             glkdate_t *dateptr = NULL;
1302             int ix = 0;
1303             if (arglist[ix++].ptrflag) {
1304                 timeptr = &timeval;
1305                 timeval.high_sec = arglist[ix++].sint;
1306                 timeval.low_sec = arglist[ix++].uint;
1307                 timeval.microsec = arglist[ix++].sint;
1308             }
1309             if (arglist[ix++].ptrflag) {
1310                 dateptr = &date;
1311             }
1312             glk_time_to_date_utc(timeptr, dateptr);
1313             if (dateptr) {
1314                 arglist[ix++].sint = date.year;
1315                 arglist[ix++].sint = date.month;
1316                 arglist[ix++].sint = date.day;
1317                 arglist[ix++].sint = date.weekday;
1318                 arglist[ix++].sint = date.hour;
1319                 arglist[ix++].sint = date.minute;
1320                 arglist[ix++].sint = date.second;
1321                 arglist[ix++].sint = date.microsec;
1322             }
1323             }
1324             break;
1325         case 0x0169: /* time_to_date_local */ {
1326             glktimeval_t timeval;
1327             glktimeval_t *timeptr = NULL;
1328             glkdate_t date;
1329             glkdate_t *dateptr = NULL;
1330             int ix = 0;
1331             if (arglist[ix++].ptrflag) {
1332                 timeptr = &timeval;
1333                 timeval.high_sec = arglist[ix++].sint;
1334                 timeval.low_sec = arglist[ix++].uint;
1335                 timeval.microsec = arglist[ix++].sint;
1336             }
1337             if (arglist[ix++].ptrflag) {
1338                 dateptr = &date;
1339             }
1340             glk_time_to_date_local(timeptr, dateptr);
1341             if (dateptr) {
1342                 arglist[ix++].sint = date.year;
1343                 arglist[ix++].sint = date.month;
1344                 arglist[ix++].sint = date.day;
1345                 arglist[ix++].sint = date.weekday;
1346                 arglist[ix++].sint = date.hour;
1347                 arglist[ix++].sint = date.minute;
1348                 arglist[ix++].sint = date.second;
1349                 arglist[ix++].sint = date.microsec;
1350             }
1351             }
1352             break;
1353         case 0x016A: /* simple_time_to_date_utc */ {
1354             glkdate_t date;
1355             glkdate_t *dateptr = NULL;
1356             int ix = 2;
1357             if (arglist[ix++].ptrflag) {
1358                 dateptr = &date;
1359             }
1360             glk_simple_time_to_date_utc(arglist[0].sint, arglist[1].uint, dateptr);
1361             if (dateptr) {
1362                 arglist[ix++].sint = date.year;
1363                 arglist[ix++].sint = date.month;
1364                 arglist[ix++].sint = date.day;
1365                 arglist[ix++].sint = date.weekday;
1366                 arglist[ix++].sint = date.hour;
1367                 arglist[ix++].sint = date.minute;
1368                 arglist[ix++].sint = date.second;
1369                 arglist[ix++].sint = date.microsec;
1370             }
1371             }
1372             break;
1373         case 0x016B: /* simple_time_to_date_local */ {
1374             glkdate_t date;
1375             glkdate_t *dateptr = NULL;
1376             int ix = 2;
1377             if (arglist[ix++].ptrflag) {
1378                 dateptr = &date;
1379             }
1380             glk_simple_time_to_date_local(arglist[0].sint, arglist[1].uint, dateptr);
1381             if (dateptr) {
1382                 arglist[ix++].sint = date.year;
1383                 arglist[ix++].sint = date.month;
1384                 arglist[ix++].sint = date.day;
1385                 arglist[ix++].sint = date.weekday;
1386                 arglist[ix++].sint = date.hour;
1387                 arglist[ix++].sint = date.minute;
1388                 arglist[ix++].sint = date.second;
1389                 arglist[ix++].sint = date.microsec;
1390             }
1391             }
1392             break;
1393         case 0x016C: /* date_to_time_utc */ {
1394             glkdate_t date;
1395             glkdate_t *dateptr = NULL;
1396             glktimeval_t timeval;
1397             glktimeval_t *timeptr = NULL;
1398             int ix = 0;
1399             if (arglist[ix++].ptrflag) {
1400                 dateptr = &date;
1401                 date.year = arglist[ix++].sint;
1402                 date.month = arglist[ix++].sint;
1403                 date.day = arglist[ix++].sint;
1404                 date.weekday = arglist[ix++].sint;
1405                 date.hour = arglist[ix++].sint;
1406                 date.minute = arglist[ix++].sint;
1407                 date.second = arglist[ix++].sint;
1408                 date.microsec = arglist[ix++].sint;
1409             }
1410             if (arglist[ix++].ptrflag) {
1411                 timeptr = &timeval;
1412             }
1413             glk_date_to_time_utc(dateptr, timeptr);
1414             if (timeptr) {
1415                 arglist[ix++].sint = timeval.high_sec;
1416                 arglist[ix++].uint = timeval.low_sec;
1417                 arglist[ix++].sint = timeval.microsec;
1418             }
1419             }
1420             break;
1421         case 0x016D: /* date_to_time_local */ {
1422             glkdate_t date;
1423             glkdate_t *dateptr = NULL;
1424             glktimeval_t timeval;
1425             glktimeval_t *timeptr = NULL;
1426             int ix = 0;
1427             if (arglist[ix++].ptrflag) {
1428                 dateptr = &date;
1429                 date.year = arglist[ix++].sint;
1430                 date.month = arglist[ix++].sint;
1431                 date.day = arglist[ix++].sint;
1432                 date.weekday = arglist[ix++].sint;
1433                 date.hour = arglist[ix++].sint;
1434                 date.minute = arglist[ix++].sint;
1435                 date.second = arglist[ix++].sint;
1436                 date.microsec = arglist[ix++].sint;
1437             }
1438             if (arglist[ix++].ptrflag) {
1439                 timeptr = &timeval;
1440             }
1441             glk_date_to_time_local(dateptr, timeptr);
1442             if (timeptr) {
1443                 arglist[ix++].sint = timeval.high_sec;
1444                 arglist[ix++].uint = timeval.low_sec;
1445                 arglist[ix++].sint = timeval.microsec;
1446             }
1447             }
1448             break;
1449         case 0x016E: /* date_to_simple_time_utc */ {
1450             glkdate_t date;
1451             glkdate_t *dateptr = NULL;
1452             int ix = 0;
1453             if (arglist[ix++].ptrflag) {
1454                 dateptr = &date;
1455                 date.year = arglist[ix++].sint;
1456                 date.month = arglist[ix++].sint;
1457                 date.day = arglist[ix++].sint;
1458                 date.weekday = arglist[ix++].sint;
1459                 date.hour = arglist[ix++].sint;
1460                 date.minute = arglist[ix++].sint;
1461                 date.second = arglist[ix++].sint;
1462                 date.microsec = arglist[ix++].sint;
1463             }
1464             arglist[ix+2].sint = glk_date_to_simple_time_utc(dateptr, arglist[ix].uint);
1465             }
1466             break;
1467         case 0x016F: /* date_to_simple_time_local */ {
1468             glkdate_t date;
1469             glkdate_t *dateptr = NULL;
1470             int ix = 0;
1471             if (arglist[ix++].ptrflag) {
1472                 dateptr = &date;
1473                 date.year = arglist[ix++].sint;
1474                 date.month = arglist[ix++].sint;
1475                 date.day = arglist[ix++].sint;
1476                 date.weekday = arglist[ix++].sint;
1477                 date.hour = arglist[ix++].sint;
1478                 date.minute = arglist[ix++].sint;
1479                 date.second = arglist[ix++].sint;
1480                 date.microsec = arglist[ix++].sint;
1481             }
1482             arglist[ix+2].sint = glk_date_to_simple_time_local(dateptr, arglist[ix].uint);
1483             }
1484             break;
1485 #endif /* GLK_MODULE_DATETIME */
1486
1487 #ifdef GLK_MODULE_RESOURCE_STREAM
1488         case 0x0049: /* stream_open_resource */
1489             arglist[3].opaqueref = glk_stream_open_resource(arglist[0].uint, arglist[1].uint);
1490             break;
1491         case 0x013A: /* stream_open_resource_uni */
1492             arglist[3].opaqueref = glk_stream_open_resource_uni(arglist[0].uint, arglist[1].uint);
1493             break;
1494 #endif /* GLK_MODULE_RESOURCE_STREAM */
1495
1496         default:
1497             /* do nothing */
1498             break;
1499     }
1500 }
1501