1 #include "angband.h"
2 
3 /* Hack - main-gcu.c wants to set this to TRUE */
4 bool multi_key_macros = FALSE;
5 
6 static bool flush_later = FALSE;
7 
move_cursor(int row,int col)8 void move_cursor(int row, int col)
9 {
10 	Term_gotoxy(col, row);
11 }
12 
flush(void)13 void flush(void)
14 {
15 	flush_later = TRUE;
16 }
17 
18 
19 /*
20  * XXX -- Temporary version of "inkey" with no macros
21  */
inkey(void)22 char inkey(void)
23 {
24 	char ch;
25 
26 	/* Refresh screen */
27 	Term_fresh();
28 
29 	/* Check for flush */
30 	if (flush_later)
31 	{
32 		/* Flush input */
33 		Term_flush();
34 
35 		/* Clear the flag */
36 		flush_later = FALSE;
37 	}
38 
39 	(void)(Term_inkey(&ch, TRUE, TRUE));
40 
41 	return ch;
42 }
43 
44 
45 /*
46  * Flush the screen, make a noise
47  */
bell(void)48 void bell(void)
49 {
50 	/* Mega-Hack -- Flush the output */
51 	Term_fresh();
52 
53 	/* Make a bell noise (if allowed) */
54 	/*if (ring_bell)*/ Term_xtra(TERM_XTRA_NOISE, 0);
55 
56 	/* Flush the input (later!) */
57 	flush();
58 }
59 
60 /*
61  * Display a string on the screen using an attribute, and clear
62  * to the end of the line.
63  */
c_prt(byte attr,cptr str,int row,int col)64 void c_prt(byte attr, cptr str, int row, int col)
65 {
66 	/* Hack -- fake monochrome */
67 	/* if (!use_color) attr = TERM_WHITE; */
68 
69 	/* Clear line, position cursor */
70 	Term_erase(col, row, 255);
71 
72 	/* Dump the attr/text */
73 	Term_addstr(-1, attr, str);
74 }
75 
76 /*
77  * As above, but in "white"
78  */
prt(cptr str,int row,int col)79 void prt(cptr str, int row, int col)
80 {
81 	/* Spawn */
82 	c_prt(TERM_WHITE, str, row, col);
83 }
84 
85 /*
86  * Get some input at the cursor location.
87  * Assume the buffer is initialized to a default string.
88  * Note that this string is often "empty" (see below).
89  * The default buffer is displayed in yellow until cleared.
90  * Pressing RETURN right away accepts the default entry.
91  * Normal chars clear the default and append the char.
92  * Backspace clears the default or deletes the final char.
93  * ESCAPE clears the buffer and the window and returns FALSE.
94  * RETURN accepts the current buffer contents and returns TRUE.
95  */
96 
97 /* APD -- added private so passwords will not be displayed. */
askfor_aux(char * buf,int len,char private)98 bool askfor_aux(char *buf, int len, char private)
99 {
100 	int y, x;
101 
102 	int i = 0;
103 
104 	int k = 0;
105 
106 	bool done = FALSE;
107 
108 
109 	/* Locate the cursor */
110 	Term_locate(&x, &y);
111 
112 	/* Paranoia -- check len */
113 	if (len < 1) len = 1;
114 
115 	/* Paranoia -- check column */
116 	if ((x < 0) || (x >= 80)) x = 0;
117 
118 	/* Restrict the length */
119 	if (x + len > 80) len = 80 - x;
120 
121 
122 	/* Paranoia -- Clip the default entry */
123 	buf[len] = '\0';
124 
125 
126 	/* Display the default answer */
127 	Term_erase(x, y, len);
128 	Term_putstr(x, y, -1, TERM_YELLOW, buf);
129 
130 
131 	/* Process input */
132 	while (!done)
133 	{
134 		/* Place cursor */
135 		Term_gotoxy(x + k, y);
136 
137 		/* Get a key */
138 		i = inkey();
139 
140 		/* Analyze the key */
141 		switch (i)
142 		{
143 			case ESCAPE:
144 			k = 0;
145 			done = TRUE;
146 			break;
147 
148 			case '\n':
149 			case '\r':
150 			k = strlen(buf);
151 			done = TRUE;
152 			break;
153 
154 			case 0x7F:
155 			case '\010':
156 			if (k > 0) k--;
157 			break;
158 
159 			default:
160 			if ((k < len) && (isprint(i)))
161 			{
162 				buf[k++] = i;
163 			}
164 			else
165 			{
166 				bell();
167 			}
168 			break;
169 		}
170 
171 		/* Terminate */
172 		buf[k] = '\0';
173 
174 		/* Update the entry */
175 		if (!private)
176 		{
177 			Term_erase(x, y, len);
178 			Term_putstr(x, y, -1, TERM_WHITE, buf);
179 		}
180 		else
181 		{
182 			Term_erase(x+k, y, len-k);
183 			if(k) Term_putch(x+k-1, y, TERM_WHITE, 'x');
184 		}
185 	}
186 
187 	/* Aborted */
188 	if (i == ESCAPE) return (FALSE);
189 
190 	/* Success */
191 	return (TRUE);
192 }
193 
194 
195 
196 /*
197  * Get a string from the user
198  *
199  * The "prompt" should take the form "Prompt: "
200  *
201  * Note that the initial contents of the string is used as
202  * the default response, so be sure to "clear" it if needed.
203  *
204  * We clear the input, and return FALSE, on "ESCAPE".
205  */
get_string(cptr prompt,char * buf,int len)206 bool get_string(cptr prompt, char *buf, int len)
207 {
208 	bool res;
209 
210 	/* Display prompt */
211 	prt(prompt, 0, 0);
212 
213 	/* Ask the user for a string */
214 	res = askfor_aux(buf, len, 0);
215 
216 	/* Clear prompt */
217 	prt("", 0, 0);
218 
219 	/* Result */
220 	return (res);
221 }
222 
223 /*
224  * Prompts for a keypress
225  *
226  * The "prompt" should take the form "Command: "
227  *
228  * Returns TRUE unless the character is "Escape"
229  */
get_com(cptr prompt,char * command)230 bool get_com(cptr prompt, char *command)
231 {
232 	/* Display a prompt */
233 	prt(prompt, 0, 0);
234 
235 	/* Get a key */
236 	*command = inkey();
237 
238 	/* Clear the prompt */
239 	prt("", 0, 0);
240 
241 	/* Handle "cancel" */
242 	if (*command == ESCAPE) return (FALSE);
243 
244 	/* Success */
245 	return (TRUE);
246 }
247 
248 
249 /*
250  * Request a command from the user.
251  *
252  * Sets command_cmd, command_dir, command_rep, command_arg.
253  *
254  * Note that "caret" ("^") is treated special, and is used to
255  * allow manual input of control characters.  This can be used
256  * on many machines to request repeated tunneling (Ctrl-H) and
257  * on the Macintosh to request "Control-Caret".
258  *
259  * Note that this command is used both in the dungeon and in
260  * stores, and must be careful to work in both situations.
261  */
request_command(bool shopping)262 void request_command(bool shopping)
263 {
264 	char cmd;
265 
266 
267 	/* Flush the input */
268 	/* flush(); */
269 
270 	/* Get a command */
271 	cmd = inkey();
272 
273 	/* Return if no key was pressed */
274 	if (!cmd) return;
275 
276 	/* Clear top line */
277 	prt("", 0, 0);
278 
279 	/* Bypass "keymap" */
280 	if (cmd == '\\')
281 	{
282 		/* Get a char to use without casting */
283 		(void)(get_com("Command: ", &cmd));
284 
285 		/* Hack -- allow "control chars" to be entered */
286 		if (cmd == '^')
287 		{
288 			/* Get a char to "cast" into a control char */
289 			(void)(get_com("Command: Control: ", &cmd));
290 
291 			/* Convert */
292 			cmd = KTRL(cmd);
293 		}
294 
295 		/* Use the key directly */
296 		command_cmd = cmd;
297 	}
298 
299 	else
300 	{
301 		/* Hack -- allow "control chars" to be entered */
302 		if (cmd == '^')
303 		{
304 			/* Get a char to "cast" into a control char */
305 			(void)(get_com("Control: ", &cmd));
306 
307 			/* Convert */
308 			cmd = KTRL(cmd);
309 		}
310 
311 		/* Use the key directly */
312 		command_cmd = cmd;
313 	}
314 
315 	/* Paranoia */
316 	if (!command_cmd) command_cmd = ESCAPE;
317 
318 	/* Hack -- erase the message line. */
319 	prt("", 0, 0);
320 }
321 
322 /*
323  * Display a string on the screen using an attribute.
324  *
325  * At the given location, using the given attribute, if allowed,
326  * add the given string.  Do not clear the line.
327  */
c_put_str(byte attr,cptr str,int row,int col)328 void c_put_str(byte attr, cptr str, int row, int col)
329 {
330 	/* Position cursor, Dump the attr/text */
331 	Term_putstr(col, row, -1, attr, str);
332 }
333 
334 
335 /*
336  * As above, but in "white"
337  */
put_str(cptr str,int row,int col)338 void put_str(cptr str, int row, int col)
339 {
340 	/* Spawn */
341 	Term_putstr(col, row, -1, TERM_WHITE, str);
342 }
343 
344 /*
345  * Verify something with the user
346  *
347  * The "prompt" should take the form "Query? "
348  *
349  * Note that "[y/n]" is appended to the prompt.
350  */
get_check(cptr prompt)351 bool get_check(cptr prompt)
352 {
353 	int i;
354 
355 	char buf[80];
356 
357 	/* Hack -- Build a "useful" prompt */
358 	strnfmt(buf, 78, "%.70s[y/n] ", prompt);
359 
360 	/* Prompt for it */
361 	prt(buf, 0, 0);
362 
363 	/* Get an acceptable answer */
364 	while (TRUE)
365 	{
366 		i = inkey();
367 		if (i == ESCAPE) break;
368 		if (strchr("YyNn", i)) break;
369 		bell();
370 	}
371 
372 	/* Erase the prompt */
373 	prt("", 0, 0);
374 
375 	/* Normal negation */
376 	if ((i != 'Y') && (i != 'y')) return (FALSE);
377 
378 	/* Success */
379 	return (TRUE);
380 }
381 
382 
383 /*
384  * Request a "quantity" from the user
385  *
386  * Hack -- allow "command_arg" to specify a quantity
387  */
c_get_quantity(cptr prompt,int max)388 s16b c_get_quantity(cptr prompt, int max)
389 {
390 	int amt;
391 
392 	char tmp[80];
393 
394 	char buf[80];
395 
396 
397 	/* Build a prompt if needed */
398 	if (!prompt)
399 	{
400 		/* Build a prompt */
401 		sprintf(tmp, "Quantity (1-%d): ", max);
402 
403 		/* Use that prompt */
404 		prompt = tmp;
405 	}
406 
407 
408 	/* Default to one */
409 	amt = 1;
410 
411 	/* Build the default */
412 	sprintf(buf, "%d", amt);
413 
414 	/* Ask for a quantity */
415 	if (!get_string(prompt, buf, 6)) return (0);
416 
417 	/* Extract a number */
418 	amt = atoi(buf);
419 
420 	/* A letter means "all" */
421 	if (isalpha(buf[0])) amt = max;
422 
423 	/* Enforce the maximum */
424 	if (amt > max) amt = max;
425 
426 	/* Enforce the minimum */
427 	if (amt < 0) amt = 0;
428 
429 	/* Return the result */
430 	return (amt);
431 }
432 
clear_from(int row)433 void clear_from(int row)
434 {
435 	int y;
436 
437 	/* Erase requested rows */
438 	for (y = row; y < Term->hgt; y++)
439 	{
440 		/* Erase part of the screen */
441 		Term_erase(0, y, 255);
442 	}
443 }
444 
prt_num(cptr header,int num,int row,int col,byte color)445 void prt_num(cptr header, int num, int row, int col, byte color)
446 {
447 	int len = strlen(header);
448 	char out_val[32];
449 	put_str(header, row, col);
450 	put_str("   ", row, col + len);
451 	(void)sprintf(out_val, "%6d", num);
452 	c_put_str(color, out_val, row, col + len + 3);
453 }
454 
prt_lnum(cptr header,s32b num,int row,int col,byte color)455 void prt_lnum(cptr header, s32b num, int row, int col, byte color)
456 {
457 	int len = strlen(header);
458 	char out_val[32];
459 	put_str(header, row, col);
460 	(void)sprintf(out_val, "%9d", num);
461 	c_put_str(color, out_val, row, col + len);
462 }
463 
464 
465 #ifdef SET_UID
466 
467 # ifndef HAS_USLEEP
468 
469 /*
470  * For those systems that don't have "usleep()" but need it.
471  *
472  * Fake "usleep()" function grabbed from the inl netrek server -cba
473  */
usleep(huge microSeconds)474 int usleep(huge microSeconds)
475 {
476 	struct timeval		Timer;
477 
478 	int			nfds = 0;
479 
480 #ifdef FD_SET
481 	fd_set		*no_fds = NULL;
482 #else
483 	int			*no_fds = NULL;
484 #endif
485 
486 	/* Was: int readfds, writefds, exceptfds; */
487 	/* Was: readfds = writefds = exceptfds = 0; */
488 
489 
490 	/* Paranoia -- No excessive sleeping */
491 	if (microSeconds > 4000000L) core("Illegal usleep() call");
492 
493 
494 	/* Wait for it */
495 	Timer.tv_sec = (microSeconds / 1000000L);
496 	Timer.tv_usec = (microSeconds % 1000000L);
497 
498 	/* Wait for it */
499 	if (select(nfds, no_fds, no_fds, no_fds, &Timer) < 0)
500 	{
501 		/* Hack -- ignore interrupts */
502 		if (errno != EINTR) return -1;
503 	}
504 
505 	/* Success */
506 	return 0;
507 }
508 
509 # endif /* HAS_USLEEP */
510 
511 #endif /* SET_UID */
512 
513 #ifdef WIN32
usleep(long microSeconds)514 int usleep(long microSeconds)
515 {
516 	Sleep(microSeconds/10); /* meassured in milliseconds not microseconds*/
517 }
518 #endif /* WIN32 */
519