Use toupper(c) rather than homegrown code.
[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
36 #include "empire.h"
37 #include "extern.h"
38
39 static int need_delay;
40 static FILE *my_stream;
41
42 void
43 /* VARARGS1 */
44 pdebug(char *s, 
45        int a, int b, int c, int d, int e, int f, int g, int h)
46 {
47         if (!print_debug) return;
48         comment (s, a, b, c, d, e, f, g, h);
49 }
50
51 /*
52 Here are routines that handle printing to the top few lines of the
53 screen.  'topini' should be called at initialization, and whenever
54 we finish printing information to the screen.
55 */
56
57 void
58 topini(void)
59 {
60         info (0, 0, 0);
61 }
62 /*
63 Write a message to one of the top lines.
64 */
65
66 void
67 /* VARARGS2 */
68 topmsg(int linep, char *buf,
69        int a, int b, int c, int d, int e, int f, int g, int h)
70 {
71         if (linep < 1 || linep > NUMTOPS)
72                 linep = 1;
73         (void) move (linep - 1, 0);
74         
75         if (buf != NULL && strlen (buf) > 0)
76                 addprintf (buf, a, b, c, d, e, f, g, h);
77         
78         (void) clrtoeol ();
79 }
80
81 void
82 topmsg1(int linep, char *buf, char *a,
83         int b, int c, int d, int e, int f, int g, int h)
84 {
85         if (linep < 1 || linep > NUMTOPS)
86                 linep = 1;
87         (void) move (linep - 1, 0);
88         
89         if (buf != NULL && strlen (buf) > 0)
90                 addprintf1 (buf, a, b, c, d, e, f, g, h);
91         
92         (void) clrtoeol ();
93 }
94
95 void
96 topmsg2(int linep, char *buf, 
97         char *a, int b, int c, int d, char *e, char *f, int g, int h)
98 {
99         if (linep < 1 || linep > NUMTOPS)
100                 linep = 1;
101         (void) move (linep - 1, 0);
102         
103         if (buf != NULL && strlen (buf) > 0)
104                 addprintf2 (buf, a, b, c, d, e, f, g, h);
105         
106         (void) clrtoeol ();
107 }
108
109 /*
110 Print a prompt on the first message line.
111 */
112
113 void
114 /* VARARGS1 */
115 prompt(char *buf,
116        int a, int b, int c, int d, int e, int f, int g, int h)
117 {
118         topmsg(1, buf, a, b, c, d, e, f, g, h);
119 }
120
121 void
122 prompt1(char *buf, char *a, 
123         int b, int c, int d, int e, int f, int g, int h)
124 {
125         topmsg1(1, buf, a, b, c, d, e, f, g, h);
126 }
127
128 void
129 prompt2 (char *buf, 
130         char *a, int b, int c, int d, char *e, char *f, int g, int h){
131         topmsg2(1, buf, a, b, c, d, e, f, g, h);
132 }
133
134 /*
135 Print an error message on the second message line.
136 */
137
138 void
139 /* VARARGS1 */
140 error(char *buf,
141        int a, int b, int c, int d, int e, int f, int g, int h)
142 {
143         topmsg(2, buf, a, b, c, d, e, f, g, h);
144 }
145
146 /*
147 Print out extra information.
148 */
149
150 void
151 /* VARARGS1 */
152 extra(char *buf,
153        int a, int b, int c, int d, int e, int f, int g, int h)
154 {
155         topmsg(3, buf, a, b, c, d, e, f, g, h);
156 }
157
158 /*
159 Print out a generic error message.
160 */
161
162 void
163 huh(void)
164 {
165         error ("Type H for Help.",0,0,0,0,0,0,0,0);
166 }
167
168 /*
169 Display information on the screen.  If the 'need_delay' flag is set,
170 we force a delay, then print the information.  After we print the
171 information, we set the need_delay flag.
172 */
173
174 void
175 info(char *a, char *b, char *c)
176 {
177         if (need_delay) delay ();
178         topmsg (1, a,0,0,0,0,0,0,0,0);
179         topmsg (2, b,0,0,0,0,0,0,0,0);
180         topmsg (3, c,0,0,0,0,0,0,0,0);
181         need_delay = (a || b || c);
182 }
183
184 void
185 set_need_delay(void) {
186         need_delay = 1;
187 }
188
189 void
190 comment (char *buf,
191        int a, int b, int c, int d, int e, int f, int g, int h)
192 {
193         if (need_delay) delay ();
194         topmsg (1, 0,0,0,0,0,0,0,0,0);
195         topmsg (2, 0,0,0,0,0,0,0,0,0);
196         topmsg (3, buf, a, b, c, d, e, f, g, h);
197         need_delay = (buf != 0);
198 }
199         
200 void
201 comment1(char *buf, char *a,
202          int b, int c, int d, int e, int f, int g, int h)
203 {
204         if (need_delay) delay ();
205         topmsg1 (1, 0,0,0,0,0,0,0,0,0);
206         topmsg1 (2, 0,0,0,0,0,0,0,0,0);
207         topmsg1 (3, buf, a, b, c, d, e, f, g, h);
208         need_delay = (buf != 0);
209 }
210         
211 /* kermyt begin */
212 void
213 ksend(char *buf,
214        int a, int b, int c, int d, int e, int f, int g, int h)
215 {
216         if(!(my_stream=fopen("info_list.txt","a")))
217         {
218                 error("Cannot open info_list.txt",0,0,0,0,0,0,0,0);
219                 return;
220         }
221         fprintf(my_stream, buf, a, b, c, d, e, f, g, h);
222         fclose(my_stream);
223         return;
224 }
225
226 void
227 ksend1(char *buf, char *a, 
228         int b, int c, int d, int e, int f, int g, int h)
229 {
230         if(!(my_stream=fopen("info_list.txt","a")))
231         {
232                 error("Cannot open info_list.txt",0,0,0,0,0,0,0,0);
233                 return;
234         }
235         fprintf(my_stream, buf, a, b, c, d, e, f, g, h);
236         fclose(my_stream);
237         return;
238 }
239 /* kermyt end */
240 /*
241 Get a string from the user, echoing characters all the while.
242 */
243
244 void
245 get_str(char *buf, int sizep)
246 {
247         (void) echo();
248         get_strq(buf, sizep);
249         (void) noecho();
250 }
251
252 /*
253 Get a string from the user, ignoring the current echo mode.
254 */
255
256 void
257 get_strq(char *buf, int sizep)
258 {
259         sizep = sizep; /* size of buf, currently unused */
260
261         (void) nocrmode ();
262         (void) refresh ();
263         (void) getstr (buf);
264         need_delay = FALSE;
265         info (0, 0, 0);
266         (void) crmode ();
267 }
268
269 /*
270 Get a character from the user and convert it to uppercase.
271 */
272
273 char
274 get_chx(void)
275 {
276         char c;
277
278         c = get_cq ();
279
280         if (islower(c))
281                 return (toupper(c));
282         else
283                 return (c);
284 }
285
286 /*
287 Input an integer from the user.
288 */
289
290 int
291 getint(char *message)
292 {
293         char buf[STRSIZE];
294         char *p;
295
296         for (;;) { /* until we get a legal number */
297                 prompt (message,0,0,0,0,0,0,0,0);
298                 get_str (buf, sizeof (buf));
299                 
300                 for (p = buf; *p; p++) {
301                         if (*p < '0' || *p > '9') {
302                                 error ("Please enter an integer.",0,0,0,0,0,0,0,0);
303                                 break;
304                         }
305                 }
306                 if (*p == 0) { /* no error yet? */
307                         if (p - buf > 7) /* too many digits? */
308                                 error ("Please enter a small integer.",0,0,0,0,0,0,0,0);
309                         else return (atoi (buf));
310                 }
311         }
312 }
313
314 /*
315 Input a character from the user with echoing.
316 */
317
318 char
319 get_c(void)
320 {
321         char c; /* one char and a null */
322
323         (void) echo ();
324         c = get_cq ();
325         (void) noecho ();
326         return (c);
327 }
328
329 /*
330 Input a character quietly.
331 */
332
333 char
334 get_cq(void)
335 {
336         char c;
337
338         (void) crmode ();
339         (void) refresh ();
340         c = getch ();
341         topini (); /* clear information lines */
342         (void) nocrmode ();
343         return (c);
344 }
345
346 /*
347 Input a yes or no response from the user.  We loop until we get
348 a valid response.  We return TRUE iff the user replies 'y'.
349 */
350
351 int
352 getyn(char *message)
353 {
354         char c;
355
356         for (;;) {
357                 prompt (message,0,0,0,0,0,0,0,0);
358                 c = get_chx ();
359
360                 if (c == 'Y') return (TRUE);
361                 if (c == 'N') return (FALSE);
362
363                 error ("Please answer Y or N.",0,0,0,0,0,0,0,0);
364         }
365 }
366
367 /*
368 Input an integer in a range.
369 */
370
371 int
372 get_range(char *message, int low, int high)
373 {
374         int result;
375
376         for (;;) {
377                 result = getint (message);
378
379                 if (result >= low && result <= high) return (result);
380
381                 error ("Please enter an integer in the range %d..%d.",low, high,0,0,0,0,0,0);
382         }
383 }
384
385 /*
386 Print a screen of help information.
387 */
388
389 void
390 help(char **text, int nlines)
391 {
392         int i, r, c;
393         int text_lines;
394
395         text_lines = (nlines + 1) / 2; /* lines of text */
396
397         clear_screen ();
398
399         pos_str (NUMTOPS, 1, text[0],0,0,0,0,0,0,0,0); /* mode */
400         pos_str (NUMTOPS, 41, "See empire(6) for more information.",0,0,0,0,0,0,0,0);
401
402         for (i = 1; i < nlines; i++) {
403                 if (i > text_lines)
404                         pos_str (i - text_lines + NUMTOPS + 1, 41, text[i],0,0,0,0,0,0,0,0);
405                 else pos_str (i + NUMTOPS + 1, 1, text[i],0,0,0,0,0,0,0,0);
406         }
407
408         pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost",0,0,0,0,0,0,0,0);
409         pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost",0,0,0,0,0,0,0,0);
410
411         for (i = 0; i < NUM_OBJECTS; i++) {
412                 if (i >= (NUM_OBJECTS+1)/2) {
413                         r = i - (NUM_OBJECTS+1)/2;
414                         c = 41;
415                 }
416                 else {
417                         r = i;
418                         c = 1;
419                 }
420                 pos_str1 (r + text_lines + NUMTOPS + 3, c,"%-12s%c     %c%6d%5d%6d",
421                         piece_attr[i].nickname,
422                         piece_attr[i].sname,
423                         tolower (piece_attr[i].sname),
424                         piece_attr[i].speed,
425                         piece_attr[i].max_hits,
426                         piece_attr[i].build_time,0,0);          //FLAG
427
428         }
429         (void) refresh ();
430 }
431
432 #define COL_DIGITS ((MAP_WIDTH <= 100) ? 2 : ((MAP_WIDTH <= 1000 ? 3 : (1 / 0))))
433
434 int
435 loc_disp(int loc)
436 {
437   int row = loc / MAP_WIDTH;
438   int nrow = row;
439   int col = loc % MAP_WIDTH;
440   ASSERT (loc == (row * MAP_WIDTH) + col);
441   int i;
442   for (i = COL_DIGITS; i > 0; i--) {
443     nrow *= 10; }
444   move (LINES - 1, 0);
445   return nrow + col;
446 }