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