1 /* stream.c - IO stream implementation
2 * Copyright (c) 1995-1997 Stefan Jokisch
3 *
4 * This file is part of Frotz.
5 *
6 * Frotz is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Frotz is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "frotz.h"
22
23 extern bool handle_hot_key(zchar);
24
25 extern bool validate_click(void);
26
27 extern void replay_open(void);
28 extern void replay_close(void);
29 extern void memory_open(zword, zword, bool);
30 extern void memory_close(void);
31 extern void record_open(void);
32 extern void record_close(void);
33 extern void script_open(void);
34 extern void script_close(void);
35
36 extern void memory_word(const zchar *);
37 extern void memory_new_line(void);
38 extern void record_write_key(zchar);
39 extern void record_write_input(const zchar *, zchar);
40 extern void script_char(zchar);
41 extern void script_word(const zchar *);
42 extern void script_new_line(void);
43 extern void script_write_input(const zchar *, zchar);
44 extern void script_erase_input(const zchar *);
45 extern void script_mssg_on(void);
46 extern void script_mssg_off(void);
47 extern void screen_char(zchar);
48 extern void screen_word(const zchar *);
49 extern void screen_new_line(void);
50 extern void screen_write_input(const zchar *, zchar);
51 extern void screen_erase_input(const zchar *);
52 extern void screen_mssg_on(void);
53 extern void screen_mssg_off(void);
54
55 extern zchar replay_read_key(void);
56 extern zchar replay_read_input(zchar *);
57 extern zchar console_read_key(zword);
58 extern zchar console_read_input(int, zchar *, zword, bool);
59
60 extern int direct_call(zword);
61
62
63 /*
64 * stream_mssg_on
65 *
66 * Start printing a "debugging" message.
67 *
68 */
stream_mssg_on(void)69 void stream_mssg_on(void)
70 {
71 flush_buffer();
72
73 if (ostream_screen)
74 screen_mssg_on();
75 if (ostream_script && enable_scripting)
76 script_mssg_on();
77
78 message = TRUE;
79 } /* stream_mssg_on */
80
81
82 /*
83 * stream_mssg_off
84 *
85 * Stop printing a "debugging" message.
86 *
87 */
stream_mssg_off(void)88 void stream_mssg_off(void)
89 {
90 flush_buffer();
91
92 if (ostream_screen)
93 screen_mssg_off();
94 if (ostream_script && enable_scripting)
95 script_mssg_off();
96
97 message = FALSE;
98 } /* stream_mssg_off */
99
100
101 /*
102 * z_output_stream, open or close an output stream.
103 *
104 * zargs[0] = stream to open (positive) or close (negative)
105 * zargs[1] = address to redirect output to (stream 3 only)
106 * zargs[2] = width of redirected output (stream 3 only, optional)
107 *
108 */
z_output_stream(void)109 void z_output_stream(void)
110 {
111 flush_buffer();
112
113 switch ((short)zargs[0]) {
114 case 1:
115 ostream_screen = TRUE;
116 break;
117 case -1:
118 ostream_screen = FALSE;
119 break;
120 case 2:
121 if (!ostream_script)
122 script_open();
123 break;
124 case -2:
125 if (ostream_script)
126 script_close();
127 break;
128 case 3:
129 memory_open(zargs[1], zargs[2], zargc >= 3);
130 break;
131 case -3:
132 memory_close();
133 break;
134 case 4:
135 if (!ostream_record)
136 record_open();
137 break;
138 case -4:
139 if (ostream_record)
140 record_close();
141 break;
142 }
143 } /* z_output_stream */
144
145
146 /*
147 * stream_char
148 *
149 * Send a single character to the output stream.
150 *
151 */
stream_char(zchar c)152 void stream_char(zchar c)
153 {
154 if (ostream_screen)
155 screen_char(c);
156 if (ostream_script && enable_scripting)
157 script_char(c);
158 } /* stream_char */
159
160
161 /*
162 * stream_word
163 *
164 * Send a string of characters to the output streams.
165 *
166 */
stream_word(const zchar * s)167 void stream_word(const zchar * s)
168 {
169 if (ostream_memory && !message)
170 memory_word(s);
171 else {
172 if (ostream_screen)
173 screen_word(s);
174 if (ostream_script && enable_scripting)
175 script_word(s);
176 }
177 } /* stream_word */
178
179
180 /*
181 * stream_new_line
182 *
183 * Send a newline to the output streams.
184 *
185 */
stream_new_line(void)186 void stream_new_line(void)
187 {
188 if (ostream_memory && !message)
189 memory_new_line();
190 else {
191 if (ostream_screen)
192 screen_new_line();
193 if (ostream_script && enable_scripting)
194 script_new_line();
195 }
196 } /* stream_new_line */
197
198
199 /*
200 * z_input_stream, select an input stream.
201 *
202 * zargs[0] = input stream to be selected
203 *
204 */
z_input_stream(void)205 void z_input_stream(void)
206 {
207 flush_buffer();
208
209 if (zargs[0] == 0 && istream_replay)
210 replay_close();
211 if (zargs[0] == 1 && !istream_replay)
212 replay_open();
213 } /* z_input_stream */
214
215
216 /*
217 * stream_read_key
218 *
219 * Read a single keystroke from the current input stream.
220 *
221 */
stream_read_key(zword timeout,zword routine,bool hot_keys)222 zchar stream_read_key(zword timeout, zword routine, bool hot_keys)
223 {
224 zchar key = ZC_BAD;
225 flush_buffer();
226
227 /* Read key from current input stream */
228 continue_input:
229 do {
230 if (istream_replay)
231 key = replay_read_key();
232 else
233 key = console_read_key(timeout);
234 } while (key == ZC_BAD);
235
236 /* Verify mouse clicks */
237 if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
238 if (!validate_click())
239 goto continue_input;
240
241 /* Copy key to the command file */
242 if (ostream_record && !istream_replay)
243 record_write_key(key);
244
245 /* Handle timeouts */
246 /*
247 * Make sure that this is a real timeout, by checking
248 * that the requested timeout is not zero. For the case
249 * of a recorded stream, it is possible that a timeout
250 * keystroke might be replayed.
251 */
252 if (key == ZC_TIME_OUT) {
253 if (timeout != 0) {
254 if (direct_call(routine) == 0)
255 goto continue_input;
256 } else {
257 goto continue_input;
258 }
259 }
260
261 /* Handle hot keys */
262 if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
263 if (z_header.version == V4 && key == ZC_HKEY_UNDO)
264 goto continue_input;
265 if (!handle_hot_key(key))
266 goto continue_input;
267 return ZC_BAD;
268 }
269
270 /* Return key */
271 return key;
272 } /* stream_read_key */
273
274
275 /*
276 * stream_read_input
277 *
278 * Read a line of input from the current input stream.
279 *
280 */
stream_read_input(int max,zchar * buf,zword timeout,zword routine,bool hot_keys,bool no_scripting)281 zchar stream_read_input(int max, zchar * buf,
282 zword timeout, zword routine,
283 bool hot_keys, bool no_scripting)
284 {
285 zchar key = ZC_BAD;
286
287 flush_buffer();
288
289 /* Remove initial input from the transcript file or from the screen */
290 if (ostream_script && enable_scripting && !no_scripting)
291 script_erase_input(buf);
292 if (istream_replay)
293 screen_erase_input(buf);
294
295 /* Read input line from current input stream */
296 continue_input:
297 do {
298 if (istream_replay)
299 key = replay_read_input(buf);
300 else
301 key =
302 console_read_input(max, buf, timeout,
303 key != ZC_BAD);
304 } while (key == ZC_BAD);
305
306 /* Verify mouse clicks */
307 if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
308 if (!validate_click())
309 goto continue_input;
310
311 /* Copy input line to the command file */
312 if (ostream_record && !istream_replay)
313 record_write_input(buf, key);
314
315 /* Handle timeouts */
316 /*
317 * Make sure that this is a real timeout, by checking
318 * that the requested timeout is not zero. For the case
319 * of a recorded stream, it is possible that a timeout
320 * keystroke might be replayed.
321 */
322 if (key == ZC_TIME_OUT) {
323 if (timeout != 0) {
324 if (direct_call(routine) == 0)
325 goto continue_input;
326 } else {
327 goto continue_input;
328 }
329 }
330
331 /* Handle hot keys */
332 if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
333 if (!handle_hot_key(key))
334 goto continue_input;
335 return ZC_BAD;
336 }
337
338 /* Copy input line to transcript file or to the screen */
339 if (ostream_script && enable_scripting && !no_scripting)
340 script_write_input(buf, key);
341 if (istream_replay)
342 screen_write_input(buf, key);
343
344 /* Return terminating key */
345 return key;
346 } /* stream_read_input */
347