975830c68383b800daea7db25b1dca90c1c6e822
[projects/chimara/chimara.git] / interpreters / frotz / input.c
1 /* input.c - High level input functions
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include "frotz.h"
22
23 extern int save_undo (void);
24
25 extern zchar stream_read_key (zword, zword);
26 extern zchar stream_read_input (int, zchar *, zword, zword, bool);
27
28 extern void tokenise_line (zword, zword, zword, bool);
29
30 /*
31  * is_terminator
32  *
33  * Check if the given key is an input terminator.
34  *
35  */
36
37 bool is_terminator (zchar key)
38 {
39
40     if (key == ZC_TIME_OUT)
41         return TRUE;
42     if (key == ZC_RETURN)
43         return TRUE;
44     if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX)
45         return TRUE;
46
47     if (h_terminating_keys != 0)
48
49         if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) {
50
51             zword addr = h_terminating_keys;
52             zbyte c;
53
54             do {
55                 LOW_BYTE (addr, c)
56                 if (c == 255 || key == translate_from_zscii (c))
57                     return TRUE;
58                 addr++;
59             } while (c != 0);
60
61         }
62
63     return FALSE;
64
65 }/* is_terminator */
66
67 /*
68  * z_make_menu, add or remove a menu and branch if successful.
69  *
70  *      zargs[0] = number of menu
71  *      zargs[1] = table of menu entries or 0 to remove menu
72  *
73  */
74
75 void z_make_menu (void)
76 {
77
78     /* This opcode was only used for the Macintosh version of Journey.
79        It controls menus with numbers greater than 2 (menus 0, 1 and 2
80        are system menus). Frotz doesn't implement menus yet. */
81
82     branch (FALSE);
83
84 }/* z_make_menu */
85
86 /*
87  * read_yes_or_no
88  *
89  * Ask the user a question; return true if the answer is yes.
90  *
91  */
92
93 bool read_yes_or_no (const char *s)
94 {
95     zchar key;
96
97     print_string (s);
98     print_string ("? (y/n) >");
99
100     key = stream_read_key (0, 0);
101
102     if (key == 'y' || key == 'Y') {
103         print_string ("y\n");
104         return TRUE;
105     } else {
106         print_string ("n\n");
107         return FALSE;
108     }
109
110 }/* read_yes_or_no */
111
112 /*
113  * read_string
114  *
115  * Read a string from the current input stream.
116  *
117  */
118
119 void read_string (int max, zchar *buffer)
120 {
121     zchar key;
122
123     buffer[0] = 0;
124
125     do {
126
127         key = stream_read_input (max, buffer, 0, 0, FALSE);
128
129     } while (key != ZC_RETURN);
130
131 }/* read_string */
132
133 /*
134  * read_number
135  *
136  * Ask the user to type in a number and return it.
137  *
138  */
139
140 int read_number (void)
141 {
142     zchar buffer[6];
143     int value = 0;
144     int i;
145
146     read_string (5, buffer);
147
148     for (i = 0; buffer[i] != 0; i++)
149         if (buffer[i] >= '0' && buffer[i] <= '9')
150             value = 10 * value + buffer[i] - '0';
151
152     return value;
153
154 }/* read_number */
155
156 /*
157  * z_read, read a line of input and (in V5+) store the terminating key.
158  *
159  *      zargs[0] = address of text buffer
160  *      zargs[1] = address of token buffer
161  *      zargs[2] = timeout in tenths of a second (optional)
162  *      zargs[3] = packed address of routine to be called on timeout
163  *
164  */
165
166 void z_read (void)
167 {
168     zchar buffer[INPUT_BUFFER_SIZE];
169     zword addr;
170     zchar key;
171     zbyte max, size;
172     zbyte c;
173     int i;
174
175     /* Supply default arguments */
176
177     if (zargc < 3)
178         zargs[2] = 0;
179
180     /* Get maximum input size */
181
182     addr = zargs[0];
183
184     LOW_BYTE (addr, max)
185
186     if (h_version <= V4)
187         max--;
188
189     if (max >= INPUT_BUFFER_SIZE)
190         max = INPUT_BUFFER_SIZE - 1;
191
192     /* Get initial input size */
193
194     if (h_version >= V5) {
195         addr++;
196         LOW_BYTE (addr, size)
197     } else size = 0;
198
199     /* Copy initial input to local buffer */
200
201     for (i = 0; i < size; i++) {
202         addr++;
203         LOW_BYTE (addr, c)
204         buffer[i] = translate_from_zscii (c);
205     }
206
207     buffer[i] = 0;
208
209     /* Draw status line for V1 to V3 games */
210
211     if (h_version <= V3)
212         z_show_status ();
213
214     /* Read input from current input stream */
215
216     key = stream_read_input (
217         max, buffer,            /* buffer and size */
218         zargs[2],               /* timeout value   */
219         zargs[3],               /* timeout routine */
220         h_version == V6);       /* no script in V6 */
221
222     if (key == ZC_BAD)
223         return;
224
225     /* Perform save_undo for V1 to V4 games */
226
227     if (h_version <= V4)
228         save_undo ();
229
230     /* Copy local buffer back to dynamic memory */
231
232     for (i = 0; buffer[i] != 0; i++) {
233
234         if (key == ZC_RETURN) {
235
236             if (buffer[i] >= 'A' && buffer[i] <= 'Z')
237                 buffer[i] += 'a' - 'A';
238             if (buffer[i] >= 0xc0 && buffer[i] <= 0xde && buffer[i] != 0xd7)
239                 buffer[i] += 0x20;
240
241         }
242
243         storeb ((zword) (zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii (buffer[i]));
244
245     }
246
247     /* Add null character (V1-V4) or write input length into 2nd byte */
248
249     if (h_version <= V4)
250         storeb ((zword) (zargs[0] + 1 + i), 0);
251     else
252         storeb ((zword) (zargs[0] + 1), i);
253
254     /* Tokenise line if a token buffer is present */
255
256     if (key == ZC_RETURN && zargs[1] != 0)
257         tokenise_line (zargs[0], zargs[1], 0, FALSE);
258
259     /* Store key */
260
261     if (h_version >= V5)
262         store (translate_to_zscii (key));
263
264 }/* z_read */
265
266 /*
267  * z_read_char, read and store a key.
268  *
269  *      zargs[0] = input device (must be 1)
270  *      zargs[1] = timeout in tenths of a second (optional)
271  *      zargs[2] = packed address of routine to be called on timeout
272  *
273  */
274
275 void z_read_char (void)
276 {
277     zchar key;
278
279     /* Supply default arguments */
280
281     if (zargc < 2)
282         zargs[1] = 0;
283
284     /* Read input from the current input stream */
285
286     key = stream_read_key (
287         zargs[1],       /* timeout value   */
288         zargs[2]);      /* timeout routine */
289
290     if (key == ZC_BAD)
291         return;
292
293     /* Store key */
294
295     store (translate_to_zscii (key));
296
297 }/* z_read_char */
298