git: Line endings of README.txt
[projects/chimara/chimara.git] / libchimara / gestalt.c
1 #include <stddef.h> /* Surprisingly, the only symbol needed is NULL */
2 #include <config.h>
3 #include "glk.h"
4 #include "input.h"
5
6 /* Version of the Glk specification implemented by this library */
7 #define MAJOR_VERSION 0
8 #define MINOR_VERSION 7
9 #define SUB_VERSION   4
10
11 /**
12  * glk_gestalt:
13  * @sel: A selector, representing which capability to request information 
14  * about.
15  * @val: Extra information, depending on the value of @sel.
16  *
17  * Calls the gestalt system to request information about selector @sel, without
18  * passing an array to store extra information in (see glk_gestalt_ext()).
19  *
20  * Returns: an integer, depending on what selector was called.
21  */
22 glui32
23 glk_gestalt(glui32 sel, glui32 val)
24 {
25         return glk_gestalt_ext(sel, val, NULL, 0);
26 }
27
28 /**
29  * glk_gestalt_ext:
30  * @sel: A selector, representing which capability to request information
31  * about.
32  * @val: Extra information, depending on the value of @sel.
33  * @arr: Location of an array to store extra information in, or %NULL.
34  * @arrlen: Length of @arr, or 0 if @arr is %NULL.
35  *
36  * Calls the gestalt system to request information about the capabilities of the
37  * API. The selector @sel tells which capability you are requesting information
38  * about; the other three arguments are additional information, which may or may
39  * not be meaningful. The @arr and @arrlen arguments of glk_gestalt_ext() are
40  * always optional; you may always pass %NULL and 0, if you do not want whatever
41  * information they represent. glk_gestalt() is simply a shortcut for this;
42  * <code>#glk_gestalt(x, y)</code> is exactly the same as 
43  * <code>#glk_gestalt_ext(x, y, %NULL, 0)</code>.
44  *
45  * The critical point is that if the Glk library has never heard of the selector
46  * @sel, it will return 0. It is <emphasis>always</emphasis> safe to call 
47  * <code>#glk_gestalt(x, y)</code> (or <code>#glk_gestalt_ext(x, y, %NULL, 
48  * 0)</code>). Even if you are using an old library, which was compiled before
49  * the given capability was imagined, you can test for the capability by calling
50  * glk_gestalt(); the library will correctly indicate that it does not support
51  * it, by returning 0.
52  *
53  * (It is also safe to call <code>#glk_gestalt_ext(x, y, z, zlen)</code> for an
54  * unknown selector <code>x</code>, where <code>z</code> is not %NULL, as long
55  * as <code>z</code> points at an array of at least <code>zlen</code> elements.
56  * The selector will be careful not to write beyond that point in the array, if
57  * it writes to the array at all.)
58  *
59  * (If a selector does not use the second argument, you should always pass 0; do
60  * not assume that the second argument is simply ignored. This is because the
61  * selector may be extended in the future. You will continue to get the current
62  * behavior if you pass 0 as the second argument, but other values may produce
63  * other behavior.)
64  *
65  * Returns: an integer, depending on what selector was called.
66  */
67 glui32
68 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen)
69 {
70         switch(sel)
71         {
72                 /* Version number */
73                 case gestalt_Version:
74                         return (MAJOR_VERSION << 16) + (MINOR_VERSION << 8) + SUB_VERSION;
75                 
76                 /* Which characters can the player type in line input? */
77                 case gestalt_LineInput:
78                         /* Does not accept control chars */
79                         if( val < 32 || (val >= 127 && val <= 159) )
80                                 return 0;
81                         return 1;
82                         
83                 /* Which characters can the player type in char input? */
84                 case gestalt_CharInput:
85                         /* Does not accept control chars or unknown */
86                         if( val < 32 || (val >= 127 && val <= 159) || val == keycode_Unknown )
87                                 return 0;
88                         return 1;
89                 
90                 /* Which characters can we print? */    
91                 case gestalt_CharOutput:
92                         /* All characters are printed as one character, in any case */
93                         if(arr && arrlen > 0)
94                                 *arr = 1;
95                         /* Cannot print control chars except \n */
96                         if( (val < 32 && val != 10) || (val >= 127 && val <= 159) )
97                                 return gestalt_CharOutput_CannotPrint;
98                         /* Can print all other characters */
99                         return gestalt_CharOutput_ExactPrint;
100
101                 /* Hyperlinks supported on textbuffers and textgrids */
102                 case gestalt_HyperlinkInput:
103                         return val == wintype_TextBuffer || val == wintype_TextGrid;
104
105                 /* Mouse support present in textgrids */
106                 case gestalt_MouseInput:
107                         return val == wintype_TextGrid;
108
109                 case gestalt_DrawImage:
110                         return val == wintype_Graphics || val == wintype_TextBuffer;
111
112                 /* Which keycodes can be used as line terminators */
113                 case gestalt_LineTerminatorKey:
114                         return is_valid_line_terminator(val)? 1 : 0;
115
116                 /* Capabilities that are simply supported */
117                 case gestalt_Unicode:
118                 case gestalt_Timer:
119                 case gestalt_Hyperlinks:
120                 case gestalt_Graphics:
121                 case gestalt_GraphicsTransparency:
122                 case gestalt_DateTime:
123                 case gestalt_UnicodeNorm:
124                 case gestalt_LineInputEcho:
125                 case gestalt_LineTerminators:
126                 case gestalt_ResourceStream:
127                         return 1;
128
129                 /* Capabilities supported if compiled with sound support */
130                 case gestalt_Sound:
131                 case gestalt_SoundVolume:
132                 case gestalt_SoundNotify:
133                 case gestalt_SoundMusic:
134                 case gestalt_Sound2:
135 #ifdef HAVE_SOUND
136                         return 1;
137 #else
138                         return 0;
139 #endif
140                         
141                 /* Unsupported capabilities */
142                         /* None! */
143
144                 /* Selector not supported */    
145                 default:
146                         return 0;
147         }
148 }
149