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