More boolean conversions. No logic changes.
[vms-empire.git] / term.c
1 /*
2  *    Copyright (C) 1987, 1988 Chuck Simmons
3  * 
4  * See the file COPYING, distributed with empire, for restriction
5  * and warranty information.
6  */
7
8 /*
9 term.c -- this file contains various routines used to control the
10 user communications area of the terminal.  This area consists of
11 the top 3 lines of the terminal where messages are displayed to the
12 user and input is acquired from the user.
13
14 There are two types of output in this area.  One type is interactive
15 output.  This consists of a prompt line and an error message line.
16 The other type of output is informational output.  The user must
17 be given time to read informational output.
18
19 Whenever input is received, the top three lines are cleared and the
20 screen refreshed as the user has had time to read these lines.  We
21 also clear the 'need_delay' flag, saying that the user has read the
22 information on the screen.
23
24 When information is to be displayed, if the 'need_delay' flag is set,
25 we refresh the screen and pause momentarily to give the user a chance
26 to read the lines.  The new information is then displayed, and the
27 'need_delay' flag is set.
28 */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <curses.h>
34 #include <ctype.h>
35 #include <stdarg.h>
36
37 #include "empire.h"
38 #include "extern.h"
39
40 static bool need_delay;
41 static FILE *my_stream;
42
43 /*
44 Here are routines that handle printing to the top few lines of the
45 screen.  'topini' should be called at initialization, and whenever
46 we finish printing information to the screen.
47 */
48
49 void
50 topini(void)
51 {
52     info (0, 0, 0);
53 }
54 /*
55 Write a message to one of the top lines.
56 */
57
58 static void vtopmsg(int line, const char *fmt, va_list varglist)
59 /* assemble command in printf(3) style, print to a top line */
60 {
61     char junkbuf[STRSIZE];
62         
63     if (line < 1 || line > NUMTOPS)
64         line = 1;
65     (void) move (line - 1, 0);
66     vsprintf(junkbuf, fmt, varglist);
67     (void) addstr (junkbuf);
68     (void) clrtoeol();
69 }
70
71 void
72 topmsg(int line, char *fmt, ...)
73 {
74     va_list ap;
75
76     va_start(ap, fmt);
77     vtopmsg(line, fmt, ap);
78     va_end(ap);
79 }
80
81 /*
82 Print a prompt on the first message line.
83 */
84
85 void
86 prompt(char *fmt, ...)
87 {
88     va_list ap;
89
90     va_start(ap, fmt);
91     vtopmsg(1, fmt, ap);
92     va_end(ap);
93 }
94
95 /*
96 Print an error message on the second message line.
97 */
98
99 void
100 error(char *fmt, ...)
101 {
102     va_list ap;
103
104     va_start(ap, fmt);
105     vtopmsg(2, fmt, ap);
106     va_end(ap);
107 }
108
109 /*
110 Print out extra information.
111 */
112
113 void
114 extra(char *fmt, ...)
115 {
116     va_list ap;
117
118     va_start(ap, fmt);
119     vtopmsg(3, fmt, ap);
120     va_end(ap);
121 }
122
123
124 /*
125 Print out a generic error message.
126 */
127
128 void
129 huh(void)
130 {
131     error ("Type H for Help.");
132 }
133
134 /*
135 Display information on the screen.  If the 'need_delay' flag is set,
136 we force a delay, then print the information.  After we print the
137 information, we set the need_delay flag.
138 */
139
140 void
141 info(char *a, char *b, char *c)
142 {
143     if (need_delay) delay ();
144     topmsg (1, a);
145     topmsg (2, b);
146     topmsg (3, c);
147     need_delay = (a || b || c);
148 }
149
150 void
151 set_need_delay(void)
152 {
153     need_delay = true;
154 }
155
156 void
157 comment (char *fmt, ...)
158 {
159     va_list ap;
160
161     va_start(ap, fmt);
162     if (need_delay)
163         delay ();
164     topmsg (1, "");
165     topmsg (2, "");
166     vtopmsg (3, fmt, ap);
167     need_delay = (fmt != 0);
168     va_end(ap);
169 }
170         
171 void
172 pdebug(char *fmt, ...)
173 {
174     va_list ap;
175
176     if (!print_debug) return;
177
178     va_start(ap, fmt);
179     if (need_delay)
180         delay ();
181     topmsg (1, "");
182     topmsg (2, "");
183     vtopmsg (3, fmt, ap);
184     need_delay = (fmt != 0);
185     va_end(ap);
186 }
187
188 /* kermyt begin */
189
190 void
191 vksend(const char *fmt, va_list varglist)
192 {
193     if(!(my_stream=fopen("info_list.txt","a")))
194     {
195         error("Cannot open info_list.txt");
196         return;
197     }
198     vfprintf(my_stream, fmt, varglist);
199     fclose(my_stream);
200     return;
201 }
202
203 void
204 ksend(char *fmt, ...)
205 {
206     va_list ap;
207
208     va_start(ap, fmt);
209     vksend(fmt, ap);
210     va_end(ap);
211 }
212 /* kermyt end */
213
214 /*
215 Get a string from the user, echoing characters all the while.
216 */
217
218 void
219 get_str(char *buf, int sizep)
220 {
221     (void) echo();
222     get_strq(buf, sizep);
223     (void) noecho();
224 }
225
226 /*
227 Get a string from the user, ignoring the current echo mode.
228 */
229
230 void
231 get_strq(char *buf, int sizep)
232 {
233     sizep = sizep; /* size of buf, currently unused */
234
235     (void) nocrmode ();
236     (void) refresh ();
237     (void) getstr (buf);
238     need_delay = false;
239     info (0, 0, 0);
240     (void) crmode ();
241 }
242
243 /*
244 Get a character from the user and convert it to uppercase.
245 */
246
247 char
248 get_chx(void)
249 {
250     char c;
251
252     c = get_cq ();
253
254     if (islower(c))
255         return (toupper(c));
256     else
257         return (c);
258 }
259
260 /*
261 Input an integer from the user.
262 */
263
264 int
265 getint(char *message)
266 {
267     char buf[STRSIZE];
268     char *p;
269
270     for (;;) { /* until we get a legal number */
271         prompt (message,0,0,0,0,0,0,0,0);
272         get_str (buf, sizeof (buf));
273                 
274         for (p = buf; *p; p++) {
275             if (*p < '0' || *p > '9') {
276                 error ("Please enter an integer.",0,0,0,0,0,0,0,0);
277                 break;
278             }
279         }
280         if (*p == 0) { /* no error yet? */
281             if (p - buf > 7) /* too many digits? */
282                 error ("Please enter a small integer.",0,0,0,0,0,0,0,0);
283             else return (atoi (buf));
284         }
285     }
286 }
287
288 /*
289 Input a character from the user with echoing.
290 */
291
292 char
293 get_c(void)
294 {
295     char c; /* one char and a null */
296
297     (void) echo ();
298     c = get_cq ();
299     (void) noecho ();
300     return (c);
301 }
302
303 /*
304 Input a character quietly.
305 */
306
307 char
308 get_cq(void)
309 {
310     char c;
311
312     (void) crmode ();
313     (void) refresh ();
314     c = getch ();
315     topini (); /* clear information lines */
316     (void) nocrmode ();
317     return (c);
318 }
319
320 /*
321 Input a yes or no response from the user.  We loop until we get
322 a valid response.  We return true iff the user replies 'y'.
323 */
324
325 bool
326 getyn(char *message)
327 {
328     char c;
329
330     for (;;) {
331         prompt (message,0,0,0,0,0,0,0,0);
332         c = get_chx ();
333
334         if (c == 'Y') return (true);
335         if (c == 'N') return (false);
336
337         error ("Please answer Y or N.",0,0,0,0,0,0,0,0);
338     }
339 }
340
341 /*
342 Input an integer in a range.
343 */
344
345 int
346 get_range(char *message, int low, int high)
347 {
348     int result;
349
350     for (;;) {
351         result = getint (message);
352
353         if (result >= low && result <= high) return (result);
354
355         error ("Please enter an integer in the range %d..%d.",low, high);
356     }
357 }
358
359 /*
360 Print a screen of help information.
361 */
362
363 void
364 help(char **text, int nlines)
365 {
366     int i, r, c;
367     int text_lines;
368
369     text_lines = (nlines + 1) / 2; /* lines of text */
370
371     clear_screen ();
372
373     pos_str (NUMTOPS, 1, text[0]); /* mode */
374     pos_str (NUMTOPS, 41, "See empire(6) for more information.");
375
376     for (i = 1; i < nlines; i++) {
377         if (i > text_lines)
378             pos_str (i - text_lines + NUMTOPS + 1, 41, text[i]);
379         else pos_str (i + NUMTOPS + 1, 1, text[i]);
380     }
381
382     pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost");
383     pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost");
384
385     for (i = 0; i < NUM_OBJECTS; i++) {
386         if (i >= (NUM_OBJECTS+1)/2) {
387             r = i - (NUM_OBJECTS+1)/2;
388             c = 41;
389         }
390         else {
391             r = i;
392             c = 1;
393         }
394         pos_str1 (r + text_lines + NUMTOPS + 3, c,"%-12s%c     %c%6d%5d%6d",
395                   piece_attr[i].nickname,
396                   piece_attr[i].sname,
397                   tolower (piece_attr[i].sname),
398                   piece_attr[i].speed,
399                   piece_attr[i].max_hits,
400                   piece_attr[i].build_time,0,0);                //FLAG
401
402     }
403     (void) refresh ();
404 }
405
406 #define COL_DIGITS ((MAP_WIDTH <= 100) ? 2 : ((MAP_WIDTH <= 1000 ? 3 : (1 / 0))))
407
408 int
409 loc_disp(int loc)
410 {
411     int row = loc / MAP_WIDTH;
412     int nrow = row;
413     int col = loc % MAP_WIDTH;
414     ASSERT (loc == (row * MAP_WIDTH) + col);
415     int i;
416     for (i = COL_DIGITS; i > 0; i--) {
417         nrow *= 10; }
418     move (LINES - 1, 0);
419     return nrow + col;
420 }
421
422 /* end */