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