-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathevent.c
executable file
·257 lines (215 loc) · 8.34 KB
/
event.c
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#include "glknew.h"
/* The spec allows each window to have exactly one text input request
pending at once -- we can have two windows, each of which has one.
Worry about that when it happens. */
struct glk_window_struct *input_window = NULL;
int text_input_type_wanted = TEXT_INPUT_NONE;
struct line_event_request_latin1 line_event_request_info_latin1;
struct line_event_request_uni line_event_request_info_uni;
/* KEEP THIS UPDATED WITH THE #defines IN THE .h FILE! */
const char* text_input_names[] = {
"none",
"char_latin1",
"char_uni",
"line_latin1",
"line_uni"
};
void glk_request_char_event(winid_t win) {
input_window = win;
text_input_type_wanted = TEXT_INPUT_CHAR_LATIN1;
}
void glk_request_char_event_uni(winid_t win) {
input_window = win;
text_input_type_wanted = TEXT_INPUT_CHAR_UNI;
}
void glk_cancel_char_event(winid_t win) {
input_window = NULL;
text_input_type_wanted = TEXT_INPUT_NONE;
}
void glk_cancel_line_event(winid_t win, event_t *event) {
input_window = NULL;
text_input_type_wanted = TEXT_INPUT_NONE;
/* We are apparently supposed to fill in the event structure based
on what the user has already entered. Ignore this (for now?),
and simply tell the caller that the user has not yet entered
anything.
*/
if (event) {
event->type = evtype_LineInput;
event->win = win;
event->val1 = 0;
event->val2 = 0;
}
if (line_event_request_info_latin1.buf)
line_event_request_info_latin1.buf[0] = '\0';
if (line_event_request_info_uni.buf)
line_event_request_info_uni.buf[0] = '\0';
}
void glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
char *prefill;
/* This is the maximum len that select() is prepared to handle. */
if (maxlen > (1024 - 17)) {
printf("DEBUG: Game passed maxlen (%d) above what we are prepared for.\n", maxlen);
maxlen = 1024-17;
}
prefill = malloc(initlen+1);
if (!prefill) {
printf("glk_request_line_event malloc prefill failed, %d bytes\n", initlen+1);
exit(12);
}
strncpy(prefill, buf, initlen);
prefill[initlen] = '\0';
input_window = win;
text_input_type_wanted = TEXT_INPUT_LINE_LATIN1;
line_event_request_info_latin1.win = win;
line_event_request_info_latin1.buf = buf;
line_event_request_info_latin1.prefill = prefill;
line_event_request_info_latin1.maxlen = maxlen;
}
void glk_request_line_event_uni(winid_t win, glui32 *buf,
glui32 maxlen, glui32 initlen) {
glui32 *prefill;
prefill = malloc(4*(initlen+1));
if (!prefill) {
printf("glk_request_line_event_uni malloc prefill failed, %d bytes\n", 4*(initlen+1));
exit(33);
}
memcpy(prefill, buf, initlen*4);
prefill[initlen] = 0;
input_window = win;
text_input_type_wanted = TEXT_INPUT_LINE_UNI;
line_event_request_info_uni.win = win;
line_event_request_info_uni.buf = buf;
line_event_request_info_uni.prefill = prefill;
line_event_request_info_uni.maxlen = maxlen;
}
void glk_request_mouse_event(winid_t win) {
/* Ignore this for now. */
}
void glk_request_timer_events(glui32 miliseconds) {
/* Ignore this for now. Thinking about implementation anyway: store
time of next timer event in a global, if select happens after
then, throw the timer event and update the time at which the next
timer even happens. However, this contrivenes the end of
http://www.eblong.com/zarf/glk/glk-spec-070_4.html#s.4, which
says that keyboard events should win over timer events. */
}
#define evtype_charinput_special(name) \
else if (strcmp(ret, "evtype_CharInput keycode_" #name "\n") == 0) { \
event->val1 = keycode_ ## name; \
return; \
}
void glk_select(event_t *event) {
char line[1024];
char *ret;
/* glk_selects input pointer should never be null */
if(!event) {
printf(">>> glk_select, dying on NULL event pointer");
exit(10);
}
printf("???select, window=%p, want %s\n", input_window, text_input_names[text_input_type_wanted]);
/* FIXME: Do something useful when the game wanted a line and
allowed for it to be > 1024 chars. */
/* The spec states
(http://www.eblong.com/zarf/glk/glk-spec-070_2.html#s.3) that you
cannot input newlines, so we should be safe here. */
ret = fgets(line, 1024, stdin);
if (!ret) {
printf("Failed fgets in glk_select!");
exit(10);
}
/* http://www.eblong.com/zarf/glk/glk-spec-070_2.html#s.4 */
if (strncmp(ret, "evtype_CharInput ", 17) == 0) {
event->type = evtype_CharInput;
/* val2 is unused for char inputs. */
event->val2 = 0xDEADBEEF;
/* We need to set a window, else glk_select loops.. */
event->win = input_window;
if (sscanf(ret, "evtype_CharInput %d", &event->val1)) {
printf("DEBUG: Got evtype_CharInput: %d\n", event->val1);
return;
}
evtype_charinput_special(Left )
evtype_charinput_special(Right )
evtype_charinput_special(Up )
evtype_charinput_special(Down )
evtype_charinput_special(Return )
evtype_charinput_special(Delete )
evtype_charinput_special(Escape )
evtype_charinput_special(Tab )
evtype_charinput_special(PageUp )
evtype_charinput_special(PageDown)
evtype_charinput_special(Home )
evtype_charinput_special(End )
evtype_charinput_special(Func1 )
evtype_charinput_special(Func2 )
evtype_charinput_special(Func3 )
evtype_charinput_special(Func4 )
evtype_charinput_special(Func5 )
evtype_charinput_special(Func6 )
evtype_charinput_special(Func7 )
evtype_charinput_special(Func8 )
evtype_charinput_special(Func9 )
evtype_charinput_special(Func10 )
evtype_charinput_special(Func11 )
evtype_charinput_special(Func12 )
else {
printf("Couldn't process evtype_CharInput select response: '%s'\n", ret);
exit(8);
}
} else if (strncmp(ret, "evtype_LineInput ", 17) == 0) {
if (!line_event_request_info_latin1.buf) {
printf("Got [latin1] LineInput while the buffer is unset\n");
exit(34);
}
/* http://www.eblong.com/zarf/glk/glk-spec-070_4.html#s.2 second
para from the end. */
strncpy(line_event_request_info_latin1.buf, ret+17, line_event_request_info_latin1.maxlen);
line_event_request_info_latin1.buf[line_event_request_info_latin1.maxlen] = '\0';
/* Strip off the last character, which will be the trailing
newline */
line_event_request_info_latin1.buf[strlen(line_event_request_info_latin1.buf)-1] = '\0';
event->type = evtype_LineInput;
event->win = line_event_request_info_latin1.win;
event->val1 = strlen(line_event_request_info_latin1.buf);
event->val2 = 0;
glk_put_string_stream(line_event_request_info_latin1.win->stream, ret+17);
printf("DEBUG: event got '%s' of len %d\n", line_event_request_info_latin1.buf, event->val1);
} else if (strncmp(ret, "evtype_LineInputUni ", 20) == 0) {
glui32 len;
size_t fread_ret;
printf("DEBUG: Got LineInputUni, top line '%s'\n", ret);
if (!sscanf(ret, "evtype_LineInputUni %d", &len)) {
printf("Got evtype_LineInputUni, but couldn't find (or parse) length: %s\n", ret);
exit(36);
}
printf("DEBUG: Got LineInputUni, len=%d\n", len);
if (!line_event_request_info_uni.buf) {
printf("Got [uni] LineInput while the buffer is unset\n");
exit(35);
}
printf("DEBUG: Got LineInputUni, reading content...\n");
fread_ret = fread(line_event_request_info_uni.buf, 4, len, stdin);
if (fread_ret != len) {
printf("Fread of data in evtype_LineInputUni failed, got %d, errno=%d\n", fread_ret, errno);
exit(36);
}
printf("DEBUG: Got LineInputUni, read content\n");
line_event_request_info_uni.buf[len] = 0;
/* http://www.eblong.com/zarf/glk/glk-spec-070_4.html#s.2 second
para from the end. */
event->type = evtype_LineInput;
event->win = line_event_request_info_uni.win;
event->val1 = len;
event->val2 = 0;
/* glk_put_string_stream(line_event_request_info_latin1.win->stream, ret+17); */
glk_put_buffer_stream_uni(line_event_request_info_uni.win->stream, line_event_request_info_uni.buf, len);
glk_put_string_stream(line_event_request_info_uni.win->stream, "\n");
} else {
printf("Couldn't parse select response: '%s'\n", ret);
exit(9);
}
}
void glk_tick(void) {
/* NOP */
}