1 /* files.c - Transscription, recording and playback
2 * Copyright (c) 1995-1997 Stefan Jokisch
4 * This file is part of Frotz.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
25 extern void set_more_prompts (bool);
27 extern bool is_terminator (zchar);
29 extern bool read_yes_or_no (const char *);
31 static int script_width = 0;
33 static FILE *sfp = NULL;
34 static FILE *rfp = NULL;
35 static FILE *pfp = NULL;
40 * Open the transscript file. 'AMFV' makes this more complicated as it
41 * turns transscription on/off several times to exclude some text from
42 * the transscription file. This wasn't a problem for the original V4
43 * interpreters which always sent transscription to the printer, but it
44 * means a problem to modern interpreters that offer to open a new file
45 * every time transscription is turned on. Our solution is to append to
46 * the old transscription file in V1 to V4, and to ask for a new file
49 * Alas, we cannot do this, since glk cannot give us the filename
50 * to reopen it again, and I dont want to mess with filerefs here.
54 void script_open (void)
56 static bool script_valid = FALSE;
58 h_flags &= ~SCRIPTING_FLAG;
61 if (h_version >= V5 || !script_valid) {
62 if (!os_read_file_name (new_name, script_name, FILE_SCRIPT))
66 /* Opening in "at" mode doesn't work for script_erase_input... */
68 if ((sfp = fopen (sfp = fopen (script_name, "r+t")) != NULL || (sfp = fopen (script_name, "w+t")) != NULL) {
72 if ((sfp = frotzopenprompt(FILE_SCRIPT)) != NULL)
74 fseek (sfp, 0, SEEK_END);
76 h_flags |= SCRIPTING_FLAG;
79 ostream_script = TRUE;
83 } else print_string ("Cannot open file\n");
87 SET_WORD (H_FLAGS, h_flags)
94 * Stop transscription.
98 void script_close (void)
101 h_flags &= ~SCRIPTING_FLAG;
102 SET_WORD (H_FLAGS, h_flags)
104 fclose (sfp); ostream_script = FALSE;
111 * Write a newline to the transscript file.
115 void script_new_line (void)
118 if (fputc ('\n', sfp) == EOF)
123 }/* script_new_line */
128 * Write a single character to the transscript file.
132 void script_char (zchar c)
135 if (c == ZC_INDENT && script_width != 0)
139 { script_char (' '); script_char (' '); script_char (' '); return; }
141 { script_char (' '); script_char (' '); return; }
143 fputc (c, sfp); script_width++;
150 * Write a string to the transscript file.
154 void script_word (const zchar *s)
159 if (*s == ZC_INDENT && script_width != 0)
162 for (i = 0, width = 0; s[i] != 0; i++)
164 if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT)
166 else if (s[i] == ZC_GAP)
168 else if (s[i] == ZC_INDENT)
173 if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols) {
175 if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
182 for (i = 0; s[i] != 0; i++)
184 if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
194 * Send an input line to the transscript file.
198 void script_write_input (const zchar *buf, zchar key)
203 for (i = 0, width = 0; buf[i] != 0; i++)
206 if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols)
209 for (i = 0; buf[i] != 0; i++)
210 script_char (buf[i]);
212 if (key == ZC_RETURN)
215 }/* script_write_input */
220 * Remove an input line from the transscript file.
224 void script_erase_input (const zchar *buf)
229 for (i = 0, width = 0; buf[i] != 0; i++)
232 fseek (sfp, -width, SEEK_CUR); script_width -= width;
234 }/* script_erase_input */
239 * Start sending a "debugging" message to the transscript file.
243 void script_mssg_on (void)
246 if (script_width != 0)
249 script_char (ZC_INDENT);
251 }/* script_mssg_on */
256 * Stop writing a "debugging" message.
260 void script_mssg_off (void)
265 }/* script_mssg_off */
270 * Open a file to record the player's input.
274 void record_open (void)
276 if ((rfp = frotzopenprompt(FILE_RECORD)) != NULL)
277 ostream_record = TRUE;
279 print_string ("Cannot open file\n");
285 * Stop recording the player's input.
289 void record_close (void)
292 fclose (rfp); ostream_record = FALSE;
299 * Helper function for record_char.
303 static void record_code (int c, bool force_encoding)
306 if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) {
312 for (i = 10000; i != 0; i /= 10)
313 if (c >= i || i == 1)
314 fputc ('0' + (c / i) % 10, rfp);
318 } else fputc (c, rfp);
325 * Write a character to the command file.
329 static void record_char (zchar c)
332 if (c != ZC_RETURN) {
333 if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) {
334 record_code (translate_to_zscii (c), FALSE);
335 if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
336 record_code (mouse_x, TRUE);
337 record_code (mouse_y, TRUE);
339 } else record_code (1000 + c - ZC_HKEY_MIN, TRUE);
347 * Copy a keystroke to the command file.
351 void record_write_key (zchar key)
356 if (fputc ('\n', rfp) == EOF)
359 }/* record_write_key */
364 * Copy a line of input to a command file.
368 void record_write_input (const zchar *buf, zchar key)
372 while ((c = *buf++) != 0)
377 if (fputc ('\n', rfp) == EOF)
380 }/* record_write_input */
385 * Open a file of commands for playback.
389 void replay_open (void)
391 if ((pfp = frotzopenprompt(FILE_PLAYBACK)) != NULL)
392 istream_replay = TRUE;
394 print_string ("Cannot open file\n");
400 * Stop playback of commands.
404 void replay_close (void)
406 fclose (pfp); istream_replay = FALSE;
412 * Helper function for replay_key and replay_line.
416 static int replay_code (void)
420 if ((c = fgetc (pfp)) == '[') {
426 while ((c2 = fgetc (pfp)) != EOF && c2 >= '0' && c2 <= '9')
427 c = 10 * c + c2 - '0';
429 return (c2 == ']') ? c : EOF;
438 * Read a character from the command file.
442 static zchar replay_char (void)
446 if ((c = replay_code ()) != EOF) {
452 c = translate_from_zscii (c);
454 if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
455 mouse_x = replay_code ();
456 mouse_y = replay_code ();
461 } else return ZC_HKEY_MIN + c - 1000;
468 } else return ZC_BAD;
475 * Read a keystroke from a command file.
479 zchar replay_read_key (void)
483 key = replay_char ();
485 if (fgetc (pfp) != '\n') {
492 }/* replay_read_key */
497 * Read a line of input from a command file.
501 zchar replay_read_input (zchar *buf)
509 if (c == ZC_BAD || is_terminator (c))
518 if (fgetc (pfp) != '\n') {
525 }/* replay_read_input */