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