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