File: gtgestal.c

package info (click to toggle)
glktermw 1.0.4%2Bgit20200122-2.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 856 kB
  • sloc: ansic: 22,241; makefile: 27
file content (175 lines) | stat: -rw-r--r-- 6,035 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* gtgestal.c: The Gestalt system
        for GlkTerm, curses.h implementation of the Glk API.
    Designed by Andrew Plotkin <erkyrath@eblong.com>
    http://www.eblong.com/zarf/glk/index.html
*/

#define _XOPEN_SOURCE /* wcwidth */
#include "gtoption.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <wchar.h>
#include <wctype.h>
#include "glk.h"
#include "glkterm.h"

int gli_untypable (glui32 key);

glui32 glk_gestalt(glui32 id, glui32 val)
{
    return glk_gestalt_ext(id, val, NULL, 0);
}

glui32 glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen)
{
    switch (id) {
        
        case gestalt_Version:
            /* This implements Glk spec version 0.7.4. */
            return 0x00000704;
        
        case gestalt_LineInput:
            /*
             * basic text API, the buffer will contain only printable Latin-1 characters (32 to 126, 160 to 255).
             * It is guaranteed to be able to accept the ASCII characters (32 to 126.)
             * never a nonprintable Latin-1 character (0 to 31, 127 to 159)
             */
            return ! ((gli_bad_latin_key(val) || gli_untypable(val)) || (val >=0x100 && iswprint(glui32_to_wchar(val))));
                
        case gestalt_CharInput: 
            /*
             * basic text API, the character code which is returned can be any value from 0 to 255
             * Keycodes (starting backwards from(0xFFFFFFFF) 
             * keycode_Left, keycode_Right, keycode_Up, keycode_Down (arrow keys)
             * keycode_Return (return or enter)
             * keycode_Delete (delete or backspace)
             * keycode_Escape
             * keycode_Tab
             * keycode_PageUp
             * keycode_PageDown
             * keycode_Home
             * keycode_End
             * keycode_Func1, keycode_Func2, keycode_Func3, ... keycode_Func12 (twelve function keys)
             * keycode_Unknown (any key which has no Latin-1 or special code) 
             The arrow keys and return are nearly certain to be available, rest in order of decreasing importance.
             */
         return ! ((gli_bad_latin_key(val) || gli_untypable(val)) || (val >=0x100 && ! (gli_legal_keycode(val) || iswprint(glui32_to_wchar(val)))));

        case gestalt_CharOutput: 
        /* Rules
         * In Latin mode:
         * can print 32 to 126, 160 to 255 and 10.
         * cannot print 0 to 9, 11 to 31, 127 to 159
         * You may not print even common formatting characters such as tab (control-I), carriage return (control-M), or page break (control-L)
         *
         * In Uni mode:
         * gestalt_CharOutput_CannotPrint if ch is an unprintable eight-bit character (0 to 9, 11 to 31, 127 to 159.)
         */
        /* Is providing wcwidth(val) as the number of glyphs advisable?
           As long as usage is limited to deciding how to lay out a grid,
           then it's OK.  But as soon as a user tries to treat a grid 
           containing a character of width==2 as actually containing two 
           half-characters, we're going to have trouble.
         */
            if ( ! (gli_bad_latin_key(val) || (val >= 0x100 && ! iswprint(glui32_to_wchar(val)))) ) {
                int width = wcwidth(glui32_to_wchar(val));
                if (arr && arrlen >= 1) {
                    arr[0] = width;
                }
                if ( width == 1 )
                    return gestalt_CharOutput_ExactPrint;
                else
                    return gestalt_CharOutput_ApproxPrint;
            }
            else {
                   if (arr && arrlen >= 1)
                       arr[0] = 0;
                   return gestalt_CharOutput_CannotPrint;
            }
            
        case gestalt_MouseInput: 
            return FALSE;
            
        case gestalt_Timer: 
#ifdef OPT_TIMED_INPUT
            return TRUE;
#else /* !OPT_TIMED_INPUT */
            return FALSE;
#endif /* OPT_TIMED_INPUT */

        case gestalt_Graphics:
        case gestalt_GraphicsTransparency:
            return FALSE;
            
        case gestalt_DrawImage:
            return FALSE;
            
        case gestalt_Unicode:
#ifdef GLK_MODULE_UNICODE
            return TRUE;
#else
            return FALSE;
#endif /* GLK_MODULE_UNICODE */
            
        case gestalt_UnicodeNorm:
#ifdef GLK_MODULE_UNICODE_NORM
            return TRUE;
#else
            return FALSE;
#endif /* GLK_MODULE_UNICODE_NORM */
            
        case gestalt_Sound:
        case gestalt_SoundVolume:
        case gestalt_SoundNotify: 
        case gestalt_SoundMusic:
            return FALSE;
  
        case gestalt_LineInputEcho:
            return TRUE;

        case gestalt_LineTerminators:
            return TRUE;
        case gestalt_LineTerminatorKey:
            /* GlkTerm never uses the escape or function keys for anything,
               so we'll allow them to be line terminators. */
            if (val == keycode_Escape)
                return TRUE;
            if (val >= keycode_Func12 && val <= keycode_Func1)
                return TRUE;
            return FALSE;

        case gestalt_DateTime:
            return TRUE;

        case gestalt_ResourceStream:
            return TRUE;

        default:
            return 0;

    }
}

/* Keys that are not typable in this implementation */
int gli_untypable (glui32 key)
{
    /* Many control characters are untypable, for many reasons. */
    switch (key) {
    case keycode_Tab: /* reserved by the input system */
    case L'\t':   /* reserved by the input system */
        case L'\014': /* reserved by the input system */
    case L'\003': /* interrupt/suspend signals */
    case L'\032': /* interrupt/suspend signals */
    case L'\010': /* parsed as keycode_Delete */
    case L'\012': /* parsed as keycode_Return */
    case L'\015': /* parsed as keycode_Return */
    case L'\033': /* parsed as keycode_Escape */
         return TRUE;
        break;
    default:
        return FALSE;
    }
}